From 29a858b85f4c6479474b8d82c8995bde1166352b Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Tue, 31 Jan 2023 10:23:15 +0000 Subject: [PATCH 01/74] gh-98831: rewrite GET_LEN, GET_ITER, BEFORE_WITH and a few simple opcodes in the instruction definition DSL (#101443) --- Python/bytecodes.c | 57 ++++++++++++++------------------------ Python/generated_cases.c.h | 43 +++++++++++++++------------- Python/opcode_metadata.h | 28 +++++++++---------- 3 files changed, 59 insertions(+), 69 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index d1e59f7908b5803..5b3bf4ec7ba7960 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -2053,8 +2053,7 @@ dummy_func( } } - // stack effect: ( -- ) - inst(JUMP_BACKWARD_NO_INTERRUPT) { + inst(JUMP_BACKWARD_NO_INTERRUPT, (--)) { /* This bytecode is used in the `yield from` or `await` loop. * If there is an interrupt, we want it handled in the innermost * generator or coroutine, so we deliberately do not check it here. @@ -2063,18 +2062,12 @@ dummy_func( JUMPBY(-oparg); } - // stack effect: ( -- __0) - inst(GET_LEN) { + inst(GET_LEN, (obj -- obj, len_o)) { // PUSH(len(TOS)) - Py_ssize_t len_i = PyObject_Length(TOP()); - if (len_i < 0) { - goto error; - } - PyObject *len_o = PyLong_FromSsize_t(len_i); - if (len_o == NULL) { - goto error; - } - PUSH(len_o); + Py_ssize_t len_i = PyObject_Length(obj); + ERROR_IF(len_i < 0, error); + len_o = PyLong_FromSsize_t(len_i); + ERROR_IF(len_o == NULL, error); } inst(MATCH_CLASS, (subject, type, names -- attrs)) { @@ -2110,15 +2103,11 @@ dummy_func( ERROR_IF(values_or_none == NULL, error); } - // stack effect: ( -- ) - inst(GET_ITER) { + inst(GET_ITER, (iterable -- iter)) { /* before: [obj]; after [getiter(obj)] */ - PyObject *iterable = TOP(); - PyObject *iter = PyObject_GetIter(iterable); - Py_DECREF(iterable); - SET_TOP(iter); - if (iter == NULL) - goto error; + iter = PyObject_GetIter(iterable); + DECREF_INPUTS(); + ERROR_IF(iter == NULL, error); } // stack effect: ( -- ) @@ -2313,10 +2302,10 @@ dummy_func( PREDICT(GET_AWAITABLE); } - // stack effect: ( -- __0) - inst(BEFORE_WITH) { - PyObject *mgr = TOP(); - PyObject *res; + inst(BEFORE_WITH, (mgr -- exit, res)) { + /* pop the context manager, push its __exit__ and the + * value returned from calling its __enter__ + */ PyObject *enter = _PyObject_LookupSpecial(mgr, &_Py_ID(__enter__)); if (enter == NULL) { if (!_PyErr_Occurred(tstate)) { @@ -2327,7 +2316,7 @@ dummy_func( } goto error; } - PyObject *exit = _PyObject_LookupSpecial(mgr, &_Py_ID(__exit__)); + exit = _PyObject_LookupSpecial(mgr, &_Py_ID(__exit__)); if (exit == NULL) { if (!_PyErr_Occurred(tstate)) { _PyErr_Format(tstate, PyExc_TypeError, @@ -2339,14 +2328,13 @@ dummy_func( Py_DECREF(enter); goto error; } - SET_TOP(exit); - Py_DECREF(mgr); + DECREF_INPUTS(); res = _PyObject_CallNoArgs(enter); Py_DECREF(enter); if (res == NULL) { - goto error; + Py_DECREF(exit); + ERROR_IF(true, error); } - PUSH(res); } inst(WITH_EXCEPT_START, (exit_func, lasti, unused, val -- exit_func, lasti, unused, val, res)) { @@ -2469,8 +2457,7 @@ dummy_func( GO_TO_INSTRUCTION(CALL_PY_EXACT_ARGS); } - // stack effect: ( -- ) - inst(KW_NAMES) { + inst(KW_NAMES, (--)) { assert(kwnames == NULL); assert(oparg < PyTuple_GET_SIZE(consts)); kwnames = GETITEM(consts, oparg); @@ -3252,8 +3239,7 @@ dummy_func( PEEK(oparg) = top; } - // stack effect: ( -- ) - inst(EXTENDED_ARG) { + inst(EXTENDED_ARG, (--)) { assert(oparg); assert(cframe.use_tracing == 0); opcode = _Py_OPCODE(*next_instr); @@ -3262,8 +3248,7 @@ dummy_func( DISPATCH_GOTO(); } - // stack effect: ( -- ) - inst(CACHE) { + inst(CACHE, (--)) { Py_UNREACHABLE(); } diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 3ee30ae8df9e3cf..661fe27f327b330 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -2460,16 +2460,15 @@ } TARGET(GET_LEN) { + PyObject *obj = PEEK(1); + PyObject *len_o; // PUSH(len(TOS)) - Py_ssize_t len_i = PyObject_Length(TOP()); - if (len_i < 0) { - goto error; - } - PyObject *len_o = PyLong_FromSsize_t(len_i); - if (len_o == NULL) { - goto error; - } - PUSH(len_o); + Py_ssize_t len_i = PyObject_Length(obj); + if (len_i < 0) goto error; + len_o = PyLong_FromSsize_t(len_i); + if (len_o == NULL) goto error; + STACK_GROW(1); + POKE(1, len_o); DISPATCH(); } @@ -2532,13 +2531,13 @@ } TARGET(GET_ITER) { + PyObject *iterable = PEEK(1); + PyObject *iter; /* before: [obj]; after [getiter(obj)] */ - PyObject *iterable = TOP(); - PyObject *iter = PyObject_GetIter(iterable); + iter = PyObject_GetIter(iterable); Py_DECREF(iterable); - SET_TOP(iter); - if (iter == NULL) - goto error; + if (iter == NULL) goto pop_1_error; + POKE(1, iter); DISPATCH(); } @@ -2736,8 +2735,12 @@ } TARGET(BEFORE_WITH) { - PyObject *mgr = TOP(); + PyObject *mgr = PEEK(1); + PyObject *exit; PyObject *res; + /* pop the context manager, push its __exit__ and the + * value returned from calling its __enter__ + */ PyObject *enter = _PyObject_LookupSpecial(mgr, &_Py_ID(__enter__)); if (enter == NULL) { if (!_PyErr_Occurred(tstate)) { @@ -2748,7 +2751,7 @@ } goto error; } - PyObject *exit = _PyObject_LookupSpecial(mgr, &_Py_ID(__exit__)); + exit = _PyObject_LookupSpecial(mgr, &_Py_ID(__exit__)); if (exit == NULL) { if (!_PyErr_Occurred(tstate)) { _PyErr_Format(tstate, PyExc_TypeError, @@ -2760,14 +2763,16 @@ Py_DECREF(enter); goto error; } - SET_TOP(exit); Py_DECREF(mgr); res = _PyObject_CallNoArgs(enter); Py_DECREF(enter); if (res == NULL) { - goto error; + Py_DECREF(exit); + if (true) goto pop_1_error; } - PUSH(res); + STACK_GROW(1); + POKE(1, res); + POKE(2, exit); DISPATCH(); } diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index e76ddda2f0292db..c40e40ff324d11f 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -245,9 +245,9 @@ _PyOpcode_num_popped(int opcode, int oparg) { case JUMP_IF_TRUE_OR_POP: return -1; case JUMP_BACKWARD_NO_INTERRUPT: - return -1; + return 0; case GET_LEN: - return -1; + return 1; case MATCH_CLASS: return 3; case MATCH_MAPPING: @@ -257,7 +257,7 @@ _PyOpcode_num_popped(int opcode, int oparg) { case MATCH_KEYS: return 2; case GET_ITER: - return -1; + return 1; case GET_YIELD_FROM_ITER: return -1; case FOR_ITER: @@ -273,7 +273,7 @@ _PyOpcode_num_popped(int opcode, int oparg) { case BEFORE_ASYNC_WITH: return -1; case BEFORE_WITH: - return -1; + return 1; case WITH_EXCEPT_START: return 4; case PUSH_EXC_INFO: @@ -287,7 +287,7 @@ _PyOpcode_num_popped(int opcode, int oparg) { case CALL_BOUND_METHOD_EXACT_ARGS: return -1; case KW_NAMES: - return -1; + return 0; case CALL: return -1; case CALL_PY_EXACT_ARGS: @@ -339,9 +339,9 @@ _PyOpcode_num_popped(int opcode, int oparg) { case SWAP: return -1; case EXTENDED_ARG: - return -1; + return 0; case CACHE: - return -1; + return 0; default: Py_UNREACHABLE(); } @@ -591,9 +591,9 @@ _PyOpcode_num_pushed(int opcode, int oparg) { case JUMP_IF_TRUE_OR_POP: return -1; case JUMP_BACKWARD_NO_INTERRUPT: - return -1; + return 0; case GET_LEN: - return -1; + return 2; case MATCH_CLASS: return 1; case MATCH_MAPPING: @@ -603,7 +603,7 @@ _PyOpcode_num_pushed(int opcode, int oparg) { case MATCH_KEYS: return 3; case GET_ITER: - return -1; + return 1; case GET_YIELD_FROM_ITER: return -1; case FOR_ITER: @@ -619,7 +619,7 @@ _PyOpcode_num_pushed(int opcode, int oparg) { case BEFORE_ASYNC_WITH: return -1; case BEFORE_WITH: - return -1; + return 2; case WITH_EXCEPT_START: return 5; case PUSH_EXC_INFO: @@ -633,7 +633,7 @@ _PyOpcode_num_pushed(int opcode, int oparg) { case CALL_BOUND_METHOD_EXACT_ARGS: return -1; case KW_NAMES: - return -1; + return 0; case CALL: return -1; case CALL_PY_EXACT_ARGS: @@ -685,9 +685,9 @@ _PyOpcode_num_pushed(int opcode, int oparg) { case SWAP: return -1; case EXTENDED_ARG: - return -1; + return 0; case CACHE: - return -1; + return 0; default: Py_UNREACHABLE(); } From 1a62ae84c687791bc1dfb54d1eb75e1c7277bb04 Mon Sep 17 00:00:00 2001 From: Christophe Nanteuil <35002064+christopheNan@users.noreply.github.com> Date: Tue, 31 Jan 2023 14:29:29 +0100 Subject: [PATCH 02/74] Add JOBS parameter to docs Makefile (#101395) --- Doc/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Doc/Makefile b/Doc/Makefile index 3d484ac3ae7937b..ebe7f3698000fb8 100644 --- a/Doc/Makefile +++ b/Doc/Makefile @@ -9,6 +9,7 @@ VENVDIR = ./venv SPHINXBUILD = PATH=$(VENVDIR)/bin:$$PATH sphinx-build SPHINXLINT = PATH=$(VENVDIR)/bin:$$PATH sphinx-lint BLURB = PATH=$(VENVDIR)/bin:$$PATH blurb +JOBS = auto PAPER = SOURCES = DISTVERSION = $(shell $(PYTHON) tools/extensions/patchlevel.py) @@ -18,7 +19,7 @@ SPHINXERRORHANDLING = -W PAPEROPT_a4 = -D latex_elements.papersize=a4paper PAPEROPT_letter = -D latex_elements.papersize=letterpaper -ALLSPHINXOPTS = -b $(BUILDER) -d build/doctrees $(PAPEROPT_$(PAPER)) -j auto \ +ALLSPHINXOPTS = -b $(BUILDER) -d build/doctrees $(PAPEROPT_$(PAPER)) -j $(JOBS) \ $(SPHINXOPTS) $(SPHINXERRORHANDLING) . build/$(BUILDER) $(SOURCES) .PHONY: help From df0068ce4827471cc2962631ee64f6f38e818ec4 Mon Sep 17 00:00:00 2001 From: Raj <51259329+workingpayload@users.noreply.github.com> Date: Tue, 31 Jan 2023 20:46:17 +0530 Subject: [PATCH 03/74] gh-99276 - Updated Doc/faq/general.rst (#101396) Co-authored-by: Hugo van Kemenade --- Doc/faq/general.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/faq/general.rst b/Doc/faq/general.rst index 489bca76432d859..6256deb5797c893 100644 --- a/Doc/faq/general.rst +++ b/Doc/faq/general.rst @@ -248,8 +248,8 @@ Are there any published articles about Python that I can reference? It's probably best to cite your favorite book about Python. -The very first article about Python was written in 1991 and is now quite -outdated. +The `very first article `_ about Python was +written in 1991 and is now quite outdated. Guido van Rossum and Jelke de Boer, "Interactively Testing Remote Servers Using the Python Programming Language", CWI Quarterly, Volume 4, Issue 4 From 20c11f2e600e1c0bf42de4d6f2fb3ce5ccc2587c Mon Sep 17 00:00:00 2001 From: Peter Jiping Xie Date: Wed, 1 Feb 2023 02:30:38 +1100 Subject: [PATCH 04/74] gh-101440: fix json snippet error in logging-cookbook.rst (#101439) --- Doc/howto/logging-cookbook.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst index 26cf40274fd3e22..7661249ad522fa0 100644 --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -307,7 +307,7 @@ Suppose you configure logging with the following JSON: "class": "logging.StreamHandler", "level": "INFO", "formatter": "simple", - "stream": "ext://sys.stdout", + "stream": "ext://sys.stdout" }, "stderr": { "class": "logging.StreamHandler", From f80db6cef075186f888a85258ccf2164bf148921 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 31 Jan 2023 19:19:11 +0100 Subject: [PATCH 05/74] gh-101469: Optimise get_io_state() by using _PyModule_GetState() (GH-101470) Automerge-Triggered-By: GH:erlend-aasland --- Modules/_io/_iomodule.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index af5950cf66c1782..175fa97479d27d8 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -10,6 +10,7 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" #include "_iomodule.h" +#include "pycore_moduleobject.h" // _PyModule_GetState() #include "pycore_pystate.h" // _PyInterpreterState_GET() #ifdef HAVE_SYS_TYPES_H @@ -560,7 +561,7 @@ PyNumber_AsOff_t(PyObject *item, PyObject *err) static inline _PyIO_State* get_io_state(PyObject *module) { - void *state = PyModule_GetState(module); + void *state = _PyModule_GetState(module); assert(state != NULL); return (_PyIO_State *)state; } From 0062f538d937de55cf3b66b4a8d527b1fe9d5182 Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Tue, 31 Jan 2023 18:47:50 +0000 Subject: [PATCH 06/74] gh-98831: rewrite BEFORE_ASYNC_WITH and END_ASYNC_FOR in the instruction definition DSL (#101458) --- Python/bytecodes.c | 35 +++++++++++++++-------------------- Python/generated_cases.c.h | 35 +++++++++++++++++++++-------------- Python/opcode_metadata.h | 8 ++++---- 3 files changed, 40 insertions(+), 38 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 5b3bf4ec7ba7960..336088e08197deb 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -770,18 +770,16 @@ dummy_func( ERROR_IF(val == NULL, error); } - // stack effect: (__0, __1 -- ) - inst(END_ASYNC_FOR) { - PyObject *val = POP(); - assert(val && PyExceptionInstance_Check(val)); - if (PyErr_GivenExceptionMatches(val, PyExc_StopAsyncIteration)) { - Py_DECREF(val); - Py_DECREF(POP()); + inst(END_ASYNC_FOR, (awaitable, exc -- )) { + assert(exc && PyExceptionInstance_Check(exc)); + if (PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration)) { + DECREF_INPUTS(); } else { - PyObject *exc = Py_NewRef(PyExceptionInstance_Class(val)); - PyObject *tb = PyException_GetTraceback(val); - _PyErr_Restore(tstate, exc, val, tb); + Py_INCREF(exc); + PyObject *typ = Py_NewRef(PyExceptionInstance_Class(exc)); + PyObject *tb = PyException_GetTraceback(exc); + _PyErr_Restore(tstate, typ, exc, tb); goto exception_unwind; } } @@ -2266,10 +2264,7 @@ dummy_func( DISPATCH_INLINED(gen_frame); } - // stack effect: ( -- __0) - inst(BEFORE_ASYNC_WITH) { - PyObject *mgr = TOP(); - PyObject *res; + inst(BEFORE_ASYNC_WITH, (mgr -- exit, res)) { PyObject *enter = _PyObject_LookupSpecial(mgr, &_Py_ID(__aenter__)); if (enter == NULL) { if (!_PyErr_Occurred(tstate)) { @@ -2280,7 +2275,7 @@ dummy_func( } goto error; } - PyObject *exit = _PyObject_LookupSpecial(mgr, &_Py_ID(__aexit__)); + exit = _PyObject_LookupSpecial(mgr, &_Py_ID(__aexit__)); if (exit == NULL) { if (!_PyErr_Occurred(tstate)) { _PyErr_Format(tstate, PyExc_TypeError, @@ -2292,13 +2287,13 @@ dummy_func( Py_DECREF(enter); goto error; } - SET_TOP(exit); - Py_DECREF(mgr); + DECREF_INPUTS(); res = _PyObject_CallNoArgs(enter); Py_DECREF(enter); - if (res == NULL) - goto error; - PUSH(res); + if (res == NULL) { + Py_DECREF(exit); + ERROR_IF(true, error); + } PREDICT(GET_AWAITABLE); } diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 661fe27f327b330..d70d64ecbdd5c10 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -981,18 +981,21 @@ } TARGET(END_ASYNC_FOR) { - PyObject *val = POP(); - assert(val && PyExceptionInstance_Check(val)); - if (PyErr_GivenExceptionMatches(val, PyExc_StopAsyncIteration)) { - Py_DECREF(val); - Py_DECREF(POP()); + PyObject *exc = PEEK(1); + PyObject *awaitable = PEEK(2); + assert(exc && PyExceptionInstance_Check(exc)); + if (PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration)) { + Py_DECREF(awaitable); + Py_DECREF(exc); } else { - PyObject *exc = Py_NewRef(PyExceptionInstance_Class(val)); - PyObject *tb = PyException_GetTraceback(val); - _PyErr_Restore(tstate, exc, val, tb); + Py_INCREF(exc); + PyObject *typ = Py_NewRef(PyExceptionInstance_Class(exc)); + PyObject *tb = PyException_GetTraceback(exc); + _PyErr_Restore(tstate, typ, exc, tb); goto exception_unwind; } + STACK_SHRINK(2); DISPATCH(); } @@ -2699,7 +2702,8 @@ } TARGET(BEFORE_ASYNC_WITH) { - PyObject *mgr = TOP(); + PyObject *mgr = PEEK(1); + PyObject *exit; PyObject *res; PyObject *enter = _PyObject_LookupSpecial(mgr, &_Py_ID(__aenter__)); if (enter == NULL) { @@ -2711,7 +2715,7 @@ } goto error; } - PyObject *exit = _PyObject_LookupSpecial(mgr, &_Py_ID(__aexit__)); + exit = _PyObject_LookupSpecial(mgr, &_Py_ID(__aexit__)); if (exit == NULL) { if (!_PyErr_Occurred(tstate)) { _PyErr_Format(tstate, PyExc_TypeError, @@ -2723,13 +2727,16 @@ Py_DECREF(enter); goto error; } - SET_TOP(exit); Py_DECREF(mgr); res = _PyObject_CallNoArgs(enter); Py_DECREF(enter); - if (res == NULL) - goto error; - PUSH(res); + if (res == NULL) { + Py_DECREF(exit); + if (true) goto pop_1_error; + } + STACK_GROW(1); + POKE(1, res); + POKE(2, exit); PREDICT(GET_AWAITABLE); DISPATCH(); } diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index c40e40ff324d11f..171fed363d3be05 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -109,7 +109,7 @@ _PyOpcode_num_popped(int opcode, int oparg) { case PREP_RERAISE_STAR: return 2; case END_ASYNC_FOR: - return -1; + return 2; case CLEANUP_THROW: return -1; case LOAD_ASSERTION_ERROR: @@ -271,7 +271,7 @@ _PyOpcode_num_popped(int opcode, int oparg) { case FOR_ITER_GEN: return -1; case BEFORE_ASYNC_WITH: - return -1; + return 1; case BEFORE_WITH: return 1; case WITH_EXCEPT_START: @@ -455,7 +455,7 @@ _PyOpcode_num_pushed(int opcode, int oparg) { case PREP_RERAISE_STAR: return 1; case END_ASYNC_FOR: - return -1; + return 0; case CLEANUP_THROW: return -1; case LOAD_ASSERTION_ERROR: @@ -617,7 +617,7 @@ _PyOpcode_num_pushed(int opcode, int oparg) { case FOR_ITER_GEN: return -1; case BEFORE_ASYNC_WITH: - return -1; + return 2; case BEFORE_WITH: return 2; case WITH_EXCEPT_START: From 2753cf2ed6eb329bdc34b8f67228801182b82160 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 31 Jan 2023 21:42:03 +0100 Subject: [PATCH 07/74] gh-101409: Improve generated clinic code for self type checks (#101411) --- Modules/_io/clinic/bufferedio.c.h | 7 ++--- Modules/_sqlite/clinic/cursor.c.h | 7 ++--- Modules/_sqlite/clinic/row.c.h | 6 ++--- Modules/clinic/_collectionsmodule.c.h | 6 ++--- Modules/clinic/_queuemodule.c.h | 9 +++---- Modules/clinic/_ssl.c.h | 13 +++++---- Modules/clinic/itertoolsmodule.c.h | 38 +++++++++++++-------------- Modules/clinic/selectmodule.c.h | 9 +++---- Objects/clinic/classobject.c.h | 10 +++---- Objects/clinic/codeobject.c.h | 6 ++--- Objects/clinic/enumobject.c.h | 6 ++--- Objects/clinic/floatobject.c.h | 6 ++--- Objects/clinic/listobject.c.h | 7 ++--- Objects/clinic/tupleobject.c.h | 6 ++--- Tools/clinic/clinic.py | 22 +++++++++------- 15 files changed, 80 insertions(+), 78 deletions(-) diff --git a/Modules/_io/clinic/bufferedio.c.h b/Modules/_io/clinic/bufferedio.c.h index 8a8f86b2eea318f..38ea756879c122e 100644 --- a/Modules/_io/clinic/bufferedio.c.h +++ b/Modules/_io/clinic/bufferedio.c.h @@ -601,12 +601,13 @@ static int _io_BufferedRWPair___init__(PyObject *self, PyObject *args, PyObject *kwargs) { int return_value = -1; + PyTypeObject *base_tp = &PyBufferedRWPair_Type; PyObject *reader; PyObject *writer; Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE; - if ((Py_IS_TYPE(self, &PyBufferedRWPair_Type) || - Py_TYPE(self)->tp_new == PyBufferedRWPair_Type.tp_new) && + if ((Py_IS_TYPE(self, base_tp) || + Py_TYPE(self)->tp_new == base_tp->tp_new) && !_PyArg_NoKeywords("BufferedRWPair", kwargs)) { goto exit; } @@ -713,4 +714,4 @@ _io_BufferedRandom___init__(PyObject *self, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=ca87adcfff6a810b input=a9049054013a1b77]*/ +/*[clinic end generated code: output=953f1577e96e8d86 input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/clinic/cursor.c.h b/Modules/_sqlite/clinic/cursor.c.h index 36b8d0051a2915d..43e912d13479636 100644 --- a/Modules/_sqlite/clinic/cursor.c.h +++ b/Modules/_sqlite/clinic/cursor.c.h @@ -16,10 +16,11 @@ static int pysqlite_cursor_init(PyObject *self, PyObject *args, PyObject *kwargs) { int return_value = -1; + PyTypeObject *base_tp = clinic_state()->CursorType; pysqlite_Connection *connection; - if ((Py_IS_TYPE(self, clinic_state()->CursorType) || - Py_TYPE(self)->tp_new == clinic_state()->CursorType->tp_new) && + if ((Py_IS_TYPE(self, base_tp) || + Py_TYPE(self)->tp_new == base_tp->tp_new) && !_PyArg_NoKeywords("Cursor", kwargs)) { goto exit; } @@ -318,4 +319,4 @@ pysqlite_cursor_close(pysqlite_Cursor *self, PyObject *Py_UNUSED(ignored)) { return pysqlite_cursor_close_impl(self); } -/*[clinic end generated code: output=e53e75a32a9d92bd input=a9049054013a1b77]*/ +/*[clinic end generated code: output=1f82e3c9791bb9a5 input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/clinic/row.c.h b/Modules/_sqlite/clinic/row.c.h index c543b398db3fcf8..89a48fd52da2268 100644 --- a/Modules/_sqlite/clinic/row.c.h +++ b/Modules/_sqlite/clinic/row.c.h @@ -16,11 +16,11 @@ static PyObject * pysqlite_row_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; + PyTypeObject *base_tp = clinic_state()->RowType; pysqlite_Cursor *cursor; PyObject *data; - if ((type == clinic_state()->RowType || - type->tp_init == clinic_state()->RowType->tp_init) && + if ((type == base_tp || type->tp_init == base_tp->tp_init) && !_PyArg_NoKeywords("Row", kwargs)) { goto exit; } @@ -60,4 +60,4 @@ pysqlite_row_keys(pysqlite_Row *self, PyObject *Py_UNUSED(ignored)) { return pysqlite_row_keys_impl(self); } -/*[clinic end generated code: output=87b91f234633702e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=157b31ac3f6af1ba input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_collectionsmodule.c.h b/Modules/clinic/_collectionsmodule.c.h index ad4da8856ac3c38..8ea0255b0610706 100644 --- a/Modules/clinic/_collectionsmodule.c.h +++ b/Modules/clinic/_collectionsmodule.c.h @@ -46,11 +46,11 @@ static PyObject * tuplegetter_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; + PyTypeObject *base_tp = &tuplegetter_type; Py_ssize_t index; PyObject *doc; - if ((type == &tuplegetter_type || - type->tp_init == tuplegetter_type.tp_init) && + if ((type == base_tp || type->tp_init == base_tp->tp_init) && !_PyArg_NoKeywords("_tuplegetter", kwargs)) { goto exit; } @@ -75,4 +75,4 @@ tuplegetter_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=12168d58a11a4fb9 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=91a0f221c7b1f96c input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_queuemodule.c.h b/Modules/clinic/_queuemodule.c.h index f86dac3c497d641..94fb59a5b17a490 100644 --- a/Modules/clinic/_queuemodule.c.h +++ b/Modules/clinic/_queuemodule.c.h @@ -21,14 +21,13 @@ static PyObject * simplequeue_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; + PyTypeObject *base_tp = simplequeue_get_state_by_type(type)->SimpleQueueType; - if ((type == simplequeue_get_state_by_type(type)->SimpleQueueType || - type->tp_init == simplequeue_get_state_by_type(type)->SimpleQueueType->tp_init) && + if ((type == base_tp || type->tp_init == base_tp->tp_init) && !_PyArg_NoPositional("SimpleQueue", args)) { goto exit; } - if ((type == simplequeue_get_state_by_type(type)->SimpleQueueType || - type->tp_init == simplequeue_get_state_by_type(type)->SimpleQueueType->tp_init) && + if ((type == base_tp || type->tp_init == base_tp->tp_init) && !_PyArg_NoKeywords("SimpleQueue", kwargs)) { goto exit; } @@ -332,4 +331,4 @@ _queue_SimpleQueue_qsize(simplequeueobject *self, PyObject *Py_UNUSED(ignored)) exit: return return_value; } -/*[clinic end generated code: output=628e992d38f50aac input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9a72a8d1b5767f6a input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_ssl.c.h b/Modules/clinic/_ssl.c.h index 2d7c98c4f014a38..9f967ddc8e30619 100644 --- a/Modules/clinic/_ssl.c.h +++ b/Modules/clinic/_ssl.c.h @@ -435,10 +435,10 @@ static PyObject * _ssl__SSLContext(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; + PyTypeObject *base_tp = get_state_type(type)->PySSLContext_Type; int proto_version; - if ((type == get_state_type(type)->PySSLContext_Type || - type->tp_init == get_state_type(type)->PySSLContext_Type->tp_init) && + if ((type == base_tp || type->tp_init == base_tp->tp_init) && !_PyArg_NoKeywords("_SSLContext", kwargs)) { goto exit; } @@ -1028,14 +1028,13 @@ static PyObject * _ssl_MemoryBIO(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; + PyTypeObject *base_tp = get_state_type(type)->PySSLMemoryBIO_Type; - if ((type == get_state_type(type)->PySSLMemoryBIO_Type || - type->tp_init == get_state_type(type)->PySSLMemoryBIO_Type->tp_init) && + if ((type == base_tp || type->tp_init == base_tp->tp_init) && !_PyArg_NoPositional("MemoryBIO", args)) { goto exit; } - if ((type == get_state_type(type)->PySSLMemoryBIO_Type || - type->tp_init == get_state_type(type)->PySSLMemoryBIO_Type->tp_init) && + if ((type == base_tp || type->tp_init == base_tp->tp_init) && !_PyArg_NoKeywords("MemoryBIO", kwargs)) { goto exit; } @@ -1543,4 +1542,4 @@ _ssl_enum_crls(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje #ifndef _SSL_ENUM_CRLS_METHODDEF #define _SSL_ENUM_CRLS_METHODDEF #endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */ -/*[clinic end generated code: output=a3d97a19163bb044 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=4d9b81fa81f520f0 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/itertoolsmodule.c.h b/Modules/clinic/itertoolsmodule.c.h index 287de524e913079..70299aceb7a02cb 100644 --- a/Modules/clinic/itertoolsmodule.c.h +++ b/Modules/clinic/itertoolsmodule.c.h @@ -102,10 +102,10 @@ static PyObject * pairwise_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; + PyTypeObject *base_tp = &pairwise_type; PyObject *iterable; - if ((type == &pairwise_type || - type->tp_init == pairwise_type.tp_init) && + if ((type == base_tp || type->tp_init == base_tp->tp_init) && !_PyArg_NoKeywords("pairwise", kwargs)) { goto exit; } @@ -195,11 +195,11 @@ static PyObject * itertools__grouper(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; + PyTypeObject *base_tp = &_grouper_type; PyObject *parent; PyObject *tgtkey; - if ((type == &_grouper_type || - type->tp_init == _grouper_type.tp_init) && + if ((type == base_tp || type->tp_init == base_tp->tp_init) && !_PyArg_NoKeywords("_grouper", kwargs)) { goto exit; } @@ -232,12 +232,12 @@ static PyObject * itertools_teedataobject(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; + PyTypeObject *base_tp = &teedataobject_type; PyObject *it; PyObject *values; PyObject *next; - if ((type == &teedataobject_type || - type->tp_init == teedataobject_type.tp_init) && + if ((type == base_tp || type->tp_init == base_tp->tp_init) && !_PyArg_NoKeywords("teedataobject", kwargs)) { goto exit; } @@ -270,10 +270,10 @@ static PyObject * itertools__tee(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; + PyTypeObject *base_tp = &tee_type; PyObject *iterable; - if ((type == &tee_type || - type->tp_init == tee_type.tp_init) && + if ((type == base_tp || type->tp_init == base_tp->tp_init) && !_PyArg_NoKeywords("_tee", kwargs)) { goto exit; } @@ -345,10 +345,10 @@ static PyObject * itertools_cycle(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; + PyTypeObject *base_tp = &cycle_type; PyObject *iterable; - if ((type == &cycle_type || - type->tp_init == cycle_type.tp_init) && + if ((type == base_tp || type->tp_init == base_tp->tp_init) && !_PyArg_NoKeywords("cycle", kwargs)) { goto exit; } @@ -377,11 +377,11 @@ static PyObject * itertools_dropwhile(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; + PyTypeObject *base_tp = &dropwhile_type; PyObject *func; PyObject *seq; - if ((type == &dropwhile_type || - type->tp_init == dropwhile_type.tp_init) && + if ((type == base_tp || type->tp_init == base_tp->tp_init) && !_PyArg_NoKeywords("dropwhile", kwargs)) { goto exit; } @@ -409,11 +409,11 @@ static PyObject * itertools_takewhile(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; + PyTypeObject *base_tp = &takewhile_type; PyObject *func; PyObject *seq; - if ((type == &takewhile_type || - type->tp_init == takewhile_type.tp_init) && + if ((type == base_tp || type->tp_init == base_tp->tp_init) && !_PyArg_NoKeywords("takewhile", kwargs)) { goto exit; } @@ -441,11 +441,11 @@ static PyObject * itertools_starmap(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; + PyTypeObject *base_tp = &starmap_type; PyObject *func; PyObject *seq; - if ((type == &starmap_type || - type->tp_init == starmap_type.tp_init) && + if ((type == base_tp || type->tp_init == base_tp->tp_init) && !_PyArg_NoKeywords("starmap", kwargs)) { goto exit; } @@ -821,11 +821,11 @@ static PyObject * itertools_filterfalse(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; + PyTypeObject *base_tp = &filterfalse_type; PyObject *func; PyObject *seq; - if ((type == &filterfalse_type || - type->tp_init == filterfalse_type.tp_init) && + if ((type == base_tp || type->tp_init == base_tp->tp_init) && !_PyArg_NoKeywords("filterfalse", kwargs)) { goto exit; } @@ -913,4 +913,4 @@ itertools_count(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=0229ebd72962f130 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=47c8c8ccec8740d7 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/selectmodule.c.h b/Modules/clinic/selectmodule.c.h index fda9aaab475567f..f44ca1d70a1e86d 100644 --- a/Modules/clinic/selectmodule.c.h +++ b/Modules/clinic/selectmodule.c.h @@ -1061,14 +1061,13 @@ static PyObject * select_kqueue(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; + PyTypeObject *base_tp = _selectstate_by_type(type)->kqueue_queue_Type; - if ((type == _selectstate_by_type(type)->kqueue_queue_Type || - type->tp_init == _selectstate_by_type(type)->kqueue_queue_Type->tp_init) && + if ((type == base_tp || type->tp_init == base_tp->tp_init) && !_PyArg_NoPositional("kqueue", args)) { goto exit; } - if ((type == _selectstate_by_type(type)->kqueue_queue_Type || - type->tp_init == _selectstate_by_type(type)->kqueue_queue_Type->tp_init) && + if ((type == base_tp || type->tp_init == base_tp->tp_init) && !_PyArg_NoKeywords("kqueue", kwargs)) { goto exit; } @@ -1310,4 +1309,4 @@ select_kqueue_control(kqueue_queue_Object *self, PyObject *const *args, Py_ssize #ifndef SELECT_KQUEUE_CONTROL_METHODDEF #define SELECT_KQUEUE_CONTROL_METHODDEF #endif /* !defined(SELECT_KQUEUE_CONTROL_METHODDEF) */ -/*[clinic end generated code: output=9556c7d6cd5192d1 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=64516114287e894d input=a9049054013a1b77]*/ diff --git a/Objects/clinic/classobject.c.h b/Objects/clinic/classobject.c.h index 6c449829662af3c..a7bac63052bc408 100644 --- a/Objects/clinic/classobject.c.h +++ b/Objects/clinic/classobject.c.h @@ -38,11 +38,11 @@ static PyObject * method_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; + PyTypeObject *base_tp = &PyMethod_Type; PyObject *function; PyObject *instance; - if ((type == &PyMethod_Type || - type->tp_init == PyMethod_Type.tp_init) && + if ((type == base_tp || type->tp_init == base_tp->tp_init) && !_PyArg_NoKeywords("method", kwargs)) { goto exit; } @@ -70,10 +70,10 @@ static PyObject * instancemethod_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; + PyTypeObject *base_tp = &PyInstanceMethod_Type; PyObject *function; - if ((type == &PyInstanceMethod_Type || - type->tp_init == PyInstanceMethod_Type.tp_init) && + if ((type == base_tp || type->tp_init == base_tp->tp_init) && !_PyArg_NoKeywords("instancemethod", kwargs)) { goto exit; } @@ -86,4 +86,4 @@ instancemethod_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=e3294c26a71d456d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2a5e7fa5947a86cb input=a9049054013a1b77]*/ diff --git a/Objects/clinic/codeobject.c.h b/Objects/clinic/codeobject.c.h index da33f4a6a20c1b3..5ad4b1fed734176 100644 --- a/Objects/clinic/codeobject.c.h +++ b/Objects/clinic/codeobject.c.h @@ -30,6 +30,7 @@ static PyObject * code_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; + PyTypeObject *base_tp = &PyCode_Type; int argcount; int posonlyargcount; int kwonlyargcount; @@ -49,8 +50,7 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *freevars = NULL; PyObject *cellvars = NULL; - if ((type == &PyCode_Type || - type->tp_init == PyCode_Type.tp_init) && + if ((type == base_tp || type->tp_init == base_tp->tp_init) && !_PyArg_NoKeywords("code", kwargs)) { goto exit; } @@ -488,4 +488,4 @@ code__varname_from_oparg(PyCodeObject *self, PyObject *const *args, Py_ssize_t n exit: return return_value; } -/*[clinic end generated code: output=b6c98f17c60ace53 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f1fab6e71c785182 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/enumobject.c.h b/Objects/clinic/enumobject.c.h index 208a9e8be1a1a2f..adf78efd0d66f4f 100644 --- a/Objects/clinic/enumobject.c.h +++ b/Objects/clinic/enumobject.c.h @@ -91,10 +91,10 @@ static PyObject * reversed_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; + PyTypeObject *base_tp = &PyReversed_Type; PyObject *seq; - if ((type == &PyReversed_Type || - type->tp_init == PyReversed_Type.tp_init) && + if ((type == base_tp || type->tp_init == base_tp->tp_init) && !_PyArg_NoKeywords("reversed", kwargs)) { goto exit; } @@ -107,4 +107,4 @@ reversed_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=683261097bfd794a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=aba0ddbeab1601e3 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/floatobject.c.h b/Objects/clinic/floatobject.c.h index 1a81e173231bfa9..6bc25a0a409f97f 100644 --- a/Objects/clinic/floatobject.c.h +++ b/Objects/clinic/floatobject.c.h @@ -212,10 +212,10 @@ static PyObject * float_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; + PyTypeObject *base_tp = &PyFloat_Type; PyObject *x = NULL; - if ((type == &PyFloat_Type || - type->tp_init == PyFloat_Type.tp_init) && + if ((type == base_tp || type->tp_init == base_tp->tp_init) && !_PyArg_NoKeywords("float", kwargs)) { goto exit; } @@ -327,4 +327,4 @@ float___format__(PyObject *self, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=ac6374ac606a505e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=74bc91bb44014df9 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/listobject.c.h b/Objects/clinic/listobject.c.h index 94852e996170606..e3d6ffa9f76fdb5 100644 --- a/Objects/clinic/listobject.c.h +++ b/Objects/clinic/listobject.c.h @@ -326,10 +326,11 @@ static int list___init__(PyObject *self, PyObject *args, PyObject *kwargs) { int return_value = -1; + PyTypeObject *base_tp = &PyList_Type; PyObject *iterable = NULL; - if ((Py_IS_TYPE(self, &PyList_Type) || - Py_TYPE(self)->tp_new == PyList_Type.tp_new) && + if ((Py_IS_TYPE(self, base_tp) || + Py_TYPE(self)->tp_new == base_tp->tp_new) && !_PyArg_NoKeywords("list", kwargs)) { goto exit; } @@ -382,4 +383,4 @@ list___reversed__(PyListObject *self, PyObject *Py_UNUSED(ignored)) { return list___reversed___impl(self); } -/*[clinic end generated code: output=4e6f38b655394564 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2ca109d8acc775bc input=a9049054013a1b77]*/ diff --git a/Objects/clinic/tupleobject.c.h b/Objects/clinic/tupleobject.c.h index a4776e14fa0a9b7..3de95759a13f216 100644 --- a/Objects/clinic/tupleobject.c.h +++ b/Objects/clinic/tupleobject.c.h @@ -81,10 +81,10 @@ static PyObject * tuple_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; + PyTypeObject *base_tp = &PyTuple_Type; PyObject *iterable = NULL; - if ((type == &PyTuple_Type || - type->tp_init == PyTuple_Type.tp_init) && + if ((type == base_tp || type->tp_init == base_tp->tp_init) && !_PyArg_NoKeywords("tuple", kwargs)) { goto exit; } @@ -118,4 +118,4 @@ tuple___getnewargs__(PyTupleObject *self, PyObject *Py_UNUSED(ignored)) { return tuple___getnewargs___impl(self); } -/*[clinic end generated code: output=441d2b880e865f87 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=48a9e0834b300ac3 input=a9049054013a1b77]*/ diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index abff4d2583e170a..b8b2b75c749152e 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -1174,6 +1174,7 @@ def parser_body(prototype, *fields, declarations=''): raise ValueError("Slot methods cannot access their defining class.") if not parses_keywords: + declarations = '{base_type_ptr}' fields.insert(0, normalize_snippet(""" if ({self_type_check}!_PyArg_NoKeywords("{name}", kwargs)) {{ goto exit; @@ -1187,7 +1188,7 @@ def parser_body(prototype, *fields, declarations=''): """, indent=4)) parser_definition = parser_body(parser_prototype, *fields, - declarations=parser_body_declarations) + declarations=declarations) if flags in ('METH_NOARGS', 'METH_O', 'METH_VARARGS'): @@ -3839,21 +3840,22 @@ def set_template_dict(self, template_dict): cls = self.function.cls if ((kind in (METHOD_NEW, METHOD_INIT)) and cls and cls.typedef): - type_object = self.function.cls.type_object - prefix = (type_object[1:] + '.' if type_object[0] == '&' else - type_object + '->') if kind == METHOD_NEW: - type_check = ('({0} == {1} ||\n ' - ' {0}->tp_init == {2}tp_init)' - ).format(self.name, type_object, prefix) + type_check = ( + '({0} == base_tp || {0}->tp_init == base_tp->tp_init)' + ).format(self.name) else: - type_check = ('(Py_IS_TYPE({0}, {1}) ||\n ' - ' Py_TYPE({0})->tp_new == {2}tp_new)' - ).format(self.name, type_object, prefix) + type_check = ('(Py_IS_TYPE({0}, base_tp) ||\n ' + ' Py_TYPE({0})->tp_new == base_tp->tp_new)' + ).format(self.name) line = '{} &&\n '.format(type_check) template_dict['self_type_check'] = line + type_object = self.function.cls.type_object + type_ptr = f'PyTypeObject *base_tp = {type_object};' + template_dict['base_type_ptr'] = type_ptr + def add_c_return_converter(f, name=None): From 76efcb40930d1584e8706f015d0e5475fb16acb5 Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Tue, 31 Jan 2023 13:28:32 -0800 Subject: [PATCH 08/74] GH-100288: Skip extra work when failing to specialize LOAD_ATTR (GH-101354) --- Python/specialize.c | 84 +++++++++++++-------------------------------- 1 file changed, 24 insertions(+), 60 deletions(-) diff --git a/Python/specialize.c b/Python/specialize.c index 096687f5fdf023f..908ad6dceb57f3f 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -1039,14 +1039,6 @@ specialize_class_load_attr(PyObject *owner, _Py_CODEUNIT *instr, } } -typedef enum { - MANAGED_VALUES = 1, - MANAGED_DICT = 2, - OFFSET_DICT = 3, - NO_DICT = 4, - LAZY_DICT = 5, -} ObjectDictKind; - // Please collect stats carefully before and after modifying. A subtle change // can cause a significant drop in cache hits. A possible test is // python.exe -m test_typing test_re test_dis test_zlib. @@ -1058,71 +1050,45 @@ PyObject *descr, DescriptorClassification kind) PyTypeObject *owner_cls = Py_TYPE(owner); assert(kind == METHOD && descr != NULL); - ObjectDictKind dictkind; - PyDictKeysObject *keys; if (owner_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT) { PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); - keys = ((PyHeapTypeObject *)owner_cls)->ht_cached_keys; - if (_PyDictOrValues_IsValues(dorv)) { - dictkind = MANAGED_VALUES; - } - else { - dictkind = MANAGED_DICT; - } - } - else { - Py_ssize_t dictoffset = owner_cls->tp_dictoffset; - if (dictoffset < 0 || dictoffset > INT16_MAX) { - SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_RANGE); - goto fail; - } - if (dictoffset == 0) { - dictkind = NO_DICT; - keys = NULL; - } - else { - PyObject *dict = *(PyObject **) ((char *)owner + dictoffset); - if (dict == NULL) { - // This object will have a dict if user access __dict__ - dictkind = LAZY_DICT; - keys = NULL; - } - else { - keys = ((PyDictObject *)dict)->ma_keys; - dictkind = OFFSET_DICT; - } + PyDictKeysObject *keys = ((PyHeapTypeObject *)owner_cls)->ht_cached_keys; + if (!_PyDictOrValues_IsValues(dorv)) { + SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_HAS_MANAGED_DICT); + return 0; } - } - if (dictkind == MANAGED_VALUES || dictkind == OFFSET_DICT) { Py_ssize_t index = _PyDictKeys_StringLookup(keys, name); if (index != DKIX_EMPTY) { SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_SHADOWED); - goto fail; + return 0; } uint32_t keys_version = _PyDictKeys_GetVersionForCurrentState(keys); if (keys_version == 0) { SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS); - goto fail; + return 0; } write_u32(cache->keys_version, keys_version); + _py_set_opcode(instr, LOAD_ATTR_METHOD_WITH_VALUES); } - switch(dictkind) { - case NO_DICT: + else { + Py_ssize_t dictoffset = owner_cls->tp_dictoffset; + if (dictoffset < 0 || dictoffset > INT16_MAX) { + SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_RANGE); + return 0; + } + if (dictoffset == 0) { _py_set_opcode(instr, LOAD_ATTR_METHOD_NO_DICT); - break; - case MANAGED_VALUES: - _py_set_opcode(instr, LOAD_ATTR_METHOD_WITH_VALUES); - break; - case MANAGED_DICT: - SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_HAS_MANAGED_DICT); - goto fail; - case OFFSET_DICT: - SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NOT_MANAGED_DICT); - goto fail; - case LAZY_DICT: - assert(owner_cls->tp_dictoffset > 0 && owner_cls->tp_dictoffset <= INT16_MAX); + } + else { + PyObject *dict = *(PyObject **) ((char *)owner + dictoffset); + if (dict) { + SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NOT_MANAGED_DICT); + return 0; + } + assert(owner_cls->tp_dictoffset > 0); + assert(owner_cls->tp_dictoffset <= INT16_MAX); _py_set_opcode(instr, LOAD_ATTR_METHOD_LAZY_DICT); - break; + } } /* `descr` is borrowed. This is safe for methods (even inherited ones from * super classes!) as long as tp_version_tag is validated for two main reasons: @@ -1141,8 +1107,6 @@ PyObject *descr, DescriptorClassification kind) write_u32(cache->type_version, owner_cls->tp_version_tag); write_obj(cache->descr, descr); return 1; -fail: - return 0; } void From 75227fba1dd1683289d90ada7abba237bff55d14 Mon Sep 17 00:00:00 2001 From: John Belmonte Date: Wed, 1 Feb 2023 19:01:28 +0900 Subject: [PATCH 09/74] datetime.rst: fix combine() signature (#101490) The default `tzinfo` param of the `combine()` signature pseudocode was erroneously `self.tzinfo`. `self` has no meaning in the context of a classmethod, and the datetime class itself has no `tzinfo` attribute. The correct default pseudocode is `time.tzinfo`, reflecting that the default is the `tzinfo` attribute of the `time` parameter. --- Doc/library/datetime.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index ebb5f319efda8d8..2f1ab7c3dd4b51d 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -975,7 +975,7 @@ Other constructors, all class methods: microsecond of the result are all 0, and :attr:`.tzinfo` is ``None``. -.. classmethod:: datetime.combine(date, time, tzinfo=self.tzinfo) +.. classmethod:: datetime.combine(date, time, tzinfo=time.tzinfo) Return a new :class:`.datetime` object whose date components are equal to the given :class:`date` object's, and whose time components From cc407b9de645ab7c137df8ea2409a005369169a5 Mon Sep 17 00:00:00 2001 From: beavailable Date: Wed, 1 Feb 2023 19:03:59 +0800 Subject: [PATCH 10/74] gh-101317: Add `ssl_shutdown_timeout` parameter for `asyncio.StreamWriter.start_tls` (#101335) Co-authored-by: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> --- Doc/library/asyncio-stream.rst | 10 +++++++++- Lib/asyncio/streams.py | 6 ++++-- .../2023-01-26-01-25-56.gh-issue-101317.vWaS1x.rst | 2 ++ 3 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2023-01-26-01-25-56.gh-issue-101317.vWaS1x.rst diff --git a/Doc/library/asyncio-stream.rst b/Doc/library/asyncio-stream.rst index c1ae8abb9abcd5d..533bdec8e03993b 100644 --- a/Doc/library/asyncio-stream.rst +++ b/Doc/library/asyncio-stream.rst @@ -335,7 +335,7 @@ StreamWriter returns immediately. .. coroutinemethod:: start_tls(sslcontext, \*, server_hostname=None, \ - ssl_handshake_timeout=None) + ssl_handshake_timeout=None, ssl_shutdown_timeout=None) Upgrade an existing stream-based connection to TLS. @@ -350,8 +350,16 @@ StreamWriter handshake to complete before aborting the connection. ``60.0`` seconds if ``None`` (default). + * *ssl_shutdown_timeout* is the time in seconds to wait for the SSL shutdown + to complete before aborting the connection. ``30.0`` seconds if ``None`` + (default). + .. versionadded:: 3.11 + .. versionchanged:: 3.12 + Added the *ssl_shutdown_timeout* parameter. + + .. method:: is_closing() Return ``True`` if the stream is closed or in the process of diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py index 0f9098b4195633c..7d13e961bd2de41 100644 --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -378,7 +378,8 @@ async def drain(self): async def start_tls(self, sslcontext, *, server_hostname=None, - ssl_handshake_timeout=None): + ssl_handshake_timeout=None, + ssl_shutdown_timeout=None): """Upgrade an existing stream-based connection to TLS.""" server_side = self._protocol._client_connected_cb is not None protocol = self._protocol @@ -386,7 +387,8 @@ async def start_tls(self, sslcontext, *, new_transport = await self._loop.start_tls( # type: ignore self._transport, protocol, sslcontext, server_side=server_side, server_hostname=server_hostname, - ssl_handshake_timeout=ssl_handshake_timeout) + ssl_handshake_timeout=ssl_handshake_timeout, + ssl_shutdown_timeout=ssl_shutdown_timeout) self._transport = new_transport protocol._replace_writer(self) diff --git a/Misc/NEWS.d/next/Library/2023-01-26-01-25-56.gh-issue-101317.vWaS1x.rst b/Misc/NEWS.d/next/Library/2023-01-26-01-25-56.gh-issue-101317.vWaS1x.rst new file mode 100644 index 000000000000000..f1ce0e0a5276611 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-01-26-01-25-56.gh-issue-101317.vWaS1x.rst @@ -0,0 +1,2 @@ +Add *ssl_shutdown_timeout* parameter for :meth:`asyncio.StreamWriter.start_tls`. + From 2b3e02a705907d0db2ce5266f06ad88a6b6160db Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 1 Feb 2023 12:41:30 +0100 Subject: [PATCH 11/74] gh-101277: Isolate itertools, add group and _grouper types to module state (#101302) Co-authored-by: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> --- Lib/test/test_itertools.py | 32 ++++ Modules/clinic/itertoolsmodule.c.h | 8 +- Modules/itertoolsmodule.c | 244 ++++++++++++++++------------- 3 files changed, 173 insertions(+), 111 deletions(-) diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py index b447b6cbab9c227..7014bc97100cb49 100644 --- a/Lib/test/test_itertools.py +++ b/Lib/test/test_itertools.py @@ -1694,6 +1694,38 @@ def test_zip_longest_result_gc(self): gc.collect() self.assertTrue(gc.is_tracked(next(it))) + @support.cpython_only + def test_immutable_types(self): + from itertools import _grouper, _tee, _tee_dataobject + dataset = ( + accumulate, + batched, + chain, + combinations, + combinations_with_replacement, + compress, + count, + cycle, + dropwhile, + filterfalse, + groupby, + _grouper, + islice, + pairwise, + permutations, + product, + repeat, + starmap, + takewhile, + _tee, + _tee_dataobject, + zip_longest, + ) + for tp in dataset: + with self.subTest(tp=tp): + with self.assertRaisesRegex(TypeError, "immutable"): + tp.foobar = 1 + class TestExamples(unittest.TestCase): diff --git a/Modules/clinic/itertoolsmodule.c.h b/Modules/clinic/itertoolsmodule.c.h index 70299aceb7a02cb..c492c33daea5a26 100644 --- a/Modules/clinic/itertoolsmodule.c.h +++ b/Modules/clinic/itertoolsmodule.c.h @@ -195,7 +195,7 @@ static PyObject * itertools__grouper(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; - PyTypeObject *base_tp = &_grouper_type; + PyTypeObject *base_tp = clinic_state()->_grouper_type; PyObject *parent; PyObject *tgtkey; @@ -206,8 +206,8 @@ itertools__grouper(PyTypeObject *type, PyObject *args, PyObject *kwargs) if (!_PyArg_CheckPositional("_grouper", PyTuple_GET_SIZE(args), 2, 2)) { goto exit; } - if (!PyObject_TypeCheck(PyTuple_GET_ITEM(args, 0), &groupby_type)) { - _PyArg_BadArgument("_grouper", "argument 1", (&groupby_type)->tp_name, PyTuple_GET_ITEM(args, 0)); + if (!PyObject_TypeCheck(PyTuple_GET_ITEM(args, 0), clinic_state_by_cls()->groupby_type)) { + _PyArg_BadArgument("_grouper", "argument 1", (clinic_state_by_cls()->groupby_type)->tp_name, PyTuple_GET_ITEM(args, 0)); goto exit; } parent = PyTuple_GET_ITEM(args, 0); @@ -913,4 +913,4 @@ itertools_count(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=47c8c8ccec8740d7 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c3069caac417e165 input=a9049054013a1b77]*/ diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index c1f1e7320db7196..a2ee48228b5847a 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -2,6 +2,7 @@ #include "Python.h" #include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_long.h" // _PyLong_GetZero() +#include "pycore_moduleobject.h" // _PyModule_GetState() #include "pycore_object.h" // _PyObject_GC_TRACK() #include "pycore_tuple.h" // _PyTuple_ITEMS() #include // offsetof() @@ -10,10 +11,42 @@ by Raymond D. Hettinger */ +typedef struct { + PyTypeObject *groupby_type; + PyTypeObject *_grouper_type; +} itertools_state; + +static inline itertools_state * +get_module_state(PyObject *mod) +{ + void *state = _PyModule_GetState(mod); + assert(state != NULL); + return (itertools_state *)state; +} + +static inline itertools_state * +get_module_state_by_cls(PyTypeObject *cls) +{ + void *state = PyType_GetModuleState(cls); + assert(state != NULL); + return (itertools_state *)state; +} + +static struct PyModuleDef itertoolsmodule; + +static inline itertools_state * +find_state_by_type(PyTypeObject *tp) +{ + PyObject *mod = PyType_GetModuleByDef(tp, &itertoolsmodule); + assert(mod != NULL); + return get_module_state(mod); +} +#define clinic_state() (find_state_by_type(type)) + /*[clinic input] module itertools -class itertools.groupby "groupbyobject *" "&groupby_type" -class itertools._grouper "_grouperobject *" "&_grouper_type" +class itertools.groupby "groupbyobject *" "clinic_state()->groupby_type" +class itertools._grouper "_grouperobject *" "clinic_state()->_grouper_type" class itertools.teedataobject "teedataobject *" "&teedataobject_type" class itertools._tee "teeobject *" "&tee_type" class itertools.batched "batchedobject *" "&batched_type" @@ -31,10 +64,8 @@ class itertools.filterfalse "filterfalseobject *" "&filterfalse_type" class itertools.count "countobject *" "&count_type" class itertools.pairwise "pairwiseobject *" "&pairwise_type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=1168b274011ce21b]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=424108522584b55b]*/ -static PyTypeObject groupby_type; -static PyTypeObject _grouper_type; static PyTypeObject teedataobject_type; static PyTypeObject tee_type; static PyTypeObject batched_type; @@ -51,7 +82,10 @@ static PyTypeObject filterfalse_type; static PyTypeObject count_type; static PyTypeObject pairwise_type; +#define clinic_state_by_cls() (get_module_state_by_cls(base_tp)) #include "clinic/itertoolsmodule.c.h" +#undef clinic_state_by_cls +#undef clinic_state /* batched object ************************************************************/ @@ -372,6 +406,7 @@ typedef struct { PyObject *currkey; PyObject *currvalue; const void *currgrouper; /* borrowed reference */ + itertools_state *state; } groupbyobject; static PyObject *_grouper_create(groupbyobject *, PyObject *); @@ -408,24 +443,28 @@ itertools_groupby_impl(PyTypeObject *type, PyObject *it, PyObject *keyfunc) Py_DECREF(gbo); return NULL; } + gbo->state = find_state_by_type(type); return (PyObject *)gbo; } static void groupby_dealloc(groupbyobject *gbo) { + PyTypeObject *tp = Py_TYPE(gbo); PyObject_GC_UnTrack(gbo); Py_XDECREF(gbo->it); Py_XDECREF(gbo->keyfunc); Py_XDECREF(gbo->tgtkey); Py_XDECREF(gbo->currkey); Py_XDECREF(gbo->currvalue); - Py_TYPE(gbo)->tp_free(gbo); + tp->tp_free(gbo); + Py_DECREF(tp); } static int groupby_traverse(groupbyobject *gbo, visitproc visit, void *arg) { + Py_VISIT(Py_TYPE(gbo)); Py_VISIT(gbo->it); Py_VISIT(gbo->keyfunc); Py_VISIT(gbo->tgtkey); @@ -546,50 +585,26 @@ static PyMethodDef groupby_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject groupby_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.groupby", /* tp_name */ - sizeof(groupbyobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)groupby_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - itertools_groupby__doc__, /* tp_doc */ - (traverseproc)groupby_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)groupby_next, /* tp_iternext */ - groupby_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itertools_groupby, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot groupby_slots[] = { + {Py_tp_dealloc, groupby_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)itertools_groupby__doc__}, + {Py_tp_traverse, groupby_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, groupby_next}, + {Py_tp_methods, groupby_methods}, + {Py_tp_new, itertools_groupby}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, }; +static PyType_Spec groupby_spec = { + .name = "itertools.groupby", + .basicsize= sizeof(groupbyobject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = groupby_slots, +}; /* _grouper object (internal) ************************************************/ @@ -603,7 +618,7 @@ typedef struct { @classmethod itertools._grouper.__new__ - parent: object(subclass_of='&groupby_type') + parent: object(subclass_of='clinic_state_by_cls()->groupby_type') tgtkey: object / [clinic start generated code]*/ @@ -611,7 +626,7 @@ itertools._grouper.__new__ static PyObject * itertools__grouper_impl(PyTypeObject *type, PyObject *parent, PyObject *tgtkey) -/*[clinic end generated code: output=462efb1cdebb5914 input=dc180d7771fc8c59]*/ +/*[clinic end generated code: output=462efb1cdebb5914 input=afe05eb477118f12]*/ { return _grouper_create((groupbyobject*) parent, tgtkey); } @@ -619,9 +634,8 @@ itertools__grouper_impl(PyTypeObject *type, PyObject *parent, static PyObject * _grouper_create(groupbyobject *parent, PyObject *tgtkey) { - _grouperobject *igo; - - igo = PyObject_GC_New(_grouperobject, &_grouper_type); + itertools_state *state = parent->state; + _grouperobject *igo = PyObject_GC_New(_grouperobject, state->_grouper_type); if (igo == NULL) return NULL; igo->parent = Py_NewRef(parent); @@ -635,15 +649,18 @@ _grouper_create(groupbyobject *parent, PyObject *tgtkey) static void _grouper_dealloc(_grouperobject *igo) { + PyTypeObject *tp = Py_TYPE(igo); PyObject_GC_UnTrack(igo); Py_DECREF(igo->parent); Py_DECREF(igo->tgtkey); PyObject_GC_Del(igo); + Py_DECREF(tp); } static int _grouper_traverse(_grouperobject *igo, visitproc visit, void *arg) { + Py_VISIT(Py_TYPE(igo)); Py_VISIT(igo->parent); Py_VISIT(igo->tgtkey); return 0; @@ -691,48 +708,24 @@ static PyMethodDef _grouper_methods[] = { {NULL, NULL} /* sentinel */ }; +static PyType_Slot _grouper_slots[] = { + {Py_tp_dealloc, _grouper_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_traverse, _grouper_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, _grouper_next}, + {Py_tp_methods, _grouper_methods}, + {Py_tp_new, itertools__grouper}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; -static PyTypeObject _grouper_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools._grouper", /* tp_name */ - sizeof(_grouperobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)_grouper_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ - 0, /* tp_doc */ - (traverseproc)_grouper_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)_grouper_next, /* tp_iternext */ - _grouper_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itertools__grouper, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Spec _grouper_spec = { + .name = "itertools._grouper", + .basicsize = sizeof(_grouperobject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = _grouper_slots, }; @@ -4979,8 +4972,47 @@ combinations_with_replacement(p, r)\n\ "); static int -itertoolsmodule_exec(PyObject *m) +itertoolsmodule_traverse(PyObject *mod, visitproc visit, void *arg) +{ + itertools_state *state = get_module_state(mod); + Py_VISIT(state->groupby_type); + Py_VISIT(state->_grouper_type); + return 0; +} + +static int +itertoolsmodule_clear(PyObject *mod) +{ + itertools_state *state = get_module_state(mod); + Py_CLEAR(state->groupby_type); + Py_CLEAR(state->_grouper_type); + return 0; +} + +static void +itertoolsmodule_free(void *mod) +{ + (void)itertoolsmodule_clear((PyObject *)mod); +} + +#define ADD_TYPE(module, type, spec) \ +do { \ + type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, NULL); \ + if (type == NULL) { \ + return -1; \ + } \ + if (PyModule_AddType(module, type) < 0) { \ + return -1; \ + } \ +} while (0) + +static int +itertoolsmodule_exec(PyObject *mod) { + itertools_state *state = get_module_state(mod); + ADD_TYPE(mod, state->groupby_type, &groupby_spec); + ADD_TYPE(mod, state->_grouper_type, &_grouper_spec); + PyTypeObject *typelist[] = { &accumulate_type, &batched_type, @@ -5000,8 +5032,6 @@ itertoolsmodule_exec(PyObject *m) &permutations_type, &product_type, &repeat_type, - &groupby_type, - &_grouper_type, &tee_type, &teedataobject_type }; @@ -5009,7 +5039,7 @@ itertoolsmodule_exec(PyObject *m) Py_SET_TYPE(&teedataobject_type, &PyType_Type); for (size_t i = 0; i < Py_ARRAY_LENGTH(typelist); i++) { - if (PyModule_AddType(m, typelist[i]) < 0) { + if (PyModule_AddType(mod, typelist[i]) < 0) { return -1; } } @@ -5029,15 +5059,15 @@ static PyMethodDef module_methods[] = { static struct PyModuleDef itertoolsmodule = { - PyModuleDef_HEAD_INIT, - "itertools", - module_doc, - 0, - module_methods, - itertoolsmodule_slots, - NULL, - NULL, - NULL + .m_base = PyModuleDef_HEAD_INIT, + .m_name = "itertools", + .m_doc = module_doc, + .m_size = sizeof(itertools_state), + .m_methods = module_methods, + .m_slots = itertoolsmodule_slots, + .m_traverse = itertoolsmodule_traverse, + .m_clear = itertoolsmodule_clear, + .m_free = itertoolsmodule_free, }; PyMODINIT_FUNC From 62251c3da06eb4662502295697f39730565b1717 Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Wed, 1 Feb 2023 12:49:59 +0000 Subject: [PATCH 12/74] gh-101454: fix documentation for END_ASYNC_FOR (#101455) --- Doc/library/dis.rst | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 6a68ec4b14be319..1fe2d5d6227d615 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -616,10 +616,9 @@ not have to be) the original ``STACK[-2]``. .. opcode:: END_ASYNC_FOR Terminates an :keyword:`async for` loop. Handles an exception raised - when awaiting a next item. If ``STACK[-1]`` is :exc:`StopAsyncIteration` pop 3 - values from the stack and restore the exception state using the second - of them. Otherwise re-raise the exception using the value - from the stack. An exception handler block is removed from the block stack. + when awaiting a next item. The stack contains the async iterable in + ``STACK[-2]`` and the raised exception in ``STACK[-1]``. Both are popped. + If the exception is not :exc:`StopAsyncIteration`, it is re-raised. .. versionadded:: 3.8 From 95fb0e02582b5673eff49694eb0dce1d7df52301 Mon Sep 17 00:00:00 2001 From: Raj <51259329+workingpayload@users.noreply.github.com> Date: Wed, 1 Feb 2023 23:38:31 +0530 Subject: [PATCH 13/74] gh-101498 : Fix asyncio.Timeout example in docs (#101499) Doc/library/asyncio-task.rst#timeout --- Doc/library/asyncio-task.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 9a42b963167685b..39112580285cc0c 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -666,7 +666,7 @@ Timeouts except TimeoutError: pass - if cm.expired: + if cm.expired(): print("Looks like we haven't finished on time.") Timeout context managers can be safely nested. From 7840ff3cdbdf64f517c9f981f57eff232e676104 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Wed, 1 Feb 2023 10:56:52 -0800 Subject: [PATCH 14/74] gh-98831: Modernize the LOAD_ATTR family (#101488) --- Python/bytecodes.c | 177 ++++++++++++--------------------- Python/generated_cases.c.h | 198 +++++++++++++++++++++---------------- Python/opcode_metadata.h | 60 +++++------ 3 files changed, 205 insertions(+), 230 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 336088e08197deb..bb1deaf3fbeb4b1 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -436,7 +436,7 @@ dummy_func( PREDICT(JUMP_BACKWARD); } - family(store_subscr) = { + family(store_subscr, INLINE_CACHE_ENTRIES_STORE_SUBSCR) = { STORE_SUBSCR, STORE_SUBSCR_DICT, STORE_SUBSCR_LIST_INT, @@ -950,7 +950,7 @@ dummy_func( Py_DECREF(seq); } - family(store_attr) = { + family(store_attr, INLINE_CACHE_ENTRIES_STORE_ATTR) = { STORE_ATTR, STORE_ATTR_INSTANCE_VALUE, STORE_ATTR_SLOT, @@ -1436,6 +1436,20 @@ dummy_func( PREDICT(JUMP_BACKWARD); } + family(load_attr, INLINE_CACHE_ENTRIES_LOAD_ATTR) = { + LOAD_ATTR, + LOAD_ATTR_INSTANCE_VALUE, + LOAD_ATTR_MODULE, + LOAD_ATTR_WITH_HINT, + LOAD_ATTR_SLOT, + LOAD_ATTR_CLASS, + LOAD_ATTR_PROPERTY, + LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, + LOAD_ATTR_METHOD_WITH_VALUES, + LOAD_ATTR_METHOD_NO_DICT, + LOAD_ATTR_METHOD_LAZY_DICT, + }; + inst(LOAD_ATTR, (unused/9, owner -- res2 if (oparg & 1), res)) { #if ENABLE_SPECIALIZATION _PyAttrCache *cache = (_PyAttrCache *)next_instr; @@ -1485,64 +1499,43 @@ dummy_func( } } - // error: LOAD_ATTR has irregular stack effect - inst(LOAD_ATTR_INSTANCE_VALUE) { + inst(LOAD_ATTR_INSTANCE_VALUE, (unused/1, type_version/2, index/1, unused/5, owner -- res2 if (oparg & 1), res)) { assert(cframe.use_tracing == 0); - PyObject *owner = TOP(); - PyObject *res; PyTypeObject *tp = Py_TYPE(owner); - _PyAttrCache *cache = (_PyAttrCache *)next_instr; - uint32_t type_version = read_u32(cache->version); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); assert(tp->tp_dictoffset < 0); assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT); PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR); - res = _PyDictOrValues_GetValues(dorv)->values[cache->index]; + res = _PyDictOrValues_GetValues(dorv)->values[index]; DEOPT_IF(res == NULL, LOAD_ATTR); STAT_INC(LOAD_ATTR, hit); Py_INCREF(res); - SET_TOP(NULL); - STACK_GROW((oparg & 1)); - SET_TOP(res); + res2 = NULL; Py_DECREF(owner); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); } - // error: LOAD_ATTR has irregular stack effect - inst(LOAD_ATTR_MODULE) { + inst(LOAD_ATTR_MODULE, (unused/1, type_version/2, index/1, unused/5, owner -- res2 if (oparg & 1), res)) { assert(cframe.use_tracing == 0); - PyObject *owner = TOP(); - PyObject *res; - _PyAttrCache *cache = (_PyAttrCache *)next_instr; DEOPT_IF(!PyModule_CheckExact(owner), LOAD_ATTR); PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict; assert(dict != NULL); - DEOPT_IF(dict->ma_keys->dk_version != read_u32(cache->version), - LOAD_ATTR); + DEOPT_IF(dict->ma_keys->dk_version != type_version, LOAD_ATTR); assert(dict->ma_keys->dk_kind == DICT_KEYS_UNICODE); - assert(cache->index < dict->ma_keys->dk_nentries); - PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + cache->index; + assert(index < dict->ma_keys->dk_nentries); + PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + index; res = ep->me_value; DEOPT_IF(res == NULL, LOAD_ATTR); STAT_INC(LOAD_ATTR, hit); Py_INCREF(res); - SET_TOP(NULL); - STACK_GROW((oparg & 1)); - SET_TOP(res); + res2 = NULL; Py_DECREF(owner); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); } - // error: LOAD_ATTR has irregular stack effect - inst(LOAD_ATTR_WITH_HINT) { + inst(LOAD_ATTR_WITH_HINT, (unused/1, type_version/2, index/1, unused/5, owner -- res2 if (oparg & 1), res)) { assert(cframe.use_tracing == 0); - PyObject *owner = TOP(); - PyObject *res; PyTypeObject *tp = Py_TYPE(owner); - _PyAttrCache *cache = (_PyAttrCache *)next_instr; - uint32_t type_version = read_u32(cache->version); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT); @@ -1552,7 +1545,7 @@ dummy_func( DEOPT_IF(dict == NULL, LOAD_ATTR); assert(PyDict_CheckExact((PyObject *)dict)); PyObject *name = GETITEM(names, oparg>>1); - uint16_t hint = cache->index; + uint16_t hint = index; DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, LOAD_ATTR); if (DK_IS_UNICODE(dict->ma_keys)) { PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint; @@ -1567,73 +1560,49 @@ dummy_func( DEOPT_IF(res == NULL, LOAD_ATTR); STAT_INC(LOAD_ATTR, hit); Py_INCREF(res); - SET_TOP(NULL); - STACK_GROW((oparg & 1)); - SET_TOP(res); + res2 = NULL; Py_DECREF(owner); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); } - // error: LOAD_ATTR has irregular stack effect - inst(LOAD_ATTR_SLOT) { + inst(LOAD_ATTR_SLOT, (unused/1, type_version/2, index/1, unused/5, owner -- res2 if (oparg & 1), res)) { assert(cframe.use_tracing == 0); - PyObject *owner = TOP(); - PyObject *res; PyTypeObject *tp = Py_TYPE(owner); - _PyAttrCache *cache = (_PyAttrCache *)next_instr; - uint32_t type_version = read_u32(cache->version); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); - char *addr = (char *)owner + cache->index; + char *addr = (char *)owner + index; res = *(PyObject **)addr; DEOPT_IF(res == NULL, LOAD_ATTR); STAT_INC(LOAD_ATTR, hit); Py_INCREF(res); - SET_TOP(NULL); - STACK_GROW((oparg & 1)); - SET_TOP(res); + res2 = NULL; Py_DECREF(owner); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); } - // error: LOAD_ATTR has irregular stack effect - inst(LOAD_ATTR_CLASS) { + inst(LOAD_ATTR_CLASS, (unused/1, type_version/2, unused/2, descr/4, cls -- res2 if (oparg & 1), res)) { assert(cframe.use_tracing == 0); - _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; - PyObject *cls = TOP(); DEOPT_IF(!PyType_Check(cls), LOAD_ATTR); - uint32_t type_version = read_u32(cache->type_version); DEOPT_IF(((PyTypeObject *)cls)->tp_version_tag != type_version, LOAD_ATTR); assert(type_version != 0); STAT_INC(LOAD_ATTR, hit); - PyObject *res = read_obj(cache->descr); + res2 = NULL; + res = descr; assert(res != NULL); Py_INCREF(res); - SET_TOP(NULL); - STACK_GROW((oparg & 1)); - SET_TOP(res); Py_DECREF(cls); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); } - // error: LOAD_ATTR has irregular stack effect - inst(LOAD_ATTR_PROPERTY) { + inst(LOAD_ATTR_PROPERTY, (unused/1, type_version/2, func_version/2, fget/4, owner -- unused if (oparg & 1), unused)) { assert(cframe.use_tracing == 0); DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR); - _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; - PyObject *owner = TOP(); PyTypeObject *cls = Py_TYPE(owner); - uint32_t type_version = read_u32(cache->type_version); DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR); assert(type_version != 0); - PyObject *fget = read_obj(cache->descr); assert(Py_IS_TYPE(fget, &PyFunction_Type)); PyFunctionObject *f = (PyFunctionObject *)fget; - uint32_t func_version = read_u32(cache->keys_version); assert(func_version != 0); DEOPT_IF(f->func_version != func_version, LOAD_ATTR); PyCodeObject *code = (PyCodeObject *)f->func_code; @@ -1642,6 +1611,7 @@ dummy_func( STAT_INC(LOAD_ATTR, hit); Py_INCREF(fget); _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f, 1); + // Manipulate stack directly because we exit with DISPATCH_INLINED(). SET_TOP(NULL); int shrink_stack = !(oparg & 1); STACK_SHRINK(shrink_stack); @@ -1650,20 +1620,14 @@ dummy_func( DISPATCH_INLINED(new_frame); } - // error: LOAD_ATTR has irregular stack effect - inst(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN) { + inst(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, (unused/1, type_version/2, func_version/2, getattribute/4, owner -- unused if (oparg & 1), unused)) { assert(cframe.use_tracing == 0); DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR); - _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; - PyObject *owner = TOP(); PyTypeObject *cls = Py_TYPE(owner); - uint32_t type_version = read_u32(cache->type_version); DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR); assert(type_version != 0); - PyObject *getattribute = read_obj(cache->descr); assert(Py_IS_TYPE(getattribute, &PyFunction_Type)); PyFunctionObject *f = (PyFunctionObject *)getattribute; - uint32_t func_version = read_u32(cache->keys_version); assert(func_version != 0); DEOPT_IF(f->func_version != func_version, LOAD_ATTR); PyCodeObject *code = (PyCodeObject *)f->func_code; @@ -1674,6 +1638,7 @@ dummy_func( PyObject *name = GETITEM(names, oparg >> 1); Py_INCREF(f); _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f, 2); + // Manipulate stack directly because we exit with DISPATCH_INLINED(). SET_TOP(NULL); int shrink_stack = !(oparg & 1); STACK_SHRINK(shrink_stack); @@ -1768,6 +1733,7 @@ dummy_func( ERROR_IF(res == NULL, error); } + // No cache size here, since this is a family of super-instructions. family(compare_and_branch) = { COMPARE_AND_BRANCH, COMPARE_AND_BRANCH_FLOAT, @@ -2373,14 +2339,10 @@ dummy_func( } - // error: LOAD_ATTR has irregular stack effect - inst(LOAD_ATTR_METHOD_WITH_VALUES) { + inst(LOAD_ATTR_METHOD_WITH_VALUES, (unused/1, type_version/2, keys_version/2, descr/4, self -- res2 if (oparg & 1), res)) { /* Cached method object */ assert(cframe.use_tracing == 0); - PyObject *self = TOP(); PyTypeObject *self_cls = Py_TYPE(self); - _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; - uint32_t type_version = read_u32(cache->type_version); assert(type_version != 0); DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); assert(self_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT); @@ -2388,41 +2350,31 @@ dummy_func( DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR); PyHeapTypeObject *self_heap_type = (PyHeapTypeObject *)self_cls; DEOPT_IF(self_heap_type->ht_cached_keys->dk_version != - read_u32(cache->keys_version), LOAD_ATTR); + keys_version, LOAD_ATTR); STAT_INC(LOAD_ATTR, hit); - PyObject *res = read_obj(cache->descr); - assert(res != NULL); - assert(_PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR)); - SET_TOP(Py_NewRef(res)); - PUSH(self); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); + assert(descr != NULL); + res2 = Py_NewRef(descr); + assert(_PyType_HasFeature(Py_TYPE(res2), Py_TPFLAGS_METHOD_DESCRIPTOR)); + res = self; + assert(oparg & 1); } - // error: LOAD_ATTR has irregular stack effect - inst(LOAD_ATTR_METHOD_NO_DICT) { + inst(LOAD_ATTR_METHOD_NO_DICT, (unused/1, type_version/2, unused/2, descr/4, self -- res2 if (oparg & 1), res)) { assert(cframe.use_tracing == 0); - PyObject *self = TOP(); PyTypeObject *self_cls = Py_TYPE(self); - _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; - uint32_t type_version = read_u32(cache->type_version); DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); assert(self_cls->tp_dictoffset == 0); STAT_INC(LOAD_ATTR, hit); - PyObject *res = read_obj(cache->descr); - assert(res != NULL); - assert(_PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR)); - SET_TOP(Py_NewRef(res)); - PUSH(self); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); + assert(descr != NULL); + assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); + res2 = Py_NewRef(descr); + res = self; + assert(oparg & 1); } - // error: LOAD_ATTR has irregular stack effect - inst(LOAD_ATTR_METHOD_LAZY_DICT) { + inst(LOAD_ATTR_METHOD_LAZY_DICT, (unused/1, type_version/2, unused/2, descr/4, self -- res2 if (oparg & 1), res)) { assert(cframe.use_tracing == 0); - PyObject *self = TOP(); PyTypeObject *self_cls = Py_TYPE(self); - _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; - uint32_t type_version = read_u32(cache->type_version); DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); Py_ssize_t dictoffset = self_cls->tp_dictoffset; assert(dictoffset > 0); @@ -2430,12 +2382,11 @@ dummy_func( /* This object has a __dict__, just not yet created */ DEOPT_IF(dict != NULL, LOAD_ATTR); STAT_INC(LOAD_ATTR, hit); - PyObject *res = read_obj(cache->descr); - assert(res != NULL); - assert(_PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR)); - SET_TOP(Py_NewRef(res)); - PUSH(self); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); + assert(descr != NULL); + assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); + res2 = Py_NewRef(descr); + res = self; + assert(oparg & 1); } // stack effect: (__0, __array[oparg] -- ) @@ -3265,7 +3216,7 @@ dummy_func( // Future families go below this point // -family(call) = { +family(call, INLINE_CACHE_ENTRIES_CALL) = { CALL, CALL_PY_EXACT_ARGS, CALL_PY_WITH_DEFAULTS, CALL_BOUND_METHOD_EXACT_ARGS, CALL_BUILTIN_CLASS, CALL_BUILTIN_FAST_WITH_KEYWORDS, CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, CALL_NO_KW_BUILTIN_FAST, @@ -3273,19 +3224,13 @@ family(call) = { CALL_NO_KW_LIST_APPEND, CALL_NO_KW_METHOD_DESCRIPTOR_FAST, CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS, CALL_NO_KW_METHOD_DESCRIPTOR_O, CALL_NO_KW_STR_1, CALL_NO_KW_TUPLE_1, CALL_NO_KW_TYPE_1 }; -family(for_iter) = { +family(for_iter, INLINE_CACHE_ENTRIES_FOR_ITER) = { FOR_ITER, FOR_ITER_LIST, FOR_ITER_RANGE }; -family(load_attr) = { - LOAD_ATTR, LOAD_ATTR_CLASS, - LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, LOAD_ATTR_INSTANCE_VALUE, LOAD_ATTR_MODULE, - LOAD_ATTR_PROPERTY, LOAD_ATTR_SLOT, LOAD_ATTR_WITH_HINT, - LOAD_ATTR_METHOD_LAZY_DICT, LOAD_ATTR_METHOD_NO_DICT, - LOAD_ATTR_METHOD_WITH_VALUES }; -family(load_global) = { +family(load_global, INLINE_CACHE_ENTRIES_LOAD_GLOBAL) = { LOAD_GLOBAL, LOAD_GLOBAL_BUILTIN, LOAD_GLOBAL_MODULE }; family(store_fast) = { STORE_FAST, STORE_FAST__LOAD_FAST, STORE_FAST__STORE_FAST }; -family(unpack_sequence) = { +family(unpack_sequence, INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE) = { UNPACK_SEQUENCE, UNPACK_SEQUENCE_LIST, UNPACK_SEQUENCE_TUPLE, UNPACK_SEQUENCE_TWO_TUPLE }; diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index d70d64ecbdd5c10..e5c5c7e557a37c6 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -596,6 +596,7 @@ TARGET(STORE_SUBSCR) { PREDICTED(STORE_SUBSCR); + static_assert(INLINE_CACHE_ENTRIES_STORE_SUBSCR == 1, "incorrect cache size"); PyObject *sub = PEEK(1); PyObject *container = PEEK(2); PyObject *v = PEEK(3); @@ -1180,6 +1181,7 @@ TARGET(STORE_ATTR) { PREDICTED(STORE_ATTR); + static_assert(INLINE_CACHE_ENTRIES_STORE_ATTR == 4, "incorrect cache size"); PyObject *owner = PEEK(1); PyObject *v = PEEK(2); uint16_t counter = read_u16(&next_instr[0].cache); @@ -1748,6 +1750,7 @@ TARGET(LOAD_ATTR) { PREDICTED(LOAD_ATTR); + static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size"); PyObject *owner = PEEK(1); PyObject *res2 = NULL; PyObject *res; @@ -1805,62 +1808,67 @@ } TARGET(LOAD_ATTR_INSTANCE_VALUE) { - assert(cframe.use_tracing == 0); - PyObject *owner = TOP(); + PyObject *owner = PEEK(1); + PyObject *res2 = NULL; PyObject *res; + uint32_t type_version = read_u32(&next_instr[1].cache); + uint16_t index = read_u16(&next_instr[3].cache); + assert(cframe.use_tracing == 0); PyTypeObject *tp = Py_TYPE(owner); - _PyAttrCache *cache = (_PyAttrCache *)next_instr; - uint32_t type_version = read_u32(cache->version); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); assert(tp->tp_dictoffset < 0); assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT); PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR); - res = _PyDictOrValues_GetValues(dorv)->values[cache->index]; + res = _PyDictOrValues_GetValues(dorv)->values[index]; DEOPT_IF(res == NULL, LOAD_ATTR); STAT_INC(LOAD_ATTR, hit); Py_INCREF(res); - SET_TOP(NULL); - STACK_GROW((oparg & 1)); - SET_TOP(res); + res2 = NULL; Py_DECREF(owner); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); + STACK_GROW(((oparg & 1) ? 1 : 0)); + POKE(1, res); + if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), res2); } + JUMPBY(9); DISPATCH(); } TARGET(LOAD_ATTR_MODULE) { - assert(cframe.use_tracing == 0); - PyObject *owner = TOP(); + PyObject *owner = PEEK(1); + PyObject *res2 = NULL; PyObject *res; - _PyAttrCache *cache = (_PyAttrCache *)next_instr; + uint32_t type_version = read_u32(&next_instr[1].cache); + uint16_t index = read_u16(&next_instr[3].cache); + assert(cframe.use_tracing == 0); DEOPT_IF(!PyModule_CheckExact(owner), LOAD_ATTR); PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict; assert(dict != NULL); - DEOPT_IF(dict->ma_keys->dk_version != read_u32(cache->version), - LOAD_ATTR); + DEOPT_IF(dict->ma_keys->dk_version != type_version, LOAD_ATTR); assert(dict->ma_keys->dk_kind == DICT_KEYS_UNICODE); - assert(cache->index < dict->ma_keys->dk_nentries); - PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + cache->index; + assert(index < dict->ma_keys->dk_nentries); + PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + index; res = ep->me_value; DEOPT_IF(res == NULL, LOAD_ATTR); STAT_INC(LOAD_ATTR, hit); Py_INCREF(res); - SET_TOP(NULL); - STACK_GROW((oparg & 1)); - SET_TOP(res); + res2 = NULL; Py_DECREF(owner); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); + STACK_GROW(((oparg & 1) ? 1 : 0)); + POKE(1, res); + if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), res2); } + JUMPBY(9); DISPATCH(); } TARGET(LOAD_ATTR_WITH_HINT) { - assert(cframe.use_tracing == 0); - PyObject *owner = TOP(); + PyObject *owner = PEEK(1); + PyObject *res2 = NULL; PyObject *res; + uint32_t type_version = read_u32(&next_instr[1].cache); + uint16_t index = read_u16(&next_instr[3].cache); + assert(cframe.use_tracing == 0); PyTypeObject *tp = Py_TYPE(owner); - _PyAttrCache *cache = (_PyAttrCache *)next_instr; - uint32_t type_version = read_u32(cache->version); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT); @@ -1870,7 +1878,7 @@ DEOPT_IF(dict == NULL, LOAD_ATTR); assert(PyDict_CheckExact((PyObject *)dict)); PyObject *name = GETITEM(names, oparg>>1); - uint16_t hint = cache->index; + uint16_t hint = index; DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, LOAD_ATTR); if (DK_IS_UNICODE(dict->ma_keys)) { PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint; @@ -1885,73 +1893,78 @@ DEOPT_IF(res == NULL, LOAD_ATTR); STAT_INC(LOAD_ATTR, hit); Py_INCREF(res); - SET_TOP(NULL); - STACK_GROW((oparg & 1)); - SET_TOP(res); + res2 = NULL; Py_DECREF(owner); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); + STACK_GROW(((oparg & 1) ? 1 : 0)); + POKE(1, res); + if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), res2); } + JUMPBY(9); DISPATCH(); } TARGET(LOAD_ATTR_SLOT) { - assert(cframe.use_tracing == 0); - PyObject *owner = TOP(); + PyObject *owner = PEEK(1); + PyObject *res2 = NULL; PyObject *res; + uint32_t type_version = read_u32(&next_instr[1].cache); + uint16_t index = read_u16(&next_instr[3].cache); + assert(cframe.use_tracing == 0); PyTypeObject *tp = Py_TYPE(owner); - _PyAttrCache *cache = (_PyAttrCache *)next_instr; - uint32_t type_version = read_u32(cache->version); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); - char *addr = (char *)owner + cache->index; + char *addr = (char *)owner + index; res = *(PyObject **)addr; DEOPT_IF(res == NULL, LOAD_ATTR); STAT_INC(LOAD_ATTR, hit); Py_INCREF(res); - SET_TOP(NULL); - STACK_GROW((oparg & 1)); - SET_TOP(res); + res2 = NULL; Py_DECREF(owner); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); + STACK_GROW(((oparg & 1) ? 1 : 0)); + POKE(1, res); + if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), res2); } + JUMPBY(9); DISPATCH(); } TARGET(LOAD_ATTR_CLASS) { + PyObject *cls = PEEK(1); + PyObject *res2 = NULL; + PyObject *res; + uint32_t type_version = read_u32(&next_instr[1].cache); + PyObject *descr = read_obj(&next_instr[5].cache); assert(cframe.use_tracing == 0); - _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; - PyObject *cls = TOP(); DEOPT_IF(!PyType_Check(cls), LOAD_ATTR); - uint32_t type_version = read_u32(cache->type_version); DEOPT_IF(((PyTypeObject *)cls)->tp_version_tag != type_version, LOAD_ATTR); assert(type_version != 0); STAT_INC(LOAD_ATTR, hit); - PyObject *res = read_obj(cache->descr); + res2 = NULL; + res = descr; assert(res != NULL); Py_INCREF(res); - SET_TOP(NULL); - STACK_GROW((oparg & 1)); - SET_TOP(res); Py_DECREF(cls); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); + STACK_GROW(((oparg & 1) ? 1 : 0)); + POKE(1, res); + if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), res2); } + JUMPBY(9); DISPATCH(); } TARGET(LOAD_ATTR_PROPERTY) { + PyObject *owner = PEEK(1); + uint32_t type_version = read_u32(&next_instr[1].cache); + uint32_t func_version = read_u32(&next_instr[3].cache); + PyObject *fget = read_obj(&next_instr[5].cache); assert(cframe.use_tracing == 0); DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR); - _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; - PyObject *owner = TOP(); PyTypeObject *cls = Py_TYPE(owner); - uint32_t type_version = read_u32(cache->type_version); DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR); assert(type_version != 0); - PyObject *fget = read_obj(cache->descr); assert(Py_IS_TYPE(fget, &PyFunction_Type)); PyFunctionObject *f = (PyFunctionObject *)fget; - uint32_t func_version = read_u32(cache->keys_version); assert(func_version != 0); DEOPT_IF(f->func_version != func_version, LOAD_ATTR); PyCodeObject *code = (PyCodeObject *)f->func_code; @@ -1960,6 +1973,7 @@ STAT_INC(LOAD_ATTR, hit); Py_INCREF(fget); _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f, 1); + // Manipulate stack directly because we exit with DISPATCH_INLINED(). SET_TOP(NULL); int shrink_stack = !(oparg & 1); STACK_SHRINK(shrink_stack); @@ -1969,18 +1983,17 @@ } TARGET(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN) { + PyObject *owner = PEEK(1); + uint32_t type_version = read_u32(&next_instr[1].cache); + uint32_t func_version = read_u32(&next_instr[3].cache); + PyObject *getattribute = read_obj(&next_instr[5].cache); assert(cframe.use_tracing == 0); DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR); - _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; - PyObject *owner = TOP(); PyTypeObject *cls = Py_TYPE(owner); - uint32_t type_version = read_u32(cache->type_version); DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR); assert(type_version != 0); - PyObject *getattribute = read_obj(cache->descr); assert(Py_IS_TYPE(getattribute, &PyFunction_Type)); PyFunctionObject *f = (PyFunctionObject *)getattribute; - uint32_t func_version = read_u32(cache->keys_version); assert(func_version != 0); DEOPT_IF(f->func_version != func_version, LOAD_ATTR); PyCodeObject *code = (PyCodeObject *)f->func_code; @@ -1991,6 +2004,7 @@ PyObject *name = GETITEM(names, oparg >> 1); Py_INCREF(f); _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f, 2); + // Manipulate stack directly because we exit with DISPATCH_INLINED(). SET_TOP(NULL); int shrink_stack = !(oparg & 1); STACK_SHRINK(shrink_stack); @@ -2831,12 +2845,15 @@ } TARGET(LOAD_ATTR_METHOD_WITH_VALUES) { + PyObject *self = PEEK(1); + PyObject *res2 = NULL; + PyObject *res; + uint32_t type_version = read_u32(&next_instr[1].cache); + uint32_t keys_version = read_u32(&next_instr[3].cache); + PyObject *descr = read_obj(&next_instr[5].cache); /* Cached method object */ assert(cframe.use_tracing == 0); - PyObject *self = TOP(); PyTypeObject *self_cls = Py_TYPE(self); - _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; - uint32_t type_version = read_u32(cache->type_version); assert(type_version != 0); DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); assert(self_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT); @@ -2844,41 +2861,51 @@ DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR); PyHeapTypeObject *self_heap_type = (PyHeapTypeObject *)self_cls; DEOPT_IF(self_heap_type->ht_cached_keys->dk_version != - read_u32(cache->keys_version), LOAD_ATTR); + keys_version, LOAD_ATTR); STAT_INC(LOAD_ATTR, hit); - PyObject *res = read_obj(cache->descr); - assert(res != NULL); - assert(_PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR)); - SET_TOP(Py_NewRef(res)); - PUSH(self); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); + assert(descr != NULL); + res2 = Py_NewRef(descr); + assert(_PyType_HasFeature(Py_TYPE(res2), Py_TPFLAGS_METHOD_DESCRIPTOR)); + res = self; + assert(oparg & 1); + STACK_GROW(((oparg & 1) ? 1 : 0)); + POKE(1, res); + if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), res2); } + JUMPBY(9); DISPATCH(); } TARGET(LOAD_ATTR_METHOD_NO_DICT) { + PyObject *self = PEEK(1); + PyObject *res2 = NULL; + PyObject *res; + uint32_t type_version = read_u32(&next_instr[1].cache); + PyObject *descr = read_obj(&next_instr[5].cache); assert(cframe.use_tracing == 0); - PyObject *self = TOP(); PyTypeObject *self_cls = Py_TYPE(self); - _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; - uint32_t type_version = read_u32(cache->type_version); DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); assert(self_cls->tp_dictoffset == 0); STAT_INC(LOAD_ATTR, hit); - PyObject *res = read_obj(cache->descr); - assert(res != NULL); - assert(_PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR)); - SET_TOP(Py_NewRef(res)); - PUSH(self); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); + assert(descr != NULL); + assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); + res2 = Py_NewRef(descr); + res = self; + assert(oparg & 1); + STACK_GROW(((oparg & 1) ? 1 : 0)); + POKE(1, res); + if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), res2); } + JUMPBY(9); DISPATCH(); } TARGET(LOAD_ATTR_METHOD_LAZY_DICT) { + PyObject *self = PEEK(1); + PyObject *res2 = NULL; + PyObject *res; + uint32_t type_version = read_u32(&next_instr[1].cache); + PyObject *descr = read_obj(&next_instr[5].cache); assert(cframe.use_tracing == 0); - PyObject *self = TOP(); PyTypeObject *self_cls = Py_TYPE(self); - _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; - uint32_t type_version = read_u32(cache->type_version); DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); Py_ssize_t dictoffset = self_cls->tp_dictoffset; assert(dictoffset > 0); @@ -2886,12 +2913,15 @@ /* This object has a __dict__, just not yet created */ DEOPT_IF(dict != NULL, LOAD_ATTR); STAT_INC(LOAD_ATTR, hit); - PyObject *res = read_obj(cache->descr); - assert(res != NULL); - assert(_PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR)); - SET_TOP(Py_NewRef(res)); - PUSH(self); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); + assert(descr != NULL); + assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); + res2 = Py_NewRef(descr); + res = self; + assert(oparg & 1); + STACK_GROW(((oparg & 1) ? 1 : 0)); + POKE(1, res); + if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), res2); } + JUMPBY(9); DISPATCH(); } diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index 171fed363d3be05..96e57be8cf5deaa 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -187,19 +187,19 @@ _PyOpcode_num_popped(int opcode, int oparg) { case LOAD_ATTR: return 1; case LOAD_ATTR_INSTANCE_VALUE: - return -1; + return 1; case LOAD_ATTR_MODULE: - return -1; + return 1; case LOAD_ATTR_WITH_HINT: - return -1; + return 1; case LOAD_ATTR_SLOT: - return -1; + return 1; case LOAD_ATTR_CLASS: - return -1; + return 1; case LOAD_ATTR_PROPERTY: - return -1; + return 1; case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN: - return -1; + return 1; case STORE_ATTR_INSTANCE_VALUE: return 2; case STORE_ATTR_WITH_HINT: @@ -279,11 +279,11 @@ _PyOpcode_num_popped(int opcode, int oparg) { case PUSH_EXC_INFO: return -1; case LOAD_ATTR_METHOD_WITH_VALUES: - return -1; + return 1; case LOAD_ATTR_METHOD_NO_DICT: - return -1; + return 1; case LOAD_ATTR_METHOD_LAZY_DICT: - return -1; + return 1; case CALL_BOUND_METHOD_EXACT_ARGS: return -1; case KW_NAMES: @@ -533,19 +533,19 @@ _PyOpcode_num_pushed(int opcode, int oparg) { case LOAD_ATTR: return ((oparg & 1) ? 1 : 0) + 1; case LOAD_ATTR_INSTANCE_VALUE: - return -1; + return ((oparg & 1) ? 1 : 0) + 1; case LOAD_ATTR_MODULE: - return -1; + return ((oparg & 1) ? 1 : 0) + 1; case LOAD_ATTR_WITH_HINT: - return -1; + return ((oparg & 1) ? 1 : 0) + 1; case LOAD_ATTR_SLOT: - return -1; + return ((oparg & 1) ? 1 : 0) + 1; case LOAD_ATTR_CLASS: - return -1; + return ((oparg & 1) ? 1 : 0) + 1; case LOAD_ATTR_PROPERTY: - return -1; + return ((oparg & 1) ? 1 : 0) + 1; case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN: - return -1; + return ((oparg & 1) ? 1 : 0) + 1; case STORE_ATTR_INSTANCE_VALUE: return 0; case STORE_ATTR_WITH_HINT: @@ -625,11 +625,11 @@ _PyOpcode_num_pushed(int opcode, int oparg) { case PUSH_EXC_INFO: return -1; case LOAD_ATTR_METHOD_WITH_VALUES: - return -1; + return ((oparg & 1) ? 1 : 0) + 1; case LOAD_ATTR_METHOD_NO_DICT: - return -1; + return ((oparg & 1) ? 1 : 0) + 1; case LOAD_ATTR_METHOD_LAZY_DICT: - return -1; + return ((oparg & 1) ? 1 : 0) + 1; case CALL_BOUND_METHOD_EXACT_ARGS: return -1; case KW_NAMES: @@ -792,13 +792,13 @@ struct opcode_metadata { [DICT_MERGE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [MAP_ADD] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [LOAD_ATTR] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, - [LOAD_ATTR_INSTANCE_VALUE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, - [LOAD_ATTR_MODULE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, - [LOAD_ATTR_WITH_HINT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, - [LOAD_ATTR_SLOT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, - [LOAD_ATTR_CLASS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, - [LOAD_ATTR_PROPERTY] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, - [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, + [LOAD_ATTR_INSTANCE_VALUE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, + [LOAD_ATTR_MODULE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, + [LOAD_ATTR_WITH_HINT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, + [LOAD_ATTR_SLOT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, + [LOAD_ATTR_CLASS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, + [LOAD_ATTR_PROPERTY] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, + [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, [STORE_ATTR_INSTANCE_VALUE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC000 }, [STORE_ATTR_WITH_HINT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC000 }, [STORE_ATTR_SLOT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC000 }, @@ -838,9 +838,9 @@ struct opcode_metadata { [BEFORE_WITH] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, [WITH_EXCEPT_START] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, [PUSH_EXC_INFO] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, - [LOAD_ATTR_METHOD_WITH_VALUES] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, - [LOAD_ATTR_METHOD_NO_DICT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, - [LOAD_ATTR_METHOD_LAZY_DICT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, + [LOAD_ATTR_METHOD_WITH_VALUES] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, + [LOAD_ATTR_METHOD_NO_DICT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, + [LOAD_ATTR_METHOD_LAZY_DICT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, [CALL_BOUND_METHOD_EXACT_ARGS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [KW_NAMES] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [CALL] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, From b91b42d236c81bd7cbe402b322c82bfcd0d883a1 Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Wed, 1 Feb 2023 19:38:06 +0000 Subject: [PATCH 15/74] gh-98831: rewrite PUSH_EXC_INFO and conditional jumps in the instruction definition DSL (#101481) --- Python/bytecodes.c | 71 ++++++++++--------------- Python/compile.c | 24 +++++---- Python/generated_cases.c.h | 68 +++++++++++++---------- Python/opcode_metadata.h | 32 +++++------ Tools/cases_generator/generate_cases.py | 2 +- 5 files changed, 98 insertions(+), 99 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index bb1deaf3fbeb4b1..105bd95be0fdc3b 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -1898,9 +1898,7 @@ dummy_func( CHECK_EVAL_BREAKER(); } - // stack effect: (__0 -- ) - inst(POP_JUMP_IF_FALSE) { - PyObject *cond = POP(); + inst(POP_JUMP_IF_FALSE, (cond -- )) { if (Py_IsTrue(cond)) { _Py_DECREF_NO_DEALLOC(cond); } @@ -1911,19 +1909,16 @@ dummy_func( else { int err = PyObject_IsTrue(cond); Py_DECREF(cond); - if (err > 0) - ; - else if (err == 0) { + if (err == 0) { JUMPBY(oparg); } - else - goto error; + else { + ERROR_IF(err < 0, error); + } } } - // stack effect: (__0 -- ) - inst(POP_JUMP_IF_TRUE) { - PyObject *cond = POP(); + inst(POP_JUMP_IF_TRUE, (cond -- )) { if (Py_IsFalse(cond)) { _Py_DECREF_NO_DEALLOC(cond); } @@ -1937,25 +1932,23 @@ dummy_func( if (err > 0) { JUMPBY(oparg); } - else if (err == 0) - ; - else - goto error; + else { + ERROR_IF(err < 0, error); + } } } - // stack effect: (__0 -- ) - inst(POP_JUMP_IF_NOT_NONE) { - PyObject *value = POP(); + inst(POP_JUMP_IF_NOT_NONE, (value -- )) { if (!Py_IsNone(value)) { + Py_DECREF(value); JUMPBY(oparg); } - Py_DECREF(value); + else { + _Py_DECREF_NO_DEALLOC(value); + } } - // stack effect: (__0 -- ) - inst(POP_JUMP_IF_NONE) { - PyObject *value = POP(); + inst(POP_JUMP_IF_NONE, (value -- )) { if (Py_IsNone(value)) { _Py_DECREF_NO_DEALLOC(value); JUMPBY(oparg); @@ -1965,25 +1958,24 @@ dummy_func( } } - // error: JUMP_IF_FALSE_OR_POP stack effect depends on jump flag - inst(JUMP_IF_FALSE_OR_POP) { - PyObject *cond = TOP(); + inst(JUMP_IF_FALSE_OR_POP, (cond -- cond if (jump))) { + bool jump = false; int err; if (Py_IsTrue(cond)) { - STACK_SHRINK(1); _Py_DECREF_NO_DEALLOC(cond); } else if (Py_IsFalse(cond)) { JUMPBY(oparg); + jump = true; } else { err = PyObject_IsTrue(cond); if (err > 0) { - STACK_SHRINK(1); Py_DECREF(cond); } else if (err == 0) { JUMPBY(oparg); + jump = true; } else { goto error; @@ -1991,24 +1983,23 @@ dummy_func( } } - // error: JUMP_IF_TRUE_OR_POP stack effect depends on jump flag - inst(JUMP_IF_TRUE_OR_POP) { - PyObject *cond = TOP(); + inst(JUMP_IF_TRUE_OR_POP, (cond -- cond if (jump))) { + bool jump = false; int err; if (Py_IsFalse(cond)) { - STACK_SHRINK(1); _Py_DECREF_NO_DEALLOC(cond); } else if (Py_IsTrue(cond)) { JUMPBY(oparg); + jump = true; } else { err = PyObject_IsTrue(cond); if (err > 0) { JUMPBY(oparg); + jump = true; } else if (err == 0) { - STACK_SHRINK(1); Py_DECREF(cond); } else { @@ -2321,22 +2312,16 @@ dummy_func( ERROR_IF(res == NULL, error); } - // stack effect: ( -- __0) - inst(PUSH_EXC_INFO) { - PyObject *value = TOP(); - + inst(PUSH_EXC_INFO, (new_exc -- prev_exc, new_exc)) { _PyErr_StackItem *exc_info = tstate->exc_info; if (exc_info->exc_value != NULL) { - SET_TOP(exc_info->exc_value); + prev_exc = exc_info->exc_value; } else { - SET_TOP(Py_NewRef(Py_None)); + prev_exc = Py_NewRef(Py_None); } - - PUSH(Py_NewRef(value)); - assert(PyExceptionInstance_Check(value)); - exc_info->exc_value = value; - + assert(PyExceptionInstance_Check(new_exc)); + exc_info->exc_value = Py_NewRef(new_exc); } inst(LOAD_ATTR_METHOD_WITH_VALUES, (unused/1, type_version/2, keys_version/2, descr/4, self -- res2 if (oparg & 1), res)) { diff --git a/Python/compile.c b/Python/compile.c index a11bcc79a6dd106..d9ec68958972b5f 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -8630,17 +8630,19 @@ opcode_metadata_is_sane(cfg_builder *g) { int opcode = instr->i_opcode; int oparg = instr->i_oparg; assert(opcode <= MAX_REAL_OPCODE); - int popped = _PyOpcode_num_popped(opcode, oparg); - int pushed = _PyOpcode_num_pushed(opcode, oparg); - assert((pushed < 0) == (popped < 0)); - if (pushed >= 0) { - assert(_PyOpcode_opcode_metadata[opcode].valid_entry); - int effect = stack_effect(opcode, instr->i_oparg, -1); - if (effect != pushed - popped) { - fprintf(stderr, - "op=%d: stack_effect (%d) != pushed (%d) - popped (%d)\n", - opcode, effect, pushed, popped); - result = false; + for (int jump = 0; jump <= 1; jump++) { + int popped = _PyOpcode_num_popped(opcode, oparg, jump ? true : false); + int pushed = _PyOpcode_num_pushed(opcode, oparg, jump ? true : false); + assert((pushed < 0) == (popped < 0)); + if (pushed >= 0) { + assert(_PyOpcode_opcode_metadata[opcode].valid_entry); + int effect = stack_effect(opcode, instr->i_oparg, jump); + if (effect != pushed - popped) { + fprintf(stderr, + "op=%d arg=%d jump=%d: stack_effect (%d) != pushed (%d) - popped (%d)\n", + opcode, oparg, jump, effect, pushed, popped); + result = false; + } } } } diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index e5c5c7e557a37c6..a02d8d79c60d377 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -2348,7 +2348,7 @@ TARGET(POP_JUMP_IF_FALSE) { PREDICTED(POP_JUMP_IF_FALSE); - PyObject *cond = POP(); + PyObject *cond = PEEK(1); if (Py_IsTrue(cond)) { _Py_DECREF_NO_DEALLOC(cond); } @@ -2359,19 +2359,19 @@ else { int err = PyObject_IsTrue(cond); Py_DECREF(cond); - if (err > 0) - ; - else if (err == 0) { + if (err == 0) { JUMPBY(oparg); } - else - goto error; + else { + if (err < 0) goto pop_1_error; + } } + STACK_SHRINK(1); DISPATCH(); } TARGET(POP_JUMP_IF_TRUE) { - PyObject *cond = POP(); + PyObject *cond = PEEK(1); if (Py_IsFalse(cond)) { _Py_DECREF_NO_DEALLOC(cond); } @@ -2385,25 +2385,29 @@ if (err > 0) { JUMPBY(oparg); } - else if (err == 0) - ; - else - goto error; + else { + if (err < 0) goto pop_1_error; + } } + STACK_SHRINK(1); DISPATCH(); } TARGET(POP_JUMP_IF_NOT_NONE) { - PyObject *value = POP(); + PyObject *value = PEEK(1); if (!Py_IsNone(value)) { + Py_DECREF(value); JUMPBY(oparg); } - Py_DECREF(value); + else { + _Py_DECREF_NO_DEALLOC(value); + } + STACK_SHRINK(1); DISPATCH(); } TARGET(POP_JUMP_IF_NONE) { - PyObject *value = POP(); + PyObject *value = PEEK(1); if (Py_IsNone(value)) { _Py_DECREF_NO_DEALLOC(value); JUMPBY(oparg); @@ -2411,58 +2415,65 @@ else { Py_DECREF(value); } + STACK_SHRINK(1); DISPATCH(); } TARGET(JUMP_IF_FALSE_OR_POP) { - PyObject *cond = TOP(); + PyObject *cond = PEEK(1); + bool jump = false; int err; if (Py_IsTrue(cond)) { - STACK_SHRINK(1); _Py_DECREF_NO_DEALLOC(cond); } else if (Py_IsFalse(cond)) { JUMPBY(oparg); + jump = true; } else { err = PyObject_IsTrue(cond); if (err > 0) { - STACK_SHRINK(1); Py_DECREF(cond); } else if (err == 0) { JUMPBY(oparg); + jump = true; } else { goto error; } } + STACK_SHRINK(1); + STACK_GROW((jump ? 1 : 0)); DISPATCH(); } TARGET(JUMP_IF_TRUE_OR_POP) { - PyObject *cond = TOP(); + PyObject *cond = PEEK(1); + bool jump = false; int err; if (Py_IsFalse(cond)) { - STACK_SHRINK(1); _Py_DECREF_NO_DEALLOC(cond); } else if (Py_IsTrue(cond)) { JUMPBY(oparg); + jump = true; } else { err = PyObject_IsTrue(cond); if (err > 0) { JUMPBY(oparg); + jump = true; } else if (err == 0) { - STACK_SHRINK(1); Py_DECREF(cond); } else { goto error; } } + STACK_SHRINK(1); + STACK_GROW((jump ? 1 : 0)); DISPATCH(); } @@ -2828,19 +2839,20 @@ } TARGET(PUSH_EXC_INFO) { - PyObject *value = TOP(); - + PyObject *new_exc = PEEK(1); + PyObject *prev_exc; _PyErr_StackItem *exc_info = tstate->exc_info; if (exc_info->exc_value != NULL) { - SET_TOP(exc_info->exc_value); + prev_exc = exc_info->exc_value; } else { - SET_TOP(Py_NewRef(Py_None)); + prev_exc = Py_NewRef(Py_None); } - - PUSH(Py_NewRef(value)); - assert(PyExceptionInstance_Check(value)); - exc_info->exc_value = value; + assert(PyExceptionInstance_Check(new_exc)); + exc_info->exc_value = Py_NewRef(new_exc); + STACK_GROW(1); + POKE(1, new_exc); + POKE(2, prev_exc); DISPATCH(); } diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index 96e57be8cf5deaa..c9f9759e16b316e 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -4,7 +4,7 @@ #ifndef NDEBUG static int -_PyOpcode_num_popped(int opcode, int oparg) { +_PyOpcode_num_popped(int opcode, int oparg, bool jump) { switch(opcode) { case NOP: return 0; @@ -233,17 +233,17 @@ _PyOpcode_num_popped(int opcode, int oparg) { case JUMP_BACKWARD: return 0; case POP_JUMP_IF_FALSE: - return -1; + return 1; case POP_JUMP_IF_TRUE: - return -1; + return 1; case POP_JUMP_IF_NOT_NONE: - return -1; + return 1; case POP_JUMP_IF_NONE: - return -1; + return 1; case JUMP_IF_FALSE_OR_POP: - return -1; + return 1; case JUMP_IF_TRUE_OR_POP: - return -1; + return 1; case JUMP_BACKWARD_NO_INTERRUPT: return 0; case GET_LEN: @@ -277,7 +277,7 @@ _PyOpcode_num_popped(int opcode, int oparg) { case WITH_EXCEPT_START: return 4; case PUSH_EXC_INFO: - return -1; + return 1; case LOAD_ATTR_METHOD_WITH_VALUES: return 1; case LOAD_ATTR_METHOD_NO_DICT: @@ -350,7 +350,7 @@ _PyOpcode_num_popped(int opcode, int oparg) { #ifndef NDEBUG static int -_PyOpcode_num_pushed(int opcode, int oparg) { +_PyOpcode_num_pushed(int opcode, int oparg, bool jump) { switch(opcode) { case NOP: return 0; @@ -579,17 +579,17 @@ _PyOpcode_num_pushed(int opcode, int oparg) { case JUMP_BACKWARD: return 0; case POP_JUMP_IF_FALSE: - return -1; + return 0; case POP_JUMP_IF_TRUE: - return -1; + return 0; case POP_JUMP_IF_NOT_NONE: - return -1; + return 0; case POP_JUMP_IF_NONE: - return -1; + return 0; case JUMP_IF_FALSE_OR_POP: - return -1; + return (jump ? 1 : 0); case JUMP_IF_TRUE_OR_POP: - return -1; + return (jump ? 1 : 0); case JUMP_BACKWARD_NO_INTERRUPT: return 0; case GET_LEN: @@ -623,7 +623,7 @@ _PyOpcode_num_pushed(int opcode, int oparg) { case WITH_EXCEPT_START: return 5; case PUSH_EXC_INFO: - return -1; + return 2; case LOAD_ATTR_METHOD_WITH_VALUES: return ((oparg & 1) ? 1 : 0) + 1; case LOAD_ATTR_METHOD_NO_DICT: diff --git a/Tools/cases_generator/generate_cases.py b/Tools/cases_generator/generate_cases.py index 43685450cc0dfe1..3925583b40e728e 100644 --- a/Tools/cases_generator/generate_cases.py +++ b/Tools/cases_generator/generate_cases.py @@ -868,7 +868,7 @@ def write_function( ) -> None: self.out.emit("\n#ifndef NDEBUG") self.out.emit("static int") - self.out.emit(f"_PyOpcode_num_{direction}(int opcode, int oparg) {{") + self.out.emit(f"_PyOpcode_num_{direction}(int opcode, int oparg, bool jump) {{") self.out.emit(" switch(opcode) {") for instr, effect in data: self.out.emit(f" case {instr.name}:") From eda60916bc88f8af736790ffd52381e8bb83ae83 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Wed, 1 Feb 2023 21:06:56 +0000 Subject: [PATCH 16/74] gh-101467: Correct py.exe handling of prefix matches and cases when only one runtime is installed (GH-101468) --- Doc/using/windows.rst | 35 ++++++++-- Lib/test/test_launcher.py | 29 +++++++-- ...-01-31-16-50-07.gh-issue-101467.ye9t-L.rst | 3 + PC/launcher2.c | 65 ++++++++++++++++--- 4 files changed, 114 insertions(+), 18 deletions(-) create mode 100644 Misc/NEWS.d/next/Windows/2023-01-31-16-50-07.gh-issue-101467.ye9t-L.rst diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst index bd09666d5e01c1f..1c4e41c0e0e2399 100644 --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -743,22 +743,47 @@ command:: py -2 -You should find the latest version of Python 3.x starts. - If you see the following error, you do not have the launcher installed:: 'py' is not recognized as an internal or external command, operable program or batch file. -Per-user installations of Python do not add the launcher to :envvar:`PATH` -unless the option was selected on installation. - The command:: py --list displays the currently installed version(s) of Python. +The ``-x.y`` argument is the short form of the ``-V:Company/Tag`` argument, +which allows selecting a specific Python runtime, including those that may have +come from somewhere other than python.org. Any runtime registered by following +:pep:`514` will be discoverable. The ``--list`` command lists all available +runtimes using the ``-V:`` format. + +When using the ``-V:`` argument, specifying the Company will limit selection to +runtimes from that provider, while specifying only the Tag will select from all +providers. Note that omitting the slash implies a tag:: + + # Select any '3.*' tagged runtime + py -V:3 + + # Select any 'PythonCore' released runtime + py -V:PythonCore/ + + # Select PythonCore's latest Python 3 runtime + py -V:PythonCore/3 + +The short form of the argument (``-3``) only ever selects from core Python +releases, and not other distributions. However, the longer form (``-V:3``) will +select from any. + +The Company is matched on the full string, case-insenitive. The Tag is matched +oneither the full string, or a prefix, provided the next character is a dot or a +hyphen. This allows ``-V:3.1`` to match ``3.1-32``, but not ``3.10``. Tags are +sorted using numerical ordering (``3.10`` is newer than ``3.1``), but are +compared using text (``-V:3.01`` does not match ``3.1``). + + Virtual environments ^^^^^^^^^^^^^^^^^^^^ diff --git a/Lib/test/test_launcher.py b/Lib/test/test_launcher.py index 351a638c1dd3409..2f35eaf08a2dc9e 100644 --- a/Lib/test/test_launcher.py +++ b/Lib/test/test_launcher.py @@ -56,7 +56,17 @@ None: sys.prefix, } }, - } + }, + "PythonTestSuite1": { + "DisplayName": "Python Test Suite Single", + "3.100": { + "DisplayName": "Single Interpreter", + "InstallPath": { + None: sys.prefix, + "ExecutablePath": sys.executable, + } + } + }, } @@ -206,6 +216,7 @@ def run_py(self, args, env=None, allow_fail=False, expect_returncode=0, argv=Non **{k.upper(): v for k, v in os.environ.items() if k.upper() not in ignore}, "PYLAUNCHER_DEBUG": "1", "PYLAUNCHER_DRYRUN": "1", + "PYLAUNCHER_LIMIT_TO_COMPANY": "", **{k.upper(): v for k, v in (env or {}).items()}, } if not argv: @@ -388,23 +399,33 @@ def test_filter_to_tag(self): self.assertEqual(company, data["env.company"]) self.assertEqual("3.100", data["env.tag"]) - data = self.run_py([f"-V:3.100-3"]) + data = self.run_py([f"-V:3.100-32"]) self.assertEqual("X.Y-32.exe", data["LaunchCommand"]) self.assertEqual(company, data["env.company"]) self.assertEqual("3.100-32", data["env.tag"]) - data = self.run_py([f"-V:3.100-a"]) + data = self.run_py([f"-V:3.100-arm64"]) self.assertEqual("X.Y-arm64.exe -X fake_arg_for_test", data["LaunchCommand"]) self.assertEqual(company, data["env.company"]) self.assertEqual("3.100-arm64", data["env.tag"]) def test_filter_to_company_and_tag(self): company = "PythonTestSuite" - data = self.run_py([f"-V:{company}/3.1"]) + data = self.run_py([f"-V:{company}/3.1"], expect_returncode=103) + + data = self.run_py([f"-V:{company}/3.100"]) self.assertEqual("X.Y.exe", data["LaunchCommand"]) self.assertEqual(company, data["env.company"]) self.assertEqual("3.100", data["env.tag"]) + def test_filter_with_single_install(self): + company = "PythonTestSuite1" + data = self.run_py( + [f"-V:Nonexistent"], + env={"PYLAUNCHER_LIMIT_TO_COMPANY": company}, + expect_returncode=103, + ) + def test_search_major_3(self): try: data = self.run_py(["-3"], allow_fail=True) diff --git a/Misc/NEWS.d/next/Windows/2023-01-31-16-50-07.gh-issue-101467.ye9t-L.rst b/Misc/NEWS.d/next/Windows/2023-01-31-16-50-07.gh-issue-101467.ye9t-L.rst new file mode 100644 index 000000000000000..4d4da05afa2d161 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2023-01-31-16-50-07.gh-issue-101467.ye9t-L.rst @@ -0,0 +1,3 @@ +The ``py.exe`` launcher now correctly filters when only a single runtime is +installed. It also correctly handles prefix matches on tags so that ``-3.1`` +does not match ``3.11``, but would still match ``3.1-32``. diff --git a/PC/launcher2.c b/PC/launcher2.c index 2052a2ffeb57b78..beeb2ae46b83f04 100644 --- a/PC/launcher2.c +++ b/PC/launcher2.c @@ -295,6 +295,30 @@ _startsWithArgument(const wchar_t *x, int xLen, const wchar_t *y, int yLen) } +// Unlike regular startsWith, this function requires that the following +// character is either NULL (that is, the entire string matches) or is one of +// the characters in 'separators'. +bool +_startsWithSeparated(const wchar_t *x, int xLen, const wchar_t *y, int yLen, const wchar_t *separators) +{ + if (!x || !y) { + return false; + } + yLen = yLen < 0 ? (int)wcsnlen_s(y, MAXLEN) : yLen; + xLen = xLen < 0 ? (int)wcsnlen_s(x, MAXLEN) : xLen; + if (xLen < yLen) { + return false; + } + if (xLen == yLen) { + return 0 == _compare(x, xLen, y, yLen); + } + return separators && + 0 == _compare(x, yLen, y, yLen) && + wcschr(separators, x[yLen]) != NULL; +} + + + /******************************************************************************\ *** HELP TEXT *** \******************************************************************************/ @@ -409,6 +433,9 @@ typedef struct { bool listPaths; // if true, display help message before contiuning bool help; + // if set, limits search to registry keys with the specified Company + // This is intended for debugging and testing only + const wchar_t *limitToCompany; // dynamically allocated buffers to free later struct _SearchInfoBuffer *_buffer; } SearchInfo; @@ -489,6 +516,7 @@ dumpSearchInfo(SearchInfo *search) DEBUG_BOOL(list); DEBUG_BOOL(listPaths); DEBUG_BOOL(help); + DEBUG(limitToCompany); #undef DEBUG_BOOL #undef DEBUG_2 #undef DEBUG @@ -1606,6 +1634,10 @@ registrySearch(const SearchInfo *search, EnvironmentInfo **result, HKEY root, in } break; } + if (search->limitToCompany && 0 != _compare(search->limitToCompany, -1, buffer, cchBuffer)) { + debug(L"# Skipping %s due to PYLAUNCHER_LIMIT_TO_COMPANY\n", buffer); + continue; + } HKEY subkey; if (ERROR_SUCCESS == RegOpenKeyExW(root, buffer, 0, KEY_READ, &subkey)) { exitCode = _registrySearchTags(search, result, subkey, sortKey, buffer, fallbackArch); @@ -1884,6 +1916,11 @@ collectEnvironments(const SearchInfo *search, EnvironmentInfo **result) } } + if (search->limitToCompany) { + debug(L"# Skipping APPX search due to PYLAUNCHER_LIMIT_TO_COMPANY\n"); + return 0; + } + for (struct AppxSearchInfo *info = APPX_SEARCH; info->familyName; ++info) { exitCode = appxSearch(search, result, info->familyName, info->tag, info->sortKey); if (exitCode && exitCode != RC_NO_PYTHON) { @@ -2053,12 +2090,15 @@ _companyMatches(const SearchInfo *search, const EnvironmentInfo *env) bool -_tagMatches(const SearchInfo *search, const EnvironmentInfo *env) +_tagMatches(const SearchInfo *search, const EnvironmentInfo *env, int searchTagLength) { - if (!search->tag || !search->tagLength) { + if (searchTagLength < 0) { + searchTagLength = search->tagLength; + } + if (!search->tag || !searchTagLength) { return true; } - return _startsWith(env->tag, -1, search->tag, search->tagLength); + return _startsWithSeparated(env->tag, -1, search->tag, searchTagLength, L".-"); } @@ -2095,7 +2135,7 @@ _selectEnvironment(const SearchInfo *search, EnvironmentInfo *env, EnvironmentIn } if (!search->oldStyleTag) { - if (_companyMatches(search, env) && _tagMatches(search, env)) { + if (_companyMatches(search, env) && _tagMatches(search, env, -1)) { // Because of how our sort tree is set up, we will walk up the // "prev" side and implicitly select the "best" best. By // returning straight after a match, we skip the entire "next" @@ -2120,7 +2160,7 @@ _selectEnvironment(const SearchInfo *search, EnvironmentInfo *env, EnvironmentIn } } - if (_startsWith(env->tag, -1, search->tag, tagLength)) { + if (_tagMatches(search, env, tagLength)) { if (exclude32Bit && _is32Bit(env)) { debug(L"# Excluding %s/%s because it looks like 32bit\n", env->company, env->tag); } else if (only32Bit && !_is32Bit(env)) { @@ -2147,10 +2187,6 @@ selectEnvironment(const SearchInfo *search, EnvironmentInfo *root, EnvironmentIn *best = NULL; return RC_NO_PYTHON_AT_ALL; } - if (!root->next && !root->prev) { - *best = root; - return 0; - } EnvironmentInfo *result = NULL; int exitCode = _selectEnvironment(search, root, &result); @@ -2560,6 +2596,17 @@ process(int argc, wchar_t ** argv) debug(L"argv0: %s\nversion: %S\n", argv[0], PY_VERSION); } + DWORD len = GetEnvironmentVariableW(L"PYLAUNCHER_LIMIT_TO_COMPANY", NULL, 0); + if (len > 1) { + wchar_t *limitToCompany = allocSearchInfoBuffer(&search, len); + search.limitToCompany = limitToCompany; + if (0 == GetEnvironmentVariableW(L"PYLAUNCHER_LIMIT_TO_COMPANY", limitToCompany, len)) { + exitCode = RC_INTERNAL_ERROR; + winerror(0, L"Failed to read PYLAUNCHER_LIMIT_TO_COMPANY variable"); + goto abort; + } + } + search.originalCmdLine = GetCommandLineW(); exitCode = performSearch(&search, &envs); From ae9b38f4241a7d62ec4e9b775d4436d762b11fb3 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Wed, 1 Feb 2023 13:12:49 -0800 Subject: [PATCH 17/74] gh-98831: Modernize the LOAD_GLOBAL family (#101502) --- Python/bytecodes.c | 57 +++++++++++--------------------- Python/generated_cases.c.h | 66 +++++++++++++++++++++----------------- Python/opcode_metadata.h | 20 ++++++------ 3 files changed, 66 insertions(+), 77 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 105bd95be0fdc3b..fb41c8387ccc909 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -1068,8 +1068,13 @@ dummy_func( } } - // error: LOAD_GLOBAL has irregular stack effect - inst(LOAD_GLOBAL) { + family(load_global, INLINE_CACHE_ENTRIES_LOAD_GLOBAL) = { + LOAD_GLOBAL, + LOAD_GLOBAL_MODULE, + LOAD_GLOBAL_BUILTIN, + }; + + inst(LOAD_GLOBAL, (unused/1, unused/1, unused/2, unused/1 -- null if (oparg & 1), v)) { #if ENABLE_SPECIALIZATION _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { @@ -1082,10 +1087,7 @@ dummy_func( STAT_INC(LOAD_GLOBAL, deferred); DECREMENT_ADAPTIVE_COUNTER(cache->counter); #endif /* ENABLE_SPECIALIZATION */ - int push_null = oparg & 1; - PEEK(0) = NULL; PyObject *name = GETITEM(names, oparg>>1); - PyObject *v; if (PyDict_CheckExact(GLOBALS()) && PyDict_CheckExact(BUILTINS())) { @@ -1099,7 +1101,7 @@ dummy_func( format_exc_check_arg(tstate, PyExc_NameError, NAME_ERROR_MSG, name); } - goto error; + ERROR_IF(true, error); } Py_INCREF(v); } @@ -1109,9 +1111,7 @@ dummy_func( /* namespace 1: globals */ v = PyObject_GetItem(GLOBALS(), name); if (v == NULL) { - if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { - goto error; - } + ERROR_IF(!_PyErr_ExceptionMatches(tstate, PyExc_KeyError), error); _PyErr_Clear(tstate); /* namespace 2: builtins */ @@ -1122,58 +1122,42 @@ dummy_func( tstate, PyExc_NameError, NAME_ERROR_MSG, name); } - goto error; + ERROR_IF(true, error); } } } - /* Skip over inline cache */ - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_GLOBAL); - STACK_GROW(push_null); - PUSH(v); + null = NULL; } - // error: LOAD_GLOBAL has irregular stack effect - inst(LOAD_GLOBAL_MODULE) { + inst(LOAD_GLOBAL_MODULE, (unused/1, index/1, version/2, unused/1 -- null if (oparg & 1), res)) { assert(cframe.use_tracing == 0); DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL); PyDictObject *dict = (PyDictObject *)GLOBALS(); - _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr; - uint32_t version = read_u32(cache->module_keys_version); DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL); assert(DK_IS_UNICODE(dict->ma_keys)); PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys); - PyObject *res = entries[cache->index].me_value; + res = entries[index].me_value; DEOPT_IF(res == NULL, LOAD_GLOBAL); - int push_null = oparg & 1; - PEEK(0) = NULL; - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_GLOBAL); + Py_INCREF(res); STAT_INC(LOAD_GLOBAL, hit); - STACK_GROW(push_null+1); - SET_TOP(Py_NewRef(res)); + null = NULL; } - // error: LOAD_GLOBAL has irregular stack effect - inst(LOAD_GLOBAL_BUILTIN) { + inst(LOAD_GLOBAL_BUILTIN, (unused/1, index/1, mod_version/2, bltn_version/1 -- null if (oparg & 1), res)) { assert(cframe.use_tracing == 0); DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL); DEOPT_IF(!PyDict_CheckExact(BUILTINS()), LOAD_GLOBAL); PyDictObject *mdict = (PyDictObject *)GLOBALS(); PyDictObject *bdict = (PyDictObject *)BUILTINS(); - _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr; - uint32_t mod_version = read_u32(cache->module_keys_version); - uint16_t bltn_version = cache->builtin_keys_version; DEOPT_IF(mdict->ma_keys->dk_version != mod_version, LOAD_GLOBAL); DEOPT_IF(bdict->ma_keys->dk_version != bltn_version, LOAD_GLOBAL); assert(DK_IS_UNICODE(bdict->ma_keys)); PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(bdict->ma_keys); - PyObject *res = entries[cache->index].me_value; + res = entries[index].me_value; DEOPT_IF(res == NULL, LOAD_GLOBAL); - int push_null = oparg & 1; - PEEK(0) = NULL; - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_GLOBAL); + Py_INCREF(res); STAT_INC(LOAD_GLOBAL, hit); - STACK_GROW(push_null+1); - SET_TOP(Py_NewRef(res)); + null = NULL; } inst(DELETE_FAST, (--)) { @@ -3212,9 +3196,6 @@ family(call, INLINE_CACHE_ENTRIES_CALL) = { family(for_iter, INLINE_CACHE_ENTRIES_FOR_ITER) = { FOR_ITER, FOR_ITER_LIST, FOR_ITER_RANGE }; -family(load_global, INLINE_CACHE_ENTRIES_LOAD_GLOBAL) = { - LOAD_GLOBAL, LOAD_GLOBAL_BUILTIN, - LOAD_GLOBAL_MODULE }; family(store_fast) = { STORE_FAST, STORE_FAST__LOAD_FAST, STORE_FAST__STORE_FAST }; family(unpack_sequence, INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE) = { UNPACK_SEQUENCE, UNPACK_SEQUENCE_LIST, diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index a02d8d79c60d377..77f9b00c4f0abcb 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -1311,6 +1311,9 @@ TARGET(LOAD_GLOBAL) { PREDICTED(LOAD_GLOBAL); + static_assert(INLINE_CACHE_ENTRIES_LOAD_GLOBAL == 5, "incorrect cache size"); + PyObject *null = NULL; + PyObject *v; #if ENABLE_SPECIALIZATION _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { @@ -1323,10 +1326,7 @@ STAT_INC(LOAD_GLOBAL, deferred); DECREMENT_ADAPTIVE_COUNTER(cache->counter); #endif /* ENABLE_SPECIALIZATION */ - int push_null = oparg & 1; - PEEK(0) = NULL; PyObject *name = GETITEM(names, oparg>>1); - PyObject *v; if (PyDict_CheckExact(GLOBALS()) && PyDict_CheckExact(BUILTINS())) { @@ -1340,7 +1340,7 @@ format_exc_check_arg(tstate, PyExc_NameError, NAME_ERROR_MSG, name); } - goto error; + if (true) goto error; } Py_INCREF(v); } @@ -1350,9 +1350,7 @@ /* namespace 1: globals */ v = PyObject_GetItem(GLOBALS(), name); if (v == NULL) { - if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { - goto error; - } + if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) goto error; _PyErr_Clear(tstate); /* namespace 2: builtins */ @@ -1363,58 +1361,68 @@ tstate, PyExc_NameError, NAME_ERROR_MSG, name); } - goto error; + if (true) goto error; } } } - /* Skip over inline cache */ - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_GLOBAL); - STACK_GROW(push_null); - PUSH(v); + null = NULL; + STACK_GROW(1); + STACK_GROW(((oparg & 1) ? 1 : 0)); + POKE(1, v); + if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), null); } + JUMPBY(5); DISPATCH(); } TARGET(LOAD_GLOBAL_MODULE) { + PyObject *null = NULL; + PyObject *res; + uint16_t index = read_u16(&next_instr[1].cache); + uint32_t version = read_u32(&next_instr[2].cache); assert(cframe.use_tracing == 0); DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL); PyDictObject *dict = (PyDictObject *)GLOBALS(); - _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr; - uint32_t version = read_u32(cache->module_keys_version); DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL); assert(DK_IS_UNICODE(dict->ma_keys)); PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys); - PyObject *res = entries[cache->index].me_value; + res = entries[index].me_value; DEOPT_IF(res == NULL, LOAD_GLOBAL); - int push_null = oparg & 1; - PEEK(0) = NULL; - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_GLOBAL); + Py_INCREF(res); STAT_INC(LOAD_GLOBAL, hit); - STACK_GROW(push_null+1); - SET_TOP(Py_NewRef(res)); + null = NULL; + STACK_GROW(1); + STACK_GROW(((oparg & 1) ? 1 : 0)); + POKE(1, res); + if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), null); } + JUMPBY(5); DISPATCH(); } TARGET(LOAD_GLOBAL_BUILTIN) { + PyObject *null = NULL; + PyObject *res; + uint16_t index = read_u16(&next_instr[1].cache); + uint32_t mod_version = read_u32(&next_instr[2].cache); + uint16_t bltn_version = read_u16(&next_instr[4].cache); assert(cframe.use_tracing == 0); DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL); DEOPT_IF(!PyDict_CheckExact(BUILTINS()), LOAD_GLOBAL); PyDictObject *mdict = (PyDictObject *)GLOBALS(); PyDictObject *bdict = (PyDictObject *)BUILTINS(); - _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr; - uint32_t mod_version = read_u32(cache->module_keys_version); - uint16_t bltn_version = cache->builtin_keys_version; DEOPT_IF(mdict->ma_keys->dk_version != mod_version, LOAD_GLOBAL); DEOPT_IF(bdict->ma_keys->dk_version != bltn_version, LOAD_GLOBAL); assert(DK_IS_UNICODE(bdict->ma_keys)); PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(bdict->ma_keys); - PyObject *res = entries[cache->index].me_value; + res = entries[index].me_value; DEOPT_IF(res == NULL, LOAD_GLOBAL); - int push_null = oparg & 1; - PEEK(0) = NULL; - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_GLOBAL); + Py_INCREF(res); STAT_INC(LOAD_GLOBAL, hit); - STACK_GROW(push_null+1); - SET_TOP(Py_NewRef(res)); + null = NULL; + STACK_GROW(1); + STACK_GROW(((oparg & 1) ? 1 : 0)); + POKE(1, res); + if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), null); } + JUMPBY(5); DISPATCH(); } diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index c9f9759e16b316e..f0bdedeb667d44a 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -141,11 +141,11 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) { case LOAD_NAME: return 0; case LOAD_GLOBAL: - return -1; + return 0; case LOAD_GLOBAL_MODULE: - return -1; + return 0; case LOAD_GLOBAL_BUILTIN: - return -1; + return 0; case DELETE_FAST: return 0; case MAKE_CELL: @@ -487,11 +487,11 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { case LOAD_NAME: return 1; case LOAD_GLOBAL: - return -1; + return ((oparg & 1) ? 1 : 0) + 1; case LOAD_GLOBAL_MODULE: - return -1; + return ((oparg & 1) ? 1 : 0) + 1; case LOAD_GLOBAL_BUILTIN: - return -1; + return ((oparg & 1) ? 1 : 0) + 1; case DELETE_FAST: return 0; case MAKE_CELL: @@ -694,7 +694,7 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { } #endif enum Direction { DIR_NONE, DIR_READ, DIR_WRITE }; -enum InstructionFormat { INSTR_FMT_IB, INSTR_FMT_IBC, INSTR_FMT_IBC0, INSTR_FMT_IBC000, INSTR_FMT_IBC00000000, INSTR_FMT_IBIB, INSTR_FMT_IX, INSTR_FMT_IXC, INSTR_FMT_IXC000 }; +enum InstructionFormat { INSTR_FMT_IB, INSTR_FMT_IBC, INSTR_FMT_IBC0, INSTR_FMT_IBC000, INSTR_FMT_IBC0000, INSTR_FMT_IBC00000000, INSTR_FMT_IBIB, INSTR_FMT_IX, INSTR_FMT_IXC, INSTR_FMT_IXC000 }; struct opcode_metadata { enum Direction dir_op1; enum Direction dir_op2; @@ -769,9 +769,9 @@ struct opcode_metadata { [STORE_GLOBAL] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [DELETE_GLOBAL] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [LOAD_NAME] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, - [LOAD_GLOBAL] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, - [LOAD_GLOBAL_MODULE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, - [LOAD_GLOBAL_BUILTIN] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, + [LOAD_GLOBAL] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC0000 }, + [LOAD_GLOBAL_MODULE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC0000 }, + [LOAD_GLOBAL_BUILTIN] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC0000 }, [DELETE_FAST] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [MAKE_CELL] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [DELETE_DEREF] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, From ee21110086e277a0ac24f5f768f35847b4db3380 Mon Sep 17 00:00:00 2001 From: Marcos Pereira <3464445+marcospgp@users.noreply.github.com> Date: Wed, 1 Feb 2023 23:52:29 +0000 Subject: [PATCH 18/74] Docs: improve accuracy of sqlite3 `check_same_thread` parameter (#101351) Co-authored-by: Erlend E. Aasland Co-authored-by: C.A.M. Gerlach --- Doc/library/sqlite3.rst | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index c0f0f133f4a286f..bbdc891c930cf4a 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -302,10 +302,13 @@ Module functions :type isolation_level: str | None :param bool check_same_thread: - If ``True`` (default), only the creating thread may use the connection. - If ``False``, the connection may be shared across multiple threads; - if so, write operations should be serialized by the user to avoid data - corruption. + If ``True`` (default), :exc:`ProgrammingError` will be raised + if the database connection is used by a thread + other than the one that created it. + If ``False``, the connection may be accessed in multiple threads; + write operations may need to be serialized by the user + to avoid data corruption. + See :attr:`threadsafety` for more information. :param Connection factory: A custom subclass of :class:`Connection` to create the connection with, From 0675b8f032c69d265468b31d5cadac6a7ce4bd9c Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Thu, 2 Feb 2023 10:02:57 +0000 Subject: [PATCH 19/74] gh-98831: rewrite RERAISE and CLEANUP_THROW in the instruction definition DSL (#101511) --- Python/bytecodes.c | 28 +++++++++++----------------- Python/generated_cases.c.h | 32 +++++++++++++++++++------------- Python/opcode_metadata.h | 8 ++++---- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index fb41c8387ccc909..169a2647866b313 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -739,10 +739,10 @@ dummy_func( Py_XSETREF(exc_info->exc_value, exc_value); } - // stack effect: (__0 -- ) - inst(RERAISE) { + inst(RERAISE, (values[oparg], exc -- values[oparg])) { + assert(oparg >= 0 && oparg <= 2); if (oparg) { - PyObject *lasti = PEEK(oparg + 1); + PyObject *lasti = values[0]; if (PyLong_Check(lasti)) { frame->prev_instr = _PyCode_CODE(frame->f_code) + PyLong_AsLong(lasti); assert(!_PyErr_Occurred(tstate)); @@ -753,11 +753,11 @@ dummy_func( goto error; } } - PyObject *val = POP(); - assert(val && PyExceptionInstance_Check(val)); - PyObject *exc = Py_NewRef(PyExceptionInstance_Class(val)); - PyObject *tb = PyException_GetTraceback(val); - _PyErr_Restore(tstate, exc, val, tb); + assert(exc && PyExceptionInstance_Check(exc)); + Py_INCREF(exc); + PyObject *typ = Py_NewRef(PyExceptionInstance_Class(exc)); + PyObject *tb = PyException_GetTraceback(exc); + _PyErr_Restore(tstate, typ, exc, tb); goto exception_unwind; } @@ -784,18 +784,12 @@ dummy_func( } } - // stack effect: (__0, __1 -- ) - inst(CLEANUP_THROW) { + inst(CLEANUP_THROW, (sub_iter, last_sent_val, exc_value -- value)) { assert(throwflag); - PyObject *exc_value = TOP(); assert(exc_value && PyExceptionInstance_Check(exc_value)); if (PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration)) { - PyObject *value = ((PyStopIterationObject *)exc_value)->value; - Py_INCREF(value); - Py_DECREF(POP()); // The StopIteration. - Py_DECREF(POP()); // The last sent value. - Py_DECREF(POP()); // The delegated sub-iterator. - PUSH(value); + value = Py_NewRef(((PyStopIterationObject *)exc_value)->value); + DECREF_INPUTS(); } else { PyObject *exc_type = Py_NewRef(Py_TYPE(exc_value)); diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 77f9b00c4f0abcb..97263866fe91585 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -945,8 +945,11 @@ } TARGET(RERAISE) { + PyObject *exc = PEEK(1); + PyObject **values = &PEEK(1 + oparg); + assert(oparg >= 0 && oparg <= 2); if (oparg) { - PyObject *lasti = PEEK(oparg + 1); + PyObject *lasti = values[0]; if (PyLong_Check(lasti)) { frame->prev_instr = _PyCode_CODE(frame->f_code) + PyLong_AsLong(lasti); assert(!_PyErr_Occurred(tstate)); @@ -957,11 +960,11 @@ goto error; } } - PyObject *val = POP(); - assert(val && PyExceptionInstance_Check(val)); - PyObject *exc = Py_NewRef(PyExceptionInstance_Class(val)); - PyObject *tb = PyException_GetTraceback(val); - _PyErr_Restore(tstate, exc, val, tb); + assert(exc && PyExceptionInstance_Check(exc)); + Py_INCREF(exc); + PyObject *typ = Py_NewRef(PyExceptionInstance_Class(exc)); + PyObject *tb = PyException_GetTraceback(exc); + _PyErr_Restore(tstate, typ, exc, tb); goto exception_unwind; } @@ -1001,16 +1004,17 @@ } TARGET(CLEANUP_THROW) { + PyObject *exc_value = PEEK(1); + PyObject *last_sent_val = PEEK(2); + PyObject *sub_iter = PEEK(3); + PyObject *value; assert(throwflag); - PyObject *exc_value = TOP(); assert(exc_value && PyExceptionInstance_Check(exc_value)); if (PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration)) { - PyObject *value = ((PyStopIterationObject *)exc_value)->value; - Py_INCREF(value); - Py_DECREF(POP()); // The StopIteration. - Py_DECREF(POP()); // The last sent value. - Py_DECREF(POP()); // The delegated sub-iterator. - PUSH(value); + value = Py_NewRef(((PyStopIterationObject *)exc_value)->value); + Py_DECREF(sub_iter); + Py_DECREF(last_sent_val); + Py_DECREF(exc_value); } else { PyObject *exc_type = Py_NewRef(Py_TYPE(exc_value)); @@ -1018,6 +1022,8 @@ _PyErr_Restore(tstate, exc_type, Py_NewRef(exc_value), exc_traceback); goto exception_unwind; } + STACK_SHRINK(2); + POKE(1, value); DISPATCH(); } diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index f0bdedeb667d44a..ca3dde363bfd854 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -105,13 +105,13 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) { case POP_EXCEPT: return 1; case RERAISE: - return -1; + return oparg + 1; case PREP_RERAISE_STAR: return 2; case END_ASYNC_FOR: return 2; case CLEANUP_THROW: - return -1; + return 3; case LOAD_ASSERTION_ERROR: return 0; case LOAD_BUILD_CLASS: @@ -451,13 +451,13 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { case POP_EXCEPT: return 0; case RERAISE: - return -1; + return oparg; case PREP_RERAISE_STAR: return 1; case END_ASYNC_FOR: return 0; case CLEANUP_THROW: - return -1; + return 1; case LOAD_ASSERTION_ERROR: return 1; case LOAD_BUILD_CLASS: From 24cbc7a2a09bf22ff8122c1d50135e1c56622c95 Mon Sep 17 00:00:00 2001 From: Peter Gessler Date: Thu, 2 Feb 2023 14:12:57 -0600 Subject: [PATCH 20/74] docs: Fix enum reassign `str` documentation (GH-101507) --- Doc/library/enum.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst index cfe4fbeb0698e78..13591a1bdc73471 100644 --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -922,6 +922,6 @@ Notes or you can reassign the appropriate :meth:`str`, etc., in your enum:: - >>> from enum import IntEnum + >>> from enum import Enum, IntEnum >>> class MyIntEnum(IntEnum): - ... __str__ = IntEnum.__str__ + ... __str__ = Enum.__str__ From ba4731d149185894c77d201bc5804da90ff45eee Mon Sep 17 00:00:00 2001 From: Ayappan Perumal Date: Fri, 3 Feb 2023 02:00:49 +0530 Subject: [PATCH 21/74] gh-96305: Fix AIX build by avoiding subprocess during bootstrap (#96429) * Fix AIX build by avoiding `subprocess` during bootstrap. --- Lib/_aix_support.py | 27 +++++++++++++++++-- ...2-08-30-10-16-31.gh-issue-96305.274i8B.rst | 2 ++ 2 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Build/2022-08-30-10-16-31.gh-issue-96305.274i8B.rst diff --git a/Lib/_aix_support.py b/Lib/_aix_support.py index 18533e769b75149..dadc75c2bf4200e 100644 --- a/Lib/_aix_support.py +++ b/Lib/_aix_support.py @@ -1,10 +1,28 @@ """Shared AIX support functions.""" -import subprocess import sys import sysconfig +# Taken from _osx_support _read_output function +def _read_cmd_output(commandstring, capture_stderr=False): + """Output from successful command execution or None""" + # Similar to os.popen(commandstring, "r").read(), + # but without actually using os.popen because that + # function is not usable during python bootstrap. + import os + import contextlib + fp = open("/tmp/_aix_support.%s"%( + os.getpid(),), "w+b") + + with contextlib.closing(fp) as fp: + if capture_stderr: + cmd = "%s >'%s' 2>&1" % (commandstring, fp.name) + else: + cmd = "%s 2>/dev/null >'%s'" % (commandstring, fp.name) + return fp.read() if not os.system(cmd) else None + + def _aix_tag(vrtl, bd): # type: (List[int], int) -> str # Infer the ABI bitwidth from maxsize (assuming 64 bit as the default) @@ -30,7 +48,12 @@ def _aix_bos_rte(): If no builddate is found give a value that will satisfy pep425 related queries """ # All AIX systems to have lslpp installed in this location - out = subprocess.check_output(["/usr/bin/lslpp", "-Lqc", "bos.rte"]) + # subprocess may not be available during python bootstrap + try: + import subprocess + out = subprocess.check_output(["/usr/bin/lslpp", "-Lqc", "bos.rte"]) + except ImportError: + out = _read_cmd_output("/usr/bin/lslpp -Lqc bos.rte") out = out.decode("utf-8") out = out.strip().split(":") # type: ignore _bd = int(out[-1]) if out[-1] != '' else 9988 diff --git a/Misc/NEWS.d/next/Build/2022-08-30-10-16-31.gh-issue-96305.274i8B.rst b/Misc/NEWS.d/next/Build/2022-08-30-10-16-31.gh-issue-96305.274i8B.rst new file mode 100644 index 000000000000000..64a48da658f21f7 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2022-08-30-10-16-31.gh-issue-96305.274i8B.rst @@ -0,0 +1,2 @@ +``_aix_support`` now uses a simple code to get platform details rather than +the now non-existent ``_bootsubprocess`` during bootstrap. From 618b7a8260bb40290d6551f24885931077309590 Mon Sep 17 00:00:00 2001 From: Ayappan Perumal Date: Fri, 3 Feb 2023 02:02:33 +0530 Subject: [PATCH 22/74] gh-98705: Fix AIX build by undefining `__bool__` in C (#98768) --- Include/pyport.h | 6 ++++++ .../Build/2022-10-27-09-57-12.gh-issue-98705.H11XmR.rst | 2 ++ 2 files changed, 8 insertions(+) create mode 100644 Misc/NEWS.d/next/Build/2022-10-27-09-57-12.gh-issue-98705.H11XmR.rst diff --git a/Include/pyport.h b/Include/pyport.h index b1b2a74779691d4..22085049a304878 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -726,4 +726,10 @@ extern char * _getpty(int *, int, mode_t, int); # endif #endif + +/* AIX has __bool__ redefined in it's system header file. */ +#if defined(_AIX) && defined(__bool__) +#undef __bool__ +#endif + #endif /* Py_PYPORT_H */ diff --git a/Misc/NEWS.d/next/Build/2022-10-27-09-57-12.gh-issue-98705.H11XmR.rst b/Misc/NEWS.d/next/Build/2022-10-27-09-57-12.gh-issue-98705.H11XmR.rst new file mode 100644 index 000000000000000..4519853cdbadd1d --- /dev/null +++ b/Misc/NEWS.d/next/Build/2022-10-27-09-57-12.gh-issue-98705.H11XmR.rst @@ -0,0 +1,2 @@ +``__bool__`` is defined in AIX system header files which breaks the build in +AIX, so undefine it. From 0ca67e6313c11263ecaef7ce182308eeb5aa6814 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Thu, 2 Feb 2023 15:50:35 -0800 Subject: [PATCH 23/74] GH-84559: Deprecate fork being the multiprocessing default. (#100618) This starts the process. Users who don't specify their own start method and use the default on platforms where it is 'fork' will see a DeprecationWarning upon multiprocessing.Pool() construction or upon multiprocessing.Process.start() or concurrent.futures.ProcessPool use. See the related issue and documentation within this change for details. --- Doc/library/concurrent.futures.rst | 14 ++- Doc/library/multiprocessing.rst | 104 +++++++++++------- Doc/whatsnew/3.12.rst | 8 ++ Lib/compileall.py | 8 +- Lib/concurrent/futures/process.py | 23 +++- Lib/multiprocessing/context.py | 29 ++++- Lib/test/_test_multiprocessing.py | 21 ++-- Lib/test/_test_venv_multiprocessing.py | 1 + Lib/test/test_asyncio/test_events.py | 9 +- Lib/test/test_concurrent_futures.py | 19 ++++ Lib/test/test_fcntl.py | 8 +- Lib/test/test_logging.py | 5 +- Lib/test/test_multiprocessing_defaults.py | 82 ++++++++++++++ Lib/test/test_pickle.py | 2 + Lib/test/test_re.py | 3 +- ...3-01-01-01-19-33.gh-issue-84559.zEjsEJ.rst | 11 ++ 16 files changed, 284 insertions(+), 63 deletions(-) create mode 100644 Lib/test/test_multiprocessing_defaults.py create mode 100644 Misc/NEWS.d/next/Library/2023-01-01-01-19-33.gh-issue-84559.zEjsEJ.rst diff --git a/Doc/library/concurrent.futures.rst b/Doc/library/concurrent.futures.rst index 8106cc235e5a3c0..10cffdaee0bb8c8 100644 --- a/Doc/library/concurrent.futures.rst +++ b/Doc/library/concurrent.futures.rst @@ -250,9 +250,10 @@ to a :class:`ProcessPoolExecutor` will result in deadlock. then :exc:`ValueError` will be raised. If *max_workers* is ``None``, then the default chosen will be at most ``61``, even if more processors are available. - *mp_context* can be a multiprocessing context or None. It will be used to - launch the workers. If *mp_context* is ``None`` or not given, the default - multiprocessing context is used. + *mp_context* can be a :mod:`multiprocessing` context or ``None``. It will be + used to launch the workers. If *mp_context* is ``None`` or not given, the + default :mod:`multiprocessing` context is used. + See :ref:`multiprocessing-start-methods`. *initializer* is an optional callable that is called at the start of each worker process; *initargs* is a tuple of arguments passed to the @@ -284,6 +285,13 @@ to a :class:`ProcessPoolExecutor` will result in deadlock. The *max_tasks_per_child* argument was added to allow users to control the lifetime of workers in the pool. + .. versionchanged:: 3.12 + The implicit use of the :mod:`multiprocessing` *fork* start method as a + platform default (see :ref:`multiprocessing-start-methods`) now raises a + :exc:`DeprecationWarning`. The default will change in Python 3.14. + Code that requires *fork* should explicitly specify that when creating + their :class:`ProcessPoolExecutor` by passing a + ``mp_context=multiprocessing.get_context('fork')`` parameter. .. _processpoolexecutor-example: diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst index b5ceeb796f8f2f2..c60b229ae2d07ef 100644 --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -19,7 +19,7 @@ offers both local and remote concurrency, effectively side-stepping the :term:`Global Interpreter Lock ` by using subprocesses instead of threads. Due to this, the :mod:`multiprocessing` module allows the programmer to fully -leverage multiple processors on a given machine. It runs on both Unix and +leverage multiple processors on a given machine. It runs on both POSIX and Windows. The :mod:`multiprocessing` module also introduces APIs which do not have @@ -99,11 +99,11 @@ necessary, see :ref:`multiprocessing-programming`. +.. _multiprocessing-start-methods: + Contexts and start methods ~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. _multiprocessing-start-methods: - Depending on the platform, :mod:`multiprocessing` supports three ways to start a process. These *start methods* are @@ -115,7 +115,7 @@ to start a process. These *start methods* are will not be inherited. Starting a process using this method is rather slow compared to using *fork* or *forkserver*. - Available on Unix and Windows. The default on Windows and macOS. + Available on POSIX and Windows platforms. The default on Windows and macOS. *fork* The parent process uses :func:`os.fork` to fork the Python @@ -124,32 +124,39 @@ to start a process. These *start methods* are inherited by the child process. Note that safely forking a multithreaded process is problematic. - Available on Unix only. The default on Unix. + Available on POSIX systems. Currently the default on POSIX except macOS. *forkserver* When the program starts and selects the *forkserver* start method, - a server process is started. From then on, whenever a new process + a server process is spawned. From then on, whenever a new process is needed, the parent process connects to the server and requests - that it fork a new process. The fork server process is single - threaded so it is safe for it to use :func:`os.fork`. No - unnecessary resources are inherited. + that it fork a new process. The fork server process is single threaded + unless system libraries or preloaded imports spawn threads as a + side-effect so it is generally safe for it to use :func:`os.fork`. + No unnecessary resources are inherited. - Available on Unix platforms which support passing file descriptors - over Unix pipes. + Available on POSIX platforms which support passing file descriptors + over Unix pipes such as Linux. + +.. versionchanged:: 3.12 + Implicit use of the *fork* start method as the default now raises a + :exc:`DeprecationWarning`. Code that requires it should explicitly + specify *fork* via :func:`get_context` or :func:`set_start_method`. + The default will change away from *fork* in 3.14. .. versionchanged:: 3.8 On macOS, the *spawn* start method is now the default. The *fork* start method should be considered unsafe as it can lead to crashes of the - subprocess. See :issue:`33725`. + subprocess as macOS system libraries may start threads. See :issue:`33725`. .. versionchanged:: 3.4 - *spawn* added on all Unix platforms, and *forkserver* added for - some Unix platforms. + *spawn* added on all POSIX platforms, and *forkserver* added for + some POSIX platforms. Child processes no longer inherit all of the parents inheritable handles on Windows. -On Unix using the *spawn* or *forkserver* start methods will also +On POSIX using the *spawn* or *forkserver* start methods will also start a *resource tracker* process which tracks the unlinked named system resources (such as named semaphores or :class:`~multiprocessing.shared_memory.SharedMemory` objects) created @@ -211,10 +218,10 @@ library user. .. warning:: - The ``'spawn'`` and ``'forkserver'`` start methods cannot currently + The ``'spawn'`` and ``'forkserver'`` start methods generally cannot be used with "frozen" executables (i.e., binaries produced by - packages like **PyInstaller** and **cx_Freeze**) on Unix. - The ``'fork'`` start method does work. + packages like **PyInstaller** and **cx_Freeze**) on POSIX systems. + The ``'fork'`` start method may work if code does not use threads. Exchanging objects between processes @@ -629,14 +636,14 @@ The :mod:`multiprocessing` package mostly replicates the API of the calling :meth:`join()` is simpler. On Windows, this is an OS handle usable with the ``WaitForSingleObject`` - and ``WaitForMultipleObjects`` family of API calls. On Unix, this is + and ``WaitForMultipleObjects`` family of API calls. On POSIX, this is a file descriptor usable with primitives from the :mod:`select` module. .. versionadded:: 3.3 .. method:: terminate() - Terminate the process. On Unix this is done using the ``SIGTERM`` signal; + Terminate the process. On POSIX this is done using the ``SIGTERM`` signal; on Windows :c:func:`TerminateProcess` is used. Note that exit handlers and finally clauses, etc., will not be executed. @@ -653,7 +660,7 @@ The :mod:`multiprocessing` package mostly replicates the API of the .. method:: kill() - Same as :meth:`terminate()` but using the ``SIGKILL`` signal on Unix. + Same as :meth:`terminate()` but using the ``SIGKILL`` signal on POSIX. .. versionadded:: 3.7 @@ -676,16 +683,17 @@ The :mod:`multiprocessing` package mostly replicates the API of the .. doctest:: >>> import multiprocessing, time, signal - >>> p = multiprocessing.Process(target=time.sleep, args=(1000,)) + >>> mp_context = multiprocessing.get_context('spawn') + >>> p = mp_context.Process(target=time.sleep, args=(1000,)) >>> print(p, p.is_alive()) - False + <...Process ... initial> False >>> p.start() >>> print(p, p.is_alive()) - True + <...Process ... started> True >>> p.terminate() >>> time.sleep(0.1) >>> print(p, p.is_alive()) - False + <...Process ... stopped exitcode=-SIGTERM> False >>> p.exitcode == -signal.SIGTERM True @@ -815,7 +823,7 @@ For an example of the usage of queues for interprocess communication see Return the approximate size of the queue. Because of multithreading/multiprocessing semantics, this number is not reliable. - Note that this may raise :exc:`NotImplementedError` on Unix platforms like + Note that this may raise :exc:`NotImplementedError` on platforms like macOS where ``sem_getvalue()`` is not implemented. .. method:: empty() @@ -1034,9 +1042,8 @@ Miscellaneous Returns a list of the supported start methods, the first of which is the default. The possible start methods are ``'fork'``, - ``'spawn'`` and ``'forkserver'``. On Windows only ``'spawn'`` is - available. On Unix ``'fork'`` and ``'spawn'`` are always - supported, with ``'fork'`` being the default. + ``'spawn'`` and ``'forkserver'``. Not all platforms support all + methods. See :ref:`multiprocessing-start-methods`. .. versionadded:: 3.4 @@ -1048,7 +1055,7 @@ Miscellaneous If *method* is ``None`` then the default context is returned. Otherwise *method* should be ``'fork'``, ``'spawn'``, ``'forkserver'``. :exc:`ValueError` is raised if the specified - start method is not available. + start method is not available. See :ref:`multiprocessing-start-methods`. .. versionadded:: 3.4 @@ -1062,8 +1069,7 @@ Miscellaneous is true then ``None`` is returned. The return value can be ``'fork'``, ``'spawn'``, ``'forkserver'`` - or ``None``. ``'fork'`` is the default on Unix, while ``'spawn'`` is - the default on Windows and macOS. + or ``None``. See :ref:`multiprocessing-start-methods`. .. versionchanged:: 3.8 @@ -1084,11 +1090,26 @@ Miscellaneous before they can create child processes. .. versionchanged:: 3.4 - Now supported on Unix when the ``'spawn'`` start method is used. + Now supported on POSIX when the ``'spawn'`` start method is used. .. versionchanged:: 3.11 Accepts a :term:`path-like object`. +.. function:: set_forkserver_preload(module_names) + + Set a list of module names for the forkserver main process to attempt to + import so that their already imported state is inherited by forked + processes. Any :exc:`ImportError` when doing so is silently ignored. + This can be used as a performance enhancement to avoid repeated work + in every process. + + For this to work, it must be called before the forkserver process has been + launched (before creating a :class:`Pool` or starting a :class:`Process`). + + Only meaningful when using the ``'forkserver'`` start method. + + .. versionadded:: 3.4 + .. function:: set_start_method(method, force=False) Set the method which should be used to start child processes. @@ -1102,6 +1123,8 @@ Miscellaneous protected inside the ``if __name__ == '__main__'`` clause of the main module. + See :ref:`multiprocessing-start-methods`. + .. versionadded:: 3.4 .. note:: @@ -1906,7 +1929,8 @@ their parent process exits. The manager classes are defined in the .. doctest:: - >>> manager = multiprocessing.Manager() + >>> mp_context = multiprocessing.get_context('spawn') + >>> manager = mp_context.Manager() >>> Global = manager.Namespace() >>> Global.x = 10 >>> Global.y = 'hello' @@ -2018,8 +2042,8 @@ the proxy). In this way, a proxy can be used just like its referent can: .. doctest:: - >>> from multiprocessing import Manager - >>> manager = Manager() + >>> mp_context = multiprocessing.get_context('spawn') + >>> manager = mp_context.Manager() >>> l = manager.list([i*i for i in range(10)]) >>> print(l) [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] @@ -2520,7 +2544,7 @@ multiple connections at the same time. *timeout* is ``None`` then it will block for an unlimited period. A negative timeout is equivalent to a zero timeout. - For both Unix and Windows, an object can appear in *object_list* if + For both POSIX and Windows, an object can appear in *object_list* if it is * a readable :class:`~multiprocessing.connection.Connection` object; @@ -2531,7 +2555,7 @@ multiple connections at the same time. A connection or socket object is ready when there is data available to be read from it, or the other end has been closed. - **Unix**: ``wait(object_list, timeout)`` almost equivalent + **POSIX**: ``wait(object_list, timeout)`` almost equivalent ``select.select(object_list, [], [], timeout)``. The difference is that, if :func:`select.select` is interrupted by a signal, it can raise :exc:`OSError` with an error number of ``EINTR``, whereas @@ -2803,7 +2827,7 @@ Thread safety of proxies Joining zombie processes - On Unix when a process finishes but has not been joined it becomes a zombie. + On POSIX when a process finishes but has not been joined it becomes a zombie. There should never be very many because each time a new process starts (or :func:`~multiprocessing.active_children` is called) all completed processes which have not yet been joined will be joined. Also calling a finished @@ -2866,7 +2890,7 @@ Joining processes that use queues Explicitly pass resources to child processes - On Unix using the *fork* start method, a child process can make + On POSIX using the *fork* start method, a child process can make use of a shared resource created in a parent process using a global resource. However, it is better to pass the object as an argument to the constructor for the child process. diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index a071159b800a34d..e675fada339a1ee 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -440,6 +440,11 @@ Deprecated warning at compile time. This field will be removed in Python 3.14. (Contributed by Ramvikrams and Kumar Aditya in :gh:`101193`. PEP by Ken Jin.) +* Use of the implicit default ``'fork'`` start method for + :mod:`multiprocessing` and :class:`concurrent.futures.ProcessPoolExecutor` + now emits a :exc:`DeprecationWarning` on Linux and other non-macOS POSIX + systems. Avoid this by explicitly specifying a start method. + See :ref:`multiprocessing-start-methods`. Pending Removal in Python 3.13 ------------------------------ @@ -505,6 +510,9 @@ Pending Removal in Python 3.14 * Testing the truth value of an :class:`xml.etree.ElementTree.Element` is deprecated and will raise an exception in Python 3.14. +* The default :mod:`multiprocessing` start method will change to one of either + ``'forkserver'`` or ``'spawn'`` on all platforms for which ``'fork'`` remains + the default per :gh:`84559`. Pending Removal in Future Versions ---------------------------------- diff --git a/Lib/compileall.py b/Lib/compileall.py index a388931fb5a99da..d394156cedc4e71 100644 --- a/Lib/compileall.py +++ b/Lib/compileall.py @@ -97,9 +97,15 @@ def compile_dir(dir, maxlevels=None, ddir=None, force=False, files = _walk_dir(dir, quiet=quiet, maxlevels=maxlevels) success = True if workers != 1 and ProcessPoolExecutor is not None: + import multiprocessing + if multiprocessing.get_start_method() == 'fork': + mp_context = multiprocessing.get_context('forkserver') + else: + mp_context = None # If workers == 0, let ProcessPoolExecutor choose workers = workers or None - with ProcessPoolExecutor(max_workers=workers) as executor: + with ProcessPoolExecutor(max_workers=workers, + mp_context=mp_context) as executor: results = executor.map(partial(compile_file, ddir=ddir, force=force, rx=rx, quiet=quiet, diff --git a/Lib/concurrent/futures/process.py b/Lib/concurrent/futures/process.py index 7e2f5fa30e82641..257dd02fbc6cceb 100644 --- a/Lib/concurrent/futures/process.py +++ b/Lib/concurrent/futures/process.py @@ -57,6 +57,7 @@ import itertools import sys from traceback import format_exception +import warnings _threads_wakeups = weakref.WeakKeyDictionary() @@ -616,9 +617,9 @@ def __init__(self, max_workers=None, mp_context=None, max_workers: The maximum number of processes that can be used to execute the given calls. If None or not given then as many worker processes will be created as the machine has processors. - mp_context: A multiprocessing context to launch the workers. This - object should provide SimpleQueue, Queue and Process. Useful - to allow specific multiprocessing start methods. + mp_context: A multiprocessing context to launch the workers created + using the multiprocessing.get_context('start method') API. This + object should provide SimpleQueue, Queue and Process. initializer: A callable used to initialize worker processes. initargs: A tuple of arguments to pass to the initializer. max_tasks_per_child: The maximum number of tasks a worker process @@ -650,6 +651,22 @@ def __init__(self, max_workers=None, mp_context=None, mp_context = mp.get_context("spawn") else: mp_context = mp.get_context() + if (mp_context.get_start_method() == "fork" and + mp_context == mp.context._default_context._default_context): + warnings.warn( + "The default multiprocessing start method will change " + "away from 'fork' in Python >= 3.14, per GH-84559. " + "ProcessPoolExecutor uses multiprocessing. " + "If your application requires the 'fork' multiprocessing " + "start method, explicitly specify that by passing a " + "mp_context= parameter. " + "The safest start method is 'spawn'.", + category=mp.context.DefaultForkDeprecationWarning, + stacklevel=2, + ) + # Avoid the equivalent warning from multiprocessing itself via + # a non-default fork context. + mp_context = mp.get_context("fork") self._mp_context = mp_context # https://github.com/python/cpython/issues/90622 diff --git a/Lib/multiprocessing/context.py b/Lib/multiprocessing/context.py index b1960ea296fe208..010a920540e844d 100644 --- a/Lib/multiprocessing/context.py +++ b/Lib/multiprocessing/context.py @@ -23,6 +23,9 @@ class TimeoutError(ProcessError): class AuthenticationError(ProcessError): pass +class DefaultForkDeprecationWarning(DeprecationWarning): + pass + # # Base type for contexts. Bound methods of an instance of this type are included in __all__ of __init__.py # @@ -258,6 +261,7 @@ def get_start_method(self, allow_none=False): return self._actual_context._name def get_all_start_methods(self): + """Returns a list of the supported start methods, default first.""" if sys.platform == 'win32': return ['spawn'] else: @@ -280,6 +284,23 @@ def _Popen(process_obj): from .popen_fork import Popen return Popen(process_obj) + _warn_package_prefixes = (os.path.dirname(__file__),) + + class _DeprecatedForkProcess(ForkProcess): + @classmethod + def _Popen(cls, process_obj): + import warnings + warnings.warn( + "The default multiprocessing start method will change " + "away from 'fork' in Python >= 3.14, per GH-84559. " + "Use multiprocessing.get_context(X) or .set_start_method(X) to " + "explicitly specify it when your application requires 'fork'. " + "The safest start method is 'spawn'.", + category=DefaultForkDeprecationWarning, + skip_file_prefixes=_warn_package_prefixes, + ) + return super()._Popen(process_obj) + class SpawnProcess(process.BaseProcess): _start_method = 'spawn' @staticmethod @@ -303,6 +324,9 @@ class ForkContext(BaseContext): _name = 'fork' Process = ForkProcess + class _DefaultForkContext(ForkContext): + Process = _DeprecatedForkProcess + class SpawnContext(BaseContext): _name = 'spawn' Process = SpawnProcess @@ -318,13 +342,16 @@ def _check_available(self): 'fork': ForkContext(), 'spawn': SpawnContext(), 'forkserver': ForkServerContext(), + # Remove None and _DefaultForkContext() when changing the default + # in 3.14 for https://github.com/python/cpython/issues/84559. + None: _DefaultForkContext(), } if sys.platform == 'darwin': # bpo-33725: running arbitrary code after fork() is no longer reliable # on macOS since macOS 10.14 (Mojave). Use spawn by default instead. _default_context = DefaultContext(_concrete_contexts['spawn']) else: - _default_context = DefaultContext(_concrete_contexts['fork']) + _default_context = DefaultContext(_concrete_contexts[None]) else: diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index 2fa75eb4d113118..e4a60a4d674607b 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -4098,9 +4098,10 @@ def test_shared_memory_SharedMemoryServer_ignores_sigint(self): def test_shared_memory_SharedMemoryManager_reuses_resource_tracker(self): # bpo-36867: test that a SharedMemoryManager uses the # same resource_tracker process as its parent. - cmd = '''if 1: + cmd = f'''if 1: from multiprocessing.managers import SharedMemoryManager - + from multiprocessing import set_start_method + set_start_method({multiprocessing.get_start_method()!r}) smm = SharedMemoryManager() smm.start() @@ -4967,11 +4968,13 @@ def run_in_grandchild(cls, conn): conn.send(tuple(sys.flags)) @classmethod - def run_in_child(cls): + def run_in_child(cls, start_method): import json - r, w = multiprocessing.Pipe(duplex=False) - p = multiprocessing.Process(target=cls.run_in_grandchild, args=(w,)) - p.start() + mp = multiprocessing.get_context(start_method) + r, w = mp.Pipe(duplex=False) + p = mp.Process(target=cls.run_in_grandchild, args=(w,)) + with warnings.catch_warnings(category=DeprecationWarning): + p.start() grandchild_flags = r.recv() p.join() r.close() @@ -4982,8 +4985,10 @@ def run_in_child(cls): def test_flags(self): import json # start child process using unusual flags - prog = ('from test._test_multiprocessing import TestFlags; ' + - 'TestFlags.run_in_child()') + prog = ( + 'from test._test_multiprocessing import TestFlags; ' + f'TestFlags.run_in_child({multiprocessing.get_start_method()!r})' + ) data = subprocess.check_output( [sys.executable, '-E', '-S', '-O', '-c', prog]) child_flags, grandchild_flags = json.loads(data.decode('ascii')) diff --git a/Lib/test/_test_venv_multiprocessing.py b/Lib/test/_test_venv_multiprocessing.py index af72e915ba52bbe..044a0c6cd3f5ca0 100644 --- a/Lib/test/_test_venv_multiprocessing.py +++ b/Lib/test/_test_venv_multiprocessing.py @@ -30,6 +30,7 @@ def test_func(): def main(): + multiprocessing.set_start_method('spawn') test_pool = multiprocessing.Process(target=test_func) test_pool.start() test_pool.join() diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 214544b89bc5584..b9069056c3a4367 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -4,6 +4,7 @@ import concurrent.futures import functools import io +import multiprocessing import os import platform import re @@ -2762,7 +2763,13 @@ def test_get_event_loop_new_process(self): support.skip_if_broken_multiprocessing_synchronize() async def main(): - pool = concurrent.futures.ProcessPoolExecutor() + if multiprocessing.get_start_method() == 'fork': + # Avoid 'fork' DeprecationWarning. + mp_context = multiprocessing.get_context('forkserver') + else: + mp_context = None + pool = concurrent.futures.ProcessPoolExecutor( + mp_context=mp_context) result = await self.loop.run_in_executor( pool, _test_get_event_loop_new_process__sub_proc) pool.shutdown() diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py index b3520ae3994e034..4493cd312528d6a 100644 --- a/Lib/test/test_concurrent_futures.py +++ b/Lib/test/test_concurrent_futures.py @@ -18,6 +18,7 @@ import threading import time import unittest +import warnings import weakref from pickle import PicklingError @@ -571,6 +572,24 @@ def test_shutdown_no_wait(self): assert all([r == abs(v) for r, v in zip(res, range(-5, 5))]) +@unittest.skipIf(mp.get_all_start_methods()[0] != "fork", "non-fork default.") +class ProcessPoolExecutorDefaultForkWarning(unittest.TestCase): + def test_fork_default_warns(self): + with self.assertWarns(mp.context.DefaultForkDeprecationWarning): + with futures.ProcessPoolExecutor(2): + pass + + def test_explicit_fork_does_not_warn(self): + with warnings.catch_warnings(record=True) as ws: + warnings.simplefilter("ignore") + warnings.filterwarnings( + 'always', category=mp.context.DefaultForkDeprecationWarning) + ctx = mp.get_context("fork") # Non-default fork context. + with futures.ProcessPoolExecutor(2, mp_context=ctx): + pass + self.assertEqual(len(ws), 0, msg=[str(x) for x in ws]) + + create_executor_tests(ProcessPoolShutdownTest, executor_mixins=(ProcessPoolForkMixin, ProcessPoolForkserverMixin, diff --git a/Lib/test/test_fcntl.py b/Lib/test/test_fcntl.py index fc8c39365f12b79..113c7802821dd45 100644 --- a/Lib/test/test_fcntl.py +++ b/Lib/test/test_fcntl.py @@ -1,11 +1,11 @@ """Test program for the fcntl C module. """ +import multiprocessing import platform import os import struct import sys import unittest -from multiprocessing import Process from test.support import verbose, cpython_only from test.support.import_helper import import_module from test.support.os_helper import TESTFN, unlink @@ -160,7 +160,8 @@ def test_lockf_exclusive(self): self.f = open(TESTFN, 'wb+') cmd = fcntl.LOCK_EX | fcntl.LOCK_NB fcntl.lockf(self.f, cmd) - p = Process(target=try_lockf_on_other_process_fail, args=(TESTFN, cmd)) + mp = multiprocessing.get_context('spawn') + p = mp.Process(target=try_lockf_on_other_process_fail, args=(TESTFN, cmd)) p.start() p.join() fcntl.lockf(self.f, fcntl.LOCK_UN) @@ -171,7 +172,8 @@ def test_lockf_share(self): self.f = open(TESTFN, 'wb+') cmd = fcntl.LOCK_SH | fcntl.LOCK_NB fcntl.lockf(self.f, cmd) - p = Process(target=try_lockf_on_other_process, args=(TESTFN, cmd)) + mp = multiprocessing.get_context('spawn') + p = mp.Process(target=try_lockf_on_other_process, args=(TESTFN, cmd)) p.start() p.join() fcntl.lockf(self.f, fcntl.LOCK_UN) diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 072056d3722106a..8a12d570f26f136 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -4759,8 +4759,9 @@ def test_multiprocessing(self): # In other processes, processName is correct when multiprocessing in imported, # but it is (incorrectly) defaulted to 'MainProcess' otherwise (bpo-38762). import multiprocessing - parent_conn, child_conn = multiprocessing.Pipe() - p = multiprocessing.Process( + mp = multiprocessing.get_context('spawn') + parent_conn, child_conn = mp.Pipe() + p = mp.Process( target=self._extract_logrecord_process_name, args=(2, LOG_MULTI_PROCESSING, child_conn,) ) diff --git a/Lib/test/test_multiprocessing_defaults.py b/Lib/test/test_multiprocessing_defaults.py new file mode 100644 index 000000000000000..1da4c065238384f --- /dev/null +++ b/Lib/test/test_multiprocessing_defaults.py @@ -0,0 +1,82 @@ +"""Test default behavior of multiprocessing.""" + +from inspect import currentframe, getframeinfo +import multiprocessing +from multiprocessing.context import DefaultForkDeprecationWarning +import sys +from test.support import threading_helper +import unittest +import warnings + + +def do_nothing(): + pass + + +# Process has the same API as Thread so this helper works. +join_process = threading_helper.join_thread + + +class DefaultWarningsTest(unittest.TestCase): + + @unittest.skipIf(sys.platform in ('win32', 'darwin'), + 'The default is not "fork" on Windows or macOS.') + def setUp(self): + self.assertEqual(multiprocessing.get_start_method(), 'fork') + self.assertIsInstance(multiprocessing.get_context(), + multiprocessing.context._DefaultForkContext) + + def test_default_fork_start_method_warning_process(self): + with warnings.catch_warnings(record=True) as ws: + warnings.simplefilter('ignore') + warnings.filterwarnings('always', category=DefaultForkDeprecationWarning) + process = multiprocessing.Process(target=do_nothing) + process.start() # warning should point here. + join_process(process) + self.assertIsInstance(ws[0].message, DefaultForkDeprecationWarning) + self.assertIn(__file__, ws[0].filename) + self.assertEqual(getframeinfo(currentframe()).lineno-4, ws[0].lineno) + self.assertIn("'fork'", str(ws[0].message)) + self.assertIn("get_context", str(ws[0].message)) + self.assertEqual(len(ws), 1, msg=[str(x) for x in ws]) + + def test_default_fork_start_method_warning_pool(self): + with warnings.catch_warnings(record=True) as ws: + warnings.simplefilter('ignore') + warnings.filterwarnings('always', category=DefaultForkDeprecationWarning) + pool = multiprocessing.Pool(1) # warning should point here. + pool.terminate() + pool.join() + self.assertIsInstance(ws[0].message, DefaultForkDeprecationWarning) + self.assertIn(__file__, ws[0].filename) + self.assertEqual(getframeinfo(currentframe()).lineno-5, ws[0].lineno) + self.assertIn("'fork'", str(ws[0].message)) + self.assertIn("get_context", str(ws[0].message)) + self.assertEqual(len(ws), 1, msg=[str(x) for x in ws]) + + def test_default_fork_start_method_warning_manager(self): + with warnings.catch_warnings(record=True) as ws: + warnings.simplefilter('ignore') + warnings.filterwarnings('always', category=DefaultForkDeprecationWarning) + manager = multiprocessing.Manager() # warning should point here. + manager.shutdown() + self.assertIsInstance(ws[0].message, DefaultForkDeprecationWarning) + self.assertIn(__file__, ws[0].filename) + self.assertEqual(getframeinfo(currentframe()).lineno-4, ws[0].lineno) + self.assertIn("'fork'", str(ws[0].message)) + self.assertIn("get_context", str(ws[0].message)) + self.assertEqual(len(ws), 1, msg=[str(x) for x in ws]) + + def test_no_mp_warning_when_using_explicit_fork_context(self): + with warnings.catch_warnings(record=True) as ws: + warnings.simplefilter('ignore') + warnings.filterwarnings('always', category=DefaultForkDeprecationWarning) + fork_mp = multiprocessing.get_context('fork') + pool = fork_mp.Pool(1) + pool.terminate() + pool.join() + self.assertEqual(len(ws), 0, msg=[str(x) for x in ws]) + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_pickle.py b/Lib/test/test_pickle.py index 44fdca7a6b1688b..80e7a4d23a4ba85 100644 --- a/Lib/test/test_pickle.py +++ b/Lib/test/test_pickle.py @@ -533,6 +533,8 @@ def test_exceptions(self): def test_multiprocessing_exceptions(self): module = import_helper.import_module('multiprocessing.context') for name, exc in get_exceptions(module): + if issubclass(exc, Warning): + continue with self.subTest(name): self.assertEqual(reverse_mapping('multiprocessing.context', name), ('multiprocessing', name)) diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index 11628a236ade9a3..eacb1a7c82a54d6 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -2431,7 +2431,8 @@ def test_regression_gh94675(self): input_js = '''a(function() { /////////////////////////////////////////////////////////////////// });''' - p = multiprocessing.Process(target=pattern.sub, args=('', input_js)) + mp = multiprocessing.get_context('spawn') + p = mp.Process(target=pattern.sub, args=('', input_js)) p.start() p.join(SHORT_TIMEOUT) try: diff --git a/Misc/NEWS.d/next/Library/2023-01-01-01-19-33.gh-issue-84559.zEjsEJ.rst b/Misc/NEWS.d/next/Library/2023-01-01-01-19-33.gh-issue-84559.zEjsEJ.rst new file mode 100644 index 000000000000000..3793e0f1fddb20b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-01-01-01-19-33.gh-issue-84559.zEjsEJ.rst @@ -0,0 +1,11 @@ +The :mod:`multiprocessing` module and +:class:`concurrent.futures.ProcessPoolExecutor` will emit a +:exc:`DeprecationWarning` on Linux and other non-macOS POSIX systems when +the default multiprocessing start method of ``'fork'`` is used implicitly +rather than being explicitly specified through a +:func:`multiprocessing.get_context` context. + +This is in preparation for default start method to change in Python 3.14 to +a default that is safe for multithreaded applications. + +Windows and macOS are unaffected as their default start method is ``spawn``. From 1b6045668d233269f667c4658c7240256f37f111 Mon Sep 17 00:00:00 2001 From: "C.A.M. Gerlach" Date: Thu, 2 Feb 2023 18:03:27 -0600 Subject: [PATCH 24/74] gh-100925: Move array methods under class in array doc (#101485) * Move array methods under class in array doc * Fix a few internal references related to the touched lines --- Doc/library/array.rst | 179 +++++++++++++++++++++--------------------- 1 file changed, 89 insertions(+), 90 deletions(-) diff --git a/Doc/library/array.rst b/Doc/library/array.rst index 95f1eaf401b0526..75c49e0f6d1ebe5 100644 --- a/Doc/library/array.rst +++ b/Doc/library/array.rst @@ -60,7 +60,7 @@ Notes: The actual representation of values is determined by the machine architecture (strictly speaking, by the C implementation). The actual size can be accessed -through the :attr:`itemsize` attribute. +through the :attr:`array.itemsize` attribute. The module defines the following item: @@ -85,161 +85,160 @@ The module defines the following type: to add initial items to the array. Otherwise, the iterable initializer is passed to the :meth:`extend` method. - .. audit-event:: array.__new__ typecode,initializer array.array + Array objects support the ordinary sequence operations of indexing, slicing, + concatenation, and multiplication. When using slice assignment, the assigned + value must be an array object with the same type code; in all other cases, + :exc:`TypeError` is raised. Array objects also implement the buffer interface, + and may be used wherever :term:`bytes-like objects ` are supported. + .. audit-event:: array.__new__ typecode,initializer array.array -Array objects support the ordinary sequence operations of indexing, slicing, -concatenation, and multiplication. When using slice assignment, the assigned -value must be an array object with the same type code; in all other cases, -:exc:`TypeError` is raised. Array objects also implement the buffer interface, -and may be used wherever :term:`bytes-like objects ` are supported. -The following data items and methods are also supported: + .. attribute:: typecode -.. attribute:: array.typecode + The typecode character used to create the array. - The typecode character used to create the array. + .. attribute:: itemsize -.. attribute:: array.itemsize + The length in bytes of one array item in the internal representation. - The length in bytes of one array item in the internal representation. + .. method:: append(x) -.. method:: array.append(x) + Append a new item with value *x* to the end of the array. - Append a new item with value *x* to the end of the array. + .. method:: buffer_info() -.. method:: array.buffer_info() + Return a tuple ``(address, length)`` giving the current memory address and the + length in elements of the buffer used to hold array's contents. The size of the + memory buffer in bytes can be computed as ``array.buffer_info()[1] * + array.itemsize``. This is occasionally useful when working with low-level (and + inherently unsafe) I/O interfaces that require memory addresses, such as certain + :c:func:`!ioctl` operations. The returned numbers are valid as long as the array + exists and no length-changing operations are applied to it. - Return a tuple ``(address, length)`` giving the current memory address and the - length in elements of the buffer used to hold array's contents. The size of the - memory buffer in bytes can be computed as ``array.buffer_info()[1] * - array.itemsize``. This is occasionally useful when working with low-level (and - inherently unsafe) I/O interfaces that require memory addresses, such as certain - :c:func:`ioctl` operations. The returned numbers are valid as long as the array - exists and no length-changing operations are applied to it. + .. note:: - .. note:: + When using array objects from code written in C or C++ (the only way to + effectively make use of this information), it makes more sense to use the buffer + interface supported by array objects. This method is maintained for backward + compatibility and should be avoided in new code. The buffer interface is + documented in :ref:`bufferobjects`. - When using array objects from code written in C or C++ (the only way to - effectively make use of this information), it makes more sense to use the buffer - interface supported by array objects. This method is maintained for backward - compatibility and should be avoided in new code. The buffer interface is - documented in :ref:`bufferobjects`. + .. method:: byteswap() -.. method:: array.byteswap() + "Byteswap" all items of the array. This is only supported for values which are + 1, 2, 4, or 8 bytes in size; for other types of values, :exc:`RuntimeError` is + raised. It is useful when reading data from a file written on a machine with a + different byte order. - "Byteswap" all items of the array. This is only supported for values which are - 1, 2, 4, or 8 bytes in size; for other types of values, :exc:`RuntimeError` is - raised. It is useful when reading data from a file written on a machine with a - different byte order. + .. method:: count(x) -.. method:: array.count(x) + Return the number of occurrences of *x* in the array. - Return the number of occurrences of *x* in the array. + .. method:: extend(iterable) -.. method:: array.extend(iterable) + Append items from *iterable* to the end of the array. If *iterable* is another + array, it must have *exactly* the same type code; if not, :exc:`TypeError` will + be raised. If *iterable* is not an array, it must be iterable and its elements + must be the right type to be appended to the array. - Append items from *iterable* to the end of the array. If *iterable* is another - array, it must have *exactly* the same type code; if not, :exc:`TypeError` will - be raised. If *iterable* is not an array, it must be iterable and its elements - must be the right type to be appended to the array. + .. method:: frombytes(s) -.. method:: array.frombytes(s) + Appends items from the string, interpreting the string as an array of machine + values (as if it had been read from a file using the :meth:`fromfile` method). - Appends items from the string, interpreting the string as an array of machine - values (as if it had been read from a file using the :meth:`fromfile` method). + .. versionadded:: 3.2 + :meth:`!fromstring` is renamed to :meth:`frombytes` for clarity. - .. versionadded:: 3.2 - :meth:`fromstring` is renamed to :meth:`frombytes` for clarity. + .. method:: fromfile(f, n) -.. method:: array.fromfile(f, n) + Read *n* items (as machine values) from the :term:`file object` *f* and append + them to the end of the array. If less than *n* items are available, + :exc:`EOFError` is raised, but the items that were available are still + inserted into the array. - Read *n* items (as machine values) from the :term:`file object` *f* and append - them to the end of the array. If less than *n* items are available, - :exc:`EOFError` is raised, but the items that were available are still - inserted into the array. + .. method:: fromlist(list) -.. method:: array.fromlist(list) + Append items from the list. This is equivalent to ``for x in list: + a.append(x)`` except that if there is a type error, the array is unchanged. - Append items from the list. This is equivalent to ``for x in list: - a.append(x)`` except that if there is a type error, the array is unchanged. + .. method:: fromunicode(s) -.. method:: array.fromunicode(s) + Extends this array with data from the given unicode string. The array must + be a type ``'u'`` array; otherwise a :exc:`ValueError` is raised. Use + ``array.frombytes(unicodestring.encode(enc))`` to append Unicode data to an + array of some other type. - Extends this array with data from the given unicode string. The array must - be a type ``'u'`` array; otherwise a :exc:`ValueError` is raised. Use - ``array.frombytes(unicodestring.encode(enc))`` to append Unicode data to an - array of some other type. + .. method:: index(x[, start[, stop]]) -.. method:: array.index(x[, start[, stop]]) + Return the smallest *i* such that *i* is the index of the first occurrence of + *x* in the array. The optional arguments *start* and *stop* can be + specified to search for *x* within a subsection of the array. Raise + :exc:`ValueError` if *x* is not found. - Return the smallest *i* such that *i* is the index of the first occurrence of - *x* in the array. The optional arguments *start* and *stop* can be - specified to search for *x* within a subsection of the array. Raise - :exc:`ValueError` if *x* is not found. + .. versionchanged:: 3.10 + Added optional *start* and *stop* parameters. - .. versionchanged:: 3.10 - Added optional *start* and *stop* parameters. -.. method:: array.insert(i, x) + .. method:: insert(i, x) - Insert a new item with value *x* in the array before position *i*. Negative - values are treated as being relative to the end of the array. + Insert a new item with value *x* in the array before position *i*. Negative + values are treated as being relative to the end of the array. -.. method:: array.pop([i]) + .. method:: pop([i]) - Removes the item with the index *i* from the array and returns it. The optional - argument defaults to ``-1``, so that by default the last item is removed and - returned. + Removes the item with the index *i* from the array and returns it. The optional + argument defaults to ``-1``, so that by default the last item is removed and + returned. -.. method:: array.remove(x) + .. method:: remove(x) - Remove the first occurrence of *x* from the array. + Remove the first occurrence of *x* from the array. -.. method:: array.reverse() + .. method:: reverse() - Reverse the order of the items in the array. + Reverse the order of the items in the array. -.. method:: array.tobytes() + .. method:: tobytes() - Convert the array to an array of machine values and return the bytes - representation (the same sequence of bytes that would be written to a file by - the :meth:`tofile` method.) + Convert the array to an array of machine values and return the bytes + representation (the same sequence of bytes that would be written to a file by + the :meth:`tofile` method.) - .. versionadded:: 3.2 - :meth:`tostring` is renamed to :meth:`tobytes` for clarity. + .. versionadded:: 3.2 + :meth:`!tostring` is renamed to :meth:`tobytes` for clarity. -.. method:: array.tofile(f) + .. method:: tofile(f) - Write all items (as machine values) to the :term:`file object` *f*. + Write all items (as machine values) to the :term:`file object` *f*. -.. method:: array.tolist() + .. method:: tolist() - Convert the array to an ordinary list with the same items. + Convert the array to an ordinary list with the same items. -.. method:: array.tounicode() + .. method:: tounicode() - Convert the array to a unicode string. The array must be a type ``'u'`` array; - otherwise a :exc:`ValueError` is raised. Use ``array.tobytes().decode(enc)`` to - obtain a unicode string from an array of some other type. + Convert the array to a unicode string. The array must be a type ``'u'`` array; + otherwise a :exc:`ValueError` is raised. Use ``array.tobytes().decode(enc)`` to + obtain a unicode string from an array of some other type. When an array object is printed or converted to a string, it is represented as From 5dcae3f0c3e9072251217e814a9438670e5f1e40 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Thu, 2 Feb 2023 17:14:23 -0800 Subject: [PATCH 25/74] gh-84559: skip the test when no multiprocessing (wasm, etc) (#101530) skip test when no _multiprocessing (wasm, etc) --- Lib/test/test_multiprocessing_defaults.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_multiprocessing_defaults.py b/Lib/test/test_multiprocessing_defaults.py index 1da4c065238384f..7ea872fef20dd96 100644 --- a/Lib/test/test_multiprocessing_defaults.py +++ b/Lib/test/test_multiprocessing_defaults.py @@ -4,10 +4,13 @@ import multiprocessing from multiprocessing.context import DefaultForkDeprecationWarning import sys -from test.support import threading_helper +from test.support import import_helper, threading_helper import unittest import warnings +# Skip tests if _multiprocessing wasn't built. +import_helper.import_module('_multiprocessing') + def do_nothing(): pass From 5c39daf50b7f388f9b24bb2d6ef415955440bebf Mon Sep 17 00:00:00 2001 From: Viet Than Date: Fri, 3 Feb 2023 02:18:39 -0500 Subject: [PATCH 26/74] gh-100920: Update documentation for `asyncio.StreamWriter.wait_closed` (#101514) --- Doc/library/asyncio-stream.rst | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Doc/library/asyncio-stream.rst b/Doc/library/asyncio-stream.rst index 533bdec8e03993b..3b3c68ab6ef6258 100644 --- a/Doc/library/asyncio-stream.rst +++ b/Doc/library/asyncio-stream.rst @@ -295,7 +295,8 @@ StreamWriter The method closes the stream and the underlying socket. - The method should be used along with the ``wait_closed()`` method:: + The method should be used, though not mandatory, + along with the ``wait_closed()`` method:: stream.close() await stream.wait_closed() @@ -372,7 +373,8 @@ StreamWriter Wait until the stream is closed. Should be called after :meth:`close` to wait until the underlying - connection is closed. + connection is closed, ensuring that all data has been flushed + before e.g. exiting the program. .. versionadded:: 3.7 @@ -402,6 +404,7 @@ TCP echo client using the :func:`asyncio.open_connection` function:: print('Close the connection') writer.close() + await writer.wait_closed() asyncio.run(tcp_echo_client('Hello World!')) @@ -434,6 +437,7 @@ TCP echo server using the :func:`asyncio.start_server` function:: print("Close the connection") writer.close() + await writer.wait_closed() async def main(): server = await asyncio.start_server( @@ -490,6 +494,7 @@ Simple example querying HTTP headers of the URL passed on the command line:: # Ignore the body, close the socket writer.close() + await writer.wait_closed() url = sys.argv[1] asyncio.run(print_http_headers(url)) @@ -535,6 +540,7 @@ Coroutine waiting until a socket receives data using the # Got data, we are done: close the socket print("Received:", data.decode()) writer.close() + await writer.wait_closed() # Close the second socket wsock.close() From 45d014e03ba7ba4c9c912120ec36b2aca02061f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Magimel?= Date: Fri, 3 Feb 2023 08:23:11 +0100 Subject: [PATCH 27/74] docs: replace PyPI description with link (#101506) --- Doc/tutorial/venv.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/tutorial/venv.rst b/Doc/tutorial/venv.rst index 1fdb370b33d5af5..05f0e6bbcc1b04f 100644 --- a/Doc/tutorial/venv.rst +++ b/Doc/tutorial/venv.rst @@ -98,8 +98,8 @@ Managing Packages with pip ========================== You can install, upgrade, and remove packages using a program called -:program:`pip`. By default ``pip`` will install packages from the Python -Package Index, . You can browse the Python +:program:`pip`. By default ``pip`` will install packages from the `Python +Package Index `_. You can browse the Python Package Index by going to it in your web browser. ``pip`` has a number of subcommands: "install", "uninstall", From a52cc9853fed39b5cc90b7ffb6a64249307a990b Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 3 Feb 2023 10:54:27 +0100 Subject: [PATCH 28/74] gh-101277: Port more `itertools` static types to heap types (#101303) Add dropwhile, takewhile, starmap, combinations*, and permutations types to module state. --- Modules/clinic/itertoolsmodule.c.h | 10 +- Modules/itertoolsmodule.c | 520 +++++++++++------------------ 2 files changed, 202 insertions(+), 328 deletions(-) diff --git a/Modules/clinic/itertoolsmodule.c.h b/Modules/clinic/itertoolsmodule.c.h index c492c33daea5a26..be44246cc9705a8 100644 --- a/Modules/clinic/itertoolsmodule.c.h +++ b/Modules/clinic/itertoolsmodule.c.h @@ -345,7 +345,7 @@ static PyObject * itertools_cycle(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; - PyTypeObject *base_tp = &cycle_type; + PyTypeObject *base_tp = clinic_state()->cycle_type; PyObject *iterable; if ((type == base_tp || type->tp_init == base_tp->tp_init) && @@ -377,7 +377,7 @@ static PyObject * itertools_dropwhile(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; - PyTypeObject *base_tp = &dropwhile_type; + PyTypeObject *base_tp = clinic_state()->dropwhile_type; PyObject *func; PyObject *seq; @@ -409,7 +409,7 @@ static PyObject * itertools_takewhile(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; - PyTypeObject *base_tp = &takewhile_type; + PyTypeObject *base_tp = clinic_state()->takewhile_type; PyObject *func; PyObject *seq; @@ -441,7 +441,7 @@ static PyObject * itertools_starmap(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; - PyTypeObject *base_tp = &starmap_type; + PyTypeObject *base_tp = clinic_state()->starmap_type; PyObject *func; PyObject *seq; @@ -913,4 +913,4 @@ itertools_count(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=c3069caac417e165 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b86fcd99bd32145e input=a9049054013a1b77]*/ diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index a2ee48228b5847a..c9baa47e2c0edd0 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -12,8 +12,15 @@ */ typedef struct { + PyTypeObject *combinations_type; + PyTypeObject *cwr_type; + PyTypeObject *cycle_type; + PyTypeObject *dropwhile_type; PyTypeObject *groupby_type; PyTypeObject *_grouper_type; + PyTypeObject *permutations_type; + PyTypeObject *starmap_type; + PyTypeObject *takewhile_type; } itertools_state; static inline itertools_state * @@ -50,32 +57,25 @@ class itertools._grouper "_grouperobject *" "clinic_state()->_grouper_type" class itertools.teedataobject "teedataobject *" "&teedataobject_type" class itertools._tee "teeobject *" "&tee_type" class itertools.batched "batchedobject *" "&batched_type" -class itertools.cycle "cycleobject *" "&cycle_type" -class itertools.dropwhile "dropwhileobject *" "&dropwhile_type" -class itertools.takewhile "takewhileobject *" "&takewhile_type" -class itertools.starmap "starmapobject *" "&starmap_type" +class itertools.cycle "cycleobject *" "clinic_state()->cycle_type" +class itertools.dropwhile "dropwhileobject *" "clinic_state()->dropwhile_type" +class itertools.takewhile "takewhileobject *" "clinic_state()->takewhile_type" +class itertools.starmap "starmapobject *" "clinic_state()->starmap_type" class itertools.chain "chainobject *" "&chain_type" -class itertools.combinations "combinationsobject *" "&combinations_type" -class itertools.combinations_with_replacement "cwr_object *" "&cwr_type" -class itertools.permutations "permutationsobject *" "&permutations_type" +class itertools.combinations "combinationsobject *" "clinic_state()->combinations_type" +class itertools.combinations_with_replacement "cwr_object *" "clinic_state()->cwr_type" +class itertools.permutations "permutationsobject *" "clinic_state()->permutations_type" class itertools.accumulate "accumulateobject *" "&accumulate_type" class itertools.compress "compressobject *" "&compress_type" class itertools.filterfalse "filterfalseobject *" "&filterfalse_type" class itertools.count "countobject *" "&count_type" class itertools.pairwise "pairwiseobject *" "&pairwise_type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=424108522584b55b]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=1790ac655869a651]*/ static PyTypeObject teedataobject_type; static PyTypeObject tee_type; static PyTypeObject batched_type; -static PyTypeObject cycle_type; -static PyTypeObject dropwhile_type; -static PyTypeObject takewhile_type; -static PyTypeObject starmap_type; -static PyTypeObject combinations_type; -static PyTypeObject cwr_type; -static PyTypeObject permutations_type; static PyTypeObject accumulate_type; static PyTypeObject compress_type; static PyTypeObject filterfalse_type; @@ -1286,15 +1286,18 @@ itertools_cycle_impl(PyTypeObject *type, PyObject *iterable) static void cycle_dealloc(cycleobject *lz) { + PyTypeObject *tp = Py_TYPE(lz); PyObject_GC_UnTrack(lz); Py_XDECREF(lz->it); Py_XDECREF(lz->saved); - Py_TYPE(lz)->tp_free(lz); + tp->tp_free(lz); + Py_DECREF(tp); } static int cycle_traverse(cycleobject *lz, visitproc visit, void *arg) { + Py_VISIT(Py_TYPE(lz)); Py_VISIT(lz->it); Py_VISIT(lz->saved); return 0; @@ -1381,48 +1384,25 @@ static PyMethodDef cycle_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject cycle_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.cycle", /* tp_name */ - sizeof(cycleobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)cycle_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - itertools_cycle__doc__, /* tp_doc */ - (traverseproc)cycle_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)cycle_next, /* tp_iternext */ - cycle_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itertools_cycle, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot cycle_slots[] = { + {Py_tp_dealloc, cycle_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)itertools_cycle__doc__}, + {Py_tp_traverse, cycle_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, cycle_next}, + {Py_tp_methods, cycle_methods}, + {Py_tp_new, itertools_cycle}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; + +static PyType_Spec cycle_spec = { + .name = "itertools.cycle", + .basicsize = sizeof(cycleobject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = cycle_slots, }; @@ -1474,15 +1454,18 @@ itertools_dropwhile_impl(PyTypeObject *type, PyObject *func, PyObject *seq) static void dropwhile_dealloc(dropwhileobject *lz) { + PyTypeObject *tp = Py_TYPE(lz); PyObject_GC_UnTrack(lz); Py_XDECREF(lz->func); Py_XDECREF(lz->it); - Py_TYPE(lz)->tp_free(lz); + tp->tp_free(lz); + Py_DECREF(tp); } static int dropwhile_traverse(dropwhileobject *lz, visitproc visit, void *arg) { + Py_VISIT(Py_TYPE(lz)); Py_VISIT(lz->it); Py_VISIT(lz->func); return 0; @@ -1545,48 +1528,25 @@ static PyMethodDef dropwhile_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject dropwhile_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.dropwhile", /* tp_name */ - sizeof(dropwhileobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)dropwhile_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - itertools_dropwhile__doc__, /* tp_doc */ - (traverseproc)dropwhile_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)dropwhile_next, /* tp_iternext */ - dropwhile_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itertools_dropwhile, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot dropwhile_slots[] = { + {Py_tp_dealloc, dropwhile_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)itertools_dropwhile__doc__}, + {Py_tp_traverse, dropwhile_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, dropwhile_next}, + {Py_tp_methods, dropwhile_methods}, + {Py_tp_new, itertools_dropwhile}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; + +static PyType_Spec dropwhile_spec = { + .name = "itertools.dropwhile", + .basicsize = sizeof(dropwhileobject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = dropwhile_slots, }; @@ -1636,15 +1596,18 @@ itertools_takewhile_impl(PyTypeObject *type, PyObject *func, PyObject *seq) static void takewhile_dealloc(takewhileobject *lz) { + PyTypeObject *tp = Py_TYPE(lz); PyObject_GC_UnTrack(lz); Py_XDECREF(lz->func); Py_XDECREF(lz->it); - Py_TYPE(lz)->tp_free(lz); + tp->tp_free(lz); + Py_DECREF(tp); } static int takewhile_traverse(takewhileobject *lz, visitproc visit, void *arg) { + Py_VISIT(Py_TYPE(lz)); Py_VISIT(lz->it); Py_VISIT(lz->func); return 0; @@ -1704,48 +1667,25 @@ static PyMethodDef takewhile_reduce_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject takewhile_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.takewhile", /* tp_name */ - sizeof(takewhileobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)takewhile_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - itertools_takewhile__doc__, /* tp_doc */ - (traverseproc)takewhile_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)takewhile_next, /* tp_iternext */ - takewhile_reduce_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itertools_takewhile, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot takewhile_slots[] = { + {Py_tp_dealloc, takewhile_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)itertools_takewhile__doc__}, + {Py_tp_traverse, takewhile_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, takewhile_next}, + {Py_tp_methods, takewhile_reduce_methods}, + {Py_tp_new, itertools_takewhile}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; + +static PyType_Spec takewhile_spec = { + .name = "itertools.takewhile", + .basicsize = sizeof(takewhileobject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = takewhile_slots, }; @@ -2052,15 +1992,18 @@ itertools_starmap_impl(PyTypeObject *type, PyObject *func, PyObject *seq) static void starmap_dealloc(starmapobject *lz) { + PyTypeObject *tp = Py_TYPE(lz); PyObject_GC_UnTrack(lz); Py_XDECREF(lz->func); Py_XDECREF(lz->it); - Py_TYPE(lz)->tp_free(lz); + tp->tp_free(lz); + Py_DECREF(tp); } static int starmap_traverse(starmapobject *lz, visitproc visit, void *arg) { + Py_VISIT(Py_TYPE(lz)); Py_VISIT(lz->it); Py_VISIT(lz->func); return 0; @@ -2101,48 +2044,25 @@ static PyMethodDef starmap_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject starmap_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.starmap", /* tp_name */ - sizeof(starmapobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)starmap_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - itertools_starmap__doc__, /* tp_doc */ - (traverseproc)starmap_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)starmap_next, /* tp_iternext */ - starmap_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itertools_starmap, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot starmap_slots[] = { + {Py_tp_dealloc, starmap_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)itertools_starmap__doc__}, + {Py_tp_traverse, starmap_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, starmap_next}, + {Py_tp_methods, starmap_methods}, + {Py_tp_new, itertools_starmap}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; + +static PyType_Spec starmap_spec = { + .name = "itertools.starmap", + .basicsize = sizeof(starmapobject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = starmap_slots, }; @@ -2799,12 +2719,14 @@ itertools_combinations_impl(PyTypeObject *type, PyObject *iterable, static void combinations_dealloc(combinationsobject *co) { + PyTypeObject *tp = Py_TYPE(co); PyObject_GC_UnTrack(co); Py_XDECREF(co->pool); Py_XDECREF(co->result); if (co->indices != NULL) PyMem_Free(co->indices); - Py_TYPE(co)->tp_free(co); + tp->tp_free(co); + Py_DECREF(tp); } static PyObject * @@ -2818,6 +2740,7 @@ combinations_sizeof(combinationsobject *co, void *unused) static int combinations_traverse(combinationsobject *co, visitproc visit, void *arg) { + Py_VISIT(Py_TYPE(co)); Py_VISIT(co->pool); Py_VISIT(co->result); return 0; @@ -2988,48 +2911,25 @@ static PyMethodDef combinations_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject combinations_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.combinations", /* tp_name */ - sizeof(combinationsobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)combinations_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - itertools_combinations__doc__, /* tp_doc */ - (traverseproc)combinations_traverse,/* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)combinations_next, /* tp_iternext */ - combinations_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itertools_combinations, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot combinations_slots[] = { + {Py_tp_dealloc, combinations_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)itertools_combinations__doc__}, + {Py_tp_traverse, combinations_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, combinations_next}, + {Py_tp_methods, combinations_methods}, + {Py_tp_new, itertools_combinations}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; + +static PyType_Spec combinations_spec = { + .name = "itertools.combinations", + .basicsize = sizeof(combinationsobject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = combinations_slots, }; @@ -3133,12 +3033,14 @@ itertools_combinations_with_replacement_impl(PyTypeObject *type, static void cwr_dealloc(cwrobject *co) { + PyTypeObject *tp = Py_TYPE(co); PyObject_GC_UnTrack(co); Py_XDECREF(co->pool); Py_XDECREF(co->result); if (co->indices != NULL) PyMem_Free(co->indices); - Py_TYPE(co)->tp_free(co); + tp->tp_free(co); + Py_DECREF(tp); } static PyObject * @@ -3152,6 +3054,7 @@ cwr_sizeof(cwrobject *co, void *unused) static int cwr_traverse(cwrobject *co, visitproc visit, void *arg) { + Py_VISIT(Py_TYPE(co)); Py_VISIT(co->pool); Py_VISIT(co->result); return 0; @@ -3312,48 +3215,25 @@ static PyMethodDef cwr_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject cwr_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.combinations_with_replacement", /* tp_name */ - sizeof(cwrobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)cwr_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - itertools_combinations_with_replacement__doc__, /* tp_doc */ - (traverseproc)cwr_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)cwr_next, /* tp_iternext */ - cwr_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itertools_combinations_with_replacement, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot cwr_slots[] = { + {Py_tp_dealloc, cwr_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)itertools_combinations_with_replacement__doc__}, + {Py_tp_traverse, cwr_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, cwr_next}, + {Py_tp_methods, cwr_methods}, + {Py_tp_new, itertools_combinations_with_replacement}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; + +static PyType_Spec cwr_spec = { + .name = "itertools.combinations_with_replacement", + .basicsize = sizeof(cwrobject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = cwr_slots, }; @@ -3476,12 +3356,14 @@ itertools_permutations_impl(PyTypeObject *type, PyObject *iterable, static void permutations_dealloc(permutationsobject *po) { + PyTypeObject *tp = Py_TYPE(po); PyObject_GC_UnTrack(po); Py_XDECREF(po->pool); Py_XDECREF(po->result); PyMem_Free(po->indices); PyMem_Free(po->cycles); - Py_TYPE(po)->tp_free(po); + tp->tp_free(po); + Py_DECREF(tp); } static PyObject * @@ -3496,6 +3378,7 @@ permutations_sizeof(permutationsobject *po, void *unused) static int permutations_traverse(permutationsobject *po, visitproc visit, void *arg) { + Py_VISIT(Py_TYPE(po)); Py_VISIT(po->pool); Py_VISIT(po->result); return 0; @@ -3701,48 +3584,25 @@ static PyMethodDef permuations_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject permutations_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.permutations", /* tp_name */ - sizeof(permutationsobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)permutations_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - itertools_permutations__doc__, /* tp_doc */ - (traverseproc)permutations_traverse,/* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)permutations_next, /* tp_iternext */ - permuations_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itertools_permutations, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot permutations_slots[] = { + {Py_tp_dealloc, permutations_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)itertools_permutations__doc__}, + {Py_tp_traverse, permutations_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, permutations_next}, + {Py_tp_methods, permuations_methods}, + {Py_tp_new, itertools_permutations}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; + +static PyType_Spec permutations_spec = { + .name = "itertools.permutations", + .basicsize = sizeof(permutationsobject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = permutations_slots, }; @@ -4975,8 +4835,15 @@ static int itertoolsmodule_traverse(PyObject *mod, visitproc visit, void *arg) { itertools_state *state = get_module_state(mod); + Py_VISIT(state->combinations_type); + Py_VISIT(state->cwr_type); + Py_VISIT(state->cycle_type); + Py_VISIT(state->dropwhile_type); Py_VISIT(state->groupby_type); Py_VISIT(state->_grouper_type); + Py_VISIT(state->permutations_type); + Py_VISIT(state->starmap_type); + Py_VISIT(state->takewhile_type); return 0; } @@ -4984,8 +4851,15 @@ static int itertoolsmodule_clear(PyObject *mod) { itertools_state *state = get_module_state(mod); + Py_CLEAR(state->combinations_type); + Py_CLEAR(state->cwr_type); + Py_CLEAR(state->cycle_type); + Py_CLEAR(state->dropwhile_type); Py_CLEAR(state->groupby_type); Py_CLEAR(state->_grouper_type); + Py_CLEAR(state->permutations_type); + Py_CLEAR(state->starmap_type); + Py_CLEAR(state->takewhile_type); return 0; } @@ -5010,26 +4884,26 @@ static int itertoolsmodule_exec(PyObject *mod) { itertools_state *state = get_module_state(mod); + ADD_TYPE(mod, state->combinations_type, &combinations_spec); + ADD_TYPE(mod, state->cwr_type, &cwr_spec); + ADD_TYPE(mod, state->cycle_type, &cycle_spec); + ADD_TYPE(mod, state->dropwhile_type, &dropwhile_spec); ADD_TYPE(mod, state->groupby_type, &groupby_spec); ADD_TYPE(mod, state->_grouper_type, &_grouper_spec); + ADD_TYPE(mod, state->permutations_type, &permutations_spec); + ADD_TYPE(mod, state->starmap_type, &starmap_spec); + ADD_TYPE(mod, state->takewhile_type, &takewhile_spec); PyTypeObject *typelist[] = { &accumulate_type, &batched_type, - &combinations_type, - &cwr_type, - &cycle_type, - &dropwhile_type, - &takewhile_type, &islice_type, - &starmap_type, &chain_type, &compress_type, &filterfalse_type, &count_type, &ziplongest_type, &pairwise_type, - &permutations_type, &product_type, &repeat_type, &tee_type, From 04e06e20ee61f3c0d1d7a827b2feb4ed41bb198d Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Fri, 3 Feb 2023 11:30:21 +0000 Subject: [PATCH 29/74] gh-98831: rewrite SEND, GET_YIELD_FROM_ITER, RETURN_GENERATOR in the instruction definition DSL (#101516) --- Python/bytecodes.c | 35 ++++++++++++++--------------------- Python/generated_cases.c.h | 35 ++++++++++++++++++++--------------- Python/opcode_metadata.h | 12 ++++++------ 3 files changed, 40 insertions(+), 42 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 169a2647866b313..74c53ad1579f6c4 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -663,14 +663,10 @@ dummy_func( PREDICT(LOAD_CONST); } - // error: SEND stack effect depends on jump flag - inst(SEND) { + inst(SEND, (receiver, v -- receiver if (!jump), retval)) { assert(frame != &entry_frame); - assert(STACK_LEVEL() >= 2); - PyObject *v = POP(); - PyObject *receiver = TOP(); + bool jump = false; PySendResult gen_status; - PyObject *retval; if (tstate->c_tracefunc == NULL) { gen_status = PyIter_Send(receiver, v, &retval); } else { @@ -695,21 +691,20 @@ dummy_func( gen_status = PYGEN_NEXT; } } - Py_DECREF(v); if (gen_status == PYGEN_ERROR) { assert(retval == NULL); goto error; } + Py_DECREF(v); if (gen_status == PYGEN_RETURN) { assert(retval != NULL); Py_DECREF(receiver); - SET_TOP(retval); JUMPBY(oparg); + jump = true; } else { assert(gen_status == PYGEN_NEXT); assert(retval != NULL); - PUSH(retval); } } @@ -2043,31 +2038,30 @@ dummy_func( ERROR_IF(iter == NULL, error); } - // stack effect: ( -- ) - inst(GET_YIELD_FROM_ITER) { + inst(GET_YIELD_FROM_ITER, (iterable -- iter)) { /* before: [obj]; after [getiter(obj)] */ - PyObject *iterable = TOP(); - PyObject *iter; if (PyCoro_CheckExact(iterable)) { /* `iterable` is a coroutine */ if (!(frame->f_code->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) { /* and it is used in a 'yield from' expression of a regular generator. */ - Py_DECREF(iterable); - SET_TOP(NULL); _PyErr_SetString(tstate, PyExc_TypeError, "cannot 'yield from' a coroutine object " "in a non-coroutine generator"); goto error; } + iter = iterable; + } + else if (PyGen_CheckExact(iterable)) { + iter = iterable; } - else if (!PyGen_CheckExact(iterable)) { + else { /* `iterable` is not a generator. */ iter = PyObject_GetIter(iterable); - Py_DECREF(iterable); - SET_TOP(iter); - if (iter == NULL) + if (iter == NULL) { goto error; + } + Py_DECREF(iterable); } PREDICT(LOAD_CONST); } @@ -3010,8 +3004,7 @@ dummy_func( PUSH((PyObject *)func); } - // stack effect: ( -- ) - inst(RETURN_GENERATOR) { + inst(RETURN_GENERATOR, (--)) { assert(PyFunction_Check(frame->f_funcobj)); PyFunctionObject *func = (PyFunctionObject *)frame->f_funcobj; PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func); diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 97263866fe91585..6f90d9ca4a59ef0 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -865,12 +865,12 @@ } TARGET(SEND) { + PyObject *v = PEEK(1); + PyObject *receiver = PEEK(2); + PyObject *retval; assert(frame != &entry_frame); - assert(STACK_LEVEL() >= 2); - PyObject *v = POP(); - PyObject *receiver = TOP(); + bool jump = false; PySendResult gen_status; - PyObject *retval; if (tstate->c_tracefunc == NULL) { gen_status = PyIter_Send(receiver, v, &retval); } else { @@ -895,22 +895,24 @@ gen_status = PYGEN_NEXT; } } - Py_DECREF(v); if (gen_status == PYGEN_ERROR) { assert(retval == NULL); goto error; } + Py_DECREF(v); if (gen_status == PYGEN_RETURN) { assert(retval != NULL); Py_DECREF(receiver); - SET_TOP(retval); JUMPBY(oparg); + jump = true; } else { assert(gen_status == PYGEN_NEXT); assert(retval != NULL); - PUSH(retval); } + STACK_SHRINK(1); + STACK_GROW(((!jump) ? 1 : 0)); + POKE(1, retval); DISPATCH(); } @@ -2584,30 +2586,33 @@ } TARGET(GET_YIELD_FROM_ITER) { - /* before: [obj]; after [getiter(obj)] */ - PyObject *iterable = TOP(); + PyObject *iterable = PEEK(1); PyObject *iter; + /* before: [obj]; after [getiter(obj)] */ if (PyCoro_CheckExact(iterable)) { /* `iterable` is a coroutine */ if (!(frame->f_code->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) { /* and it is used in a 'yield from' expression of a regular generator. */ - Py_DECREF(iterable); - SET_TOP(NULL); _PyErr_SetString(tstate, PyExc_TypeError, "cannot 'yield from' a coroutine object " "in a non-coroutine generator"); goto error; } + iter = iterable; } - else if (!PyGen_CheckExact(iterable)) { + else if (PyGen_CheckExact(iterable)) { + iter = iterable; + } + else { /* `iterable` is not a generator. */ iter = PyObject_GetIter(iterable); - Py_DECREF(iterable); - SET_TOP(iter); - if (iter == NULL) + if (iter == NULL) { goto error; + } + Py_DECREF(iterable); } + POKE(1, iter); PREDICT(LOAD_CONST); DISPATCH(); } diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index ca3dde363bfd854..256f81a89fcd368 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -99,7 +99,7 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) { case GET_AWAITABLE: return 1; case SEND: - return -1; + return 2; case YIELD_VALUE: return 1; case POP_EXCEPT: @@ -259,7 +259,7 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) { case GET_ITER: return 1; case GET_YIELD_FROM_ITER: - return -1; + return 1; case FOR_ITER: return -1; case FOR_ITER_LIST: @@ -327,7 +327,7 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) { case MAKE_FUNCTION: return -1; case RETURN_GENERATOR: - return -1; + return 0; case BUILD_SLICE: return -1; case FORMAT_VALUE: @@ -445,7 +445,7 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { case GET_AWAITABLE: return 1; case SEND: - return -1; + return ((!jump) ? 1 : 0) + 1; case YIELD_VALUE: return 1; case POP_EXCEPT: @@ -605,7 +605,7 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { case GET_ITER: return 1; case GET_YIELD_FROM_ITER: - return -1; + return 1; case FOR_ITER: return -1; case FOR_ITER_LIST: @@ -673,7 +673,7 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { case MAKE_FUNCTION: return -1; case RETURN_GENERATOR: - return -1; + return 0; case BUILD_SLICE: return -1; case FORMAT_VALUE: From 433fb3ef08c71b97a0d08e522df56e0afaf3747a Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Fri, 3 Feb 2023 14:40:45 +0000 Subject: [PATCH 30/74] gh-98831: rewrite MAKE_FUNCTION and BUILD_SLICE in the instruction definition DSL (#101529) --- Python/bytecodes.c | 47 +++++++++++++++------------------- Python/generated_cases.c.h | 52 +++++++++++++++++++++----------------- Python/opcode_metadata.h | 8 +++--- 3 files changed, 53 insertions(+), 54 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 74c53ad1579f6c4..8993567ac82206b 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -2972,36 +2972,39 @@ dummy_func( CHECK_EVAL_BREAKER(); } - // error: MAKE_FUNCTION has irregular stack effect - inst(MAKE_FUNCTION) { - PyObject *codeobj = POP(); - PyFunctionObject *func = (PyFunctionObject *) + inst(MAKE_FUNCTION, (defaults if (oparg & 0x01), + kwdefaults if (oparg & 0x02), + annotations if (oparg & 0x04), + closure if (oparg & 0x08), + codeobj -- func)) { + + PyFunctionObject *func_obj = (PyFunctionObject *) PyFunction_New(codeobj, GLOBALS()); Py_DECREF(codeobj); - if (func == NULL) { + if (func_obj == NULL) { goto error; } if (oparg & 0x08) { - assert(PyTuple_CheckExact(TOP())); - func->func_closure = POP(); + assert(PyTuple_CheckExact(closure)); + func_obj->func_closure = closure; } if (oparg & 0x04) { - assert(PyTuple_CheckExact(TOP())); - func->func_annotations = POP(); + assert(PyTuple_CheckExact(annotations)); + func_obj->func_annotations = annotations; } if (oparg & 0x02) { - assert(PyDict_CheckExact(TOP())); - func->func_kwdefaults = POP(); + assert(PyDict_CheckExact(kwdefaults)); + func_obj->func_kwdefaults = kwdefaults; } if (oparg & 0x01) { - assert(PyTuple_CheckExact(TOP())); - func->func_defaults = POP(); + assert(PyTuple_CheckExact(defaults)); + func_obj->func_defaults = defaults; } - func->func_version = ((PyCodeObject *)codeobj)->co_version; - PUSH((PyObject *)func); + func_obj->func_version = ((PyCodeObject *)codeobj)->co_version; + func = (PyObject *)func_obj; } inst(RETURN_GENERATOR, (--)) { @@ -3027,22 +3030,12 @@ dummy_func( goto resume_frame; } - // error: BUILD_SLICE has irregular stack effect - inst(BUILD_SLICE) { - PyObject *start, *stop, *step, *slice; - if (oparg == 3) - step = POP(); - else - step = NULL; - stop = POP(); - start = TOP(); + inst(BUILD_SLICE, (start, stop, step if (oparg == 3) -- slice)) { slice = PySlice_New(start, stop, step); Py_DECREF(start); Py_DECREF(stop); Py_XDECREF(step); - SET_TOP(slice); - if (slice == NULL) - goto error; + ERROR_IF(slice == NULL, error); } // error: FORMAT_VALUE has irregular stack effect diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 6f90d9ca4a59ef0..e524bfcb99d4700 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -3584,34 +3584,42 @@ } TARGET(MAKE_FUNCTION) { - PyObject *codeobj = POP(); - PyFunctionObject *func = (PyFunctionObject *) + PyObject *codeobj = PEEK(1); + PyObject *closure = (oparg & 0x08) ? PEEK(1 + ((oparg & 0x08) ? 1 : 0)) : NULL; + PyObject *annotations = (oparg & 0x04) ? PEEK(1 + ((oparg & 0x08) ? 1 : 0) + ((oparg & 0x04) ? 1 : 0)) : NULL; + PyObject *kwdefaults = (oparg & 0x02) ? PEEK(1 + ((oparg & 0x08) ? 1 : 0) + ((oparg & 0x04) ? 1 : 0) + ((oparg & 0x02) ? 1 : 0)) : NULL; + PyObject *defaults = (oparg & 0x01) ? PEEK(1 + ((oparg & 0x08) ? 1 : 0) + ((oparg & 0x04) ? 1 : 0) + ((oparg & 0x02) ? 1 : 0) + ((oparg & 0x01) ? 1 : 0)) : NULL; + PyObject *func; + + PyFunctionObject *func_obj = (PyFunctionObject *) PyFunction_New(codeobj, GLOBALS()); Py_DECREF(codeobj); - if (func == NULL) { + if (func_obj == NULL) { goto error; } if (oparg & 0x08) { - assert(PyTuple_CheckExact(TOP())); - func->func_closure = POP(); + assert(PyTuple_CheckExact(closure)); + func_obj->func_closure = closure; } if (oparg & 0x04) { - assert(PyTuple_CheckExact(TOP())); - func->func_annotations = POP(); + assert(PyTuple_CheckExact(annotations)); + func_obj->func_annotations = annotations; } if (oparg & 0x02) { - assert(PyDict_CheckExact(TOP())); - func->func_kwdefaults = POP(); + assert(PyDict_CheckExact(kwdefaults)); + func_obj->func_kwdefaults = kwdefaults; } if (oparg & 0x01) { - assert(PyTuple_CheckExact(TOP())); - func->func_defaults = POP(); + assert(PyTuple_CheckExact(defaults)); + func_obj->func_defaults = defaults; } - func->func_version = ((PyCodeObject *)codeobj)->co_version; - PUSH((PyObject *)func); + func_obj->func_version = ((PyCodeObject *)codeobj)->co_version; + func = (PyObject *)func_obj; + STACK_SHRINK(((oparg & 0x01) ? 1 : 0) + ((oparg & 0x02) ? 1 : 0) + ((oparg & 0x04) ? 1 : 0) + ((oparg & 0x08) ? 1 : 0)); + POKE(1, func); DISPATCH(); } @@ -3639,20 +3647,18 @@ } TARGET(BUILD_SLICE) { - PyObject *start, *stop, *step, *slice; - if (oparg == 3) - step = POP(); - else - step = NULL; - stop = POP(); - start = TOP(); + PyObject *step = (oparg == 3) ? PEEK(((oparg == 3) ? 1 : 0)) : NULL; + PyObject *stop = PEEK(1 + ((oparg == 3) ? 1 : 0)); + PyObject *start = PEEK(2 + ((oparg == 3) ? 1 : 0)); + PyObject *slice; slice = PySlice_New(start, stop, step); Py_DECREF(start); Py_DECREF(stop); Py_XDECREF(step); - SET_TOP(slice); - if (slice == NULL) - goto error; + if (slice == NULL) { STACK_SHRINK(((oparg == 3) ? 1 : 0)); goto pop_2_error; } + STACK_SHRINK(((oparg == 3) ? 1 : 0)); + STACK_SHRINK(1); + POKE(1, slice); DISPATCH(); } diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index 256f81a89fcd368..857526c35aa5b65 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -325,11 +325,11 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) { case CALL_FUNCTION_EX: return -1; case MAKE_FUNCTION: - return -1; + return ((oparg & 0x01) ? 1 : 0) + ((oparg & 0x02) ? 1 : 0) + ((oparg & 0x04) ? 1 : 0) + ((oparg & 0x08) ? 1 : 0) + 1; case RETURN_GENERATOR: return 0; case BUILD_SLICE: - return -1; + return ((oparg == 3) ? 1 : 0) + 2; case FORMAT_VALUE: return -1; case COPY: @@ -671,11 +671,11 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { case CALL_FUNCTION_EX: return -1; case MAKE_FUNCTION: - return -1; + return 1; case RETURN_GENERATOR: return 0; case BUILD_SLICE: - return -1; + return 1; case FORMAT_VALUE: return -1; case COPY: From f6c53b80a16f63825479c5ca0f8a5e2829c3f505 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Fri, 3 Feb 2023 18:08:34 +0000 Subject: [PATCH 31/74] gh-101522: Allow overriding Windows dependencies versions and paths using MSBuild properties (GH-101523) --- ...-02-02-23-43-46.gh-issue-101522.lnUDta.rst | 2 + PCbuild/python.props | 37 ++++++++++++------- PCbuild/tcltk.props | 35 ++++++++++-------- 3 files changed, 44 insertions(+), 30 deletions(-) create mode 100644 Misc/NEWS.d/next/Build/2023-02-02-23-43-46.gh-issue-101522.lnUDta.rst diff --git a/Misc/NEWS.d/next/Build/2023-02-02-23-43-46.gh-issue-101522.lnUDta.rst b/Misc/NEWS.d/next/Build/2023-02-02-23-43-46.gh-issue-101522.lnUDta.rst new file mode 100644 index 000000000000000..2e7f9029e9ee546 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2023-02-02-23-43-46.gh-issue-101522.lnUDta.rst @@ -0,0 +1,2 @@ +Allow overriding Windows dependencies versions and paths using MSBuild +properties. diff --git a/PCbuild/python.props b/PCbuild/python.props index 971c1490d9f120b..57360e57baba669 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -56,23 +56,32 @@ ..\\.. ..\\..\\.. + - - $(EXTERNALS_DIR) + + + $(EXTERNALS_DIR) $([System.IO.Path]::GetFullPath(`$(PySourcePath)externals`)) $(ExternalsDir)\ - $(ExternalsDir)sqlite-3.39.4.0\ - $(ExternalsDir)bzip2-1.0.8\ - $(ExternalsDir)xz-5.2.5\ - $(ExternalsDir)libffi-3.4.3\ - $(ExternalsDir)libffi-3.4.3\$(ArchName)\ - $(libffiOutDir)include - $(ExternalsDir)openssl-1.1.1s\ - $(ExternalsDir)openssl-bin-1.1.1s\$(ArchName)\ - $(opensslOutDir)include - $(ExternalsDir)\nasm-2.11.06\ - $(ExternalsDir)\zlib-1.2.13\ - + + + + + + $(ExternalsDir)sqlite-3.39.4.0\ + $(ExternalsDir)bzip2-1.0.8\ + $(ExternalsDir)xz-5.2.5\ + $(ExternalsDir)libffi-3.4.3\ + $(libffiDir)$(ArchName)\ + $(libffiOutDir)include + $(ExternalsDir)openssl-1.1.1s\ + $(ExternalsDir)openssl-bin-1.1.1s\$(ArchName)\ + $(opensslOutDir)include + $(ExternalsDir)\nasm-2.11.06\ + $(ExternalsDir)\zlib-1.2.13\ + + + _d diff --git a/PCbuild/tcltk.props b/PCbuild/tcltk.props index 15c03e20fe21714..9d5189b3b8e93d1 100644 --- a/PCbuild/tcltk.props +++ b/PCbuild/tcltk.props @@ -2,22 +2,25 @@ - 8 - 6 - 13 - 0 - $(TclMajorVersion) - $(TclMinorVersion) - $(TclPatchLevel) - $(TclRevision) - 8 - 4 - 3 - 6 - $(ExternalsDir)tcl-core-$(TclMajorVersion).$(TclMinorVersion).$(TclPatchLevel).$(TclRevision)\ - $(ExternalsDir)tk-$(TkMajorVersion).$(TkMinorVersion).$(TkPatchLevel).$(TkRevision)\ - $(ExternalsDir)tix-$(TixMajorVersion).$(TixMinorVersion).$(TixPatchLevel).$(TixRevision)\ - $(ExternalsDir)tcltk-$(TclMajorVersion).$(TclMinorVersion).$(TclPatchLevel).$(TclRevision)\$(ArchName)\ + 8.6.13.0 + $(TclVersion) + 8.4.3.6 + $([System.Version]::Parse($(TclVersion)).Major) + $([System.Version]::Parse($(TclVersion)).Minor) + $([System.Version]::Parse($(TclVersion)).Build) + $([System.Version]::Parse($(TclVersion)).Revision) + $([System.Version]::Parse($(TkVersion)).Major) + $([System.Version]::Parse($(TkVersion)).Minor) + $([System.Version]::Parse($(TkVersion)).Build) + $([System.Version]::Parse($(TkVersion)).Revision) + $([System.Version]::Parse($(TixVersion)).Major) + $([System.Version]::Parse($(TixVersion)).Minor) + $([System.Version]::Parse($(TixVersion)).Build) + $([System.Version]::Parse($(TixVersion)).Revision) + $(ExternalsDir)tcl-core-$(TclVersion)\ + $(ExternalsDir)tk-$(TkVersion)\ + $(ExternalsDir)tix-$(TixVersion)\ + $(ExternalsDir)tcltk-$(TclVersion)\$(ArchName)\ $(tcltkDir)\bin\tclsh$(TclMajorVersion)$(TclMinorVersion)t.exe $(tcltkDir)\..\win32\bin\tclsh$(TclMajorVersion)$(TclMinorVersion)t.exe From d4c410f0f922683f38c9d435923939d037fbd8c2 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Fri, 3 Feb 2023 15:20:46 -0800 Subject: [PATCH 32/74] gh-84559: Remove the new multiprocessing warning, too disruptive. (#101551) This reverts the core of #100618 while leaving relevant documentation improvements and minor refactorings in place. --- Doc/library/concurrent.futures.rst | 16 ++-- Doc/library/multiprocessing.rst | 11 +-- Doc/whatsnew/3.12.rst | 16 ++-- Lib/concurrent/futures/process.py | 17 ---- Lib/multiprocessing/context.py | 28 +----- Lib/test/_test_multiprocessing.py | 5 +- Lib/test/test_concurrent_futures.py | 19 ----- Lib/test/test_logging.py | 5 +- Lib/test/test_multiprocessing_defaults.py | 85 ------------------- Lib/test/test_re.py | 3 +- ...3-01-01-01-19-33.gh-issue-84559.zEjsEJ.rst | 11 --- 11 files changed, 27 insertions(+), 189 deletions(-) delete mode 100644 Lib/test/test_multiprocessing_defaults.py delete mode 100644 Misc/NEWS.d/next/Library/2023-01-01-01-19-33.gh-issue-84559.zEjsEJ.rst diff --git a/Doc/library/concurrent.futures.rst b/Doc/library/concurrent.futures.rst index 10cffdaee0bb8c8..c543c849585b7f0 100644 --- a/Doc/library/concurrent.futures.rst +++ b/Doc/library/concurrent.futures.rst @@ -281,18 +281,18 @@ to a :class:`ProcessPoolExecutor` will result in deadlock. Added the *initializer* and *initargs* arguments. + .. note:: + The default :mod:`multiprocessing` start method + (see :ref:`multiprocessing-start-methods`) will change away from + *fork* in Python 3.14. Code that requires *fork* be used for their + :class:`ProcessPoolExecutor` should explicitly specify that by + passing a ``mp_context=multiprocessing.get_context("fork")`` + parameter. + .. versionchanged:: 3.11 The *max_tasks_per_child* argument was added to allow users to control the lifetime of workers in the pool. - .. versionchanged:: 3.12 - The implicit use of the :mod:`multiprocessing` *fork* start method as a - platform default (see :ref:`multiprocessing-start-methods`) now raises a - :exc:`DeprecationWarning`. The default will change in Python 3.14. - Code that requires *fork* should explicitly specify that when creating - their :class:`ProcessPoolExecutor` by passing a - ``mp_context=multiprocessing.get_context('fork')`` parameter. - .. _processpoolexecutor-example: ProcessPoolExecutor Example diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst index c60b229ae2d07ef..0ec47bb956a99e0 100644 --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -126,6 +126,11 @@ to start a process. These *start methods* are Available on POSIX systems. Currently the default on POSIX except macOS. + .. note:: + The default start method will change away from *fork* in Python 3.14. + Code that requires *fork* should explicitly specify that via + :func:`get_context` or :func:`set_start_method`. + *forkserver* When the program starts and selects the *forkserver* start method, a server process is spawned. From then on, whenever a new process @@ -138,11 +143,6 @@ to start a process. These *start methods* are Available on POSIX platforms which support passing file descriptors over Unix pipes such as Linux. -.. versionchanged:: 3.12 - Implicit use of the *fork* start method as the default now raises a - :exc:`DeprecationWarning`. Code that requires it should explicitly - specify *fork* via :func:`get_context` or :func:`set_start_method`. - The default will change away from *fork* in 3.14. .. versionchanged:: 3.8 @@ -1107,6 +1107,7 @@ Miscellaneous launched (before creating a :class:`Pool` or starting a :class:`Process`). Only meaningful when using the ``'forkserver'`` start method. + See :ref:`multiprocessing-start-methods`. .. versionadded:: 3.4 diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index e675fada339a1ee..0c5a70b64574efc 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -440,12 +440,6 @@ Deprecated warning at compile time. This field will be removed in Python 3.14. (Contributed by Ramvikrams and Kumar Aditya in :gh:`101193`. PEP by Ken Jin.) -* Use of the implicit default ``'fork'`` start method for - :mod:`multiprocessing` and :class:`concurrent.futures.ProcessPoolExecutor` - now emits a :exc:`DeprecationWarning` on Linux and other non-macOS POSIX - systems. Avoid this by explicitly specifying a start method. - See :ref:`multiprocessing-start-methods`. - Pending Removal in Python 3.13 ------------------------------ @@ -510,9 +504,13 @@ Pending Removal in Python 3.14 * Testing the truth value of an :class:`xml.etree.ElementTree.Element` is deprecated and will raise an exception in Python 3.14. -* The default :mod:`multiprocessing` start method will change to one of either - ``'forkserver'`` or ``'spawn'`` on all platforms for which ``'fork'`` remains - the default per :gh:`84559`. +* The default :mod:`multiprocessing` start method will change to a safer one on + Linux, BSDs, and other non-macOS POSIX platforms where ``'fork'`` is currently + the default (:gh:`84559`). Adding a runtime warning about this was deemed too + disruptive as the majority of code is not expected to care. Use the + :func:`~multiprocessing.get_context` or + :func:`~multiprocessing.set_start_method` APIs to explicitly specify when + your code *requires* ``'fork'``. See :ref:`multiprocessing-start-methods`. Pending Removal in Future Versions ---------------------------------- diff --git a/Lib/concurrent/futures/process.py b/Lib/concurrent/futures/process.py index 257dd02fbc6cceb..bee162430a6f8e1 100644 --- a/Lib/concurrent/futures/process.py +++ b/Lib/concurrent/futures/process.py @@ -57,7 +57,6 @@ import itertools import sys from traceback import format_exception -import warnings _threads_wakeups = weakref.WeakKeyDictionary() @@ -651,22 +650,6 @@ def __init__(self, max_workers=None, mp_context=None, mp_context = mp.get_context("spawn") else: mp_context = mp.get_context() - if (mp_context.get_start_method() == "fork" and - mp_context == mp.context._default_context._default_context): - warnings.warn( - "The default multiprocessing start method will change " - "away from 'fork' in Python >= 3.14, per GH-84559. " - "ProcessPoolExecutor uses multiprocessing. " - "If your application requires the 'fork' multiprocessing " - "start method, explicitly specify that by passing a " - "mp_context= parameter. " - "The safest start method is 'spawn'.", - category=mp.context.DefaultForkDeprecationWarning, - stacklevel=2, - ) - # Avoid the equivalent warning from multiprocessing itself via - # a non-default fork context. - mp_context = mp.get_context("fork") self._mp_context = mp_context # https://github.com/python/cpython/issues/90622 diff --git a/Lib/multiprocessing/context.py b/Lib/multiprocessing/context.py index 010a920540e844d..de8a264829dff3b 100644 --- a/Lib/multiprocessing/context.py +++ b/Lib/multiprocessing/context.py @@ -23,9 +23,6 @@ class TimeoutError(ProcessError): class AuthenticationError(ProcessError): pass -class DefaultForkDeprecationWarning(DeprecationWarning): - pass - # # Base type for contexts. Bound methods of an instance of this type are included in __all__ of __init__.py # @@ -284,23 +281,6 @@ def _Popen(process_obj): from .popen_fork import Popen return Popen(process_obj) - _warn_package_prefixes = (os.path.dirname(__file__),) - - class _DeprecatedForkProcess(ForkProcess): - @classmethod - def _Popen(cls, process_obj): - import warnings - warnings.warn( - "The default multiprocessing start method will change " - "away from 'fork' in Python >= 3.14, per GH-84559. " - "Use multiprocessing.get_context(X) or .set_start_method(X) to " - "explicitly specify it when your application requires 'fork'. " - "The safest start method is 'spawn'.", - category=DefaultForkDeprecationWarning, - skip_file_prefixes=_warn_package_prefixes, - ) - return super()._Popen(process_obj) - class SpawnProcess(process.BaseProcess): _start_method = 'spawn' @staticmethod @@ -324,9 +304,6 @@ class ForkContext(BaseContext): _name = 'fork' Process = ForkProcess - class _DefaultForkContext(ForkContext): - Process = _DeprecatedForkProcess - class SpawnContext(BaseContext): _name = 'spawn' Process = SpawnProcess @@ -342,16 +319,13 @@ def _check_available(self): 'fork': ForkContext(), 'spawn': SpawnContext(), 'forkserver': ForkServerContext(), - # Remove None and _DefaultForkContext() when changing the default - # in 3.14 for https://github.com/python/cpython/issues/84559. - None: _DefaultForkContext(), } if sys.platform == 'darwin': # bpo-33725: running arbitrary code after fork() is no longer reliable # on macOS since macOS 10.14 (Mojave). Use spawn by default instead. _default_context = DefaultContext(_concrete_contexts['spawn']) else: - _default_context = DefaultContext(_concrete_contexts[None]) + _default_context = DefaultContext(_concrete_contexts['fork']) else: diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index e4a60a4d674607b..9a2db24b4bd597a 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -4098,10 +4098,9 @@ def test_shared_memory_SharedMemoryServer_ignores_sigint(self): def test_shared_memory_SharedMemoryManager_reuses_resource_tracker(self): # bpo-36867: test that a SharedMemoryManager uses the # same resource_tracker process as its parent. - cmd = f'''if 1: + cmd = '''if 1: from multiprocessing.managers import SharedMemoryManager - from multiprocessing import set_start_method - set_start_method({multiprocessing.get_start_method()!r}) + smm = SharedMemoryManager() smm.start() diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py index 4493cd312528d6a..b3520ae3994e034 100644 --- a/Lib/test/test_concurrent_futures.py +++ b/Lib/test/test_concurrent_futures.py @@ -18,7 +18,6 @@ import threading import time import unittest -import warnings import weakref from pickle import PicklingError @@ -572,24 +571,6 @@ def test_shutdown_no_wait(self): assert all([r == abs(v) for r, v in zip(res, range(-5, 5))]) -@unittest.skipIf(mp.get_all_start_methods()[0] != "fork", "non-fork default.") -class ProcessPoolExecutorDefaultForkWarning(unittest.TestCase): - def test_fork_default_warns(self): - with self.assertWarns(mp.context.DefaultForkDeprecationWarning): - with futures.ProcessPoolExecutor(2): - pass - - def test_explicit_fork_does_not_warn(self): - with warnings.catch_warnings(record=True) as ws: - warnings.simplefilter("ignore") - warnings.filterwarnings( - 'always', category=mp.context.DefaultForkDeprecationWarning) - ctx = mp.get_context("fork") # Non-default fork context. - with futures.ProcessPoolExecutor(2, mp_context=ctx): - pass - self.assertEqual(len(ws), 0, msg=[str(x) for x in ws]) - - create_executor_tests(ProcessPoolShutdownTest, executor_mixins=(ProcessPoolForkMixin, ProcessPoolForkserverMixin, diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 8a12d570f26f136..072056d3722106a 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -4759,9 +4759,8 @@ def test_multiprocessing(self): # In other processes, processName is correct when multiprocessing in imported, # but it is (incorrectly) defaulted to 'MainProcess' otherwise (bpo-38762). import multiprocessing - mp = multiprocessing.get_context('spawn') - parent_conn, child_conn = mp.Pipe() - p = mp.Process( + parent_conn, child_conn = multiprocessing.Pipe() + p = multiprocessing.Process( target=self._extract_logrecord_process_name, args=(2, LOG_MULTI_PROCESSING, child_conn,) ) diff --git a/Lib/test/test_multiprocessing_defaults.py b/Lib/test/test_multiprocessing_defaults.py deleted file mode 100644 index 7ea872fef20dd96..000000000000000 --- a/Lib/test/test_multiprocessing_defaults.py +++ /dev/null @@ -1,85 +0,0 @@ -"""Test default behavior of multiprocessing.""" - -from inspect import currentframe, getframeinfo -import multiprocessing -from multiprocessing.context import DefaultForkDeprecationWarning -import sys -from test.support import import_helper, threading_helper -import unittest -import warnings - -# Skip tests if _multiprocessing wasn't built. -import_helper.import_module('_multiprocessing') - - -def do_nothing(): - pass - - -# Process has the same API as Thread so this helper works. -join_process = threading_helper.join_thread - - -class DefaultWarningsTest(unittest.TestCase): - - @unittest.skipIf(sys.platform in ('win32', 'darwin'), - 'The default is not "fork" on Windows or macOS.') - def setUp(self): - self.assertEqual(multiprocessing.get_start_method(), 'fork') - self.assertIsInstance(multiprocessing.get_context(), - multiprocessing.context._DefaultForkContext) - - def test_default_fork_start_method_warning_process(self): - with warnings.catch_warnings(record=True) as ws: - warnings.simplefilter('ignore') - warnings.filterwarnings('always', category=DefaultForkDeprecationWarning) - process = multiprocessing.Process(target=do_nothing) - process.start() # warning should point here. - join_process(process) - self.assertIsInstance(ws[0].message, DefaultForkDeprecationWarning) - self.assertIn(__file__, ws[0].filename) - self.assertEqual(getframeinfo(currentframe()).lineno-4, ws[0].lineno) - self.assertIn("'fork'", str(ws[0].message)) - self.assertIn("get_context", str(ws[0].message)) - self.assertEqual(len(ws), 1, msg=[str(x) for x in ws]) - - def test_default_fork_start_method_warning_pool(self): - with warnings.catch_warnings(record=True) as ws: - warnings.simplefilter('ignore') - warnings.filterwarnings('always', category=DefaultForkDeprecationWarning) - pool = multiprocessing.Pool(1) # warning should point here. - pool.terminate() - pool.join() - self.assertIsInstance(ws[0].message, DefaultForkDeprecationWarning) - self.assertIn(__file__, ws[0].filename) - self.assertEqual(getframeinfo(currentframe()).lineno-5, ws[0].lineno) - self.assertIn("'fork'", str(ws[0].message)) - self.assertIn("get_context", str(ws[0].message)) - self.assertEqual(len(ws), 1, msg=[str(x) for x in ws]) - - def test_default_fork_start_method_warning_manager(self): - with warnings.catch_warnings(record=True) as ws: - warnings.simplefilter('ignore') - warnings.filterwarnings('always', category=DefaultForkDeprecationWarning) - manager = multiprocessing.Manager() # warning should point here. - manager.shutdown() - self.assertIsInstance(ws[0].message, DefaultForkDeprecationWarning) - self.assertIn(__file__, ws[0].filename) - self.assertEqual(getframeinfo(currentframe()).lineno-4, ws[0].lineno) - self.assertIn("'fork'", str(ws[0].message)) - self.assertIn("get_context", str(ws[0].message)) - self.assertEqual(len(ws), 1, msg=[str(x) for x in ws]) - - def test_no_mp_warning_when_using_explicit_fork_context(self): - with warnings.catch_warnings(record=True) as ws: - warnings.simplefilter('ignore') - warnings.filterwarnings('always', category=DefaultForkDeprecationWarning) - fork_mp = multiprocessing.get_context('fork') - pool = fork_mp.Pool(1) - pool.terminate() - pool.join() - self.assertEqual(len(ws), 0, msg=[str(x) for x in ws]) - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index eacb1a7c82a54d6..11628a236ade9a3 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -2431,8 +2431,7 @@ def test_regression_gh94675(self): input_js = '''a(function() { /////////////////////////////////////////////////////////////////// });''' - mp = multiprocessing.get_context('spawn') - p = mp.Process(target=pattern.sub, args=('', input_js)) + p = multiprocessing.Process(target=pattern.sub, args=('', input_js)) p.start() p.join(SHORT_TIMEOUT) try: diff --git a/Misc/NEWS.d/next/Library/2023-01-01-01-19-33.gh-issue-84559.zEjsEJ.rst b/Misc/NEWS.d/next/Library/2023-01-01-01-19-33.gh-issue-84559.zEjsEJ.rst deleted file mode 100644 index 3793e0f1fddb20b..000000000000000 --- a/Misc/NEWS.d/next/Library/2023-01-01-01-19-33.gh-issue-84559.zEjsEJ.rst +++ /dev/null @@ -1,11 +0,0 @@ -The :mod:`multiprocessing` module and -:class:`concurrent.futures.ProcessPoolExecutor` will emit a -:exc:`DeprecationWarning` on Linux and other non-macOS POSIX systems when -the default multiprocessing start method of ``'fork'`` is used implicitly -rather than being explicitly specified through a -:func:`multiprocessing.get_context` context. - -This is in preparation for default start method to change in Python 3.14 to -a default that is safe for multithreaded applications. - -Windows and macOS are unaffected as their default start method is ``spawn``. From c67b00534abfeca83016a00818cf1fd949613d6b Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 3 Feb 2023 18:14:43 -0700 Subject: [PATCH 33/74] gh-101524: Split Up the _xxsubinterpreters Module (gh-101526) This is step 1 in potentially dropping all the "channel"-related code. Channels have already been removed from PEP 554. https://github.com/python/cpython/issues/101524 --- Lib/test/support/interpreters.py | 23 +- Lib/test/test__xxinterpchannels.py | 1541 ++++++++++++ Lib/test/test__xxsubinterpreters.py | 1529 +----------- Lib/test/test_interpreters.py | 5 +- Modules/Setup | 1 + Modules/Setup.stdlib.in | 1 + Modules/_testcapimodule.c | 54 + Modules/_xxinterpchannelsmodule.c | 2325 +++++++++++++++++++ Modules/_xxsubinterpretersmodule.c | 2291 +----------------- PC/config.c | 2 + PCbuild/pythoncore.vcxproj | 1 + PCbuild/pythoncore.vcxproj.filters | 3 + Tools/build/generate_stdlib_module_names.py | 1 + configure | 27 + configure.ac | 2 + 15 files changed, 4058 insertions(+), 3748 deletions(-) create mode 100644 Lib/test/test__xxinterpchannels.py create mode 100644 Modules/_xxinterpchannelsmodule.c diff --git a/Lib/test/support/interpreters.py b/Lib/test/support/interpreters.py index 2935708f9df1a5f..eeff3abe0324e58 100644 --- a/Lib/test/support/interpreters.py +++ b/Lib/test/support/interpreters.py @@ -2,11 +2,12 @@ import time import _xxsubinterpreters as _interpreters +import _xxinterpchannels as _channels # aliases: -from _xxsubinterpreters import ( +from _xxsubinterpreters import is_shareable +from _xxinterpchannels import ( ChannelError, ChannelNotFoundError, ChannelEmptyError, - is_shareable, ) @@ -102,7 +103,7 @@ def create_channel(): The channel may be used to pass data safely between interpreters. """ - cid = _interpreters.channel_create() + cid = _channels.create() recv, send = RecvChannel(cid), SendChannel(cid) return recv, send @@ -110,14 +111,14 @@ def create_channel(): def list_all_channels(): """Return a list of (recv, send) for all open channels.""" return [(RecvChannel(cid), SendChannel(cid)) - for cid in _interpreters.channel_list_all()] + for cid in _channels.list_all()] class _ChannelEnd: """The base class for RecvChannel and SendChannel.""" def __init__(self, id): - if not isinstance(id, (int, _interpreters.ChannelID)): + if not isinstance(id, (int, _channels.ChannelID)): raise TypeError(f'id must be an int, got {id!r}') self._id = id @@ -152,10 +153,10 @@ def recv(self, *, _sentinel=object(), _delay=10 / 1000): # 10 milliseconds This blocks until an object has been sent, if none have been sent already. """ - obj = _interpreters.channel_recv(self._id, _sentinel) + obj = _channels.recv(self._id, _sentinel) while obj is _sentinel: time.sleep(_delay) - obj = _interpreters.channel_recv(self._id, _sentinel) + obj = _channels.recv(self._id, _sentinel) return obj def recv_nowait(self, default=_NOT_SET): @@ -166,9 +167,9 @@ def recv_nowait(self, default=_NOT_SET): is the same as recv(). """ if default is _NOT_SET: - return _interpreters.channel_recv(self._id) + return _channels.recv(self._id) else: - return _interpreters.channel_recv(self._id, default) + return _channels.recv(self._id, default) class SendChannel(_ChannelEnd): @@ -179,7 +180,7 @@ def send(self, obj): This blocks until the object is received. """ - _interpreters.channel_send(self._id, obj) + _channels.send(self._id, obj) # XXX We are missing a low-level channel_send_wait(). # See bpo-32604 and gh-19829. # Until that shows up we fake it: @@ -194,4 +195,4 @@ def send_nowait(self, obj): # XXX Note that at the moment channel_send() only ever returns # None. This should be fixed when channel_send_wait() is added. # See bpo-32604 and gh-19829. - return _interpreters.channel_send(self._id, obj) + return _channels.send(self._id, obj) diff --git a/Lib/test/test__xxinterpchannels.py b/Lib/test/test__xxinterpchannels.py new file mode 100644 index 000000000000000..03bb5c80b8dac92 --- /dev/null +++ b/Lib/test/test__xxinterpchannels.py @@ -0,0 +1,1541 @@ +from collections import namedtuple +import contextlib +import os +import sys +from textwrap import dedent +import threading +import time +import unittest + +from test.support import import_helper + +from test.test__xxsubinterpreters import ( + interpreters, + _run_output, + clean_up_interpreters, +) + + +channels = import_helper.import_module('_xxinterpchannels') + + +################################## +# helpers + +#@contextmanager +#def run_threaded(id, source, **shared): +# def run(): +# run_interp(id, source, **shared) +# t = threading.Thread(target=run) +# t.start() +# yield +# t.join() + + +def run_interp(id, source, **shared): + _run_interp(id, source, shared) + + +def _run_interp(id, source, shared, _mainns={}): + source = dedent(source) + main = interpreters.get_main() + if main == id: + if interpreters.get_current() != main: + raise RuntimeError + # XXX Run a func? + exec(source, _mainns) + else: + interpreters.run_string(id, source, shared) + + +class Interpreter(namedtuple('Interpreter', 'name id')): + + @classmethod + def from_raw(cls, raw): + if isinstance(raw, cls): + return raw + elif isinstance(raw, str): + return cls(raw) + else: + raise NotImplementedError + + def __new__(cls, name=None, id=None): + main = interpreters.get_main() + if id == main: + if not name: + name = 'main' + elif name != 'main': + raise ValueError( + 'name mismatch (expected "main", got "{}")'.format(name)) + id = main + elif id is not None: + if not name: + name = 'interp' + elif name == 'main': + raise ValueError('name mismatch (unexpected "main")') + if not isinstance(id, interpreters.InterpreterID): + id = interpreters.InterpreterID(id) + elif not name or name == 'main': + name = 'main' + id = main + else: + id = interpreters.create() + self = super().__new__(cls, name, id) + return self + + +# XXX expect_channel_closed() is unnecessary once we improve exc propagation. + +@contextlib.contextmanager +def expect_channel_closed(): + try: + yield + except channels.ChannelClosedError: + pass + else: + assert False, 'channel not closed' + + +class ChannelAction(namedtuple('ChannelAction', 'action end interp')): + + def __new__(cls, action, end=None, interp=None): + if not end: + end = 'both' + if not interp: + interp = 'main' + self = super().__new__(cls, action, end, interp) + return self + + def __init__(self, *args, **kwargs): + if self.action == 'use': + if self.end not in ('same', 'opposite', 'send', 'recv'): + raise ValueError(self.end) + elif self.action in ('close', 'force-close'): + if self.end not in ('both', 'same', 'opposite', 'send', 'recv'): + raise ValueError(self.end) + else: + raise ValueError(self.action) + if self.interp not in ('main', 'same', 'other', 'extra'): + raise ValueError(self.interp) + + def resolve_end(self, end): + if self.end == 'same': + return end + elif self.end == 'opposite': + return 'recv' if end == 'send' else 'send' + else: + return self.end + + def resolve_interp(self, interp, other, extra): + if self.interp == 'same': + return interp + elif self.interp == 'other': + if other is None: + raise RuntimeError + return other + elif self.interp == 'extra': + if extra is None: + raise RuntimeError + return extra + elif self.interp == 'main': + if interp.name == 'main': + return interp + elif other and other.name == 'main': + return other + else: + raise RuntimeError + # Per __init__(), there aren't any others. + + +class ChannelState(namedtuple('ChannelState', 'pending closed')): + + def __new__(cls, pending=0, *, closed=False): + self = super().__new__(cls, pending, closed) + return self + + def incr(self): + return type(self)(self.pending + 1, closed=self.closed) + + def decr(self): + return type(self)(self.pending - 1, closed=self.closed) + + def close(self, *, force=True): + if self.closed: + if not force or self.pending == 0: + return self + return type(self)(0 if force else self.pending, closed=True) + + +def run_action(cid, action, end, state, *, hideclosed=True): + if state.closed: + if action == 'use' and end == 'recv' and state.pending: + expectfail = False + else: + expectfail = True + else: + expectfail = False + + try: + result = _run_action(cid, action, end, state) + except channels.ChannelClosedError: + if not hideclosed and not expectfail: + raise + result = state.close() + else: + if expectfail: + raise ... # XXX + return result + + +def _run_action(cid, action, end, state): + if action == 'use': + if end == 'send': + channels.send(cid, b'spam') + return state.incr() + elif end == 'recv': + if not state.pending: + try: + channels.recv(cid) + except channels.ChannelEmptyError: + return state + else: + raise Exception('expected ChannelEmptyError') + else: + channels.recv(cid) + return state.decr() + else: + raise ValueError(end) + elif action == 'close': + kwargs = {} + if end in ('recv', 'send'): + kwargs[end] = True + channels.close(cid, **kwargs) + return state.close() + elif action == 'force-close': + kwargs = { + 'force': True, + } + if end in ('recv', 'send'): + kwargs[end] = True + channels.close(cid, **kwargs) + return state.close(force=True) + else: + raise ValueError(action) + + +def clean_up_channels(): + for cid in channels.list_all(): + try: + channels.destroy(cid) + except channels.ChannelNotFoundError: + pass # already destroyed + + +class TestBase(unittest.TestCase): + + def tearDown(self): + clean_up_channels() + clean_up_interpreters() + + +################################## +# channel tests + +class ChannelIDTests(TestBase): + + def test_default_kwargs(self): + cid = channels._channel_id(10, force=True) + + self.assertEqual(int(cid), 10) + self.assertEqual(cid.end, 'both') + + def test_with_kwargs(self): + cid = channels._channel_id(10, send=True, force=True) + self.assertEqual(cid.end, 'send') + + cid = channels._channel_id(10, send=True, recv=False, force=True) + self.assertEqual(cid.end, 'send') + + cid = channels._channel_id(10, recv=True, force=True) + self.assertEqual(cid.end, 'recv') + + cid = channels._channel_id(10, recv=True, send=False, force=True) + self.assertEqual(cid.end, 'recv') + + cid = channels._channel_id(10, send=True, recv=True, force=True) + self.assertEqual(cid.end, 'both') + + def test_coerce_id(self): + class Int(str): + def __index__(self): + return 10 + + cid = channels._channel_id(Int(), force=True) + self.assertEqual(int(cid), 10) + + def test_bad_id(self): + self.assertRaises(TypeError, channels._channel_id, object()) + self.assertRaises(TypeError, channels._channel_id, 10.0) + self.assertRaises(TypeError, channels._channel_id, '10') + self.assertRaises(TypeError, channels._channel_id, b'10') + self.assertRaises(ValueError, channels._channel_id, -1) + self.assertRaises(OverflowError, channels._channel_id, 2**64) + + def test_bad_kwargs(self): + with self.assertRaises(ValueError): + channels._channel_id(10, send=False, recv=False) + + def test_does_not_exist(self): + cid = channels.create() + with self.assertRaises(channels.ChannelNotFoundError): + channels._channel_id(int(cid) + 1) # unforced + + def test_str(self): + cid = channels._channel_id(10, force=True) + self.assertEqual(str(cid), '10') + + def test_repr(self): + cid = channels._channel_id(10, force=True) + self.assertEqual(repr(cid), 'ChannelID(10)') + + cid = channels._channel_id(10, send=True, force=True) + self.assertEqual(repr(cid), 'ChannelID(10, send=True)') + + cid = channels._channel_id(10, recv=True, force=True) + self.assertEqual(repr(cid), 'ChannelID(10, recv=True)') + + cid = channels._channel_id(10, send=True, recv=True, force=True) + self.assertEqual(repr(cid), 'ChannelID(10)') + + def test_equality(self): + cid1 = channels.create() + cid2 = channels._channel_id(int(cid1)) + cid3 = channels.create() + + self.assertTrue(cid1 == cid1) + self.assertTrue(cid1 == cid2) + self.assertTrue(cid1 == int(cid1)) + self.assertTrue(int(cid1) == cid1) + self.assertTrue(cid1 == float(int(cid1))) + self.assertTrue(float(int(cid1)) == cid1) + self.assertFalse(cid1 == float(int(cid1)) + 0.1) + self.assertFalse(cid1 == str(int(cid1))) + self.assertFalse(cid1 == 2**1000) + self.assertFalse(cid1 == float('inf')) + self.assertFalse(cid1 == 'spam') + self.assertFalse(cid1 == cid3) + + self.assertFalse(cid1 != cid1) + self.assertFalse(cid1 != cid2) + self.assertTrue(cid1 != cid3) + + def test_shareable(self): + chan = channels.create() + + obj = channels.create() + channels.send(chan, obj) + got = channels.recv(chan) + + self.assertEqual(got, obj) + self.assertIs(type(got), type(obj)) + # XXX Check the following in the channel tests? + #self.assertIsNot(got, obj) + + +class ChannelTests(TestBase): + + def test_create_cid(self): + cid = channels.create() + self.assertIsInstance(cid, channels.ChannelID) + + def test_sequential_ids(self): + before = channels.list_all() + id1 = channels.create() + id2 = channels.create() + id3 = channels.create() + after = channels.list_all() + + self.assertEqual(id2, int(id1) + 1) + self.assertEqual(id3, int(id2) + 1) + self.assertEqual(set(after) - set(before), {id1, id2, id3}) + + def test_ids_global(self): + id1 = interpreters.create() + out = _run_output(id1, dedent(""" + import _xxinterpchannels as _channels + cid = _channels.create() + print(cid) + """)) + cid1 = int(out.strip()) + + id2 = interpreters.create() + out = _run_output(id2, dedent(""" + import _xxinterpchannels as _channels + cid = _channels.create() + print(cid) + """)) + cid2 = int(out.strip()) + + self.assertEqual(cid2, int(cid1) + 1) + + def test_channel_list_interpreters_none(self): + """Test listing interpreters for a channel with no associations.""" + # Test for channel with no associated interpreters. + cid = channels.create() + send_interps = channels.list_interpreters(cid, send=True) + recv_interps = channels.list_interpreters(cid, send=False) + self.assertEqual(send_interps, []) + self.assertEqual(recv_interps, []) + + def test_channel_list_interpreters_basic(self): + """Test basic listing channel interpreters.""" + interp0 = interpreters.get_main() + cid = channels.create() + channels.send(cid, "send") + # Test for a channel that has one end associated to an interpreter. + send_interps = channels.list_interpreters(cid, send=True) + recv_interps = channels.list_interpreters(cid, send=False) + self.assertEqual(send_interps, [interp0]) + self.assertEqual(recv_interps, []) + + interp1 = interpreters.create() + _run_output(interp1, dedent(f""" + import _xxinterpchannels as _channels + obj = _channels.recv({cid}) + """)) + # Test for channel that has both ends associated to an interpreter. + send_interps = channels.list_interpreters(cid, send=True) + recv_interps = channels.list_interpreters(cid, send=False) + self.assertEqual(send_interps, [interp0]) + self.assertEqual(recv_interps, [interp1]) + + def test_channel_list_interpreters_multiple(self): + """Test listing interpreters for a channel with many associations.""" + interp0 = interpreters.get_main() + interp1 = interpreters.create() + interp2 = interpreters.create() + interp3 = interpreters.create() + cid = channels.create() + + channels.send(cid, "send") + _run_output(interp1, dedent(f""" + import _xxinterpchannels as _channels + _channels.send({cid}, "send") + """)) + _run_output(interp2, dedent(f""" + import _xxinterpchannels as _channels + obj = _channels.recv({cid}) + """)) + _run_output(interp3, dedent(f""" + import _xxinterpchannels as _channels + obj = _channels.recv({cid}) + """)) + send_interps = channels.list_interpreters(cid, send=True) + recv_interps = channels.list_interpreters(cid, send=False) + self.assertEqual(set(send_interps), {interp0, interp1}) + self.assertEqual(set(recv_interps), {interp2, interp3}) + + def test_channel_list_interpreters_destroyed(self): + """Test listing channel interpreters with a destroyed interpreter.""" + interp0 = interpreters.get_main() + interp1 = interpreters.create() + cid = channels.create() + channels.send(cid, "send") + _run_output(interp1, dedent(f""" + import _xxinterpchannels as _channels + obj = _channels.recv({cid}) + """)) + # Should be one interpreter associated with each end. + send_interps = channels.list_interpreters(cid, send=True) + recv_interps = channels.list_interpreters(cid, send=False) + self.assertEqual(send_interps, [interp0]) + self.assertEqual(recv_interps, [interp1]) + + interpreters.destroy(interp1) + # Destroyed interpreter should not be listed. + send_interps = channels.list_interpreters(cid, send=True) + recv_interps = channels.list_interpreters(cid, send=False) + self.assertEqual(send_interps, [interp0]) + self.assertEqual(recv_interps, []) + + def test_channel_list_interpreters_released(self): + """Test listing channel interpreters with a released channel.""" + # Set up one channel with main interpreter on the send end and two + # subinterpreters on the receive end. + interp0 = interpreters.get_main() + interp1 = interpreters.create() + interp2 = interpreters.create() + cid = channels.create() + channels.send(cid, "data") + _run_output(interp1, dedent(f""" + import _xxinterpchannels as _channels + obj = _channels.recv({cid}) + """)) + channels.send(cid, "data") + _run_output(interp2, dedent(f""" + import _xxinterpchannels as _channels + obj = _channels.recv({cid}) + """)) + # Check the setup. + send_interps = channels.list_interpreters(cid, send=True) + recv_interps = channels.list_interpreters(cid, send=False) + self.assertEqual(len(send_interps), 1) + self.assertEqual(len(recv_interps), 2) + + # Release the main interpreter from the send end. + channels.release(cid, send=True) + # Send end should have no associated interpreters. + send_interps = channels.list_interpreters(cid, send=True) + recv_interps = channels.list_interpreters(cid, send=False) + self.assertEqual(len(send_interps), 0) + self.assertEqual(len(recv_interps), 2) + + # Release one of the subinterpreters from the receive end. + _run_output(interp2, dedent(f""" + import _xxinterpchannels as _channels + _channels.release({cid}) + """)) + # Receive end should have the released interpreter removed. + send_interps = channels.list_interpreters(cid, send=True) + recv_interps = channels.list_interpreters(cid, send=False) + self.assertEqual(len(send_interps), 0) + self.assertEqual(recv_interps, [interp1]) + + def test_channel_list_interpreters_closed(self): + """Test listing channel interpreters with a closed channel.""" + interp0 = interpreters.get_main() + interp1 = interpreters.create() + cid = channels.create() + # Put something in the channel so that it's not empty. + channels.send(cid, "send") + + # Check initial state. + send_interps = channels.list_interpreters(cid, send=True) + recv_interps = channels.list_interpreters(cid, send=False) + self.assertEqual(len(send_interps), 1) + self.assertEqual(len(recv_interps), 0) + + # Force close the channel. + channels.close(cid, force=True) + # Both ends should raise an error. + with self.assertRaises(channels.ChannelClosedError): + channels.list_interpreters(cid, send=True) + with self.assertRaises(channels.ChannelClosedError): + channels.list_interpreters(cid, send=False) + + def test_channel_list_interpreters_closed_send_end(self): + """Test listing channel interpreters with a channel's send end closed.""" + interp0 = interpreters.get_main() + interp1 = interpreters.create() + cid = channels.create() + # Put something in the channel so that it's not empty. + channels.send(cid, "send") + + # Check initial state. + send_interps = channels.list_interpreters(cid, send=True) + recv_interps = channels.list_interpreters(cid, send=False) + self.assertEqual(len(send_interps), 1) + self.assertEqual(len(recv_interps), 0) + + # Close the send end of the channel. + channels.close(cid, send=True) + # Send end should raise an error. + with self.assertRaises(channels.ChannelClosedError): + channels.list_interpreters(cid, send=True) + # Receive end should not be closed (since channel is not empty). + recv_interps = channels.list_interpreters(cid, send=False) + self.assertEqual(len(recv_interps), 0) + + # Close the receive end of the channel from a subinterpreter. + _run_output(interp1, dedent(f""" + import _xxinterpchannels as _channels + _channels.close({cid}, force=True) + """)) + # Both ends should raise an error. + with self.assertRaises(channels.ChannelClosedError): + channels.list_interpreters(cid, send=True) + with self.assertRaises(channels.ChannelClosedError): + channels.list_interpreters(cid, send=False) + + #################### + + def test_send_recv_main(self): + cid = channels.create() + orig = b'spam' + channels.send(cid, orig) + obj = channels.recv(cid) + + self.assertEqual(obj, orig) + self.assertIsNot(obj, orig) + + def test_send_recv_same_interpreter(self): + id1 = interpreters.create() + out = _run_output(id1, dedent(""" + import _xxinterpchannels as _channels + cid = _channels.create() + orig = b'spam' + _channels.send(cid, orig) + obj = _channels.recv(cid) + assert obj is not orig + assert obj == orig + """)) + + def test_send_recv_different_interpreters(self): + cid = channels.create() + id1 = interpreters.create() + out = _run_output(id1, dedent(f""" + import _xxinterpchannels as _channels + _channels.send({cid}, b'spam') + """)) + obj = channels.recv(cid) + + self.assertEqual(obj, b'spam') + + def test_send_recv_different_threads(self): + cid = channels.create() + + def f(): + while True: + try: + obj = channels.recv(cid) + break + except channels.ChannelEmptyError: + time.sleep(0.1) + channels.send(cid, obj) + t = threading.Thread(target=f) + t.start() + + channels.send(cid, b'spam') + t.join() + obj = channels.recv(cid) + + self.assertEqual(obj, b'spam') + + def test_send_recv_different_interpreters_and_threads(self): + cid = channels.create() + id1 = interpreters.create() + out = None + + def f(): + nonlocal out + out = _run_output(id1, dedent(f""" + import time + import _xxinterpchannels as _channels + while True: + try: + obj = _channels.recv({cid}) + break + except _channels.ChannelEmptyError: + time.sleep(0.1) + assert(obj == b'spam') + _channels.send({cid}, b'eggs') + """)) + t = threading.Thread(target=f) + t.start() + + channels.send(cid, b'spam') + t.join() + obj = channels.recv(cid) + + self.assertEqual(obj, b'eggs') + + def test_send_not_found(self): + with self.assertRaises(channels.ChannelNotFoundError): + channels.send(10, b'spam') + + def test_recv_not_found(self): + with self.assertRaises(channels.ChannelNotFoundError): + channels.recv(10) + + def test_recv_empty(self): + cid = channels.create() + with self.assertRaises(channels.ChannelEmptyError): + channels.recv(cid) + + def test_recv_default(self): + default = object() + cid = channels.create() + obj1 = channels.recv(cid, default) + channels.send(cid, None) + channels.send(cid, 1) + channels.send(cid, b'spam') + channels.send(cid, b'eggs') + obj2 = channels.recv(cid, default) + obj3 = channels.recv(cid, default) + obj4 = channels.recv(cid) + obj5 = channels.recv(cid, default) + obj6 = channels.recv(cid, default) + + self.assertIs(obj1, default) + self.assertIs(obj2, None) + self.assertEqual(obj3, 1) + self.assertEqual(obj4, b'spam') + self.assertEqual(obj5, b'eggs') + self.assertIs(obj6, default) + + def test_recv_sending_interp_destroyed(self): + cid = channels.create() + interp = interpreters.create() + interpreters.run_string(interp, dedent(f""" + import _xxinterpchannels as _channels + _channels.send({cid}, b'spam') + """)) + interpreters.destroy(interp) + + with self.assertRaisesRegex(RuntimeError, + 'unrecognized interpreter ID'): + channels.recv(cid) + + def test_allowed_types(self): + cid = channels.create() + objects = [ + None, + 'spam', + b'spam', + 42, + ] + for obj in objects: + with self.subTest(obj): + channels.send(cid, obj) + got = channels.recv(cid) + + self.assertEqual(got, obj) + self.assertIs(type(got), type(obj)) + # XXX Check the following? + #self.assertIsNot(got, obj) + # XXX What about between interpreters? + + def test_run_string_arg_unresolved(self): + cid = channels.create() + interp = interpreters.create() + + out = _run_output(interp, dedent(""" + import _xxinterpchannels as _channels + print(cid.end) + _channels.send(cid, b'spam') + """), + dict(cid=cid.send)) + obj = channels.recv(cid) + + self.assertEqual(obj, b'spam') + self.assertEqual(out.strip(), 'send') + + # XXX For now there is no high-level channel into which the + # sent channel ID can be converted... + # Note: this test caused crashes on some buildbots (bpo-33615). + @unittest.skip('disabled until high-level channels exist') + def test_run_string_arg_resolved(self): + cid = channels.create() + cid = channels._channel_id(cid, _resolve=True) + interp = interpreters.create() + + out = _run_output(interp, dedent(""" + import _xxinterpchannels as _channels + print(chan.id.end) + _channels.send(chan.id, b'spam') + """), + dict(chan=cid.send)) + obj = channels.recv(cid) + + self.assertEqual(obj, b'spam') + self.assertEqual(out.strip(), 'send') + + # close + + def test_close_single_user(self): + cid = channels.create() + channels.send(cid, b'spam') + channels.recv(cid) + channels.close(cid) + + with self.assertRaises(channels.ChannelClosedError): + channels.send(cid, b'eggs') + with self.assertRaises(channels.ChannelClosedError): + channels.recv(cid) + + def test_close_multiple_users(self): + cid = channels.create() + id1 = interpreters.create() + id2 = interpreters.create() + interpreters.run_string(id1, dedent(f""" + import _xxinterpchannels as _channels + _channels.send({cid}, b'spam') + """)) + interpreters.run_string(id2, dedent(f""" + import _xxinterpchannels as _channels + _channels.recv({cid}) + """)) + channels.close(cid) + with self.assertRaises(interpreters.RunFailedError) as cm: + interpreters.run_string(id1, dedent(f""" + _channels.send({cid}, b'spam') + """)) + self.assertIn('ChannelClosedError', str(cm.exception)) + with self.assertRaises(interpreters.RunFailedError) as cm: + interpreters.run_string(id2, dedent(f""" + _channels.send({cid}, b'spam') + """)) + self.assertIn('ChannelClosedError', str(cm.exception)) + + def test_close_multiple_times(self): + cid = channels.create() + channels.send(cid, b'spam') + channels.recv(cid) + channels.close(cid) + + with self.assertRaises(channels.ChannelClosedError): + channels.close(cid) + + def test_close_empty(self): + tests = [ + (False, False), + (True, False), + (False, True), + (True, True), + ] + for send, recv in tests: + with self.subTest((send, recv)): + cid = channels.create() + channels.send(cid, b'spam') + channels.recv(cid) + channels.close(cid, send=send, recv=recv) + + with self.assertRaises(channels.ChannelClosedError): + channels.send(cid, b'eggs') + with self.assertRaises(channels.ChannelClosedError): + channels.recv(cid) + + def test_close_defaults_with_unused_items(self): + cid = channels.create() + channels.send(cid, b'spam') + channels.send(cid, b'ham') + + with self.assertRaises(channels.ChannelNotEmptyError): + channels.close(cid) + channels.recv(cid) + channels.send(cid, b'eggs') + + def test_close_recv_with_unused_items_unforced(self): + cid = channels.create() + channels.send(cid, b'spam') + channels.send(cid, b'ham') + + with self.assertRaises(channels.ChannelNotEmptyError): + channels.close(cid, recv=True) + channels.recv(cid) + channels.send(cid, b'eggs') + channels.recv(cid) + channels.recv(cid) + channels.close(cid, recv=True) + + def test_close_send_with_unused_items_unforced(self): + cid = channels.create() + channels.send(cid, b'spam') + channels.send(cid, b'ham') + channels.close(cid, send=True) + + with self.assertRaises(channels.ChannelClosedError): + channels.send(cid, b'eggs') + channels.recv(cid) + channels.recv(cid) + with self.assertRaises(channels.ChannelClosedError): + channels.recv(cid) + + def test_close_both_with_unused_items_unforced(self): + cid = channels.create() + channels.send(cid, b'spam') + channels.send(cid, b'ham') + + with self.assertRaises(channels.ChannelNotEmptyError): + channels.close(cid, recv=True, send=True) + channels.recv(cid) + channels.send(cid, b'eggs') + channels.recv(cid) + channels.recv(cid) + channels.close(cid, recv=True) + + def test_close_recv_with_unused_items_forced(self): + cid = channels.create() + channels.send(cid, b'spam') + channels.send(cid, b'ham') + channels.close(cid, recv=True, force=True) + + with self.assertRaises(channels.ChannelClosedError): + channels.send(cid, b'eggs') + with self.assertRaises(channels.ChannelClosedError): + channels.recv(cid) + + def test_close_send_with_unused_items_forced(self): + cid = channels.create() + channels.send(cid, b'spam') + channels.send(cid, b'ham') + channels.close(cid, send=True, force=True) + + with self.assertRaises(channels.ChannelClosedError): + channels.send(cid, b'eggs') + with self.assertRaises(channels.ChannelClosedError): + channels.recv(cid) + + def test_close_both_with_unused_items_forced(self): + cid = channels.create() + channels.send(cid, b'spam') + channels.send(cid, b'ham') + channels.close(cid, send=True, recv=True, force=True) + + with self.assertRaises(channels.ChannelClosedError): + channels.send(cid, b'eggs') + with self.assertRaises(channels.ChannelClosedError): + channels.recv(cid) + + def test_close_never_used(self): + cid = channels.create() + channels.close(cid) + + with self.assertRaises(channels.ChannelClosedError): + channels.send(cid, b'spam') + with self.assertRaises(channels.ChannelClosedError): + channels.recv(cid) + + def test_close_by_unassociated_interp(self): + cid = channels.create() + channels.send(cid, b'spam') + interp = interpreters.create() + interpreters.run_string(interp, dedent(f""" + import _xxinterpchannels as _channels + _channels.close({cid}, force=True) + """)) + with self.assertRaises(channels.ChannelClosedError): + channels.recv(cid) + with self.assertRaises(channels.ChannelClosedError): + channels.close(cid) + + def test_close_used_multiple_times_by_single_user(self): + cid = channels.create() + channels.send(cid, b'spam') + channels.send(cid, b'spam') + channels.send(cid, b'spam') + channels.recv(cid) + channels.close(cid, force=True) + + with self.assertRaises(channels.ChannelClosedError): + channels.send(cid, b'eggs') + with self.assertRaises(channels.ChannelClosedError): + channels.recv(cid) + + def test_channel_list_interpreters_invalid_channel(self): + cid = channels.create() + # Test for invalid channel ID. + with self.assertRaises(channels.ChannelNotFoundError): + channels.list_interpreters(1000, send=True) + + channels.close(cid) + # Test for a channel that has been closed. + with self.assertRaises(channels.ChannelClosedError): + channels.list_interpreters(cid, send=True) + + def test_channel_list_interpreters_invalid_args(self): + # Tests for invalid arguments passed to the API. + cid = channels.create() + with self.assertRaises(TypeError): + channels.list_interpreters(cid) + + +class ChannelReleaseTests(TestBase): + + # XXX Add more test coverage a la the tests for close(). + + """ + - main / interp / other + - run in: current thread / new thread / other thread / different threads + - end / opposite + - force / no force + - used / not used (associated / not associated) + - empty / emptied / never emptied / partly emptied + - closed / not closed + - released / not released + - creator (interp) / other + - associated interpreter not running + - associated interpreter destroyed + """ + + """ + use + pre-release + release + after + check + """ + + """ + release in: main, interp1 + creator: same, other (incl. interp2) + + use: None,send,recv,send/recv in None,same,other(incl. interp2),same+other(incl. interp2),all + pre-release: None,send,recv,both in None,same,other(incl. interp2),same+other(incl. interp2),all + pre-release forced: None,send,recv,both in None,same,other(incl. interp2),same+other(incl. interp2),all + + release: same + release forced: same + + use after: None,send,recv,send/recv in None,same,other(incl. interp2),same+other(incl. interp2),all + release after: None,send,recv,send/recv in None,same,other(incl. interp2),same+other(incl. interp2),all + check released: send/recv for same/other(incl. interp2) + check closed: send/recv for same/other(incl. interp2) + """ + + def test_single_user(self): + cid = channels.create() + channels.send(cid, b'spam') + channels.recv(cid) + channels.release(cid, send=True, recv=True) + + with self.assertRaises(channels.ChannelClosedError): + channels.send(cid, b'eggs') + with self.assertRaises(channels.ChannelClosedError): + channels.recv(cid) + + def test_multiple_users(self): + cid = channels.create() + id1 = interpreters.create() + id2 = interpreters.create() + interpreters.run_string(id1, dedent(f""" + import _xxinterpchannels as _channels + _channels.send({cid}, b'spam') + """)) + out = _run_output(id2, dedent(f""" + import _xxinterpchannels as _channels + obj = _channels.recv({cid}) + _channels.release({cid}) + print(repr(obj)) + """)) + interpreters.run_string(id1, dedent(f""" + _channels.release({cid}) + """)) + + self.assertEqual(out.strip(), "b'spam'") + + def test_no_kwargs(self): + cid = channels.create() + channels.send(cid, b'spam') + channels.recv(cid) + channels.release(cid) + + with self.assertRaises(channels.ChannelClosedError): + channels.send(cid, b'eggs') + with self.assertRaises(channels.ChannelClosedError): + channels.recv(cid) + + def test_multiple_times(self): + cid = channels.create() + channels.send(cid, b'spam') + channels.recv(cid) + channels.release(cid, send=True, recv=True) + + with self.assertRaises(channels.ChannelClosedError): + channels.release(cid, send=True, recv=True) + + def test_with_unused_items(self): + cid = channels.create() + channels.send(cid, b'spam') + channels.send(cid, b'ham') + channels.release(cid, send=True, recv=True) + + with self.assertRaises(channels.ChannelClosedError): + channels.recv(cid) + + def test_never_used(self): + cid = channels.create() + channels.release(cid) + + with self.assertRaises(channels.ChannelClosedError): + channels.send(cid, b'spam') + with self.assertRaises(channels.ChannelClosedError): + channels.recv(cid) + + def test_by_unassociated_interp(self): + cid = channels.create() + channels.send(cid, b'spam') + interp = interpreters.create() + interpreters.run_string(interp, dedent(f""" + import _xxinterpchannels as _channels + _channels.release({cid}) + """)) + obj = channels.recv(cid) + channels.release(cid) + + with self.assertRaises(channels.ChannelClosedError): + channels.send(cid, b'eggs') + self.assertEqual(obj, b'spam') + + def test_close_if_unassociated(self): + # XXX Something's not right with this test... + cid = channels.create() + interp = interpreters.create() + interpreters.run_string(interp, dedent(f""" + import _xxinterpchannels as _channels + obj = _channels.send({cid}, b'spam') + _channels.release({cid}) + """)) + + with self.assertRaises(channels.ChannelClosedError): + channels.recv(cid) + + def test_partially(self): + # XXX Is partial close too weird/confusing? + cid = channels.create() + channels.send(cid, None) + channels.recv(cid) + channels.send(cid, b'spam') + channels.release(cid, send=True) + obj = channels.recv(cid) + + self.assertEqual(obj, b'spam') + + def test_used_multiple_times_by_single_user(self): + cid = channels.create() + channels.send(cid, b'spam') + channels.send(cid, b'spam') + channels.send(cid, b'spam') + channels.recv(cid) + channels.release(cid, send=True, recv=True) + + with self.assertRaises(channels.ChannelClosedError): + channels.send(cid, b'eggs') + with self.assertRaises(channels.ChannelClosedError): + channels.recv(cid) + + +class ChannelCloseFixture(namedtuple('ChannelCloseFixture', + 'end interp other extra creator')): + + # Set this to True to avoid creating interpreters, e.g. when + # scanning through test permutations without running them. + QUICK = False + + def __new__(cls, end, interp, other, extra, creator): + assert end in ('send', 'recv') + if cls.QUICK: + known = {} + else: + interp = Interpreter.from_raw(interp) + other = Interpreter.from_raw(other) + extra = Interpreter.from_raw(extra) + known = { + interp.name: interp, + other.name: other, + extra.name: extra, + } + if not creator: + creator = 'same' + self = super().__new__(cls, end, interp, other, extra, creator) + self._prepped = set() + self._state = ChannelState() + self._known = known + return self + + @property + def state(self): + return self._state + + @property + def cid(self): + try: + return self._cid + except AttributeError: + creator = self._get_interpreter(self.creator) + self._cid = self._new_channel(creator) + return self._cid + + def get_interpreter(self, interp): + interp = self._get_interpreter(interp) + self._prep_interpreter(interp) + return interp + + def expect_closed_error(self, end=None): + if end is None: + end = self.end + if end == 'recv' and self.state.closed == 'send': + return False + return bool(self.state.closed) + + def prep_interpreter(self, interp): + self._prep_interpreter(interp) + + def record_action(self, action, result): + self._state = result + + def clean_up(self): + clean_up_interpreters() + clean_up_channels() + + # internal methods + + def _new_channel(self, creator): + if creator.name == 'main': + return channels.create() + else: + ch = channels.create() + run_interp(creator.id, f""" + import _xxsubinterpreters + cid = _xxsubchannels.create() + # We purposefully send back an int to avoid tying the + # channel to the other interpreter. + _xxsubchannels.send({ch}, int(cid)) + del _xxsubinterpreters + """) + self._cid = channels.recv(ch) + return self._cid + + def _get_interpreter(self, interp): + if interp in ('same', 'interp'): + return self.interp + elif interp == 'other': + return self.other + elif interp == 'extra': + return self.extra + else: + name = interp + try: + interp = self._known[name] + except KeyError: + interp = self._known[name] = Interpreter(name) + return interp + + def _prep_interpreter(self, interp): + if interp.id in self._prepped: + return + self._prepped.add(interp.id) + if interp.name == 'main': + return + run_interp(interp.id, f""" + import _xxinterpchannels as channels + import test.test__xxinterpchannels as helpers + ChannelState = helpers.ChannelState + try: + cid + except NameError: + cid = channels._channel_id({self.cid}) + """) + + +@unittest.skip('these tests take several hours to run') +class ExhaustiveChannelTests(TestBase): + + """ + - main / interp / other + - run in: current thread / new thread / other thread / different threads + - end / opposite + - force / no force + - used / not used (associated / not associated) + - empty / emptied / never emptied / partly emptied + - closed / not closed + - released / not released + - creator (interp) / other + - associated interpreter not running + - associated interpreter destroyed + + - close after unbound + """ + + """ + use + pre-close + close + after + check + """ + + """ + close in: main, interp1 + creator: same, other, extra + + use: None,send,recv,send/recv in None,same,other,same+other,all + pre-close: None,send,recv in None,same,other,same+other,all + pre-close forced: None,send,recv in None,same,other,same+other,all + + close: same + close forced: same + + use after: None,send,recv,send/recv in None,same,other,extra,same+other,all + close after: None,send,recv,send/recv in None,same,other,extra,same+other,all + check closed: send/recv for same/other(incl. interp2) + """ + + def iter_action_sets(self): + # - used / not used (associated / not associated) + # - empty / emptied / never emptied / partly emptied + # - closed / not closed + # - released / not released + + # never used + yield [] + + # only pre-closed (and possible used after) + for closeactions in self._iter_close_action_sets('same', 'other'): + yield closeactions + for postactions in self._iter_post_close_action_sets(): + yield closeactions + postactions + for closeactions in self._iter_close_action_sets('other', 'extra'): + yield closeactions + for postactions in self._iter_post_close_action_sets(): + yield closeactions + postactions + + # used + for useactions in self._iter_use_action_sets('same', 'other'): + yield useactions + for closeactions in self._iter_close_action_sets('same', 'other'): + actions = useactions + closeactions + yield actions + for postactions in self._iter_post_close_action_sets(): + yield actions + postactions + for closeactions in self._iter_close_action_sets('other', 'extra'): + actions = useactions + closeactions + yield actions + for postactions in self._iter_post_close_action_sets(): + yield actions + postactions + for useactions in self._iter_use_action_sets('other', 'extra'): + yield useactions + for closeactions in self._iter_close_action_sets('same', 'other'): + actions = useactions + closeactions + yield actions + for postactions in self._iter_post_close_action_sets(): + yield actions + postactions + for closeactions in self._iter_close_action_sets('other', 'extra'): + actions = useactions + closeactions + yield actions + for postactions in self._iter_post_close_action_sets(): + yield actions + postactions + + def _iter_use_action_sets(self, interp1, interp2): + interps = (interp1, interp2) + + # only recv end used + yield [ + ChannelAction('use', 'recv', interp1), + ] + yield [ + ChannelAction('use', 'recv', interp2), + ] + yield [ + ChannelAction('use', 'recv', interp1), + ChannelAction('use', 'recv', interp2), + ] + + # never emptied + yield [ + ChannelAction('use', 'send', interp1), + ] + yield [ + ChannelAction('use', 'send', interp2), + ] + yield [ + ChannelAction('use', 'send', interp1), + ChannelAction('use', 'send', interp2), + ] + + # partially emptied + for interp1 in interps: + for interp2 in interps: + for interp3 in interps: + yield [ + ChannelAction('use', 'send', interp1), + ChannelAction('use', 'send', interp2), + ChannelAction('use', 'recv', interp3), + ] + + # fully emptied + for interp1 in interps: + for interp2 in interps: + for interp3 in interps: + for interp4 in interps: + yield [ + ChannelAction('use', 'send', interp1), + ChannelAction('use', 'send', interp2), + ChannelAction('use', 'recv', interp3), + ChannelAction('use', 'recv', interp4), + ] + + def _iter_close_action_sets(self, interp1, interp2): + ends = ('recv', 'send') + interps = (interp1, interp2) + for force in (True, False): + op = 'force-close' if force else 'close' + for interp in interps: + for end in ends: + yield [ + ChannelAction(op, end, interp), + ] + for recvop in ('close', 'force-close'): + for sendop in ('close', 'force-close'): + for recv in interps: + for send in interps: + yield [ + ChannelAction(recvop, 'recv', recv), + ChannelAction(sendop, 'send', send), + ] + + def _iter_post_close_action_sets(self): + for interp in ('same', 'extra', 'other'): + yield [ + ChannelAction('use', 'recv', interp), + ] + yield [ + ChannelAction('use', 'send', interp), + ] + + def run_actions(self, fix, actions): + for action in actions: + self.run_action(fix, action) + + def run_action(self, fix, action, *, hideclosed=True): + end = action.resolve_end(fix.end) + interp = action.resolve_interp(fix.interp, fix.other, fix.extra) + fix.prep_interpreter(interp) + if interp.name == 'main': + result = run_action( + fix.cid, + action.action, + end, + fix.state, + hideclosed=hideclosed, + ) + fix.record_action(action, result) + else: + _cid = channels.create() + run_interp(interp.id, f""" + result = helpers.run_action( + {fix.cid}, + {repr(action.action)}, + {repr(end)}, + {repr(fix.state)}, + hideclosed={hideclosed}, + ) + channels.send({_cid}, result.pending.to_bytes(1, 'little')) + channels.send({_cid}, b'X' if result.closed else b'') + """) + result = ChannelState( + pending=int.from_bytes(channels.recv(_cid), 'little'), + closed=bool(channels.recv(_cid)), + ) + fix.record_action(action, result) + + def iter_fixtures(self): + # XXX threads? + interpreters = [ + ('main', 'interp', 'extra'), + ('interp', 'main', 'extra'), + ('interp1', 'interp2', 'extra'), + ('interp1', 'interp2', 'main'), + ] + for interp, other, extra in interpreters: + for creator in ('same', 'other', 'creator'): + for end in ('send', 'recv'): + yield ChannelCloseFixture(end, interp, other, extra, creator) + + def _close(self, fix, *, force): + op = 'force-close' if force else 'close' + close = ChannelAction(op, fix.end, 'same') + if not fix.expect_closed_error(): + self.run_action(fix, close, hideclosed=False) + else: + with self.assertRaises(channels.ChannelClosedError): + self.run_action(fix, close, hideclosed=False) + + def _assert_closed_in_interp(self, fix, interp=None): + if interp is None or interp.name == 'main': + with self.assertRaises(channels.ChannelClosedError): + channels.recv(fix.cid) + with self.assertRaises(channels.ChannelClosedError): + channels.send(fix.cid, b'spam') + with self.assertRaises(channels.ChannelClosedError): + channels.close(fix.cid) + with self.assertRaises(channels.ChannelClosedError): + channels.close(fix.cid, force=True) + else: + run_interp(interp.id, f""" + with helpers.expect_channel_closed(): + channels.recv(cid) + """) + run_interp(interp.id, f""" + with helpers.expect_channel_closed(): + channels.send(cid, b'spam') + """) + run_interp(interp.id, f""" + with helpers.expect_channel_closed(): + channels.close(cid) + """) + run_interp(interp.id, f""" + with helpers.expect_channel_closed(): + channels.close(cid, force=True) + """) + + def _assert_closed(self, fix): + self.assertTrue(fix.state.closed) + + for _ in range(fix.state.pending): + channels.recv(fix.cid) + self._assert_closed_in_interp(fix) + + for interp in ('same', 'other'): + interp = fix.get_interpreter(interp) + if interp.name == 'main': + continue + self._assert_closed_in_interp(fix, interp) + + interp = fix.get_interpreter('fresh') + self._assert_closed_in_interp(fix, interp) + + def _iter_close_tests(self, verbose=False): + i = 0 + for actions in self.iter_action_sets(): + print() + for fix in self.iter_fixtures(): + i += 1 + if i > 1000: + return + if verbose: + if (i - 1) % 6 == 0: + print() + print(i, fix, '({} actions)'.format(len(actions))) + else: + if (i - 1) % 6 == 0: + print(' ', end='') + print('.', end=''); sys.stdout.flush() + yield i, fix, actions + if verbose: + print('---') + print() + + # This is useful for scanning through the possible tests. + def _skim_close_tests(self): + ChannelCloseFixture.QUICK = True + for i, fix, actions in self._iter_close_tests(): + pass + + def test_close(self): + for i, fix, actions in self._iter_close_tests(): + with self.subTest('{} {} {}'.format(i, fix, actions)): + fix.prep_interpreter(fix.interp) + self.run_actions(fix, actions) + + self._close(fix, force=False) + + self._assert_closed(fix) + # XXX Things slow down if we have too many interpreters. + fix.clean_up() + + def test_force_close(self): + for i, fix, actions in self._iter_close_tests(): + with self.subTest('{} {} {}'.format(i, fix, actions)): + fix.prep_interpreter(fix.interp) + self.run_actions(fix, actions) + + self._close(fix, force=True) + + self._assert_closed(fix) + # XXX Things slow down if we have too many interpreters. + fix.clean_up() + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test__xxsubinterpreters.py b/Lib/test/test__xxsubinterpreters.py index 18900bb9f7162c8..687fcf3b770522a 100644 --- a/Lib/test/test__xxsubinterpreters.py +++ b/Lib/test/test__xxsubinterpreters.py @@ -9,6 +9,7 @@ import time import unittest +import _testcapi from test import support from test.support import import_helper from test.support import script_helper @@ -73,207 +74,6 @@ def run(): t.join() -#@contextmanager -#def run_threaded(id, source, **shared): -# def run(): -# run_interp(id, source, **shared) -# t = threading.Thread(target=run) -# t.start() -# yield -# t.join() - - -def run_interp(id, source, **shared): - _run_interp(id, source, shared) - - -def _run_interp(id, source, shared, _mainns={}): - source = dedent(source) - main = interpreters.get_main() - if main == id: - if interpreters.get_current() != main: - raise RuntimeError - # XXX Run a func? - exec(source, _mainns) - else: - interpreters.run_string(id, source, shared) - - -class Interpreter(namedtuple('Interpreter', 'name id')): - - @classmethod - def from_raw(cls, raw): - if isinstance(raw, cls): - return raw - elif isinstance(raw, str): - return cls(raw) - else: - raise NotImplementedError - - def __new__(cls, name=None, id=None): - main = interpreters.get_main() - if id == main: - if not name: - name = 'main' - elif name != 'main': - raise ValueError( - 'name mismatch (expected "main", got "{}")'.format(name)) - id = main - elif id is not None: - if not name: - name = 'interp' - elif name == 'main': - raise ValueError('name mismatch (unexpected "main")') - if not isinstance(id, interpreters.InterpreterID): - id = interpreters.InterpreterID(id) - elif not name or name == 'main': - name = 'main' - id = main - else: - id = interpreters.create() - self = super().__new__(cls, name, id) - return self - - -# XXX expect_channel_closed() is unnecessary once we improve exc propagation. - -@contextlib.contextmanager -def expect_channel_closed(): - try: - yield - except interpreters.ChannelClosedError: - pass - else: - assert False, 'channel not closed' - - -class ChannelAction(namedtuple('ChannelAction', 'action end interp')): - - def __new__(cls, action, end=None, interp=None): - if not end: - end = 'both' - if not interp: - interp = 'main' - self = super().__new__(cls, action, end, interp) - return self - - def __init__(self, *args, **kwargs): - if self.action == 'use': - if self.end not in ('same', 'opposite', 'send', 'recv'): - raise ValueError(self.end) - elif self.action in ('close', 'force-close'): - if self.end not in ('both', 'same', 'opposite', 'send', 'recv'): - raise ValueError(self.end) - else: - raise ValueError(self.action) - if self.interp not in ('main', 'same', 'other', 'extra'): - raise ValueError(self.interp) - - def resolve_end(self, end): - if self.end == 'same': - return end - elif self.end == 'opposite': - return 'recv' if end == 'send' else 'send' - else: - return self.end - - def resolve_interp(self, interp, other, extra): - if self.interp == 'same': - return interp - elif self.interp == 'other': - if other is None: - raise RuntimeError - return other - elif self.interp == 'extra': - if extra is None: - raise RuntimeError - return extra - elif self.interp == 'main': - if interp.name == 'main': - return interp - elif other and other.name == 'main': - return other - else: - raise RuntimeError - # Per __init__(), there aren't any others. - - -class ChannelState(namedtuple('ChannelState', 'pending closed')): - - def __new__(cls, pending=0, *, closed=False): - self = super().__new__(cls, pending, closed) - return self - - def incr(self): - return type(self)(self.pending + 1, closed=self.closed) - - def decr(self): - return type(self)(self.pending - 1, closed=self.closed) - - def close(self, *, force=True): - if self.closed: - if not force or self.pending == 0: - return self - return type(self)(0 if force else self.pending, closed=True) - - -def run_action(cid, action, end, state, *, hideclosed=True): - if state.closed: - if action == 'use' and end == 'recv' and state.pending: - expectfail = False - else: - expectfail = True - else: - expectfail = False - - try: - result = _run_action(cid, action, end, state) - except interpreters.ChannelClosedError: - if not hideclosed and not expectfail: - raise - result = state.close() - else: - if expectfail: - raise ... # XXX - return result - - -def _run_action(cid, action, end, state): - if action == 'use': - if end == 'send': - interpreters.channel_send(cid, b'spam') - return state.incr() - elif end == 'recv': - if not state.pending: - try: - interpreters.channel_recv(cid) - except interpreters.ChannelEmptyError: - return state - else: - raise Exception('expected ChannelEmptyError') - else: - interpreters.channel_recv(cid) - return state.decr() - else: - raise ValueError(end) - elif action == 'close': - kwargs = {} - if end in ('recv', 'send'): - kwargs[end] = True - interpreters.channel_close(cid, **kwargs) - return state.close() - elif action == 'force-close': - kwargs = { - 'force': True, - } - if end in ('recv', 'send'): - kwargs[end] = True - interpreters.channel_close(cid, **kwargs) - return state.close(force=True) - else: - raise ValueError(action) - - def clean_up_interpreters(): for id in interpreters.list_all(): if id == 0: # main @@ -284,18 +84,9 @@ def clean_up_interpreters(): pass # already destroyed -def clean_up_channels(): - for cid in interpreters.channel_list_all(): - try: - interpreters.channel_destroy(cid) - except interpreters.ChannelNotFoundError: - pass # already destroyed - - class TestBase(unittest.TestCase): def tearDown(self): - clean_up_channels() clean_up_interpreters() @@ -354,30 +145,20 @@ class SubBytes(bytes): class ShareableTypeTests(unittest.TestCase): - def setUp(self): - super().setUp() - self.cid = interpreters.channel_create() - - def tearDown(self): - interpreters.channel_destroy(self.cid) - super().tearDown() - def _assert_values(self, values): for obj in values: with self.subTest(obj): - interpreters.channel_send(self.cid, obj) - got = interpreters.channel_recv(self.cid) + xid = _testcapi.get_crossinterp_data(obj) + got = _testcapi.restore_crossinterp_data(xid) self.assertEqual(got, obj) self.assertIs(type(got), type(obj)) - # XXX Check the following in the channel tests? - #self.assertIsNot(got, obj) def test_singletons(self): for obj in [None]: with self.subTest(obj): - interpreters.channel_send(self.cid, obj) - got = interpreters.channel_recv(self.cid) + xid = _testcapi.get_crossinterp_data(obj) + got = _testcapi.restore_crossinterp_data(xid) # XXX What about between interpreters? self.assertIs(got, obj) @@ -408,7 +189,7 @@ def test_non_shareable_int(self): for i in ints: with self.subTest(i): with self.assertRaises(OverflowError): - interpreters.channel_send(self.cid, i) + _testcapi.get_crossinterp_data(i) class ModuleTests(TestBase): @@ -555,7 +336,7 @@ def test_bad_id(self): self.assertRaises(OverflowError, interpreters.InterpreterID, 2**64) def test_does_not_exist(self): - id = interpreters.channel_create() + id = interpreters.create() with self.assertRaises(RuntimeError): interpreters.InterpreterID(int(id) + 1) # unforced @@ -864,6 +645,22 @@ def f(): self.assertEqual(out, 'it worked!') + def test_shareable_types(self): + interp = interpreters.create() + objects = [ + None, + 'spam', + b'spam', + 42, + ] + for obj in objects: + with self.subTest(obj): + interpreters.run_string( + interp, + f'assert(obj == {obj!r})', + shared=dict(obj=obj), + ) + def test_os_exec(self): expected = 'spam spam spam spam spam' subinterp = interpreters.create() @@ -1130,1285 +927,5 @@ def f(): self.assertEqual(retcode, 0) -################################## -# channel tests - -class ChannelIDTests(TestBase): - - def test_default_kwargs(self): - cid = interpreters._channel_id(10, force=True) - - self.assertEqual(int(cid), 10) - self.assertEqual(cid.end, 'both') - - def test_with_kwargs(self): - cid = interpreters._channel_id(10, send=True, force=True) - self.assertEqual(cid.end, 'send') - - cid = interpreters._channel_id(10, send=True, recv=False, force=True) - self.assertEqual(cid.end, 'send') - - cid = interpreters._channel_id(10, recv=True, force=True) - self.assertEqual(cid.end, 'recv') - - cid = interpreters._channel_id(10, recv=True, send=False, force=True) - self.assertEqual(cid.end, 'recv') - - cid = interpreters._channel_id(10, send=True, recv=True, force=True) - self.assertEqual(cid.end, 'both') - - def test_coerce_id(self): - class Int(str): - def __index__(self): - return 10 - - cid = interpreters._channel_id(Int(), force=True) - self.assertEqual(int(cid), 10) - - def test_bad_id(self): - self.assertRaises(TypeError, interpreters._channel_id, object()) - self.assertRaises(TypeError, interpreters._channel_id, 10.0) - self.assertRaises(TypeError, interpreters._channel_id, '10') - self.assertRaises(TypeError, interpreters._channel_id, b'10') - self.assertRaises(ValueError, interpreters._channel_id, -1) - self.assertRaises(OverflowError, interpreters._channel_id, 2**64) - - def test_bad_kwargs(self): - with self.assertRaises(ValueError): - interpreters._channel_id(10, send=False, recv=False) - - def test_does_not_exist(self): - cid = interpreters.channel_create() - with self.assertRaises(interpreters.ChannelNotFoundError): - interpreters._channel_id(int(cid) + 1) # unforced - - def test_str(self): - cid = interpreters._channel_id(10, force=True) - self.assertEqual(str(cid), '10') - - def test_repr(self): - cid = interpreters._channel_id(10, force=True) - self.assertEqual(repr(cid), 'ChannelID(10)') - - cid = interpreters._channel_id(10, send=True, force=True) - self.assertEqual(repr(cid), 'ChannelID(10, send=True)') - - cid = interpreters._channel_id(10, recv=True, force=True) - self.assertEqual(repr(cid), 'ChannelID(10, recv=True)') - - cid = interpreters._channel_id(10, send=True, recv=True, force=True) - self.assertEqual(repr(cid), 'ChannelID(10)') - - def test_equality(self): - cid1 = interpreters.channel_create() - cid2 = interpreters._channel_id(int(cid1)) - cid3 = interpreters.channel_create() - - self.assertTrue(cid1 == cid1) - self.assertTrue(cid1 == cid2) - self.assertTrue(cid1 == int(cid1)) - self.assertTrue(int(cid1) == cid1) - self.assertTrue(cid1 == float(int(cid1))) - self.assertTrue(float(int(cid1)) == cid1) - self.assertFalse(cid1 == float(int(cid1)) + 0.1) - self.assertFalse(cid1 == str(int(cid1))) - self.assertFalse(cid1 == 2**1000) - self.assertFalse(cid1 == float('inf')) - self.assertFalse(cid1 == 'spam') - self.assertFalse(cid1 == cid3) - - self.assertFalse(cid1 != cid1) - self.assertFalse(cid1 != cid2) - self.assertTrue(cid1 != cid3) - - def test_shareable(self): - chan = interpreters.channel_create() - - obj = interpreters.channel_create() - interpreters.channel_send(chan, obj) - got = interpreters.channel_recv(chan) - - self.assertEqual(got, obj) - self.assertIs(type(got), type(obj)) - # XXX Check the following in the channel tests? - #self.assertIsNot(got, obj) - - -class ChannelTests(TestBase): - - def test_create_cid(self): - cid = interpreters.channel_create() - self.assertIsInstance(cid, interpreters.ChannelID) - - def test_sequential_ids(self): - before = interpreters.channel_list_all() - id1 = interpreters.channel_create() - id2 = interpreters.channel_create() - id3 = interpreters.channel_create() - after = interpreters.channel_list_all() - - self.assertEqual(id2, int(id1) + 1) - self.assertEqual(id3, int(id2) + 1) - self.assertEqual(set(after) - set(before), {id1, id2, id3}) - - def test_ids_global(self): - id1 = interpreters.create() - out = _run_output(id1, dedent(""" - import _xxsubinterpreters as _interpreters - cid = _interpreters.channel_create() - print(cid) - """)) - cid1 = int(out.strip()) - - id2 = interpreters.create() - out = _run_output(id2, dedent(""" - import _xxsubinterpreters as _interpreters - cid = _interpreters.channel_create() - print(cid) - """)) - cid2 = int(out.strip()) - - self.assertEqual(cid2, int(cid1) + 1) - - def test_channel_list_interpreters_none(self): - """Test listing interpreters for a channel with no associations.""" - # Test for channel with no associated interpreters. - cid = interpreters.channel_create() - send_interps = interpreters.channel_list_interpreters(cid, send=True) - recv_interps = interpreters.channel_list_interpreters(cid, send=False) - self.assertEqual(send_interps, []) - self.assertEqual(recv_interps, []) - - def test_channel_list_interpreters_basic(self): - """Test basic listing channel interpreters.""" - interp0 = interpreters.get_main() - cid = interpreters.channel_create() - interpreters.channel_send(cid, "send") - # Test for a channel that has one end associated to an interpreter. - send_interps = interpreters.channel_list_interpreters(cid, send=True) - recv_interps = interpreters.channel_list_interpreters(cid, send=False) - self.assertEqual(send_interps, [interp0]) - self.assertEqual(recv_interps, []) - - interp1 = interpreters.create() - _run_output(interp1, dedent(f""" - import _xxsubinterpreters as _interpreters - obj = _interpreters.channel_recv({cid}) - """)) - # Test for channel that has both ends associated to an interpreter. - send_interps = interpreters.channel_list_interpreters(cid, send=True) - recv_interps = interpreters.channel_list_interpreters(cid, send=False) - self.assertEqual(send_interps, [interp0]) - self.assertEqual(recv_interps, [interp1]) - - def test_channel_list_interpreters_multiple(self): - """Test listing interpreters for a channel with many associations.""" - interp0 = interpreters.get_main() - interp1 = interpreters.create() - interp2 = interpreters.create() - interp3 = interpreters.create() - cid = interpreters.channel_create() - - interpreters.channel_send(cid, "send") - _run_output(interp1, dedent(f""" - import _xxsubinterpreters as _interpreters - _interpreters.channel_send({cid}, "send") - """)) - _run_output(interp2, dedent(f""" - import _xxsubinterpreters as _interpreters - obj = _interpreters.channel_recv({cid}) - """)) - _run_output(interp3, dedent(f""" - import _xxsubinterpreters as _interpreters - obj = _interpreters.channel_recv({cid}) - """)) - send_interps = interpreters.channel_list_interpreters(cid, send=True) - recv_interps = interpreters.channel_list_interpreters(cid, send=False) - self.assertEqual(set(send_interps), {interp0, interp1}) - self.assertEqual(set(recv_interps), {interp2, interp3}) - - def test_channel_list_interpreters_destroyed(self): - """Test listing channel interpreters with a destroyed interpreter.""" - interp0 = interpreters.get_main() - interp1 = interpreters.create() - cid = interpreters.channel_create() - interpreters.channel_send(cid, "send") - _run_output(interp1, dedent(f""" - import _xxsubinterpreters as _interpreters - obj = _interpreters.channel_recv({cid}) - """)) - # Should be one interpreter associated with each end. - send_interps = interpreters.channel_list_interpreters(cid, send=True) - recv_interps = interpreters.channel_list_interpreters(cid, send=False) - self.assertEqual(send_interps, [interp0]) - self.assertEqual(recv_interps, [interp1]) - - interpreters.destroy(interp1) - # Destroyed interpreter should not be listed. - send_interps = interpreters.channel_list_interpreters(cid, send=True) - recv_interps = interpreters.channel_list_interpreters(cid, send=False) - self.assertEqual(send_interps, [interp0]) - self.assertEqual(recv_interps, []) - - def test_channel_list_interpreters_released(self): - """Test listing channel interpreters with a released channel.""" - # Set up one channel with main interpreter on the send end and two - # subinterpreters on the receive end. - interp0 = interpreters.get_main() - interp1 = interpreters.create() - interp2 = interpreters.create() - cid = interpreters.channel_create() - interpreters.channel_send(cid, "data") - _run_output(interp1, dedent(f""" - import _xxsubinterpreters as _interpreters - obj = _interpreters.channel_recv({cid}) - """)) - interpreters.channel_send(cid, "data") - _run_output(interp2, dedent(f""" - import _xxsubinterpreters as _interpreters - obj = _interpreters.channel_recv({cid}) - """)) - # Check the setup. - send_interps = interpreters.channel_list_interpreters(cid, send=True) - recv_interps = interpreters.channel_list_interpreters(cid, send=False) - self.assertEqual(len(send_interps), 1) - self.assertEqual(len(recv_interps), 2) - - # Release the main interpreter from the send end. - interpreters.channel_release(cid, send=True) - # Send end should have no associated interpreters. - send_interps = interpreters.channel_list_interpreters(cid, send=True) - recv_interps = interpreters.channel_list_interpreters(cid, send=False) - self.assertEqual(len(send_interps), 0) - self.assertEqual(len(recv_interps), 2) - - # Release one of the subinterpreters from the receive end. - _run_output(interp2, dedent(f""" - import _xxsubinterpreters as _interpreters - _interpreters.channel_release({cid}) - """)) - # Receive end should have the released interpreter removed. - send_interps = interpreters.channel_list_interpreters(cid, send=True) - recv_interps = interpreters.channel_list_interpreters(cid, send=False) - self.assertEqual(len(send_interps), 0) - self.assertEqual(recv_interps, [interp1]) - - def test_channel_list_interpreters_closed(self): - """Test listing channel interpreters with a closed channel.""" - interp0 = interpreters.get_main() - interp1 = interpreters.create() - cid = interpreters.channel_create() - # Put something in the channel so that it's not empty. - interpreters.channel_send(cid, "send") - - # Check initial state. - send_interps = interpreters.channel_list_interpreters(cid, send=True) - recv_interps = interpreters.channel_list_interpreters(cid, send=False) - self.assertEqual(len(send_interps), 1) - self.assertEqual(len(recv_interps), 0) - - # Force close the channel. - interpreters.channel_close(cid, force=True) - # Both ends should raise an error. - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_list_interpreters(cid, send=True) - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_list_interpreters(cid, send=False) - - def test_channel_list_interpreters_closed_send_end(self): - """Test listing channel interpreters with a channel's send end closed.""" - interp0 = interpreters.get_main() - interp1 = interpreters.create() - cid = interpreters.channel_create() - # Put something in the channel so that it's not empty. - interpreters.channel_send(cid, "send") - - # Check initial state. - send_interps = interpreters.channel_list_interpreters(cid, send=True) - recv_interps = interpreters.channel_list_interpreters(cid, send=False) - self.assertEqual(len(send_interps), 1) - self.assertEqual(len(recv_interps), 0) - - # Close the send end of the channel. - interpreters.channel_close(cid, send=True) - # Send end should raise an error. - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_list_interpreters(cid, send=True) - # Receive end should not be closed (since channel is not empty). - recv_interps = interpreters.channel_list_interpreters(cid, send=False) - self.assertEqual(len(recv_interps), 0) - - # Close the receive end of the channel from a subinterpreter. - _run_output(interp1, dedent(f""" - import _xxsubinterpreters as _interpreters - _interpreters.channel_close({cid}, force=True) - """)) - # Both ends should raise an error. - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_list_interpreters(cid, send=True) - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_list_interpreters(cid, send=False) - - #################### - - def test_send_recv_main(self): - cid = interpreters.channel_create() - orig = b'spam' - interpreters.channel_send(cid, orig) - obj = interpreters.channel_recv(cid) - - self.assertEqual(obj, orig) - self.assertIsNot(obj, orig) - - def test_send_recv_same_interpreter(self): - id1 = interpreters.create() - out = _run_output(id1, dedent(""" - import _xxsubinterpreters as _interpreters - cid = _interpreters.channel_create() - orig = b'spam' - _interpreters.channel_send(cid, orig) - obj = _interpreters.channel_recv(cid) - assert obj is not orig - assert obj == orig - """)) - - def test_send_recv_different_interpreters(self): - cid = interpreters.channel_create() - id1 = interpreters.create() - out = _run_output(id1, dedent(f""" - import _xxsubinterpreters as _interpreters - _interpreters.channel_send({cid}, b'spam') - """)) - obj = interpreters.channel_recv(cid) - - self.assertEqual(obj, b'spam') - - def test_send_recv_different_threads(self): - cid = interpreters.channel_create() - - def f(): - while True: - try: - obj = interpreters.channel_recv(cid) - break - except interpreters.ChannelEmptyError: - time.sleep(0.1) - interpreters.channel_send(cid, obj) - t = threading.Thread(target=f) - t.start() - - interpreters.channel_send(cid, b'spam') - t.join() - obj = interpreters.channel_recv(cid) - - self.assertEqual(obj, b'spam') - - def test_send_recv_different_interpreters_and_threads(self): - cid = interpreters.channel_create() - id1 = interpreters.create() - out = None - - def f(): - nonlocal out - out = _run_output(id1, dedent(f""" - import time - import _xxsubinterpreters as _interpreters - while True: - try: - obj = _interpreters.channel_recv({cid}) - break - except _interpreters.ChannelEmptyError: - time.sleep(0.1) - assert(obj == b'spam') - _interpreters.channel_send({cid}, b'eggs') - """)) - t = threading.Thread(target=f) - t.start() - - interpreters.channel_send(cid, b'spam') - t.join() - obj = interpreters.channel_recv(cid) - - self.assertEqual(obj, b'eggs') - - def test_send_not_found(self): - with self.assertRaises(interpreters.ChannelNotFoundError): - interpreters.channel_send(10, b'spam') - - def test_recv_not_found(self): - with self.assertRaises(interpreters.ChannelNotFoundError): - interpreters.channel_recv(10) - - def test_recv_empty(self): - cid = interpreters.channel_create() - with self.assertRaises(interpreters.ChannelEmptyError): - interpreters.channel_recv(cid) - - def test_recv_default(self): - default = object() - cid = interpreters.channel_create() - obj1 = interpreters.channel_recv(cid, default) - interpreters.channel_send(cid, None) - interpreters.channel_send(cid, 1) - interpreters.channel_send(cid, b'spam') - interpreters.channel_send(cid, b'eggs') - obj2 = interpreters.channel_recv(cid, default) - obj3 = interpreters.channel_recv(cid, default) - obj4 = interpreters.channel_recv(cid) - obj5 = interpreters.channel_recv(cid, default) - obj6 = interpreters.channel_recv(cid, default) - - self.assertIs(obj1, default) - self.assertIs(obj2, None) - self.assertEqual(obj3, 1) - self.assertEqual(obj4, b'spam') - self.assertEqual(obj5, b'eggs') - self.assertIs(obj6, default) - - def test_recv_sending_interp_destroyed(self): - cid = interpreters.channel_create() - interp = interpreters.create() - interpreters.run_string(interp, dedent(f""" - import _xxsubinterpreters as _interpreters - _interpreters.channel_send({cid}, b'spam') - """)) - interpreters.destroy(interp) - - with self.assertRaisesRegex(RuntimeError, - 'unrecognized interpreter ID'): - interpreters.channel_recv(cid) - - def test_run_string_arg_unresolved(self): - cid = interpreters.channel_create() - interp = interpreters.create() - - out = _run_output(interp, dedent(""" - import _xxsubinterpreters as _interpreters - print(cid.end) - _interpreters.channel_send(cid, b'spam') - """), - dict(cid=cid.send)) - obj = interpreters.channel_recv(cid) - - self.assertEqual(obj, b'spam') - self.assertEqual(out.strip(), 'send') - - # XXX For now there is no high-level channel into which the - # sent channel ID can be converted... - # Note: this test caused crashes on some buildbots (bpo-33615). - @unittest.skip('disabled until high-level channels exist') - def test_run_string_arg_resolved(self): - cid = interpreters.channel_create() - cid = interpreters._channel_id(cid, _resolve=True) - interp = interpreters.create() - - out = _run_output(interp, dedent(""" - import _xxsubinterpreters as _interpreters - print(chan.id.end) - _interpreters.channel_send(chan.id, b'spam') - """), - dict(chan=cid.send)) - obj = interpreters.channel_recv(cid) - - self.assertEqual(obj, b'spam') - self.assertEqual(out.strip(), 'send') - - # close - - def test_close_single_user(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_recv(cid) - interpreters.channel_close(cid) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_send(cid, b'eggs') - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - - def test_close_multiple_users(self): - cid = interpreters.channel_create() - id1 = interpreters.create() - id2 = interpreters.create() - interpreters.run_string(id1, dedent(f""" - import _xxsubinterpreters as _interpreters - _interpreters.channel_send({cid}, b'spam') - """)) - interpreters.run_string(id2, dedent(f""" - import _xxsubinterpreters as _interpreters - _interpreters.channel_recv({cid}) - """)) - interpreters.channel_close(cid) - with self.assertRaises(interpreters.RunFailedError) as cm: - interpreters.run_string(id1, dedent(f""" - _interpreters.channel_send({cid}, b'spam') - """)) - self.assertIn('ChannelClosedError', str(cm.exception)) - with self.assertRaises(interpreters.RunFailedError) as cm: - interpreters.run_string(id2, dedent(f""" - _interpreters.channel_send({cid}, b'spam') - """)) - self.assertIn('ChannelClosedError', str(cm.exception)) - - def test_close_multiple_times(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_recv(cid) - interpreters.channel_close(cid) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_close(cid) - - def test_close_empty(self): - tests = [ - (False, False), - (True, False), - (False, True), - (True, True), - ] - for send, recv in tests: - with self.subTest((send, recv)): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_recv(cid) - interpreters.channel_close(cid, send=send, recv=recv) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_send(cid, b'eggs') - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - - def test_close_defaults_with_unused_items(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_send(cid, b'ham') - - with self.assertRaises(interpreters.ChannelNotEmptyError): - interpreters.channel_close(cid) - interpreters.channel_recv(cid) - interpreters.channel_send(cid, b'eggs') - - def test_close_recv_with_unused_items_unforced(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_send(cid, b'ham') - - with self.assertRaises(interpreters.ChannelNotEmptyError): - interpreters.channel_close(cid, recv=True) - interpreters.channel_recv(cid) - interpreters.channel_send(cid, b'eggs') - interpreters.channel_recv(cid) - interpreters.channel_recv(cid) - interpreters.channel_close(cid, recv=True) - - def test_close_send_with_unused_items_unforced(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_send(cid, b'ham') - interpreters.channel_close(cid, send=True) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_send(cid, b'eggs') - interpreters.channel_recv(cid) - interpreters.channel_recv(cid) - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - - def test_close_both_with_unused_items_unforced(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_send(cid, b'ham') - - with self.assertRaises(interpreters.ChannelNotEmptyError): - interpreters.channel_close(cid, recv=True, send=True) - interpreters.channel_recv(cid) - interpreters.channel_send(cid, b'eggs') - interpreters.channel_recv(cid) - interpreters.channel_recv(cid) - interpreters.channel_close(cid, recv=True) - - def test_close_recv_with_unused_items_forced(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_send(cid, b'ham') - interpreters.channel_close(cid, recv=True, force=True) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_send(cid, b'eggs') - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - - def test_close_send_with_unused_items_forced(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_send(cid, b'ham') - interpreters.channel_close(cid, send=True, force=True) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_send(cid, b'eggs') - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - - def test_close_both_with_unused_items_forced(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_send(cid, b'ham') - interpreters.channel_close(cid, send=True, recv=True, force=True) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_send(cid, b'eggs') - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - - def test_close_never_used(self): - cid = interpreters.channel_create() - interpreters.channel_close(cid) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_send(cid, b'spam') - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - - def test_close_by_unassociated_interp(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interp = interpreters.create() - interpreters.run_string(interp, dedent(f""" - import _xxsubinterpreters as _interpreters - _interpreters.channel_close({cid}, force=True) - """)) - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_close(cid) - - def test_close_used_multiple_times_by_single_user(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_send(cid, b'spam') - interpreters.channel_send(cid, b'spam') - interpreters.channel_recv(cid) - interpreters.channel_close(cid, force=True) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_send(cid, b'eggs') - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - - def test_channel_list_interpreters_invalid_channel(self): - cid = interpreters.channel_create() - # Test for invalid channel ID. - with self.assertRaises(interpreters.ChannelNotFoundError): - interpreters.channel_list_interpreters(1000, send=True) - - interpreters.channel_close(cid) - # Test for a channel that has been closed. - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_list_interpreters(cid, send=True) - - def test_channel_list_interpreters_invalid_args(self): - # Tests for invalid arguments passed to the API. - cid = interpreters.channel_create() - with self.assertRaises(TypeError): - interpreters.channel_list_interpreters(cid) - - -class ChannelReleaseTests(TestBase): - - # XXX Add more test coverage a la the tests for close(). - - """ - - main / interp / other - - run in: current thread / new thread / other thread / different threads - - end / opposite - - force / no force - - used / not used (associated / not associated) - - empty / emptied / never emptied / partly emptied - - closed / not closed - - released / not released - - creator (interp) / other - - associated interpreter not running - - associated interpreter destroyed - """ - - """ - use - pre-release - release - after - check - """ - - """ - release in: main, interp1 - creator: same, other (incl. interp2) - - use: None,send,recv,send/recv in None,same,other(incl. interp2),same+other(incl. interp2),all - pre-release: None,send,recv,both in None,same,other(incl. interp2),same+other(incl. interp2),all - pre-release forced: None,send,recv,both in None,same,other(incl. interp2),same+other(incl. interp2),all - - release: same - release forced: same - - use after: None,send,recv,send/recv in None,same,other(incl. interp2),same+other(incl. interp2),all - release after: None,send,recv,send/recv in None,same,other(incl. interp2),same+other(incl. interp2),all - check released: send/recv for same/other(incl. interp2) - check closed: send/recv for same/other(incl. interp2) - """ - - def test_single_user(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_recv(cid) - interpreters.channel_release(cid, send=True, recv=True) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_send(cid, b'eggs') - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - - def test_multiple_users(self): - cid = interpreters.channel_create() - id1 = interpreters.create() - id2 = interpreters.create() - interpreters.run_string(id1, dedent(f""" - import _xxsubinterpreters as _interpreters - _interpreters.channel_send({cid}, b'spam') - """)) - out = _run_output(id2, dedent(f""" - import _xxsubinterpreters as _interpreters - obj = _interpreters.channel_recv({cid}) - _interpreters.channel_release({cid}) - print(repr(obj)) - """)) - interpreters.run_string(id1, dedent(f""" - _interpreters.channel_release({cid}) - """)) - - self.assertEqual(out.strip(), "b'spam'") - - def test_no_kwargs(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_recv(cid) - interpreters.channel_release(cid) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_send(cid, b'eggs') - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - - def test_multiple_times(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_recv(cid) - interpreters.channel_release(cid, send=True, recv=True) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_release(cid, send=True, recv=True) - - def test_with_unused_items(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_send(cid, b'ham') - interpreters.channel_release(cid, send=True, recv=True) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - - def test_never_used(self): - cid = interpreters.channel_create() - interpreters.channel_release(cid) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_send(cid, b'spam') - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - - def test_by_unassociated_interp(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interp = interpreters.create() - interpreters.run_string(interp, dedent(f""" - import _xxsubinterpreters as _interpreters - _interpreters.channel_release({cid}) - """)) - obj = interpreters.channel_recv(cid) - interpreters.channel_release(cid) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_send(cid, b'eggs') - self.assertEqual(obj, b'spam') - - def test_close_if_unassociated(self): - # XXX Something's not right with this test... - cid = interpreters.channel_create() - interp = interpreters.create() - interpreters.run_string(interp, dedent(f""" - import _xxsubinterpreters as _interpreters - obj = _interpreters.channel_send({cid}, b'spam') - _interpreters.channel_release({cid}) - """)) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - - def test_partially(self): - # XXX Is partial close too weird/confusing? - cid = interpreters.channel_create() - interpreters.channel_send(cid, None) - interpreters.channel_recv(cid) - interpreters.channel_send(cid, b'spam') - interpreters.channel_release(cid, send=True) - obj = interpreters.channel_recv(cid) - - self.assertEqual(obj, b'spam') - - def test_used_multiple_times_by_single_user(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_send(cid, b'spam') - interpreters.channel_send(cid, b'spam') - interpreters.channel_recv(cid) - interpreters.channel_release(cid, send=True, recv=True) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_send(cid, b'eggs') - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - - -class ChannelCloseFixture(namedtuple('ChannelCloseFixture', - 'end interp other extra creator')): - - # Set this to True to avoid creating interpreters, e.g. when - # scanning through test permutations without running them. - QUICK = False - - def __new__(cls, end, interp, other, extra, creator): - assert end in ('send', 'recv') - if cls.QUICK: - known = {} - else: - interp = Interpreter.from_raw(interp) - other = Interpreter.from_raw(other) - extra = Interpreter.from_raw(extra) - known = { - interp.name: interp, - other.name: other, - extra.name: extra, - } - if not creator: - creator = 'same' - self = super().__new__(cls, end, interp, other, extra, creator) - self._prepped = set() - self._state = ChannelState() - self._known = known - return self - - @property - def state(self): - return self._state - - @property - def cid(self): - try: - return self._cid - except AttributeError: - creator = self._get_interpreter(self.creator) - self._cid = self._new_channel(creator) - return self._cid - - def get_interpreter(self, interp): - interp = self._get_interpreter(interp) - self._prep_interpreter(interp) - return interp - - def expect_closed_error(self, end=None): - if end is None: - end = self.end - if end == 'recv' and self.state.closed == 'send': - return False - return bool(self.state.closed) - - def prep_interpreter(self, interp): - self._prep_interpreter(interp) - - def record_action(self, action, result): - self._state = result - - def clean_up(self): - clean_up_interpreters() - clean_up_channels() - - # internal methods - - def _new_channel(self, creator): - if creator.name == 'main': - return interpreters.channel_create() - else: - ch = interpreters.channel_create() - run_interp(creator.id, f""" - import _xxsubinterpreters - cid = _xxsubinterpreters.channel_create() - # We purposefully send back an int to avoid tying the - # channel to the other interpreter. - _xxsubinterpreters.channel_send({ch}, int(cid)) - del _xxsubinterpreters - """) - self._cid = interpreters.channel_recv(ch) - return self._cid - - def _get_interpreter(self, interp): - if interp in ('same', 'interp'): - return self.interp - elif interp == 'other': - return self.other - elif interp == 'extra': - return self.extra - else: - name = interp - try: - interp = self._known[name] - except KeyError: - interp = self._known[name] = Interpreter(name) - return interp - - def _prep_interpreter(self, interp): - if interp.id in self._prepped: - return - self._prepped.add(interp.id) - if interp.name == 'main': - return - run_interp(interp.id, f""" - import _xxsubinterpreters as interpreters - import test.test__xxsubinterpreters as helpers - ChannelState = helpers.ChannelState - try: - cid - except NameError: - cid = interpreters._channel_id({self.cid}) - """) - - -@unittest.skip('these tests take several hours to run') -class ExhaustiveChannelTests(TestBase): - - """ - - main / interp / other - - run in: current thread / new thread / other thread / different threads - - end / opposite - - force / no force - - used / not used (associated / not associated) - - empty / emptied / never emptied / partly emptied - - closed / not closed - - released / not released - - creator (interp) / other - - associated interpreter not running - - associated interpreter destroyed - - - close after unbound - """ - - """ - use - pre-close - close - after - check - """ - - """ - close in: main, interp1 - creator: same, other, extra - - use: None,send,recv,send/recv in None,same,other,same+other,all - pre-close: None,send,recv in None,same,other,same+other,all - pre-close forced: None,send,recv in None,same,other,same+other,all - - close: same - close forced: same - - use after: None,send,recv,send/recv in None,same,other,extra,same+other,all - close after: None,send,recv,send/recv in None,same,other,extra,same+other,all - check closed: send/recv for same/other(incl. interp2) - """ - - def iter_action_sets(self): - # - used / not used (associated / not associated) - # - empty / emptied / never emptied / partly emptied - # - closed / not closed - # - released / not released - - # never used - yield [] - - # only pre-closed (and possible used after) - for closeactions in self._iter_close_action_sets('same', 'other'): - yield closeactions - for postactions in self._iter_post_close_action_sets(): - yield closeactions + postactions - for closeactions in self._iter_close_action_sets('other', 'extra'): - yield closeactions - for postactions in self._iter_post_close_action_sets(): - yield closeactions + postactions - - # used - for useactions in self._iter_use_action_sets('same', 'other'): - yield useactions - for closeactions in self._iter_close_action_sets('same', 'other'): - actions = useactions + closeactions - yield actions - for postactions in self._iter_post_close_action_sets(): - yield actions + postactions - for closeactions in self._iter_close_action_sets('other', 'extra'): - actions = useactions + closeactions - yield actions - for postactions in self._iter_post_close_action_sets(): - yield actions + postactions - for useactions in self._iter_use_action_sets('other', 'extra'): - yield useactions - for closeactions in self._iter_close_action_sets('same', 'other'): - actions = useactions + closeactions - yield actions - for postactions in self._iter_post_close_action_sets(): - yield actions + postactions - for closeactions in self._iter_close_action_sets('other', 'extra'): - actions = useactions + closeactions - yield actions - for postactions in self._iter_post_close_action_sets(): - yield actions + postactions - - def _iter_use_action_sets(self, interp1, interp2): - interps = (interp1, interp2) - - # only recv end used - yield [ - ChannelAction('use', 'recv', interp1), - ] - yield [ - ChannelAction('use', 'recv', interp2), - ] - yield [ - ChannelAction('use', 'recv', interp1), - ChannelAction('use', 'recv', interp2), - ] - - # never emptied - yield [ - ChannelAction('use', 'send', interp1), - ] - yield [ - ChannelAction('use', 'send', interp2), - ] - yield [ - ChannelAction('use', 'send', interp1), - ChannelAction('use', 'send', interp2), - ] - - # partially emptied - for interp1 in interps: - for interp2 in interps: - for interp3 in interps: - yield [ - ChannelAction('use', 'send', interp1), - ChannelAction('use', 'send', interp2), - ChannelAction('use', 'recv', interp3), - ] - - # fully emptied - for interp1 in interps: - for interp2 in interps: - for interp3 in interps: - for interp4 in interps: - yield [ - ChannelAction('use', 'send', interp1), - ChannelAction('use', 'send', interp2), - ChannelAction('use', 'recv', interp3), - ChannelAction('use', 'recv', interp4), - ] - - def _iter_close_action_sets(self, interp1, interp2): - ends = ('recv', 'send') - interps = (interp1, interp2) - for force in (True, False): - op = 'force-close' if force else 'close' - for interp in interps: - for end in ends: - yield [ - ChannelAction(op, end, interp), - ] - for recvop in ('close', 'force-close'): - for sendop in ('close', 'force-close'): - for recv in interps: - for send in interps: - yield [ - ChannelAction(recvop, 'recv', recv), - ChannelAction(sendop, 'send', send), - ] - - def _iter_post_close_action_sets(self): - for interp in ('same', 'extra', 'other'): - yield [ - ChannelAction('use', 'recv', interp), - ] - yield [ - ChannelAction('use', 'send', interp), - ] - - def run_actions(self, fix, actions): - for action in actions: - self.run_action(fix, action) - - def run_action(self, fix, action, *, hideclosed=True): - end = action.resolve_end(fix.end) - interp = action.resolve_interp(fix.interp, fix.other, fix.extra) - fix.prep_interpreter(interp) - if interp.name == 'main': - result = run_action( - fix.cid, - action.action, - end, - fix.state, - hideclosed=hideclosed, - ) - fix.record_action(action, result) - else: - _cid = interpreters.channel_create() - run_interp(interp.id, f""" - result = helpers.run_action( - {fix.cid}, - {repr(action.action)}, - {repr(end)}, - {repr(fix.state)}, - hideclosed={hideclosed}, - ) - interpreters.channel_send({_cid}, result.pending.to_bytes(1, 'little')) - interpreters.channel_send({_cid}, b'X' if result.closed else b'') - """) - result = ChannelState( - pending=int.from_bytes(interpreters.channel_recv(_cid), 'little'), - closed=bool(interpreters.channel_recv(_cid)), - ) - fix.record_action(action, result) - - def iter_fixtures(self): - # XXX threads? - interpreters = [ - ('main', 'interp', 'extra'), - ('interp', 'main', 'extra'), - ('interp1', 'interp2', 'extra'), - ('interp1', 'interp2', 'main'), - ] - for interp, other, extra in interpreters: - for creator in ('same', 'other', 'creator'): - for end in ('send', 'recv'): - yield ChannelCloseFixture(end, interp, other, extra, creator) - - def _close(self, fix, *, force): - op = 'force-close' if force else 'close' - close = ChannelAction(op, fix.end, 'same') - if not fix.expect_closed_error(): - self.run_action(fix, close, hideclosed=False) - else: - with self.assertRaises(interpreters.ChannelClosedError): - self.run_action(fix, close, hideclosed=False) - - def _assert_closed_in_interp(self, fix, interp=None): - if interp is None or interp.name == 'main': - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(fix.cid) - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_send(fix.cid, b'spam') - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_close(fix.cid) - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_close(fix.cid, force=True) - else: - run_interp(interp.id, f""" - with helpers.expect_channel_closed(): - interpreters.channel_recv(cid) - """) - run_interp(interp.id, f""" - with helpers.expect_channel_closed(): - interpreters.channel_send(cid, b'spam') - """) - run_interp(interp.id, f""" - with helpers.expect_channel_closed(): - interpreters.channel_close(cid) - """) - run_interp(interp.id, f""" - with helpers.expect_channel_closed(): - interpreters.channel_close(cid, force=True) - """) - - def _assert_closed(self, fix): - self.assertTrue(fix.state.closed) - - for _ in range(fix.state.pending): - interpreters.channel_recv(fix.cid) - self._assert_closed_in_interp(fix) - - for interp in ('same', 'other'): - interp = fix.get_interpreter(interp) - if interp.name == 'main': - continue - self._assert_closed_in_interp(fix, interp) - - interp = fix.get_interpreter('fresh') - self._assert_closed_in_interp(fix, interp) - - def _iter_close_tests(self, verbose=False): - i = 0 - for actions in self.iter_action_sets(): - print() - for fix in self.iter_fixtures(): - i += 1 - if i > 1000: - return - if verbose: - if (i - 1) % 6 == 0: - print() - print(i, fix, '({} actions)'.format(len(actions))) - else: - if (i - 1) % 6 == 0: - print(' ', end='') - print('.', end=''); sys.stdout.flush() - yield i, fix, actions - if verbose: - print('---') - print() - - # This is useful for scanning through the possible tests. - def _skim_close_tests(self): - ChannelCloseFixture.QUICK = True - for i, fix, actions in self._iter_close_tests(): - pass - - def test_close(self): - for i, fix, actions in self._iter_close_tests(): - with self.subTest('{} {} {}'.format(i, fix, actions)): - fix.prep_interpreter(fix.interp) - self.run_actions(fix, actions) - - self._close(fix, force=False) - - self._assert_closed(fix) - # XXX Things slow down if we have too many interpreters. - fix.clean_up() - - def test_force_close(self): - for i, fix, actions in self._iter_close_tests(): - with self.subTest('{} {} {}'.format(i, fix, actions)): - fix.prep_interpreter(fix.interp) - self.run_actions(fix, actions) - - self._close(fix, force=True) - - self._assert_closed(fix) - # XXX Things slow down if we have too many interpreters. - fix.clean_up() - - if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_interpreters.py b/Lib/test/test_interpreters.py index b969ddf33d81bc8..d1bebe471583228 100644 --- a/Lib/test/test_interpreters.py +++ b/Lib/test/test_interpreters.py @@ -8,6 +8,7 @@ from test import support from test.support import import_helper _interpreters = import_helper.import_module('_xxsubinterpreters') +_channels = import_helper.import_module('_xxinterpchannels') from test.support import interpreters @@ -533,7 +534,7 @@ class TestRecvChannelAttrs(TestBase): def test_id_type(self): rch, _ = interpreters.create_channel() - self.assertIsInstance(rch.id, _interpreters.ChannelID) + self.assertIsInstance(rch.id, _channels.ChannelID) def test_custom_id(self): rch = interpreters.RecvChannel(1) @@ -558,7 +559,7 @@ class TestSendChannelAttrs(TestBase): def test_id_type(self): _, sch = interpreters.create_channel() - self.assertIsInstance(sch.id, _interpreters.ChannelID) + self.assertIsInstance(sch.id, _channels.ChannelID) def test_custom_id(self): sch = interpreters.SendChannel(1) diff --git a/Modules/Setup b/Modules/Setup index e3a82975b5ff5e6..428be0a1bf8fa15 100644 --- a/Modules/Setup +++ b/Modules/Setup @@ -280,6 +280,7 @@ PYTHONPATH=$(COREPYTHONPATH) # Testing #_xxsubinterpreters _xxsubinterpretersmodule.c +#_xxinterpchannels _xxinterpchannelsmodule.c #_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c #_testbuffer _testbuffer.c #_testinternalcapi _testinternalcapi.c diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index d64752e8ca96095..3fd591c70d493f2 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -43,6 +43,7 @@ @MODULE__STRUCT_TRUE@_struct _struct.c @MODULE__TYPING_TRUE@_typing _typingmodule.c @MODULE__XXSUBINTERPRETERS_TRUE@_xxsubinterpreters _xxsubinterpretersmodule.c +@MODULE__XXINTERPCHANNELS_TRUE@_xxinterpchannels _xxinterpchannelsmodule.c @MODULE__ZONEINFO_TRUE@_zoneinfo _zoneinfo.c # needs libm diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 46c025bf53404a2..f0d6e404f54a2f1 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -1639,6 +1639,58 @@ run_in_subinterp_with_config(PyObject *self, PyObject *args, PyObject *kwargs) return PyLong_FromLong(r); } +static void +_xid_capsule_destructor(PyObject *capsule) +{ + _PyCrossInterpreterData *data = \ + (_PyCrossInterpreterData *)PyCapsule_GetPointer(capsule, NULL); + if (data != NULL) { + assert(_PyCrossInterpreterData_Release(data) == 0); + PyMem_Free(data); + } +} + +static PyObject * +get_crossinterp_data(PyObject *self, PyObject *args) +{ + PyObject *obj = NULL; + if (!PyArg_ParseTuple(args, "O:get_crossinterp_data", &obj)) { + return NULL; + } + + _PyCrossInterpreterData *data = PyMem_NEW(_PyCrossInterpreterData, 1); + if (data == NULL) { + PyErr_NoMemory(); + return NULL; + } + if (_PyObject_GetCrossInterpreterData(obj, data) != 0) { + PyMem_Free(data); + return NULL; + } + PyObject *capsule = PyCapsule_New(data, NULL, _xid_capsule_destructor); + if (capsule == NULL) { + assert(_PyCrossInterpreterData_Release(data) == 0); + PyMem_Free(data); + } + return capsule; +} + +static PyObject * +restore_crossinterp_data(PyObject *self, PyObject *args) +{ + PyObject *capsule = NULL; + if (!PyArg_ParseTuple(args, "O:restore_crossinterp_data", &capsule)) { + return NULL; + } + + _PyCrossInterpreterData *data = \ + (_PyCrossInterpreterData *)PyCapsule_GetPointer(capsule, NULL); + if (data == NULL) { + return NULL; + } + return _PyCrossInterpreterData_NewObject(data); +} + static void slot_tp_del(PyObject *self) { @@ -3306,6 +3358,8 @@ static PyMethodDef TestMethods[] = { {"run_in_subinterp_with_config", _PyCFunction_CAST(run_in_subinterp_with_config), METH_VARARGS | METH_KEYWORDS}, + {"get_crossinterp_data", get_crossinterp_data, METH_VARARGS}, + {"restore_crossinterp_data", restore_crossinterp_data, METH_VARARGS}, {"with_tp_del", with_tp_del, METH_VARARGS}, {"create_cfunction", create_cfunction, METH_NOARGS}, {"call_in_temporary_c_thread", call_in_temporary_c_thread, METH_VARARGS, diff --git a/Modules/_xxinterpchannelsmodule.c b/Modules/_xxinterpchannelsmodule.c new file mode 100644 index 000000000000000..8601a189e87526b --- /dev/null +++ b/Modules/_xxinterpchannelsmodule.c @@ -0,0 +1,2325 @@ + +/* interpreters module */ +/* low-level access to interpreter primitives */ +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + +#include "Python.h" +#include "pycore_pystate.h" // _PyThreadState_GET() +#include "pycore_interpreteridobject.h" + + +#define MODULE_NAME "_xxinterpchannels" + + +static PyInterpreterState * +_get_current_interp(void) +{ + // PyInterpreterState_Get() aborts if lookup fails, so don't need + // to check the result for NULL. + return PyInterpreterState_Get(); +} + +static PyObject * +_get_current_module(void) +{ + PyObject *name = PyUnicode_FromString(MODULE_NAME); + if (name == NULL) { + return NULL; + } + PyObject *mod = PyImport_GetModule(name); + Py_DECREF(name); + if (mod == NULL) { + return NULL; + } + assert(mod != Py_None); + return mod; +} + +static PyObject * +get_module_from_owned_type(PyTypeObject *cls) +{ + assert(cls != NULL); + return _get_current_module(); + // XXX Use the more efficient API now that we use heap types: + //return PyType_GetModule(cls); +} + +static struct PyModuleDef moduledef; + +static PyObject * +get_module_from_type(PyTypeObject *cls) +{ + assert(cls != NULL); + return _get_current_module(); + // XXX Use the more efficient API now that we use heap types: + //return PyType_GetModuleByDef(cls, &moduledef); +} + +static PyObject * +add_new_exception(PyObject *mod, const char *name, PyObject *base) +{ + assert(!PyObject_HasAttrString(mod, name)); + PyObject *exctype = PyErr_NewException(name, base, NULL); + if (exctype == NULL) { + return NULL; + } + int res = PyModule_AddType(mod, (PyTypeObject *)exctype); + if (res < 0) { + Py_DECREF(exctype); + return NULL; + } + return exctype; +} + +#define ADD_NEW_EXCEPTION(MOD, NAME, BASE) \ + add_new_exception(MOD, MODULE_NAME "." Py_STRINGIFY(NAME), BASE) + +static PyTypeObject * +add_new_type(PyObject *mod, PyType_Spec *spec, crossinterpdatafunc shared) +{ + PyTypeObject *cls = (PyTypeObject *)PyType_FromMetaclass( + NULL, mod, spec, NULL); + if (cls == NULL) { + return NULL; + } + if (PyModule_AddType(mod, cls) < 0) { + Py_DECREF(cls); + return NULL; + } + if (shared != NULL) { + if (_PyCrossInterpreterData_RegisterClass(cls, shared)) { + Py_DECREF(cls); + return NULL; + } + } + return cls; +} + +static int +_release_xid_data(_PyCrossInterpreterData *data, int ignoreexc) +{ + PyObject *exctype, *excval, *exctb; + if (ignoreexc) { + PyErr_Fetch(&exctype, &excval, &exctb); + } + int res = _PyCrossInterpreterData_Release(data); + if (res < 0) { + // XXX Fix this! + /* The owning interpreter is already destroyed. + * Ideally, this shouldn't ever happen. When an interpreter is + * about to be destroyed, we should clear out all of its objects + * from every channel associated with that interpreter. + * For now we hack around that to resolve refleaks, by decref'ing + * the released object here, even if its the wrong interpreter. + * The owning interpreter has already been destroyed + * so we should be okay, especially since the currently + * shareable types are all very basic, with no GC. + * That said, it becomes much messier once interpreters + * no longer share a GIL, so this needs to be fixed before then. */ + _PyCrossInterpreterData_Clear(NULL, data); + if (ignoreexc) { + // XXX Emit a warning? + PyErr_Clear(); + } + } + if (ignoreexc) { + PyErr_Restore(exctype, excval, exctb); + } + return res; +} + + +/* module state *************************************************************/ + +typedef struct { + /* heap types */ + PyTypeObject *ChannelIDType; + + /* exceptions */ + PyObject *ChannelError; + PyObject *ChannelNotFoundError; + PyObject *ChannelClosedError; + PyObject *ChannelEmptyError; + PyObject *ChannelNotEmptyError; +} module_state; + +static inline module_state * +get_module_state(PyObject *mod) +{ + assert(mod != NULL); + module_state *state = PyModule_GetState(mod); + assert(state != NULL); + return state; +} + +static int +traverse_module_state(module_state *state, visitproc visit, void *arg) +{ + /* heap types */ + Py_VISIT(state->ChannelIDType); + + /* exceptions */ + Py_VISIT(state->ChannelError); + Py_VISIT(state->ChannelNotFoundError); + Py_VISIT(state->ChannelClosedError); + Py_VISIT(state->ChannelEmptyError); + Py_VISIT(state->ChannelNotEmptyError); + + return 0; +} + +static int +clear_module_state(module_state *state) +{ + /* heap types */ + (void)_PyCrossInterpreterData_UnregisterClass(state->ChannelIDType); + Py_CLEAR(state->ChannelIDType); + + /* exceptions */ + Py_CLEAR(state->ChannelError); + Py_CLEAR(state->ChannelNotFoundError); + Py_CLEAR(state->ChannelClosedError); + Py_CLEAR(state->ChannelEmptyError); + Py_CLEAR(state->ChannelNotEmptyError); + + return 0; +} + + +/* channel-specific code ****************************************************/ + +#define CHANNEL_SEND 1 +#define CHANNEL_BOTH 0 +#define CHANNEL_RECV -1 + +/* channel errors */ + +#define ERR_CHANNEL_NOT_FOUND -2 +#define ERR_CHANNEL_CLOSED -3 +#define ERR_CHANNEL_INTERP_CLOSED -4 +#define ERR_CHANNEL_EMPTY -5 +#define ERR_CHANNEL_NOT_EMPTY -6 +#define ERR_CHANNEL_MUTEX_INIT -7 +#define ERR_CHANNELS_MUTEX_INIT -8 +#define ERR_NO_NEXT_CHANNEL_ID -9 + +static int +exceptions_init(PyObject *mod) +{ + module_state *state = get_module_state(mod); + if (state == NULL) { + return -1; + } + +#define ADD(NAME, BASE) \ + do { \ + assert(state->NAME == NULL); \ + state->NAME = ADD_NEW_EXCEPTION(mod, NAME, BASE); \ + if (state->NAME == NULL) { \ + return -1; \ + } \ + } while (0) + + // A channel-related operation failed. + ADD(ChannelError, PyExc_RuntimeError); + // An operation tried to use a channel that doesn't exist. + ADD(ChannelNotFoundError, state->ChannelError); + // An operation tried to use a closed channel. + ADD(ChannelClosedError, state->ChannelError); + // An operation tried to pop from an empty channel. + ADD(ChannelEmptyError, state->ChannelError); + // An operation tried to close a non-empty channel. + ADD(ChannelNotEmptyError, state->ChannelError); +#undef ADD + + return 0; +} + +static int +handle_channel_error(int err, PyObject *mod, int64_t cid) +{ + if (err == 0) { + assert(!PyErr_Occurred()); + return 0; + } + assert(err < 0); + module_state *state = get_module_state(mod); + assert(state != NULL); + if (err == ERR_CHANNEL_NOT_FOUND) { + PyErr_Format(state->ChannelNotFoundError, + "channel %" PRId64 " not found", cid); + } + else if (err == ERR_CHANNEL_CLOSED) { + PyErr_Format(state->ChannelClosedError, + "channel %" PRId64 " is closed", cid); + } + else if (err == ERR_CHANNEL_INTERP_CLOSED) { + PyErr_Format(state->ChannelClosedError, + "channel %" PRId64 " is already closed", cid); + } + else if (err == ERR_CHANNEL_EMPTY) { + PyErr_Format(state->ChannelEmptyError, + "channel %" PRId64 " is empty", cid); + } + else if (err == ERR_CHANNEL_NOT_EMPTY) { + PyErr_Format(state->ChannelNotEmptyError, + "channel %" PRId64 " may not be closed " + "if not empty (try force=True)", + cid); + } + else if (err == ERR_CHANNEL_MUTEX_INIT) { + PyErr_SetString(state->ChannelError, + "can't initialize mutex for new channel"); + } + else if (err == ERR_CHANNELS_MUTEX_INIT) { + PyErr_SetString(state->ChannelError, + "can't initialize mutex for channel management"); + } + else if (err == ERR_NO_NEXT_CHANNEL_ID) { + PyErr_SetString(state->ChannelError, + "failed to get a channel ID"); + } + else { + assert(PyErr_Occurred()); + } + return 1; +} + +/* the channel queue */ + +struct _channelitem; + +typedef struct _channelitem { + _PyCrossInterpreterData *data; + struct _channelitem *next; +} _channelitem; + +static _channelitem * +_channelitem_new(void) +{ + _channelitem *item = PyMem_NEW(_channelitem, 1); + if (item == NULL) { + PyErr_NoMemory(); + return NULL; + } + item->data = NULL; + item->next = NULL; + return item; +} + +static void +_channelitem_clear(_channelitem *item) +{ + if (item->data != NULL) { + (void)_release_xid_data(item->data, 1); + PyMem_Free(item->data); + item->data = NULL; + } + item->next = NULL; +} + +static void +_channelitem_free(_channelitem *item) +{ + _channelitem_clear(item); + PyMem_Free(item); +} + +static void +_channelitem_free_all(_channelitem *item) +{ + while (item != NULL) { + _channelitem *last = item; + item = item->next; + _channelitem_free(last); + } +} + +static _PyCrossInterpreterData * +_channelitem_popped(_channelitem *item) +{ + _PyCrossInterpreterData *data = item->data; + item->data = NULL; + _channelitem_free(item); + return data; +} + +typedef struct _channelqueue { + int64_t count; + _channelitem *first; + _channelitem *last; +} _channelqueue; + +static _channelqueue * +_channelqueue_new(void) +{ + _channelqueue *queue = PyMem_NEW(_channelqueue, 1); + if (queue == NULL) { + PyErr_NoMemory(); + return NULL; + } + queue->count = 0; + queue->first = NULL; + queue->last = NULL; + return queue; +} + +static void +_channelqueue_clear(_channelqueue *queue) +{ + _channelitem_free_all(queue->first); + queue->count = 0; + queue->first = NULL; + queue->last = NULL; +} + +static void +_channelqueue_free(_channelqueue *queue) +{ + _channelqueue_clear(queue); + PyMem_Free(queue); +} + +static int +_channelqueue_put(_channelqueue *queue, _PyCrossInterpreterData *data) +{ + _channelitem *item = _channelitem_new(); + if (item == NULL) { + return -1; + } + item->data = data; + + queue->count += 1; + if (queue->first == NULL) { + queue->first = item; + } + else { + queue->last->next = item; + } + queue->last = item; + return 0; +} + +static _PyCrossInterpreterData * +_channelqueue_get(_channelqueue *queue) +{ + _channelitem *item = queue->first; + if (item == NULL) { + return NULL; + } + queue->first = item->next; + if (queue->last == item) { + queue->last = NULL; + } + queue->count -= 1; + + return _channelitem_popped(item); +} + +/* channel-interpreter associations */ + +struct _channelend; + +typedef struct _channelend { + struct _channelend *next; + int64_t interp; + int open; +} _channelend; + +static _channelend * +_channelend_new(int64_t interp) +{ + _channelend *end = PyMem_NEW(_channelend, 1); + if (end == NULL) { + PyErr_NoMemory(); + return NULL; + } + end->next = NULL; + end->interp = interp; + end->open = 1; + return end; +} + +static void +_channelend_free(_channelend *end) +{ + PyMem_Free(end); +} + +static void +_channelend_free_all(_channelend *end) +{ + while (end != NULL) { + _channelend *last = end; + end = end->next; + _channelend_free(last); + } +} + +static _channelend * +_channelend_find(_channelend *first, int64_t interp, _channelend **pprev) +{ + _channelend *prev = NULL; + _channelend *end = first; + while (end != NULL) { + if (end->interp == interp) { + break; + } + prev = end; + end = end->next; + } + if (pprev != NULL) { + *pprev = prev; + } + return end; +} + +typedef struct _channelassociations { + // Note that the list entries are never removed for interpreter + // for which the channel is closed. This should not be a problem in + // practice. Also, a channel isn't automatically closed when an + // interpreter is destroyed. + int64_t numsendopen; + int64_t numrecvopen; + _channelend *send; + _channelend *recv; +} _channelends; + +static _channelends * +_channelends_new(void) +{ + _channelends *ends = PyMem_NEW(_channelends, 1); + if (ends== NULL) { + return NULL; + } + ends->numsendopen = 0; + ends->numrecvopen = 0; + ends->send = NULL; + ends->recv = NULL; + return ends; +} + +static void +_channelends_clear(_channelends *ends) +{ + _channelend_free_all(ends->send); + ends->send = NULL; + ends->numsendopen = 0; + + _channelend_free_all(ends->recv); + ends->recv = NULL; + ends->numrecvopen = 0; +} + +static void +_channelends_free(_channelends *ends) +{ + _channelends_clear(ends); + PyMem_Free(ends); +} + +static _channelend * +_channelends_add(_channelends *ends, _channelend *prev, int64_t interp, + int send) +{ + _channelend *end = _channelend_new(interp); + if (end == NULL) { + return NULL; + } + + if (prev == NULL) { + if (send) { + ends->send = end; + } + else { + ends->recv = end; + } + } + else { + prev->next = end; + } + if (send) { + ends->numsendopen += 1; + } + else { + ends->numrecvopen += 1; + } + return end; +} + +static int +_channelends_associate(_channelends *ends, int64_t interp, int send) +{ + _channelend *prev; + _channelend *end = _channelend_find(send ? ends->send : ends->recv, + interp, &prev); + if (end != NULL) { + if (!end->open) { + return ERR_CHANNEL_CLOSED; + } + // already associated + return 0; + } + if (_channelends_add(ends, prev, interp, send) == NULL) { + return -1; + } + return 0; +} + +static int +_channelends_is_open(_channelends *ends) +{ + if (ends->numsendopen != 0 || ends->numrecvopen != 0) { + return 1; + } + if (ends->send == NULL && ends->recv == NULL) { + return 1; + } + return 0; +} + +static void +_channelends_close_end(_channelends *ends, _channelend *end, int send) +{ + end->open = 0; + if (send) { + ends->numsendopen -= 1; + } + else { + ends->numrecvopen -= 1; + } +} + +static int +_channelends_close_interpreter(_channelends *ends, int64_t interp, int which) +{ + _channelend *prev; + _channelend *end; + if (which >= 0) { // send/both + end = _channelend_find(ends->send, interp, &prev); + if (end == NULL) { + // never associated so add it + end = _channelends_add(ends, prev, interp, 1); + if (end == NULL) { + return -1; + } + } + _channelends_close_end(ends, end, 1); + } + if (which <= 0) { // recv/both + end = _channelend_find(ends->recv, interp, &prev); + if (end == NULL) { + // never associated so add it + end = _channelends_add(ends, prev, interp, 0); + if (end == NULL) { + return -1; + } + } + _channelends_close_end(ends, end, 0); + } + return 0; +} + +static void +_channelends_close_all(_channelends *ends, int which, int force) +{ + // XXX Handle the ends. + // XXX Handle force is True. + + // Ensure all the "send"-associated interpreters are closed. + _channelend *end; + for (end = ends->send; end != NULL; end = end->next) { + _channelends_close_end(ends, end, 1); + } + + // Ensure all the "recv"-associated interpreters are closed. + for (end = ends->recv; end != NULL; end = end->next) { + _channelends_close_end(ends, end, 0); + } +} + +/* channels */ + +struct _channel; +struct _channel_closing; +static void _channel_clear_closing(struct _channel *); +static void _channel_finish_closing(struct _channel *); + +typedef struct _channel { + PyThread_type_lock mutex; + _channelqueue *queue; + _channelends *ends; + int open; + struct _channel_closing *closing; +} _PyChannelState; + +static _PyChannelState * +_channel_new(PyThread_type_lock mutex) +{ + _PyChannelState *chan = PyMem_NEW(_PyChannelState, 1); + if (chan == NULL) { + return NULL; + } + chan->mutex = mutex; + chan->queue = _channelqueue_new(); + if (chan->queue == NULL) { + PyMem_Free(chan); + return NULL; + } + chan->ends = _channelends_new(); + if (chan->ends == NULL) { + _channelqueue_free(chan->queue); + PyMem_Free(chan); + return NULL; + } + chan->open = 1; + chan->closing = NULL; + return chan; +} + +static void +_channel_free(_PyChannelState *chan) +{ + _channel_clear_closing(chan); + PyThread_acquire_lock(chan->mutex, WAIT_LOCK); + _channelqueue_free(chan->queue); + _channelends_free(chan->ends); + PyThread_release_lock(chan->mutex); + + PyThread_free_lock(chan->mutex); + PyMem_Free(chan); +} + +static int +_channel_add(_PyChannelState *chan, int64_t interp, + _PyCrossInterpreterData *data) +{ + int res = -1; + PyThread_acquire_lock(chan->mutex, WAIT_LOCK); + + if (!chan->open) { + res = ERR_CHANNEL_CLOSED; + goto done; + } + if (_channelends_associate(chan->ends, interp, 1) != 0) { + res = ERR_CHANNEL_INTERP_CLOSED; + goto done; + } + + if (_channelqueue_put(chan->queue, data) != 0) { + goto done; + } + + res = 0; +done: + PyThread_release_lock(chan->mutex); + return res; +} + +static int +_channel_next(_PyChannelState *chan, int64_t interp, + _PyCrossInterpreterData **res) +{ + int err = 0; + PyThread_acquire_lock(chan->mutex, WAIT_LOCK); + + if (!chan->open) { + err = ERR_CHANNEL_CLOSED; + goto done; + } + if (_channelends_associate(chan->ends, interp, 0) != 0) { + err = ERR_CHANNEL_INTERP_CLOSED; + goto done; + } + + _PyCrossInterpreterData *data = _channelqueue_get(chan->queue); + if (data == NULL && !PyErr_Occurred() && chan->closing != NULL) { + chan->open = 0; + } + *res = data; + +done: + PyThread_release_lock(chan->mutex); + if (chan->queue->count == 0) { + _channel_finish_closing(chan); + } + return err; +} + +static int +_channel_close_interpreter(_PyChannelState *chan, int64_t interp, int end) +{ + PyThread_acquire_lock(chan->mutex, WAIT_LOCK); + + int res = -1; + if (!chan->open) { + res = ERR_CHANNEL_CLOSED; + goto done; + } + + if (_channelends_close_interpreter(chan->ends, interp, end) != 0) { + goto done; + } + chan->open = _channelends_is_open(chan->ends); + + res = 0; +done: + PyThread_release_lock(chan->mutex); + return res; +} + +static int +_channel_close_all(_PyChannelState *chan, int end, int force) +{ + int res = -1; + PyThread_acquire_lock(chan->mutex, WAIT_LOCK); + + if (!chan->open) { + res = ERR_CHANNEL_CLOSED; + goto done; + } + + if (!force && chan->queue->count > 0) { + res = ERR_CHANNEL_NOT_EMPTY; + goto done; + } + + chan->open = 0; + + // We *could* also just leave these in place, since we've marked + // the channel as closed already. + _channelends_close_all(chan->ends, end, force); + + res = 0; +done: + PyThread_release_lock(chan->mutex); + return res; +} + +/* the set of channels */ + +struct _channelref; + +typedef struct _channelref { + int64_t id; + _PyChannelState *chan; + struct _channelref *next; + Py_ssize_t objcount; +} _channelref; + +static _channelref * +_channelref_new(int64_t id, _PyChannelState *chan) +{ + _channelref *ref = PyMem_NEW(_channelref, 1); + if (ref == NULL) { + return NULL; + } + ref->id = id; + ref->chan = chan; + ref->next = NULL; + ref->objcount = 0; + return ref; +} + +//static void +//_channelref_clear(_channelref *ref) +//{ +// ref->id = -1; +// ref->chan = NULL; +// ref->next = NULL; +// ref->objcount = 0; +//} + +static void +_channelref_free(_channelref *ref) +{ + if (ref->chan != NULL) { + _channel_clear_closing(ref->chan); + } + //_channelref_clear(ref); + PyMem_Free(ref); +} + +static _channelref * +_channelref_find(_channelref *first, int64_t id, _channelref **pprev) +{ + _channelref *prev = NULL; + _channelref *ref = first; + while (ref != NULL) { + if (ref->id == id) { + break; + } + prev = ref; + ref = ref->next; + } + if (pprev != NULL) { + *pprev = prev; + } + return ref; +} + +typedef struct _channels { + PyThread_type_lock mutex; + _channelref *head; + int64_t numopen; + int64_t next_id; +} _channels; + +static void +_channels_init(_channels *channels, PyThread_type_lock mutex) +{ + channels->mutex = mutex; + channels->head = NULL; + channels->numopen = 0; + channels->next_id = 0; +} + +static void +_channels_fini(_channels *channels) +{ + assert(channels->numopen == 0); + assert(channels->head == NULL); + if (channels->mutex != NULL) { + PyThread_free_lock(channels->mutex); + channels->mutex = NULL; + } +} + +static int64_t +_channels_next_id(_channels *channels) // needs lock +{ + int64_t id = channels->next_id; + if (id < 0) { + /* overflow */ + return -1; + } + channels->next_id += 1; + return id; +} + +static int +_channels_lookup(_channels *channels, int64_t id, PyThread_type_lock *pmutex, + _PyChannelState **res) +{ + int err = -1; + _PyChannelState *chan = NULL; + PyThread_acquire_lock(channels->mutex, WAIT_LOCK); + if (pmutex != NULL) { + *pmutex = NULL; + } + + _channelref *ref = _channelref_find(channels->head, id, NULL); + if (ref == NULL) { + err = ERR_CHANNEL_NOT_FOUND; + goto done; + } + if (ref->chan == NULL || !ref->chan->open) { + err = ERR_CHANNEL_CLOSED; + goto done; + } + + if (pmutex != NULL) { + // The mutex will be closed by the caller. + *pmutex = channels->mutex; + } + + chan = ref->chan; + err = 0; + +done: + if (pmutex == NULL || *pmutex == NULL) { + PyThread_release_lock(channels->mutex); + } + *res = chan; + return err; +} + +static int64_t +_channels_add(_channels *channels, _PyChannelState *chan) +{ + int64_t cid = -1; + PyThread_acquire_lock(channels->mutex, WAIT_LOCK); + + // Create a new ref. + int64_t id = _channels_next_id(channels); + if (id < 0) { + cid = ERR_NO_NEXT_CHANNEL_ID; + goto done; + } + _channelref *ref = _channelref_new(id, chan); + if (ref == NULL) { + goto done; + } + + // Add it to the list. + // We assume that the channel is a new one (not already in the list). + ref->next = channels->head; + channels->head = ref; + channels->numopen += 1; + + cid = id; +done: + PyThread_release_lock(channels->mutex); + return cid; +} + +/* forward */ +static int _channel_set_closing(struct _channelref *, PyThread_type_lock); + +static int +_channels_close(_channels *channels, int64_t cid, _PyChannelState **pchan, + int end, int force) +{ + int res = -1; + PyThread_acquire_lock(channels->mutex, WAIT_LOCK); + if (pchan != NULL) { + *pchan = NULL; + } + + _channelref *ref = _channelref_find(channels->head, cid, NULL); + if (ref == NULL) { + res = ERR_CHANNEL_NOT_FOUND; + goto done; + } + + if (ref->chan == NULL) { + res = ERR_CHANNEL_CLOSED; + goto done; + } + else if (!force && end == CHANNEL_SEND && ref->chan->closing != NULL) { + res = ERR_CHANNEL_CLOSED; + goto done; + } + else { + int err = _channel_close_all(ref->chan, end, force); + if (err != 0) { + if (end == CHANNEL_SEND && err == ERR_CHANNEL_NOT_EMPTY) { + if (ref->chan->closing != NULL) { + res = ERR_CHANNEL_CLOSED; + goto done; + } + // Mark the channel as closing and return. The channel + // will be cleaned up in _channel_next(). + PyErr_Clear(); + int err = _channel_set_closing(ref, channels->mutex); + if (err != 0) { + res = err; + goto done; + } + if (pchan != NULL) { + *pchan = ref->chan; + } + res = 0; + } + else { + res = err; + } + goto done; + } + if (pchan != NULL) { + *pchan = ref->chan; + } + else { + _channel_free(ref->chan); + } + ref->chan = NULL; + } + + res = 0; +done: + PyThread_release_lock(channels->mutex); + return res; +} + +static void +_channels_remove_ref(_channels *channels, _channelref *ref, _channelref *prev, + _PyChannelState **pchan) +{ + if (ref == channels->head) { + channels->head = ref->next; + } + else { + prev->next = ref->next; + } + channels->numopen -= 1; + + if (pchan != NULL) { + *pchan = ref->chan; + } + _channelref_free(ref); +} + +static int +_channels_remove(_channels *channels, int64_t id, _PyChannelState **pchan) +{ + int res = -1; + PyThread_acquire_lock(channels->mutex, WAIT_LOCK); + + if (pchan != NULL) { + *pchan = NULL; + } + + _channelref *prev = NULL; + _channelref *ref = _channelref_find(channels->head, id, &prev); + if (ref == NULL) { + res = ERR_CHANNEL_NOT_FOUND; + goto done; + } + + _channels_remove_ref(channels, ref, prev, pchan); + + res = 0; +done: + PyThread_release_lock(channels->mutex); + return res; +} + +static int +_channels_add_id_object(_channels *channels, int64_t id) +{ + int res = -1; + PyThread_acquire_lock(channels->mutex, WAIT_LOCK); + + _channelref *ref = _channelref_find(channels->head, id, NULL); + if (ref == NULL) { + res = ERR_CHANNEL_NOT_FOUND; + goto done; + } + ref->objcount += 1; + + res = 0; +done: + PyThread_release_lock(channels->mutex); + return res; +} + +static void +_channels_drop_id_object(_channels *channels, int64_t id) +{ + PyThread_acquire_lock(channels->mutex, WAIT_LOCK); + + _channelref *prev = NULL; + _channelref *ref = _channelref_find(channels->head, id, &prev); + if (ref == NULL) { + // Already destroyed. + goto done; + } + ref->objcount -= 1; + + // Destroy if no longer used. + if (ref->objcount == 0) { + _PyChannelState *chan = NULL; + _channels_remove_ref(channels, ref, prev, &chan); + if (chan != NULL) { + _channel_free(chan); + } + } + +done: + PyThread_release_lock(channels->mutex); +} + +static int64_t * +_channels_list_all(_channels *channels, int64_t *count) +{ + int64_t *cids = NULL; + PyThread_acquire_lock(channels->mutex, WAIT_LOCK); + int64_t *ids = PyMem_NEW(int64_t, (Py_ssize_t)(channels->numopen)); + if (ids == NULL) { + goto done; + } + _channelref *ref = channels->head; + for (int64_t i=0; ref != NULL; ref = ref->next, i++) { + ids[i] = ref->id; + } + *count = channels->numopen; + + cids = ids; +done: + PyThread_release_lock(channels->mutex); + return cids; +} + +/* support for closing non-empty channels */ + +struct _channel_closing { + struct _channelref *ref; +}; + +static int +_channel_set_closing(struct _channelref *ref, PyThread_type_lock mutex) { + struct _channel *chan = ref->chan; + if (chan == NULL) { + // already closed + return 0; + } + int res = -1; + PyThread_acquire_lock(chan->mutex, WAIT_LOCK); + if (chan->closing != NULL) { + res = ERR_CHANNEL_CLOSED; + goto done; + } + chan->closing = PyMem_NEW(struct _channel_closing, 1); + if (chan->closing == NULL) { + goto done; + } + chan->closing->ref = ref; + + res = 0; +done: + PyThread_release_lock(chan->mutex); + return res; +} + +static void +_channel_clear_closing(struct _channel *chan) { + PyThread_acquire_lock(chan->mutex, WAIT_LOCK); + if (chan->closing != NULL) { + PyMem_Free(chan->closing); + chan->closing = NULL; + } + PyThread_release_lock(chan->mutex); +} + +static void +_channel_finish_closing(struct _channel *chan) { + struct _channel_closing *closing = chan->closing; + if (closing == NULL) { + return; + } + _channelref *ref = closing->ref; + _channel_clear_closing(chan); + // Do the things that would have been done in _channels_close(). + ref->chan = NULL; + _channel_free(chan); +} + +/* "high"-level channel-related functions */ + +static int64_t +_channel_create(_channels *channels) +{ + PyThread_type_lock mutex = PyThread_allocate_lock(); + if (mutex == NULL) { + return ERR_CHANNEL_MUTEX_INIT; + } + _PyChannelState *chan = _channel_new(mutex); + if (chan == NULL) { + PyThread_free_lock(mutex); + return -1; + } + int64_t id = _channels_add(channels, chan); + if (id < 0) { + _channel_free(chan); + } + return id; +} + +static int +_channel_destroy(_channels *channels, int64_t id) +{ + _PyChannelState *chan = NULL; + int err = _channels_remove(channels, id, &chan); + if (err != 0) { + return err; + } + if (chan != NULL) { + _channel_free(chan); + } + return 0; +} + +static int +_channel_send(_channels *channels, int64_t id, PyObject *obj) +{ + PyInterpreterState *interp = _get_current_interp(); + if (interp == NULL) { + return -1; + } + + // Look up the channel. + PyThread_type_lock mutex = NULL; + _PyChannelState *chan = NULL; + int err = _channels_lookup(channels, id, &mutex, &chan); + if (err != 0) { + return err; + } + assert(chan != NULL); + // Past this point we are responsible for releasing the mutex. + + if (chan->closing != NULL) { + PyThread_release_lock(mutex); + return ERR_CHANNEL_CLOSED; + } + + // Convert the object to cross-interpreter data. + _PyCrossInterpreterData *data = PyMem_NEW(_PyCrossInterpreterData, 1); + if (data == NULL) { + PyThread_release_lock(mutex); + return -1; + } + if (_PyObject_GetCrossInterpreterData(obj, data) != 0) { + PyThread_release_lock(mutex); + PyMem_Free(data); + return -1; + } + + // Add the data to the channel. + int res = _channel_add(chan, PyInterpreterState_GetID(interp), data); + PyThread_release_lock(mutex); + if (res != 0) { + // We may chain an exception here: + (void)_release_xid_data(data, 0); + PyMem_Free(data); + return res; + } + + return 0; +} + +static int +_channel_recv(_channels *channels, int64_t id, PyObject **res) +{ + int err; + *res = NULL; + + PyInterpreterState *interp = _get_current_interp(); + if (interp == NULL) { + // XXX Is this always an error? + if (PyErr_Occurred()) { + return -1; + } + return 0; + } + + // Look up the channel. + PyThread_type_lock mutex = NULL; + _PyChannelState *chan = NULL; + err = _channels_lookup(channels, id, &mutex, &chan); + if (err != 0) { + return err; + } + assert(chan != NULL); + // Past this point we are responsible for releasing the mutex. + + // Pop off the next item from the channel. + _PyCrossInterpreterData *data = NULL; + err = _channel_next(chan, PyInterpreterState_GetID(interp), &data); + PyThread_release_lock(mutex); + if (err != 0) { + return err; + } + else if (data == NULL) { + assert(!PyErr_Occurred()); + return 0; + } + + // Convert the data back to an object. + PyObject *obj = _PyCrossInterpreterData_NewObject(data); + if (obj == NULL) { + assert(PyErr_Occurred()); + (void)_release_xid_data(data, 1); + PyMem_Free(data); + return -1; + } + int release_res = _release_xid_data(data, 0); + PyMem_Free(data); + if (release_res < 0) { + // The source interpreter has been destroyed already. + assert(PyErr_Occurred()); + Py_DECREF(obj); + return -1; + } + + *res = obj; + return 0; +} + +static int +_channel_drop(_channels *channels, int64_t id, int send, int recv) +{ + PyInterpreterState *interp = _get_current_interp(); + if (interp == NULL) { + return -1; + } + + // Look up the channel. + PyThread_type_lock mutex = NULL; + _PyChannelState *chan = NULL; + int err = _channels_lookup(channels, id, &mutex, &chan); + if (err != 0) { + return err; + } + // Past this point we are responsible for releasing the mutex. + + // Close one or both of the two ends. + int res = _channel_close_interpreter(chan, PyInterpreterState_GetID(interp), send-recv); + PyThread_release_lock(mutex); + return res; +} + +static int +_channel_close(_channels *channels, int64_t id, int end, int force) +{ + return _channels_close(channels, id, NULL, end, force); +} + +static int +_channel_is_associated(_channels *channels, int64_t cid, int64_t interp, + int send) +{ + _PyChannelState *chan = NULL; + int err = _channels_lookup(channels, cid, NULL, &chan); + if (err != 0) { + return err; + } + else if (send && chan->closing != NULL) { + return ERR_CHANNEL_CLOSED; + } + + _channelend *end = _channelend_find(send ? chan->ends->send : chan->ends->recv, + interp, NULL); + + return (end != NULL && end->open); +} + +/* ChannelID class */ + +typedef struct channelid { + PyObject_HEAD + int64_t id; + int end; + int resolve; + _channels *channels; +} channelid; + +struct channel_id_converter_data { + PyObject *module; + int64_t cid; +}; + +static int +channel_id_converter(PyObject *arg, void *ptr) +{ + int64_t cid; + struct channel_id_converter_data *data = ptr; + module_state *state = get_module_state(data->module); + assert(state != NULL); + if (PyObject_TypeCheck(arg, state->ChannelIDType)) { + cid = ((channelid *)arg)->id; + } + else if (PyIndex_Check(arg)) { + cid = PyLong_AsLongLong(arg); + if (cid == -1 && PyErr_Occurred()) { + return 0; + } + if (cid < 0) { + PyErr_Format(PyExc_ValueError, + "channel ID must be a non-negative int, got %R", arg); + return 0; + } + } + else { + PyErr_Format(PyExc_TypeError, + "channel ID must be an int, got %.100s", + Py_TYPE(arg)->tp_name); + return 0; + } + data->cid = cid; + return 1; +} + +static int +newchannelid(PyTypeObject *cls, int64_t cid, int end, _channels *channels, + int force, int resolve, channelid **res) +{ + *res = NULL; + + channelid *self = PyObject_New(channelid, cls); + if (self == NULL) { + return -1; + } + self->id = cid; + self->end = end; + self->resolve = resolve; + self->channels = channels; + + int err = _channels_add_id_object(channels, cid); + if (err != 0) { + if (force && err == ERR_CHANNEL_NOT_FOUND) { + assert(!PyErr_Occurred()); + } + else { + Py_DECREF((PyObject *)self); + return err; + } + } + + *res = self; + return 0; +} + +static _channels * _global_channels(void); + +static PyObject * +_channelid_new(PyObject *mod, PyTypeObject *cls, + PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"id", "send", "recv", "force", "_resolve", NULL}; + int64_t cid; + struct channel_id_converter_data cid_data = { + .module = mod, + }; + int send = -1; + int recv = -1; + int force = 0; + int resolve = 0; + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "O&|$pppp:ChannelID.__new__", kwlist, + channel_id_converter, &cid_data, + &send, &recv, &force, &resolve)) { + return NULL; + } + cid = cid_data.cid; + + // Handle "send" and "recv". + if (send == 0 && recv == 0) { + PyErr_SetString(PyExc_ValueError, + "'send' and 'recv' cannot both be False"); + return NULL; + } + + int end = 0; + if (send == 1) { + if (recv == 0 || recv == -1) { + end = CHANNEL_SEND; + } + } + else if (recv == 1) { + end = CHANNEL_RECV; + } + + PyObject *id = NULL; + int err = newchannelid(cls, cid, end, _global_channels(), + force, resolve, + (channelid **)&id); + if (handle_channel_error(err, mod, cid)) { + assert(id == NULL); + return NULL; + } + assert(id != NULL); + return id; +} + +static void +channelid_dealloc(PyObject *self) +{ + int64_t cid = ((channelid *)self)->id; + _channels *channels = ((channelid *)self)->channels; + + PyTypeObject *tp = Py_TYPE(self); + tp->tp_free(self); + /* "Instances of heap-allocated types hold a reference to their type." + * See: https://docs.python.org/3.11/howto/isolating-extensions.html#garbage-collection-protocol + * See: https://docs.python.org/3.11/c-api/typeobj.html#c.PyTypeObject.tp_traverse + */ + // XXX Why don't we implement Py_TPFLAGS_HAVE_GC, e.g. Py_tp_traverse, + // like we do for _abc._abc_data? + Py_DECREF(tp); + + _channels_drop_id_object(channels, cid); +} + +static PyObject * +channelid_repr(PyObject *self) +{ + PyTypeObject *type = Py_TYPE(self); + const char *name = _PyType_Name(type); + + channelid *cid = (channelid *)self; + const char *fmt; + if (cid->end == CHANNEL_SEND) { + fmt = "%s(%" PRId64 ", send=True)"; + } + else if (cid->end == CHANNEL_RECV) { + fmt = "%s(%" PRId64 ", recv=True)"; + } + else { + fmt = "%s(%" PRId64 ")"; + } + return PyUnicode_FromFormat(fmt, name, cid->id); +} + +static PyObject * +channelid_str(PyObject *self) +{ + channelid *cid = (channelid *)self; + return PyUnicode_FromFormat("%" PRId64 "", cid->id); +} + +static PyObject * +channelid_int(PyObject *self) +{ + channelid *cid = (channelid *)self; + return PyLong_FromLongLong(cid->id); +} + +static Py_hash_t +channelid_hash(PyObject *self) +{ + channelid *cid = (channelid *)self; + PyObject *id = PyLong_FromLongLong(cid->id); + if (id == NULL) { + return -1; + } + Py_hash_t hash = PyObject_Hash(id); + Py_DECREF(id); + return hash; +} + +static PyObject * +channelid_richcompare(PyObject *self, PyObject *other, int op) +{ + PyObject *res = NULL; + if (op != Py_EQ && op != Py_NE) { + Py_RETURN_NOTIMPLEMENTED; + } + + PyObject *mod = get_module_from_type(Py_TYPE(self)); + if (mod == NULL) { + return NULL; + } + module_state *state = get_module_state(mod); + if (state == NULL) { + goto done; + } + + if (!PyObject_TypeCheck(self, state->ChannelIDType)) { + res = Py_NewRef(Py_NotImplemented); + goto done; + } + + channelid *cid = (channelid *)self; + int equal; + if (PyObject_TypeCheck(other, state->ChannelIDType)) { + channelid *othercid = (channelid *)other; + equal = (cid->end == othercid->end) && (cid->id == othercid->id); + } + else if (PyLong_Check(other)) { + /* Fast path */ + int overflow; + long long othercid = PyLong_AsLongLongAndOverflow(other, &overflow); + if (othercid == -1 && PyErr_Occurred()) { + goto done; + } + equal = !overflow && (othercid >= 0) && (cid->id == othercid); + } + else if (PyNumber_Check(other)) { + PyObject *pyid = PyLong_FromLongLong(cid->id); + if (pyid == NULL) { + goto done; + } + res = PyObject_RichCompare(pyid, other, op); + Py_DECREF(pyid); + goto done; + } + else { + res = Py_NewRef(Py_NotImplemented); + goto done; + } + + if ((op == Py_EQ && equal) || (op == Py_NE && !equal)) { + res = Py_NewRef(Py_True); + } + else { + res = Py_NewRef(Py_False); + } + +done: + Py_DECREF(mod); + return res; +} + +static PyObject * +_channel_from_cid(PyObject *cid, int end) +{ + PyObject *highlevel = PyImport_ImportModule("interpreters"); + if (highlevel == NULL) { + PyErr_Clear(); + highlevel = PyImport_ImportModule("test.support.interpreters"); + if (highlevel == NULL) { + return NULL; + } + } + const char *clsname = (end == CHANNEL_RECV) ? "RecvChannel" : + "SendChannel"; + PyObject *cls = PyObject_GetAttrString(highlevel, clsname); + Py_DECREF(highlevel); + if (cls == NULL) { + return NULL; + } + PyObject *chan = PyObject_CallFunctionObjArgs(cls, cid, NULL); + Py_DECREF(cls); + if (chan == NULL) { + return NULL; + } + return chan; +} + +struct _channelid_xid { + int64_t id; + int end; + int resolve; +}; + +static PyObject * +_channelid_from_xid(_PyCrossInterpreterData *data) +{ + struct _channelid_xid *xid = (struct _channelid_xid *)data->data; + + // It might not be imported yet, so we can't use _get_current_module(). + PyObject *mod = PyImport_ImportModule(MODULE_NAME); + if (mod == NULL) { + return NULL; + } + assert(mod != Py_None); + module_state *state = get_module_state(mod); + if (state == NULL) { + return NULL; + } + + // Note that we do not preserve the "resolve" flag. + PyObject *cid = NULL; + int err = newchannelid(state->ChannelIDType, xid->id, xid->end, + _global_channels(), 0, 0, + (channelid **)&cid); + if (err != 0) { + assert(cid == NULL); + (void)handle_channel_error(err, mod, xid->id); + goto done; + } + assert(cid != NULL); + if (xid->end == 0) { + goto done; + } + if (!xid->resolve) { + goto done; + } + + /* Try returning a high-level channel end but fall back to the ID. */ + PyObject *chan = _channel_from_cid(cid, xid->end); + if (chan == NULL) { + PyErr_Clear(); + goto done; + } + Py_DECREF(cid); + cid = chan; + +done: + Py_DECREF(mod); + return cid; +} + +static int +_channelid_shared(PyThreadState *tstate, PyObject *obj, + _PyCrossInterpreterData *data) +{ + if (_PyCrossInterpreterData_InitWithSize( + data, tstate->interp, sizeof(struct _channelid_xid), obj, + _channelid_from_xid + ) < 0) + { + return -1; + } + struct _channelid_xid *xid = (struct _channelid_xid *)data->data; + xid->id = ((channelid *)obj)->id; + xid->end = ((channelid *)obj)->end; + xid->resolve = ((channelid *)obj)->resolve; + return 0; +} + +static PyObject * +channelid_end(PyObject *self, void *end) +{ + int force = 1; + channelid *cid = (channelid *)self; + if (end != NULL) { + PyObject *id = NULL; + int err = newchannelid(Py_TYPE(self), cid->id, *(int *)end, + cid->channels, force, cid->resolve, + (channelid **)&id); + if (err != 0) { + assert(id == NULL); + PyObject *mod = get_module_from_type(Py_TYPE(self)); + if (mod == NULL) { + return NULL; + } + (void)handle_channel_error(err, mod, cid->id); + Py_DECREF(mod); + return NULL; + } + assert(id != NULL); + return id; + } + + if (cid->end == CHANNEL_SEND) { + return PyUnicode_InternFromString("send"); + } + if (cid->end == CHANNEL_RECV) { + return PyUnicode_InternFromString("recv"); + } + return PyUnicode_InternFromString("both"); +} + +static int _channelid_end_send = CHANNEL_SEND; +static int _channelid_end_recv = CHANNEL_RECV; + +static PyGetSetDef channelid_getsets[] = { + {"end", (getter)channelid_end, NULL, + PyDoc_STR("'send', 'recv', or 'both'")}, + {"send", (getter)channelid_end, NULL, + PyDoc_STR("the 'send' end of the channel"), &_channelid_end_send}, + {"recv", (getter)channelid_end, NULL, + PyDoc_STR("the 'recv' end of the channel"), &_channelid_end_recv}, + {NULL} +}; + +PyDoc_STRVAR(channelid_doc, +"A channel ID identifies a channel and may be used as an int."); + +static PyType_Slot ChannelIDType_slots[] = { + {Py_tp_dealloc, (destructor)channelid_dealloc}, + {Py_tp_doc, (void *)channelid_doc}, + {Py_tp_repr, (reprfunc)channelid_repr}, + {Py_tp_str, (reprfunc)channelid_str}, + {Py_tp_hash, channelid_hash}, + {Py_tp_richcompare, channelid_richcompare}, + {Py_tp_getset, channelid_getsets}, + // number slots + {Py_nb_int, (unaryfunc)channelid_int}, + {Py_nb_index, (unaryfunc)channelid_int}, + {0, NULL}, +}; + +static PyType_Spec ChannelIDType_spec = { + .name = "_xxsubinterpreters.ChannelID", + .basicsize = sizeof(channelid), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE), + .slots = ChannelIDType_slots, +}; + + +/* module level code ********************************************************/ + +/* globals is the process-global state for the module. It holds all + the data that we need to share between interpreters, so it cannot + hold PyObject values. */ +static struct globals { + int module_count; + _channels channels; +} _globals = {0}; + +static int +_globals_init(void) +{ + // XXX This isn't thread-safe. + _globals.module_count++; + if (_globals.module_count > 1) { + // Already initialized. + return 0; + } + + assert(_globals.channels.mutex == NULL); + PyThread_type_lock mutex = PyThread_allocate_lock(); + if (mutex == NULL) { + return ERR_CHANNELS_MUTEX_INIT; + } + _channels_init(&_globals.channels, mutex); + return 0; +} + +static void +_globals_fini(void) +{ + // XXX This isn't thread-safe. + _globals.module_count--; + if (_globals.module_count > 0) { + return; + } + + _channels_fini(&_globals.channels); +} + +static _channels * +_global_channels(void) { + return &_globals.channels; +} + + +static PyObject * +channel_create(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + int64_t cid = _channel_create(&_globals.channels); + if (cid < 0) { + (void)handle_channel_error(-1, self, cid); + return NULL; + } + module_state *state = get_module_state(self); + if (state == NULL) { + return NULL; + } + PyObject *id = NULL; + int err = newchannelid(state->ChannelIDType, cid, 0, + &_globals.channels, 0, 0, + (channelid **)&id); + if (handle_channel_error(err, self, cid)) { + assert(id == NULL); + err = _channel_destroy(&_globals.channels, cid); + if (handle_channel_error(err, self, cid)) { + // XXX issue a warning? + } + return NULL; + } + assert(id != NULL); + assert(((channelid *)id)->channels != NULL); + return id; +} + +PyDoc_STRVAR(channel_create_doc, +"channel_create() -> cid\n\ +\n\ +Create a new cross-interpreter channel and return a unique generated ID."); + +static PyObject * +channel_destroy(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"cid", NULL}; + int64_t cid; + struct channel_id_converter_data cid_data = { + .module = self, + }; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&:channel_destroy", kwlist, + channel_id_converter, &cid_data)) { + return NULL; + } + cid = cid_data.cid; + + int err = _channel_destroy(&_globals.channels, cid); + if (handle_channel_error(err, self, cid)) { + return NULL; + } + Py_RETURN_NONE; +} + +PyDoc_STRVAR(channel_destroy_doc, +"channel_destroy(cid)\n\ +\n\ +Close and finalize the channel. Afterward attempts to use the channel\n\ +will behave as though it never existed."); + +static PyObject * +channel_list_all(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + int64_t count = 0; + int64_t *cids = _channels_list_all(&_globals.channels, &count); + if (cids == NULL) { + if (count == 0) { + return PyList_New(0); + } + return NULL; + } + PyObject *ids = PyList_New((Py_ssize_t)count); + if (ids == NULL) { + goto finally; + } + module_state *state = get_module_state(self); + if (state == NULL) { + Py_DECREF(ids); + ids = NULL; + goto finally; + } + int64_t *cur = cids; + for (int64_t i=0; i < count; cur++, i++) { + PyObject *id = NULL; + int err = newchannelid(state->ChannelIDType, *cur, 0, + &_globals.channels, 0, 0, + (channelid **)&id); + if (handle_channel_error(err, self, *cur)) { + assert(id == NULL); + Py_SETREF(ids, NULL); + break; + } + assert(id != NULL); + PyList_SET_ITEM(ids, (Py_ssize_t)i, id); + } + +finally: + PyMem_Free(cids); + return ids; +} + +PyDoc_STRVAR(channel_list_all_doc, +"channel_list_all() -> [cid]\n\ +\n\ +Return the list of all IDs for active channels."); + +static PyObject * +channel_list_interpreters(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"cid", "send", NULL}; + int64_t cid; /* Channel ID */ + struct channel_id_converter_data cid_data = { + .module = self, + }; + int send = 0; /* Send or receive end? */ + int64_t id; + PyObject *ids, *id_obj; + PyInterpreterState *interp; + + if (!PyArg_ParseTupleAndKeywords( + args, kwds, "O&$p:channel_list_interpreters", + kwlist, channel_id_converter, &cid_data, &send)) { + return NULL; + } + cid = cid_data.cid; + + ids = PyList_New(0); + if (ids == NULL) { + goto except; + } + + interp = PyInterpreterState_Head(); + while (interp != NULL) { + id = PyInterpreterState_GetID(interp); + assert(id >= 0); + int res = _channel_is_associated(&_globals.channels, cid, id, send); + if (res < 0) { + (void)handle_channel_error(res, self, cid); + goto except; + } + if (res) { + id_obj = _PyInterpreterState_GetIDObject(interp); + if (id_obj == NULL) { + goto except; + } + res = PyList_Insert(ids, 0, id_obj); + Py_DECREF(id_obj); + if (res < 0) { + goto except; + } + } + interp = PyInterpreterState_Next(interp); + } + + goto finally; + +except: + Py_CLEAR(ids); + +finally: + return ids; +} + +PyDoc_STRVAR(channel_list_interpreters_doc, +"channel_list_interpreters(cid, *, send) -> [id]\n\ +\n\ +Return the list of all interpreter IDs associated with an end of the channel.\n\ +\n\ +The 'send' argument should be a boolean indicating whether to use the send or\n\ +receive end."); + + +static PyObject * +channel_send(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"cid", "obj", NULL}; + int64_t cid; + struct channel_id_converter_data cid_data = { + .module = self, + }; + PyObject *obj; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&O:channel_send", kwlist, + channel_id_converter, &cid_data, &obj)) { + return NULL; + } + cid = cid_data.cid; + + int err = _channel_send(&_globals.channels, cid, obj); + if (handle_channel_error(err, self, cid)) { + return NULL; + } + Py_RETURN_NONE; +} + +PyDoc_STRVAR(channel_send_doc, +"channel_send(cid, obj)\n\ +\n\ +Add the object's data to the channel's queue."); + +static PyObject * +channel_recv(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"cid", "default", NULL}; + int64_t cid; + struct channel_id_converter_data cid_data = { + .module = self, + }; + PyObject *dflt = NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|O:channel_recv", kwlist, + channel_id_converter, &cid_data, &dflt)) { + return NULL; + } + cid = cid_data.cid; + + PyObject *obj = NULL; + int err = _channel_recv(&_globals.channels, cid, &obj); + if (handle_channel_error(err, self, cid)) { + return NULL; + } + Py_XINCREF(dflt); + if (obj == NULL) { + // Use the default. + if (dflt == NULL) { + (void)handle_channel_error(ERR_CHANNEL_EMPTY, self, cid); + return NULL; + } + obj = Py_NewRef(dflt); + } + Py_XDECREF(dflt); + return obj; +} + +PyDoc_STRVAR(channel_recv_doc, +"channel_recv(cid, [default]) -> obj\n\ +\n\ +Return a new object from the data at the front of the channel's queue.\n\ +\n\ +If there is nothing to receive then raise ChannelEmptyError, unless\n\ +a default value is provided. In that case return it."); + +static PyObject * +channel_close(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"cid", "send", "recv", "force", NULL}; + int64_t cid; + struct channel_id_converter_data cid_data = { + .module = self, + }; + int send = 0; + int recv = 0; + int force = 0; + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "O&|$ppp:channel_close", kwlist, + channel_id_converter, &cid_data, + &send, &recv, &force)) { + return NULL; + } + cid = cid_data.cid; + + int err = _channel_close(&_globals.channels, cid, send-recv, force); + if (handle_channel_error(err, self, cid)) { + return NULL; + } + Py_RETURN_NONE; +} + +PyDoc_STRVAR(channel_close_doc, +"channel_close(cid, *, send=None, recv=None, force=False)\n\ +\n\ +Close the channel for all interpreters.\n\ +\n\ +If the channel is empty then the keyword args are ignored and both\n\ +ends are immediately closed. Otherwise, if 'force' is True then\n\ +all queued items are released and both ends are immediately\n\ +closed.\n\ +\n\ +If the channel is not empty *and* 'force' is False then following\n\ +happens:\n\ +\n\ + * recv is True (regardless of send):\n\ + - raise ChannelNotEmptyError\n\ + * recv is None and send is None:\n\ + - raise ChannelNotEmptyError\n\ + * send is True and recv is not True:\n\ + - fully close the 'send' end\n\ + - close the 'recv' end to interpreters not already receiving\n\ + - fully close it once empty\n\ +\n\ +Closing an already closed channel results in a ChannelClosedError.\n\ +\n\ +Once the channel's ID has no more ref counts in any interpreter\n\ +the channel will be destroyed."); + +static PyObject * +channel_release(PyObject *self, PyObject *args, PyObject *kwds) +{ + // Note that only the current interpreter is affected. + static char *kwlist[] = {"cid", "send", "recv", "force", NULL}; + int64_t cid; + struct channel_id_converter_data cid_data = { + .module = self, + }; + int send = 0; + int recv = 0; + int force = 0; + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "O&|$ppp:channel_release", kwlist, + channel_id_converter, &cid_data, + &send, &recv, &force)) { + return NULL; + } + cid = cid_data.cid; + if (send == 0 && recv == 0) { + send = 1; + recv = 1; + } + + // XXX Handle force is True. + // XXX Fix implicit release. + + int err = _channel_drop(&_globals.channels, cid, send, recv); + if (handle_channel_error(err, self, cid)) { + return NULL; + } + Py_RETURN_NONE; +} + +PyDoc_STRVAR(channel_release_doc, +"channel_release(cid, *, send=None, recv=None, force=True)\n\ +\n\ +Close the channel for the current interpreter. 'send' and 'recv'\n\ +(bool) may be used to indicate the ends to close. By default both\n\ +ends are closed. Closing an already closed end is a noop."); + +static PyObject * +channel__channel_id(PyObject *self, PyObject *args, PyObject *kwds) +{ + module_state *state = get_module_state(self); + if (state == NULL) { + return NULL; + } + PyTypeObject *cls = state->ChannelIDType; + PyObject *mod = get_module_from_owned_type(cls); + if (mod == NULL) { + return NULL; + } + PyObject *cid = _channelid_new(mod, cls, args, kwds); + Py_DECREF(mod); + return cid; +} + +static PyMethodDef module_functions[] = { + {"create", channel_create, + METH_NOARGS, channel_create_doc}, + {"destroy", _PyCFunction_CAST(channel_destroy), + METH_VARARGS | METH_KEYWORDS, channel_destroy_doc}, + {"list_all", channel_list_all, + METH_NOARGS, channel_list_all_doc}, + {"list_interpreters", _PyCFunction_CAST(channel_list_interpreters), + METH_VARARGS | METH_KEYWORDS, channel_list_interpreters_doc}, + {"send", _PyCFunction_CAST(channel_send), + METH_VARARGS | METH_KEYWORDS, channel_send_doc}, + {"recv", _PyCFunction_CAST(channel_recv), + METH_VARARGS | METH_KEYWORDS, channel_recv_doc}, + {"close", _PyCFunction_CAST(channel_close), + METH_VARARGS | METH_KEYWORDS, channel_close_doc}, + {"release", _PyCFunction_CAST(channel_release), + METH_VARARGS | METH_KEYWORDS, channel_release_doc}, + {"_channel_id", _PyCFunction_CAST(channel__channel_id), + METH_VARARGS | METH_KEYWORDS, NULL}, + + {NULL, NULL} /* sentinel */ +}; + + +/* initialization function */ + +PyDoc_STRVAR(module_doc, +"This module provides primitive operations to manage Python interpreters.\n\ +The 'interpreters' module provides a more convenient interface."); + +static int +module_exec(PyObject *mod) +{ + if (_globals_init() != 0) { + return -1; + } + + /* Add exception types */ + if (exceptions_init(mod) != 0) { + goto error; + } + + /* Add other types */ + module_state *state = get_module_state(mod); + if (state == NULL) { + goto error; + } + + // ChannelID + state->ChannelIDType = add_new_type( + mod, &ChannelIDType_spec, _channelid_shared); + if (state->ChannelIDType == NULL) { + goto error; + } + + return 0; + +error: + (void)_PyCrossInterpreterData_UnregisterClass(state->ChannelIDType); + _globals_fini(); + return -1; +} + +static struct PyModuleDef_Slot module_slots[] = { + {Py_mod_exec, module_exec}, + {0, NULL}, +}; + +static int +module_traverse(PyObject *mod, visitproc visit, void *arg) +{ + module_state *state = get_module_state(mod); + assert(state != NULL); + traverse_module_state(state, visit, arg); + return 0; +} + +static int +module_clear(PyObject *mod) +{ + module_state *state = get_module_state(mod); + assert(state != NULL); + clear_module_state(state); + return 0; +} + +static void +module_free(void *mod) +{ + module_state *state = get_module_state(mod); + assert(state != NULL); + clear_module_state(state); + _globals_fini(); +} + +static struct PyModuleDef moduledef = { + .m_base = PyModuleDef_HEAD_INIT, + .m_name = MODULE_NAME, + .m_doc = module_doc, + .m_size = sizeof(module_state), + .m_methods = module_functions, + .m_slots = module_slots, + .m_traverse = module_traverse, + .m_clear = module_clear, + .m_free = (freefunc)module_free, +}; + +PyMODINIT_FUNC +PyInit__xxinterpchannels(void) +{ + return PyModuleDef_Init(&moduledef); +} diff --git a/Modules/_xxsubinterpretersmodule.c b/Modules/_xxsubinterpretersmodule.c index 0892fa3a9595e81..461c505c092c701 100644 --- a/Modules/_xxsubinterpretersmodule.c +++ b/Modules/_xxsubinterpretersmodule.c @@ -39,43 +39,6 @@ _get_current_interp(void) return PyInterpreterState_Get(); } -static PyObject * -_get_current_module(void) -{ - // We ensured it was imported in _run_script(). - PyObject *name = PyUnicode_FromString(MODULE_NAME); - if (name == NULL) { - return NULL; - } - PyObject *mod = PyImport_GetModule(name); - Py_DECREF(name); - if (mod == NULL) { - return NULL; - } - assert(mod != Py_None); - return mod; -} - -static PyObject * -get_module_from_owned_type(PyTypeObject *cls) -{ - assert(cls != NULL); - return _get_current_module(); - // XXX Use the more efficient API now that we use heap types: - //return PyType_GetModule(cls); -} - -static struct PyModuleDef moduledef; - -static PyObject * -get_module_from_type(PyTypeObject *cls) -{ - assert(cls != NULL); - return _get_current_module(); - // XXX Use the more efficient API now that we use heap types: - //return PyType_GetModuleByDef(cls, &moduledef); -} - static PyObject * add_new_exception(PyObject *mod, const char *name, PyObject *base) { @@ -95,27 +58,6 @@ add_new_exception(PyObject *mod, const char *name, PyObject *base) #define ADD_NEW_EXCEPTION(MOD, NAME, BASE) \ add_new_exception(MOD, MODULE_NAME "." Py_STRINGIFY(NAME), BASE) -static PyTypeObject * -add_new_type(PyObject *mod, PyType_Spec *spec, crossinterpdatafunc shared) -{ - PyTypeObject *cls = (PyTypeObject *)PyType_FromMetaclass( - NULL, mod, spec, NULL); - if (cls == NULL) { - return NULL; - } - if (PyModule_AddType(mod, cls) < 0) { - Py_DECREF(cls); - return NULL; - } - if (shared != NULL) { - if (_PyCrossInterpreterData_RegisterClass(cls, shared)) { - Py_DECREF(cls); - return NULL; - } - } - return cls; -} - static int _release_xid_data(_PyCrossInterpreterData *data, int ignoreexc) { @@ -127,9 +69,7 @@ _release_xid_data(_PyCrossInterpreterData *data, int ignoreexc) if (res < 0) { // XXX Fix this! /* The owning interpreter is already destroyed. - * Ideally, this shouldn't ever happen. When an interpreter is - * about to be destroyed, we should clear out all of its objects - * from every channel associated with that interpreter. + * Ideally, this shouldn't ever happen. (It's highly unlikely.) * For now we hack around that to resolve refleaks, by decref'ing * the released object here, even if its the wrong interpreter. * The owning interpreter has already been destroyed @@ -153,17 +93,8 @@ _release_xid_data(_PyCrossInterpreterData *data, int ignoreexc) /* module state *************************************************************/ typedef struct { - PyTypeObject *ChannelIDType; - - /* interpreter exceptions */ + /* exceptions */ PyObject *RunFailedError; - - /* channel exceptions */ - PyObject *ChannelError; - PyObject *ChannelNotFoundError; - PyObject *ChannelClosedError; - PyObject *ChannelEmptyError; - PyObject *ChannelNotEmptyError; } module_state; static inline module_state * @@ -178,37 +109,18 @@ get_module_state(PyObject *mod) static int traverse_module_state(module_state *state, visitproc visit, void *arg) { - /* heap types */ - Py_VISIT(state->ChannelIDType); - - /* interpreter exceptions */ + /* exceptions */ Py_VISIT(state->RunFailedError); - /* channel exceptions */ - Py_VISIT(state->ChannelError); - Py_VISIT(state->ChannelNotFoundError); - Py_VISIT(state->ChannelClosedError); - Py_VISIT(state->ChannelEmptyError); - Py_VISIT(state->ChannelNotEmptyError); return 0; } static int clear_module_state(module_state *state) { - /* heap types */ - (void)_PyCrossInterpreterData_UnregisterClass(state->ChannelIDType); - Py_CLEAR(state->ChannelIDType); - - /* interpreter exceptions */ + /* exceptions */ Py_CLEAR(state->RunFailedError); - /* channel exceptions */ - Py_CLEAR(state->ChannelError); - Py_CLEAR(state->ChannelNotFoundError); - Py_CLEAR(state->ChannelClosedError); - Py_CLEAR(state->ChannelEmptyError); - Py_CLEAR(state->ChannelNotEmptyError); return 0; } @@ -298,10 +210,8 @@ _sharedns_free(_sharedns *shared) } static _sharedns * -_get_shared_ns(PyObject *shareable, PyTypeObject *channelidtype, - int *needs_import) +_get_shared_ns(PyObject *shareable) { - *needs_import = 0; if (shareable == NULL || shareable == Py_None) { return NULL; } @@ -323,9 +233,6 @@ _get_shared_ns(PyObject *shareable, PyTypeObject *channelidtype, if (_sharednsitem_init(&shared->items[i], key, value) != 0) { break; } - if (Py_TYPE(value) == channelidtype) { - *needs_import = 1; - } } if (PyErr_Occurred()) { _sharedns_free(shared); @@ -394,1701 +301,79 @@ _sharedexception_bind(PyObject *exctype, PyObject *exc, PyObject *tb) _sharedexception *err = _sharedexception_new(); if (err == NULL) { - goto finally; - } - - PyObject *name = PyUnicode_FromFormat("%S", exctype); - if (name == NULL) { - failure = "unable to format exception type name"; - goto finally; - } - err->name = _copy_raw_string(name); - Py_DECREF(name); - if (err->name == NULL) { - if (PyErr_ExceptionMatches(PyExc_MemoryError)) { - failure = "out of memory copying exception type name"; - } else { - failure = "unable to encode and copy exception type name"; - } - goto finally; - } - - if (exc != NULL) { - PyObject *msg = PyUnicode_FromFormat("%S", exc); - if (msg == NULL) { - failure = "unable to format exception message"; - goto finally; - } - err->msg = _copy_raw_string(msg); - Py_DECREF(msg); - if (err->msg == NULL) { - if (PyErr_ExceptionMatches(PyExc_MemoryError)) { - failure = "out of memory copying exception message"; - } else { - failure = "unable to encode and copy exception message"; - } - goto finally; - } - } - -finally: - if (failure != NULL) { - PyErr_Clear(); - if (err->name != NULL) { - PyMem_Free(err->name); - err->name = NULL; - } - err->msg = failure; - } - return err; -} - -static void -_sharedexception_apply(_sharedexception *exc, PyObject *wrapperclass) -{ - if (exc->name != NULL) { - if (exc->msg != NULL) { - PyErr_Format(wrapperclass, "%s: %s", exc->name, exc->msg); - } - else { - PyErr_SetString(wrapperclass, exc->name); - } - } - else if (exc->msg != NULL) { - PyErr_SetString(wrapperclass, exc->msg); - } - else { - PyErr_SetNone(wrapperclass); - } -} - - -/* channel-specific code ****************************************************/ - -#define CHANNEL_SEND 1 -#define CHANNEL_BOTH 0 -#define CHANNEL_RECV -1 - -/* channel errors */ - -#define ERR_CHANNEL_NOT_FOUND -2 -#define ERR_CHANNEL_CLOSED -3 -#define ERR_CHANNEL_INTERP_CLOSED -4 -#define ERR_CHANNEL_EMPTY -5 -#define ERR_CHANNEL_NOT_EMPTY -6 -#define ERR_CHANNEL_MUTEX_INIT -7 -#define ERR_CHANNELS_MUTEX_INIT -8 -#define ERR_NO_NEXT_CHANNEL_ID -9 - -static int -channel_exceptions_init(PyObject *mod) -{ - module_state *state = get_module_state(mod); - if (state == NULL) { - return -1; - } - -#define ADD(NAME, BASE) \ - do { \ - assert(state->NAME == NULL); \ - state->NAME = ADD_NEW_EXCEPTION(mod, NAME, BASE); \ - if (state->NAME == NULL) { \ - return -1; \ - } \ - } while (0) - - // A channel-related operation failed. - ADD(ChannelError, PyExc_RuntimeError); - // An operation tried to use a channel that doesn't exist. - ADD(ChannelNotFoundError, state->ChannelError); - // An operation tried to use a closed channel. - ADD(ChannelClosedError, state->ChannelError); - // An operation tried to pop from an empty channel. - ADD(ChannelEmptyError, state->ChannelError); - // An operation tried to close a non-empty channel. - ADD(ChannelNotEmptyError, state->ChannelError); -#undef ADD - - return 0; -} - -static int -handle_channel_error(int err, PyObject *mod, int64_t cid) -{ - if (err == 0) { - assert(!PyErr_Occurred()); - return 0; - } - assert(err < 0); - module_state *state = get_module_state(mod); - assert(state != NULL); - if (err == ERR_CHANNEL_NOT_FOUND) { - PyErr_Format(state->ChannelNotFoundError, - "channel %" PRId64 " not found", cid); - } - else if (err == ERR_CHANNEL_CLOSED) { - PyErr_Format(state->ChannelClosedError, - "channel %" PRId64 " is closed", cid); - } - else if (err == ERR_CHANNEL_INTERP_CLOSED) { - PyErr_Format(state->ChannelClosedError, - "channel %" PRId64 " is already closed", cid); - } - else if (err == ERR_CHANNEL_EMPTY) { - PyErr_Format(state->ChannelEmptyError, - "channel %" PRId64 " is empty", cid); - } - else if (err == ERR_CHANNEL_NOT_EMPTY) { - PyErr_Format(state->ChannelNotEmptyError, - "channel %" PRId64 " may not be closed " - "if not empty (try force=True)", - cid); - } - else if (err == ERR_CHANNEL_MUTEX_INIT) { - PyErr_SetString(state->ChannelError, - "can't initialize mutex for new channel"); - } - else if (err == ERR_CHANNELS_MUTEX_INIT) { - PyErr_SetString(state->ChannelError, - "can't initialize mutex for channel management"); - } - else if (err == ERR_NO_NEXT_CHANNEL_ID) { - PyErr_SetString(state->ChannelError, - "failed to get a channel ID"); - } - else { - assert(PyErr_Occurred()); - } - return 1; -} - -/* the channel queue */ - -struct _channelitem; - -typedef struct _channelitem { - _PyCrossInterpreterData *data; - struct _channelitem *next; -} _channelitem; - -static _channelitem * -_channelitem_new(void) -{ - _channelitem *item = PyMem_NEW(_channelitem, 1); - if (item == NULL) { - PyErr_NoMemory(); - return NULL; - } - item->data = NULL; - item->next = NULL; - return item; -} - -static void -_channelitem_clear(_channelitem *item) -{ - if (item->data != NULL) { - (void)_release_xid_data(item->data, 1); - PyMem_Free(item->data); - item->data = NULL; - } - item->next = NULL; -} - -static void -_channelitem_free(_channelitem *item) -{ - _channelitem_clear(item); - PyMem_Free(item); -} - -static void -_channelitem_free_all(_channelitem *item) -{ - while (item != NULL) { - _channelitem *last = item; - item = item->next; - _channelitem_free(last); - } -} - -static _PyCrossInterpreterData * -_channelitem_popped(_channelitem *item) -{ - _PyCrossInterpreterData *data = item->data; - item->data = NULL; - _channelitem_free(item); - return data; -} - -typedef struct _channelqueue { - int64_t count; - _channelitem *first; - _channelitem *last; -} _channelqueue; - -static _channelqueue * -_channelqueue_new(void) -{ - _channelqueue *queue = PyMem_NEW(_channelqueue, 1); - if (queue == NULL) { - PyErr_NoMemory(); - return NULL; - } - queue->count = 0; - queue->first = NULL; - queue->last = NULL; - return queue; -} - -static void -_channelqueue_clear(_channelqueue *queue) -{ - _channelitem_free_all(queue->first); - queue->count = 0; - queue->first = NULL; - queue->last = NULL; -} - -static void -_channelqueue_free(_channelqueue *queue) -{ - _channelqueue_clear(queue); - PyMem_Free(queue); -} - -static int -_channelqueue_put(_channelqueue *queue, _PyCrossInterpreterData *data) -{ - _channelitem *item = _channelitem_new(); - if (item == NULL) { - return -1; - } - item->data = data; - - queue->count += 1; - if (queue->first == NULL) { - queue->first = item; - } - else { - queue->last->next = item; - } - queue->last = item; - return 0; -} - -static _PyCrossInterpreterData * -_channelqueue_get(_channelqueue *queue) -{ - _channelitem *item = queue->first; - if (item == NULL) { - return NULL; - } - queue->first = item->next; - if (queue->last == item) { - queue->last = NULL; - } - queue->count -= 1; - - return _channelitem_popped(item); -} - -/* channel-interpreter associations */ - -struct _channelend; - -typedef struct _channelend { - struct _channelend *next; - int64_t interp; - int open; -} _channelend; - -static _channelend * -_channelend_new(int64_t interp) -{ - _channelend *end = PyMem_NEW(_channelend, 1); - if (end == NULL) { - PyErr_NoMemory(); - return NULL; - } - end->next = NULL; - end->interp = interp; - end->open = 1; - return end; -} - -static void -_channelend_free(_channelend *end) -{ - PyMem_Free(end); -} - -static void -_channelend_free_all(_channelend *end) -{ - while (end != NULL) { - _channelend *last = end; - end = end->next; - _channelend_free(last); - } -} - -static _channelend * -_channelend_find(_channelend *first, int64_t interp, _channelend **pprev) -{ - _channelend *prev = NULL; - _channelend *end = first; - while (end != NULL) { - if (end->interp == interp) { - break; - } - prev = end; - end = end->next; - } - if (pprev != NULL) { - *pprev = prev; - } - return end; -} - -typedef struct _channelassociations { - // Note that the list entries are never removed for interpreter - // for which the channel is closed. This should not be a problem in - // practice. Also, a channel isn't automatically closed when an - // interpreter is destroyed. - int64_t numsendopen; - int64_t numrecvopen; - _channelend *send; - _channelend *recv; -} _channelends; - -static _channelends * -_channelends_new(void) -{ - _channelends *ends = PyMem_NEW(_channelends, 1); - if (ends== NULL) { - return NULL; - } - ends->numsendopen = 0; - ends->numrecvopen = 0; - ends->send = NULL; - ends->recv = NULL; - return ends; -} - -static void -_channelends_clear(_channelends *ends) -{ - _channelend_free_all(ends->send); - ends->send = NULL; - ends->numsendopen = 0; - - _channelend_free_all(ends->recv); - ends->recv = NULL; - ends->numrecvopen = 0; -} - -static void -_channelends_free(_channelends *ends) -{ - _channelends_clear(ends); - PyMem_Free(ends); -} - -static _channelend * -_channelends_add(_channelends *ends, _channelend *prev, int64_t interp, - int send) -{ - _channelend *end = _channelend_new(interp); - if (end == NULL) { - return NULL; - } - - if (prev == NULL) { - if (send) { - ends->send = end; - } - else { - ends->recv = end; - } - } - else { - prev->next = end; - } - if (send) { - ends->numsendopen += 1; - } - else { - ends->numrecvopen += 1; - } - return end; -} - -static int -_channelends_associate(_channelends *ends, int64_t interp, int send) -{ - _channelend *prev; - _channelend *end = _channelend_find(send ? ends->send : ends->recv, - interp, &prev); - if (end != NULL) { - if (!end->open) { - return ERR_CHANNEL_CLOSED; - } - // already associated - return 0; - } - if (_channelends_add(ends, prev, interp, send) == NULL) { - return -1; - } - return 0; -} - -static int -_channelends_is_open(_channelends *ends) -{ - if (ends->numsendopen != 0 || ends->numrecvopen != 0) { - return 1; - } - if (ends->send == NULL && ends->recv == NULL) { - return 1; - } - return 0; -} - -static void -_channelends_close_end(_channelends *ends, _channelend *end, int send) -{ - end->open = 0; - if (send) { - ends->numsendopen -= 1; - } - else { - ends->numrecvopen -= 1; - } -} - -static int -_channelends_close_interpreter(_channelends *ends, int64_t interp, int which) -{ - _channelend *prev; - _channelend *end; - if (which >= 0) { // send/both - end = _channelend_find(ends->send, interp, &prev); - if (end == NULL) { - // never associated so add it - end = _channelends_add(ends, prev, interp, 1); - if (end == NULL) { - return -1; - } - } - _channelends_close_end(ends, end, 1); - } - if (which <= 0) { // recv/both - end = _channelend_find(ends->recv, interp, &prev); - if (end == NULL) { - // never associated so add it - end = _channelends_add(ends, prev, interp, 0); - if (end == NULL) { - return -1; - } - } - _channelends_close_end(ends, end, 0); - } - return 0; -} - -static void -_channelends_close_all(_channelends *ends, int which, int force) -{ - // XXX Handle the ends. - // XXX Handle force is True. - - // Ensure all the "send"-associated interpreters are closed. - _channelend *end; - for (end = ends->send; end != NULL; end = end->next) { - _channelends_close_end(ends, end, 1); - } - - // Ensure all the "recv"-associated interpreters are closed. - for (end = ends->recv; end != NULL; end = end->next) { - _channelends_close_end(ends, end, 0); - } -} - -/* channels */ - -struct _channel; -struct _channel_closing; -static void _channel_clear_closing(struct _channel *); -static void _channel_finish_closing(struct _channel *); - -typedef struct _channel { - PyThread_type_lock mutex; - _channelqueue *queue; - _channelends *ends; - int open; - struct _channel_closing *closing; -} _PyChannelState; - -static _PyChannelState * -_channel_new(PyThread_type_lock mutex) -{ - _PyChannelState *chan = PyMem_NEW(_PyChannelState, 1); - if (chan == NULL) { - return NULL; - } - chan->mutex = mutex; - chan->queue = _channelqueue_new(); - if (chan->queue == NULL) { - PyMem_Free(chan); - return NULL; - } - chan->ends = _channelends_new(); - if (chan->ends == NULL) { - _channelqueue_free(chan->queue); - PyMem_Free(chan); - return NULL; - } - chan->open = 1; - chan->closing = NULL; - return chan; -} - -static void -_channel_free(_PyChannelState *chan) -{ - _channel_clear_closing(chan); - PyThread_acquire_lock(chan->mutex, WAIT_LOCK); - _channelqueue_free(chan->queue); - _channelends_free(chan->ends); - PyThread_release_lock(chan->mutex); - - PyThread_free_lock(chan->mutex); - PyMem_Free(chan); -} - -static int -_channel_add(_PyChannelState *chan, int64_t interp, - _PyCrossInterpreterData *data) -{ - int res = -1; - PyThread_acquire_lock(chan->mutex, WAIT_LOCK); - - if (!chan->open) { - res = ERR_CHANNEL_CLOSED; - goto done; - } - if (_channelends_associate(chan->ends, interp, 1) != 0) { - res = ERR_CHANNEL_INTERP_CLOSED; - goto done; - } - - if (_channelqueue_put(chan->queue, data) != 0) { - goto done; - } - - res = 0; -done: - PyThread_release_lock(chan->mutex); - return res; -} - -static int -_channel_next(_PyChannelState *chan, int64_t interp, - _PyCrossInterpreterData **res) -{ - int err = 0; - PyThread_acquire_lock(chan->mutex, WAIT_LOCK); - - if (!chan->open) { - err = ERR_CHANNEL_CLOSED; - goto done; - } - if (_channelends_associate(chan->ends, interp, 0) != 0) { - err = ERR_CHANNEL_INTERP_CLOSED; - goto done; - } - - _PyCrossInterpreterData *data = _channelqueue_get(chan->queue); - if (data == NULL && !PyErr_Occurred() && chan->closing != NULL) { - chan->open = 0; - } - *res = data; - -done: - PyThread_release_lock(chan->mutex); - if (chan->queue->count == 0) { - _channel_finish_closing(chan); - } - return err; -} - -static int -_channel_close_interpreter(_PyChannelState *chan, int64_t interp, int end) -{ - PyThread_acquire_lock(chan->mutex, WAIT_LOCK); - - int res = -1; - if (!chan->open) { - res = ERR_CHANNEL_CLOSED; - goto done; - } - - if (_channelends_close_interpreter(chan->ends, interp, end) != 0) { - goto done; - } - chan->open = _channelends_is_open(chan->ends); - - res = 0; -done: - PyThread_release_lock(chan->mutex); - return res; -} - -static int -_channel_close_all(_PyChannelState *chan, int end, int force) -{ - int res = -1; - PyThread_acquire_lock(chan->mutex, WAIT_LOCK); - - if (!chan->open) { - res = ERR_CHANNEL_CLOSED; - goto done; - } - - if (!force && chan->queue->count > 0) { - res = ERR_CHANNEL_NOT_EMPTY; - goto done; - } - - chan->open = 0; - - // We *could* also just leave these in place, since we've marked - // the channel as closed already. - _channelends_close_all(chan->ends, end, force); - - res = 0; -done: - PyThread_release_lock(chan->mutex); - return res; -} - -/* the set of channels */ - -struct _channelref; - -typedef struct _channelref { - int64_t id; - _PyChannelState *chan; - struct _channelref *next; - Py_ssize_t objcount; -} _channelref; - -static _channelref * -_channelref_new(int64_t id, _PyChannelState *chan) -{ - _channelref *ref = PyMem_NEW(_channelref, 1); - if (ref == NULL) { - return NULL; - } - ref->id = id; - ref->chan = chan; - ref->next = NULL; - ref->objcount = 0; - return ref; -} - -//static void -//_channelref_clear(_channelref *ref) -//{ -// ref->id = -1; -// ref->chan = NULL; -// ref->next = NULL; -// ref->objcount = 0; -//} - -static void -_channelref_free(_channelref *ref) -{ - if (ref->chan != NULL) { - _channel_clear_closing(ref->chan); - } - //_channelref_clear(ref); - PyMem_Free(ref); -} - -static _channelref * -_channelref_find(_channelref *first, int64_t id, _channelref **pprev) -{ - _channelref *prev = NULL; - _channelref *ref = first; - while (ref != NULL) { - if (ref->id == id) { - break; - } - prev = ref; - ref = ref->next; - } - if (pprev != NULL) { - *pprev = prev; - } - return ref; -} - -typedef struct _channels { - PyThread_type_lock mutex; - _channelref *head; - int64_t numopen; - int64_t next_id; -} _channels; - -static void -_channels_init(_channels *channels, PyThread_type_lock mutex) -{ - channels->mutex = mutex; - channels->head = NULL; - channels->numopen = 0; - channels->next_id = 0; -} - -static void -_channels_fini(_channels *channels) -{ - assert(channels->numopen == 0); - assert(channels->head == NULL); - if (channels->mutex != NULL) { - PyThread_free_lock(channels->mutex); - channels->mutex = NULL; - } -} - -static int64_t -_channels_next_id(_channels *channels) // needs lock -{ - int64_t id = channels->next_id; - if (id < 0) { - /* overflow */ - return -1; - } - channels->next_id += 1; - return id; -} - -static int -_channels_lookup(_channels *channels, int64_t id, PyThread_type_lock *pmutex, - _PyChannelState **res) -{ - int err = -1; - _PyChannelState *chan = NULL; - PyThread_acquire_lock(channels->mutex, WAIT_LOCK); - if (pmutex != NULL) { - *pmutex = NULL; - } - - _channelref *ref = _channelref_find(channels->head, id, NULL); - if (ref == NULL) { - err = ERR_CHANNEL_NOT_FOUND; - goto done; - } - if (ref->chan == NULL || !ref->chan->open) { - err = ERR_CHANNEL_CLOSED; - goto done; - } - - if (pmutex != NULL) { - // The mutex will be closed by the caller. - *pmutex = channels->mutex; - } - - chan = ref->chan; - err = 0; - -done: - if (pmutex == NULL || *pmutex == NULL) { - PyThread_release_lock(channels->mutex); - } - *res = chan; - return err; -} - -static int64_t -_channels_add(_channels *channels, _PyChannelState *chan) -{ - int64_t cid = -1; - PyThread_acquire_lock(channels->mutex, WAIT_LOCK); - - // Create a new ref. - int64_t id = _channels_next_id(channels); - if (id < 0) { - cid = ERR_NO_NEXT_CHANNEL_ID; - goto done; - } - _channelref *ref = _channelref_new(id, chan); - if (ref == NULL) { - goto done; - } - - // Add it to the list. - // We assume that the channel is a new one (not already in the list). - ref->next = channels->head; - channels->head = ref; - channels->numopen += 1; - - cid = id; -done: - PyThread_release_lock(channels->mutex); - return cid; -} - -/* forward */ -static int _channel_set_closing(struct _channelref *, PyThread_type_lock); - -static int -_channels_close(_channels *channels, int64_t cid, _PyChannelState **pchan, - int end, int force) -{ - int res = -1; - PyThread_acquire_lock(channels->mutex, WAIT_LOCK); - if (pchan != NULL) { - *pchan = NULL; - } - - _channelref *ref = _channelref_find(channels->head, cid, NULL); - if (ref == NULL) { - res = ERR_CHANNEL_NOT_FOUND; - goto done; - } - - if (ref->chan == NULL) { - res = ERR_CHANNEL_CLOSED; - goto done; - } - else if (!force && end == CHANNEL_SEND && ref->chan->closing != NULL) { - res = ERR_CHANNEL_CLOSED; - goto done; - } - else { - int err = _channel_close_all(ref->chan, end, force); - if (err != 0) { - if (end == CHANNEL_SEND && err == ERR_CHANNEL_NOT_EMPTY) { - if (ref->chan->closing != NULL) { - res = ERR_CHANNEL_CLOSED; - goto done; - } - // Mark the channel as closing and return. The channel - // will be cleaned up in _channel_next(). - PyErr_Clear(); - int err = _channel_set_closing(ref, channels->mutex); - if (err != 0) { - res = err; - goto done; - } - if (pchan != NULL) { - *pchan = ref->chan; - } - res = 0; - } - else { - res = err; - } - goto done; - } - if (pchan != NULL) { - *pchan = ref->chan; - } - else { - _channel_free(ref->chan); - } - ref->chan = NULL; - } - - res = 0; -done: - PyThread_release_lock(channels->mutex); - return res; -} - -static void -_channels_remove_ref(_channels *channels, _channelref *ref, _channelref *prev, - _PyChannelState **pchan) -{ - if (ref == channels->head) { - channels->head = ref->next; - } - else { - prev->next = ref->next; - } - channels->numopen -= 1; - - if (pchan != NULL) { - *pchan = ref->chan; - } - _channelref_free(ref); -} - -static int -_channels_remove(_channels *channels, int64_t id, _PyChannelState **pchan) -{ - int res = -1; - PyThread_acquire_lock(channels->mutex, WAIT_LOCK); - - if (pchan != NULL) { - *pchan = NULL; - } - - _channelref *prev = NULL; - _channelref *ref = _channelref_find(channels->head, id, &prev); - if (ref == NULL) { - res = ERR_CHANNEL_NOT_FOUND; - goto done; - } - - _channels_remove_ref(channels, ref, prev, pchan); - - res = 0; -done: - PyThread_release_lock(channels->mutex); - return res; -} - -static int -_channels_add_id_object(_channels *channels, int64_t id) -{ - int res = -1; - PyThread_acquire_lock(channels->mutex, WAIT_LOCK); - - _channelref *ref = _channelref_find(channels->head, id, NULL); - if (ref == NULL) { - res = ERR_CHANNEL_NOT_FOUND; - goto done; - } - ref->objcount += 1; - - res = 0; -done: - PyThread_release_lock(channels->mutex); - return res; -} - -static void -_channels_drop_id_object(_channels *channels, int64_t id) -{ - PyThread_acquire_lock(channels->mutex, WAIT_LOCK); - - _channelref *prev = NULL; - _channelref *ref = _channelref_find(channels->head, id, &prev); - if (ref == NULL) { - // Already destroyed. - goto done; - } - ref->objcount -= 1; - - // Destroy if no longer used. - if (ref->objcount == 0) { - _PyChannelState *chan = NULL; - _channels_remove_ref(channels, ref, prev, &chan); - if (chan != NULL) { - _channel_free(chan); - } - } - -done: - PyThread_release_lock(channels->mutex); -} - -static int64_t * -_channels_list_all(_channels *channels, int64_t *count) -{ - int64_t *cids = NULL; - PyThread_acquire_lock(channels->mutex, WAIT_LOCK); - int64_t *ids = PyMem_NEW(int64_t, (Py_ssize_t)(channels->numopen)); - if (ids == NULL) { - goto done; - } - _channelref *ref = channels->head; - for (int64_t i=0; ref != NULL; ref = ref->next, i++) { - ids[i] = ref->id; - } - *count = channels->numopen; - - cids = ids; -done: - PyThread_release_lock(channels->mutex); - return cids; -} - -/* support for closing non-empty channels */ - -struct _channel_closing { - struct _channelref *ref; -}; - -static int -_channel_set_closing(struct _channelref *ref, PyThread_type_lock mutex) { - struct _channel *chan = ref->chan; - if (chan == NULL) { - // already closed - return 0; - } - int res = -1; - PyThread_acquire_lock(chan->mutex, WAIT_LOCK); - if (chan->closing != NULL) { - res = ERR_CHANNEL_CLOSED; - goto done; - } - chan->closing = PyMem_NEW(struct _channel_closing, 1); - if (chan->closing == NULL) { - goto done; - } - chan->closing->ref = ref; - - res = 0; -done: - PyThread_release_lock(chan->mutex); - return res; -} - -static void -_channel_clear_closing(struct _channel *chan) { - PyThread_acquire_lock(chan->mutex, WAIT_LOCK); - if (chan->closing != NULL) { - PyMem_Free(chan->closing); - chan->closing = NULL; - } - PyThread_release_lock(chan->mutex); -} - -static void -_channel_finish_closing(struct _channel *chan) { - struct _channel_closing *closing = chan->closing; - if (closing == NULL) { - return; - } - _channelref *ref = closing->ref; - _channel_clear_closing(chan); - // Do the things that would have been done in _channels_close(). - ref->chan = NULL; - _channel_free(chan); -} - -/* "high"-level channel-related functions */ - -static int64_t -_channel_create(_channels *channels) -{ - PyThread_type_lock mutex = PyThread_allocate_lock(); - if (mutex == NULL) { - return ERR_CHANNEL_MUTEX_INIT; - } - _PyChannelState *chan = _channel_new(mutex); - if (chan == NULL) { - PyThread_free_lock(mutex); - return -1; - } - int64_t id = _channels_add(channels, chan); - if (id < 0) { - _channel_free(chan); - } - return id; -} - -static int -_channel_destroy(_channels *channels, int64_t id) -{ - _PyChannelState *chan = NULL; - int err = _channels_remove(channels, id, &chan); - if (err != 0) { - return err; - } - if (chan != NULL) { - _channel_free(chan); - } - return 0; -} - -static int -_channel_send(_channels *channels, int64_t id, PyObject *obj) -{ - PyInterpreterState *interp = _get_current_interp(); - if (interp == NULL) { - return -1; - } - - // Look up the channel. - PyThread_type_lock mutex = NULL; - _PyChannelState *chan = NULL; - int err = _channels_lookup(channels, id, &mutex, &chan); - if (err != 0) { - return err; - } - assert(chan != NULL); - // Past this point we are responsible for releasing the mutex. - - if (chan->closing != NULL) { - PyThread_release_lock(mutex); - return ERR_CHANNEL_CLOSED; - } - - // Convert the object to cross-interpreter data. - _PyCrossInterpreterData *data = PyMem_NEW(_PyCrossInterpreterData, 1); - if (data == NULL) { - PyThread_release_lock(mutex); - return -1; - } - if (_PyObject_GetCrossInterpreterData(obj, data) != 0) { - PyThread_release_lock(mutex); - PyMem_Free(data); - return -1; - } - - // Add the data to the channel. - int res = _channel_add(chan, PyInterpreterState_GetID(interp), data); - PyThread_release_lock(mutex); - if (res != 0) { - // We may chain an exception here: - (void)_release_xid_data(data, 0); - PyMem_Free(data); - return res; - } - - return 0; -} - -static int -_channel_recv(_channels *channels, int64_t id, PyObject **res) -{ - int err; - *res = NULL; - - PyInterpreterState *interp = _get_current_interp(); - if (interp == NULL) { - // XXX Is this always an error? - if (PyErr_Occurred()) { - return -1; - } - return 0; - } - - // Look up the channel. - PyThread_type_lock mutex = NULL; - _PyChannelState *chan = NULL; - err = _channels_lookup(channels, id, &mutex, &chan); - if (err != 0) { - return err; - } - assert(chan != NULL); - // Past this point we are responsible for releasing the mutex. - - // Pop off the next item from the channel. - _PyCrossInterpreterData *data = NULL; - err = _channel_next(chan, PyInterpreterState_GetID(interp), &data); - PyThread_release_lock(mutex); - if (err != 0) { - return err; - } - else if (data == NULL) { - assert(!PyErr_Occurred()); - return 0; - } - - // Convert the data back to an object. - PyObject *obj = _PyCrossInterpreterData_NewObject(data); - if (obj == NULL) { - assert(PyErr_Occurred()); - (void)_release_xid_data(data, 1); - PyMem_Free(data); - return -1; - } - int release_res = _release_xid_data(data, 0); - PyMem_Free(data); - if (release_res < 0) { - // The source interpreter has been destroyed already. - assert(PyErr_Occurred()); - Py_DECREF(obj); - return -1; - } - - *res = obj; - return 0; -} - -static int -_channel_drop(_channels *channels, int64_t id, int send, int recv) -{ - PyInterpreterState *interp = _get_current_interp(); - if (interp == NULL) { - return -1; - } - - // Look up the channel. - PyThread_type_lock mutex = NULL; - _PyChannelState *chan = NULL; - int err = _channels_lookup(channels, id, &mutex, &chan); - if (err != 0) { - return err; - } - // Past this point we are responsible for releasing the mutex. - - // Close one or both of the two ends. - int res = _channel_close_interpreter(chan, PyInterpreterState_GetID(interp), send-recv); - PyThread_release_lock(mutex); - return res; -} - -static int -_channel_close(_channels *channels, int64_t id, int end, int force) -{ - return _channels_close(channels, id, NULL, end, force); -} - -static int -_channel_is_associated(_channels *channels, int64_t cid, int64_t interp, - int send) -{ - _PyChannelState *chan = NULL; - int err = _channels_lookup(channels, cid, NULL, &chan); - if (err != 0) { - return err; - } - else if (send && chan->closing != NULL) { - return ERR_CHANNEL_CLOSED; - } - - _channelend *end = _channelend_find(send ? chan->ends->send : chan->ends->recv, - interp, NULL); - - return (end != NULL && end->open); -} - -/* ChannelID class */ - -typedef struct channelid { - PyObject_HEAD - int64_t id; - int end; - int resolve; - _channels *channels; -} channelid; - -struct channel_id_converter_data { - PyObject *module; - int64_t cid; -}; - -static int -channel_id_converter(PyObject *arg, void *ptr) -{ - int64_t cid; - struct channel_id_converter_data *data = ptr; - module_state *state = get_module_state(data->module); - assert(state != NULL); - if (PyObject_TypeCheck(arg, state->ChannelIDType)) { - cid = ((channelid *)arg)->id; - } - else if (PyIndex_Check(arg)) { - cid = PyLong_AsLongLong(arg); - if (cid == -1 && PyErr_Occurred()) { - return 0; - } - if (cid < 0) { - PyErr_Format(PyExc_ValueError, - "channel ID must be a non-negative int, got %R", arg); - return 0; - } - } - else { - PyErr_Format(PyExc_TypeError, - "channel ID must be an int, got %.100s", - Py_TYPE(arg)->tp_name); - return 0; - } - data->cid = cid; - return 1; -} - -static int -newchannelid(PyTypeObject *cls, int64_t cid, int end, _channels *channels, - int force, int resolve, channelid **res) -{ - *res = NULL; - - channelid *self = PyObject_New(channelid, cls); - if (self == NULL) { - return -1; - } - self->id = cid; - self->end = end; - self->resolve = resolve; - self->channels = channels; - - int err = _channels_add_id_object(channels, cid); - if (err != 0) { - if (force && err == ERR_CHANNEL_NOT_FOUND) { - assert(!PyErr_Occurred()); - } - else { - Py_DECREF((PyObject *)self); - return err; - } - } - - *res = self; - return 0; -} - -static _channels * _global_channels(void); - -static PyObject * -_channelid_new(PyObject *mod, PyTypeObject *cls, - PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"id", "send", "recv", "force", "_resolve", NULL}; - int64_t cid; - struct channel_id_converter_data cid_data = { - .module = mod, - }; - int send = -1; - int recv = -1; - int force = 0; - int resolve = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "O&|$pppp:ChannelID.__new__", kwlist, - channel_id_converter, &cid_data, - &send, &recv, &force, &resolve)) { - return NULL; - } - cid = cid_data.cid; - - // Handle "send" and "recv". - if (send == 0 && recv == 0) { - PyErr_SetString(PyExc_ValueError, - "'send' and 'recv' cannot both be False"); - return NULL; - } - - int end = 0; - if (send == 1) { - if (recv == 0 || recv == -1) { - end = CHANNEL_SEND; - } - } - else if (recv == 1) { - end = CHANNEL_RECV; - } - - PyObject *id = NULL; - int err = newchannelid(cls, cid, end, _global_channels(), - force, resolve, - (channelid **)&id); - if (handle_channel_error(err, mod, cid)) { - assert(id == NULL); - return NULL; - } - assert(id != NULL); - return id; -} - -static void -channelid_dealloc(PyObject *self) -{ - int64_t cid = ((channelid *)self)->id; - _channels *channels = ((channelid *)self)->channels; - - PyTypeObject *tp = Py_TYPE(self); - tp->tp_free(self); - /* "Instances of heap-allocated types hold a reference to their type." - * See: https://docs.python.org/3.11/howto/isolating-extensions.html#garbage-collection-protocol - * See: https://docs.python.org/3.11/c-api/typeobj.html#c.PyTypeObject.tp_traverse - */ - // XXX Why don't we implement Py_TPFLAGS_HAVE_GC, e.g. Py_tp_traverse, - // like we do for _abc._abc_data? - Py_DECREF(tp); - - _channels_drop_id_object(channels, cid); -} - -static PyObject * -channelid_repr(PyObject *self) -{ - PyTypeObject *type = Py_TYPE(self); - const char *name = _PyType_Name(type); - - channelid *cid = (channelid *)self; - const char *fmt; - if (cid->end == CHANNEL_SEND) { - fmt = "%s(%" PRId64 ", send=True)"; - } - else if (cid->end == CHANNEL_RECV) { - fmt = "%s(%" PRId64 ", recv=True)"; - } - else { - fmt = "%s(%" PRId64 ")"; - } - return PyUnicode_FromFormat(fmt, name, cid->id); -} - -static PyObject * -channelid_str(PyObject *self) -{ - channelid *cid = (channelid *)self; - return PyUnicode_FromFormat("%" PRId64 "", cid->id); -} - -static PyObject * -channelid_int(PyObject *self) -{ - channelid *cid = (channelid *)self; - return PyLong_FromLongLong(cid->id); -} - -static Py_hash_t -channelid_hash(PyObject *self) -{ - channelid *cid = (channelid *)self; - PyObject *id = PyLong_FromLongLong(cid->id); - if (id == NULL) { - return -1; - } - Py_hash_t hash = PyObject_Hash(id); - Py_DECREF(id); - return hash; -} - -static PyObject * -channelid_richcompare(PyObject *self, PyObject *other, int op) -{ - PyObject *res = NULL; - if (op != Py_EQ && op != Py_NE) { - Py_RETURN_NOTIMPLEMENTED; - } - - PyObject *mod = get_module_from_type(Py_TYPE(self)); - if (mod == NULL) { - return NULL; - } - module_state *state = get_module_state(mod); - if (state == NULL) { - goto done; - } - - if (!PyObject_TypeCheck(self, state->ChannelIDType)) { - res = Py_NewRef(Py_NotImplemented); - goto done; - } - - channelid *cid = (channelid *)self; - int equal; - if (PyObject_TypeCheck(other, state->ChannelIDType)) { - channelid *othercid = (channelid *)other; - equal = (cid->end == othercid->end) && (cid->id == othercid->id); - } - else if (PyLong_Check(other)) { - /* Fast path */ - int overflow; - long long othercid = PyLong_AsLongLongAndOverflow(other, &overflow); - if (othercid == -1 && PyErr_Occurred()) { - goto done; - } - equal = !overflow && (othercid >= 0) && (cid->id == othercid); - } - else if (PyNumber_Check(other)) { - PyObject *pyid = PyLong_FromLongLong(cid->id); - if (pyid == NULL) { - goto done; - } - res = PyObject_RichCompare(pyid, other, op); - Py_DECREF(pyid); - goto done; - } - else { - res = Py_NewRef(Py_NotImplemented); - goto done; - } - - if ((op == Py_EQ && equal) || (op == Py_NE && !equal)) { - res = Py_NewRef(Py_True); - } - else { - res = Py_NewRef(Py_False); - } - -done: - Py_DECREF(mod); - return res; -} - -static PyObject * -_channel_from_cid(PyObject *cid, int end) -{ - PyObject *highlevel = PyImport_ImportModule("interpreters"); - if (highlevel == NULL) { - PyErr_Clear(); - highlevel = PyImport_ImportModule("test.support.interpreters"); - if (highlevel == NULL) { - return NULL; - } - } - const char *clsname = (end == CHANNEL_RECV) ? "RecvChannel" : - "SendChannel"; - PyObject *cls = PyObject_GetAttrString(highlevel, clsname); - Py_DECREF(highlevel); - if (cls == NULL) { - return NULL; - } - PyObject *chan = PyObject_CallFunctionObjArgs(cls, cid, NULL); - Py_DECREF(cls); - if (chan == NULL) { - return NULL; - } - return chan; -} - -struct _channelid_xid { - int64_t id; - int end; - int resolve; -}; - -static PyObject * -_channelid_from_xid(_PyCrossInterpreterData *data) -{ - struct _channelid_xid *xid = (struct _channelid_xid *)data->data; - - PyObject *mod = _get_current_module(); - if (mod == NULL) { - return NULL; - } - module_state *state = get_module_state(mod); - if (state == NULL) { - return NULL; + goto finally; } - // Note that we do not preserve the "resolve" flag. - PyObject *cid = NULL; - int err = newchannelid(state->ChannelIDType, xid->id, xid->end, - _global_channels(), 0, 0, - (channelid **)&cid); - if (err != 0) { - assert(cid == NULL); - (void)handle_channel_error(err, mod, xid->id); - goto done; - } - assert(cid != NULL); - if (xid->end == 0) { - goto done; + PyObject *name = PyUnicode_FromFormat("%S", exctype); + if (name == NULL) { + failure = "unable to format exception type name"; + goto finally; } - if (!xid->resolve) { - goto done; + err->name = _copy_raw_string(name); + Py_DECREF(name); + if (err->name == NULL) { + if (PyErr_ExceptionMatches(PyExc_MemoryError)) { + failure = "out of memory copying exception type name"; + } else { + failure = "unable to encode and copy exception type name"; + } + goto finally; } - /* Try returning a high-level channel end but fall back to the ID. */ - PyObject *chan = _channel_from_cid(cid, xid->end); - if (chan == NULL) { - PyErr_Clear(); - goto done; + if (exc != NULL) { + PyObject *msg = PyUnicode_FromFormat("%S", exc); + if (msg == NULL) { + failure = "unable to format exception message"; + goto finally; + } + err->msg = _copy_raw_string(msg); + Py_DECREF(msg); + if (err->msg == NULL) { + if (PyErr_ExceptionMatches(PyExc_MemoryError)) { + failure = "out of memory copying exception message"; + } else { + failure = "unable to encode and copy exception message"; + } + goto finally; + } } - Py_DECREF(cid); - cid = chan; -done: - Py_DECREF(mod); - return cid; -} - -static int -_channelid_shared(PyThreadState *tstate, PyObject *obj, - _PyCrossInterpreterData *data) -{ - if (_PyCrossInterpreterData_InitWithSize( - data, tstate->interp, sizeof(struct _channelid_xid), obj, - _channelid_from_xid - ) < 0) - { - return -1; +finally: + if (failure != NULL) { + PyErr_Clear(); + if (err->name != NULL) { + PyMem_Free(err->name); + err->name = NULL; + } + err->msg = failure; } - struct _channelid_xid *xid = (struct _channelid_xid *)data->data; - xid->id = ((channelid *)obj)->id; - xid->end = ((channelid *)obj)->end; - xid->resolve = ((channelid *)obj)->resolve; - return 0; + return err; } -static PyObject * -channelid_end(PyObject *self, void *end) +static void +_sharedexception_apply(_sharedexception *exc, PyObject *wrapperclass) { - int force = 1; - channelid *cid = (channelid *)self; - if (end != NULL) { - PyObject *id = NULL; - int err = newchannelid(Py_TYPE(self), cid->id, *(int *)end, - cid->channels, force, cid->resolve, - (channelid **)&id); - if (err != 0) { - assert(id == NULL); - PyObject *mod = get_module_from_type(Py_TYPE(self)); - if (mod == NULL) { - return NULL; - } - (void)handle_channel_error(err, mod, cid->id); - Py_DECREF(mod); - return NULL; + if (exc->name != NULL) { + if (exc->msg != NULL) { + PyErr_Format(wrapperclass, "%s: %s", exc->name, exc->msg); + } + else { + PyErr_SetString(wrapperclass, exc->name); } - assert(id != NULL); - return id; } - - if (cid->end == CHANNEL_SEND) { - return PyUnicode_InternFromString("send"); + else if (exc->msg != NULL) { + PyErr_SetString(wrapperclass, exc->msg); } - if (cid->end == CHANNEL_RECV) { - return PyUnicode_InternFromString("recv"); + else { + PyErr_SetNone(wrapperclass); } - return PyUnicode_InternFromString("both"); } -static int _channelid_end_send = CHANNEL_SEND; -static int _channelid_end_recv = CHANNEL_RECV; - -static PyGetSetDef channelid_getsets[] = { - {"end", (getter)channelid_end, NULL, - PyDoc_STR("'send', 'recv', or 'both'")}, - {"send", (getter)channelid_end, NULL, - PyDoc_STR("the 'send' end of the channel"), &_channelid_end_send}, - {"recv", (getter)channelid_end, NULL, - PyDoc_STR("the 'recv' end of the channel"), &_channelid_end_recv}, - {NULL} -}; - -PyDoc_STRVAR(channelid_doc, -"A channel ID identifies a channel and may be used as an int."); - -static PyType_Slot ChannelIDType_slots[] = { - {Py_tp_dealloc, (destructor)channelid_dealloc}, - {Py_tp_doc, (void *)channelid_doc}, - {Py_tp_repr, (reprfunc)channelid_repr}, - {Py_tp_str, (reprfunc)channelid_str}, - {Py_tp_hash, channelid_hash}, - {Py_tp_richcompare, channelid_richcompare}, - {Py_tp_getset, channelid_getsets}, - // number slots - {Py_nb_int, (unaryfunc)channelid_int}, - {Py_nb_index, (unaryfunc)channelid_int}, - {0, NULL}, -}; - -static PyType_Spec ChannelIDType_spec = { - .name = "_xxsubinterpreters.ChannelID", - .basicsize = sizeof(channelid), - .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE), - .slots = ChannelIDType_slots, -}; - /* interpreter-specific code ************************************************/ static int -interp_exceptions_init(PyObject *mod) +exceptions_init(PyObject *mod) { module_state *state = get_module_state(mod); if (state == NULL) { @@ -2145,24 +430,12 @@ _ensure_not_running(PyInterpreterState *interp) static int _run_script(PyInterpreterState *interp, const char *codestr, - _sharedns *shared, int needs_import, - _sharedexception **exc) + _sharedns *shared, _sharedexception **exc) { PyObject *exctype = NULL; PyObject *excval = NULL; PyObject *tb = NULL; - if (needs_import) { - // It might not have been imported yet in the current interpreter. - // However, it will (almost) always have been imported already - // in the main interpreter. - PyObject *mod = PyImport_ImportModule(MODULE_NAME); - if (mod == NULL) { - goto error; - } - Py_DECREF(mod); - } - PyObject *main_mod = _PyInterpreterState_GetMainModule(interp); if (main_mod == NULL) { goto error; @@ -2223,9 +496,7 @@ _run_script_in_interpreter(PyObject *mod, PyInterpreterState *interp, } module_state *state = get_module_state(mod); - int needs_import = 0; - _sharedns *shared = _get_shared_ns(shareables, state->ChannelIDType, - &needs_import); + _sharedns *shared = _get_shared_ns(shareables); if (shared == NULL && PyErr_Occurred()) { return -1; } @@ -2241,7 +512,7 @@ _run_script_in_interpreter(PyObject *mod, PyInterpreterState *interp, // Run the script. _sharedexception *exc = NULL; - int result = _run_script(interp, codestr, shared, needs_import, &exc); + int result = _run_script(interp, codestr, shared, &exc); // Switch back. if (save_tstate != NULL) { @@ -2269,50 +540,6 @@ _run_script_in_interpreter(PyObject *mod, PyInterpreterState *interp, /* module level code ********************************************************/ -/* globals is the process-global state for the module. It holds all - the data that we need to share between interpreters, so it cannot - hold PyObject values. */ -static struct globals { - int module_count; - _channels channels; -} _globals = {0}; - -static int -_globals_init(void) -{ - // XXX This isn't thread-safe. - _globals.module_count++; - if (_globals.module_count > 1) { - // Already initialized. - return 0; - } - - assert(_globals.channels.mutex == NULL); - PyThread_type_lock mutex = PyThread_allocate_lock(); - if (mutex == NULL) { - return ERR_CHANNELS_MUTEX_INIT; - } - _channels_init(&_globals.channels, mutex); - return 0; -} - -static void -_globals_fini(void) -{ - // XXX This isn't thread-safe. - _globals.module_count--; - if (_globals.module_count > 0) { - return; - } - - _channels_fini(&_globals.channels); -} - -static _channels * -_global_channels(void) { - return &_globals.channels; -} - static PyObject * interp_create(PyObject *self, PyObject *args, PyObject *kwds) { @@ -2578,358 +805,6 @@ PyDoc_STRVAR(is_running_doc, \n\ Return whether or not the identified interpreter is running."); -static PyObject * -channel_create(PyObject *self, PyObject *Py_UNUSED(ignored)) -{ - int64_t cid = _channel_create(&_globals.channels); - if (cid < 0) { - (void)handle_channel_error(-1, self, cid); - return NULL; - } - module_state *state = get_module_state(self); - if (state == NULL) { - return NULL; - } - PyObject *id = NULL; - int err = newchannelid(state->ChannelIDType, cid, 0, - &_globals.channels, 0, 0, - (channelid **)&id); - if (handle_channel_error(err, self, cid)) { - assert(id == NULL); - err = _channel_destroy(&_globals.channels, cid); - if (handle_channel_error(err, self, cid)) { - // XXX issue a warning? - } - return NULL; - } - assert(id != NULL); - assert(((channelid *)id)->channels != NULL); - return id; -} - -PyDoc_STRVAR(channel_create_doc, -"channel_create() -> cid\n\ -\n\ -Create a new cross-interpreter channel and return a unique generated ID."); - -static PyObject * -channel_destroy(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"cid", NULL}; - int64_t cid; - struct channel_id_converter_data cid_data = { - .module = self, - }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&:channel_destroy", kwlist, - channel_id_converter, &cid_data)) { - return NULL; - } - cid = cid_data.cid; - - int err = _channel_destroy(&_globals.channels, cid); - if (handle_channel_error(err, self, cid)) { - return NULL; - } - Py_RETURN_NONE; -} - -PyDoc_STRVAR(channel_destroy_doc, -"channel_destroy(cid)\n\ -\n\ -Close and finalize the channel. Afterward attempts to use the channel\n\ -will behave as though it never existed."); - -static PyObject * -channel_list_all(PyObject *self, PyObject *Py_UNUSED(ignored)) -{ - int64_t count = 0; - int64_t *cids = _channels_list_all(&_globals.channels, &count); - if (cids == NULL) { - if (count == 0) { - return PyList_New(0); - } - return NULL; - } - PyObject *ids = PyList_New((Py_ssize_t)count); - if (ids == NULL) { - goto finally; - } - module_state *state = get_module_state(self); - if (state == NULL) { - Py_DECREF(ids); - ids = NULL; - goto finally; - } - int64_t *cur = cids; - for (int64_t i=0; i < count; cur++, i++) { - PyObject *id = NULL; - int err = newchannelid(state->ChannelIDType, *cur, 0, - &_globals.channels, 0, 0, - (channelid **)&id); - if (handle_channel_error(err, self, *cur)) { - assert(id == NULL); - Py_SETREF(ids, NULL); - break; - } - assert(id != NULL); - PyList_SET_ITEM(ids, (Py_ssize_t)i, id); - } - -finally: - PyMem_Free(cids); - return ids; -} - -PyDoc_STRVAR(channel_list_all_doc, -"channel_list_all() -> [cid]\n\ -\n\ -Return the list of all IDs for active channels."); - -static PyObject * -channel_list_interpreters(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"cid", "send", NULL}; - int64_t cid; /* Channel ID */ - struct channel_id_converter_data cid_data = { - .module = self, - }; - int send = 0; /* Send or receive end? */ - int64_t id; - PyObject *ids, *id_obj; - PyInterpreterState *interp; - - if (!PyArg_ParseTupleAndKeywords( - args, kwds, "O&$p:channel_list_interpreters", - kwlist, channel_id_converter, &cid_data, &send)) { - return NULL; - } - cid = cid_data.cid; - - ids = PyList_New(0); - if (ids == NULL) { - goto except; - } - - interp = PyInterpreterState_Head(); - while (interp != NULL) { - id = PyInterpreterState_GetID(interp); - assert(id >= 0); - int res = _channel_is_associated(&_globals.channels, cid, id, send); - if (res < 0) { - (void)handle_channel_error(res, self, cid); - goto except; - } - if (res) { - id_obj = _PyInterpreterState_GetIDObject(interp); - if (id_obj == NULL) { - goto except; - } - res = PyList_Insert(ids, 0, id_obj); - Py_DECREF(id_obj); - if (res < 0) { - goto except; - } - } - interp = PyInterpreterState_Next(interp); - } - - goto finally; - -except: - Py_CLEAR(ids); - -finally: - return ids; -} - -PyDoc_STRVAR(channel_list_interpreters_doc, -"channel_list_interpreters(cid, *, send) -> [id]\n\ -\n\ -Return the list of all interpreter IDs associated with an end of the channel.\n\ -\n\ -The 'send' argument should be a boolean indicating whether to use the send or\n\ -receive end."); - - -static PyObject * -channel_send(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"cid", "obj", NULL}; - int64_t cid; - struct channel_id_converter_data cid_data = { - .module = self, - }; - PyObject *obj; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&O:channel_send", kwlist, - channel_id_converter, &cid_data, &obj)) { - return NULL; - } - cid = cid_data.cid; - - int err = _channel_send(&_globals.channels, cid, obj); - if (handle_channel_error(err, self, cid)) { - return NULL; - } - Py_RETURN_NONE; -} - -PyDoc_STRVAR(channel_send_doc, -"channel_send(cid, obj)\n\ -\n\ -Add the object's data to the channel's queue."); - -static PyObject * -channel_recv(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"cid", "default", NULL}; - int64_t cid; - struct channel_id_converter_data cid_data = { - .module = self, - }; - PyObject *dflt = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|O:channel_recv", kwlist, - channel_id_converter, &cid_data, &dflt)) { - return NULL; - } - cid = cid_data.cid; - - PyObject *obj = NULL; - int err = _channel_recv(&_globals.channels, cid, &obj); - if (handle_channel_error(err, self, cid)) { - return NULL; - } - Py_XINCREF(dflt); - if (obj == NULL) { - // Use the default. - if (dflt == NULL) { - (void)handle_channel_error(ERR_CHANNEL_EMPTY, self, cid); - return NULL; - } - obj = Py_NewRef(dflt); - } - Py_XDECREF(dflt); - return obj; -} - -PyDoc_STRVAR(channel_recv_doc, -"channel_recv(cid, [default]) -> obj\n\ -\n\ -Return a new object from the data at the front of the channel's queue.\n\ -\n\ -If there is nothing to receive then raise ChannelEmptyError, unless\n\ -a default value is provided. In that case return it."); - -static PyObject * -channel_close(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"cid", "send", "recv", "force", NULL}; - int64_t cid; - struct channel_id_converter_data cid_data = { - .module = self, - }; - int send = 0; - int recv = 0; - int force = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "O&|$ppp:channel_close", kwlist, - channel_id_converter, &cid_data, - &send, &recv, &force)) { - return NULL; - } - cid = cid_data.cid; - - int err = _channel_close(&_globals.channels, cid, send-recv, force); - if (handle_channel_error(err, self, cid)) { - return NULL; - } - Py_RETURN_NONE; -} - -PyDoc_STRVAR(channel_close_doc, -"channel_close(cid, *, send=None, recv=None, force=False)\n\ -\n\ -Close the channel for all interpreters.\n\ -\n\ -If the channel is empty then the keyword args are ignored and both\n\ -ends are immediately closed. Otherwise, if 'force' is True then\n\ -all queued items are released and both ends are immediately\n\ -closed.\n\ -\n\ -If the channel is not empty *and* 'force' is False then following\n\ -happens:\n\ -\n\ - * recv is True (regardless of send):\n\ - - raise ChannelNotEmptyError\n\ - * recv is None and send is None:\n\ - - raise ChannelNotEmptyError\n\ - * send is True and recv is not True:\n\ - - fully close the 'send' end\n\ - - close the 'recv' end to interpreters not already receiving\n\ - - fully close it once empty\n\ -\n\ -Closing an already closed channel results in a ChannelClosedError.\n\ -\n\ -Once the channel's ID has no more ref counts in any interpreter\n\ -the channel will be destroyed."); - -static PyObject * -channel_release(PyObject *self, PyObject *args, PyObject *kwds) -{ - // Note that only the current interpreter is affected. - static char *kwlist[] = {"cid", "send", "recv", "force", NULL}; - int64_t cid; - struct channel_id_converter_data cid_data = { - .module = self, - }; - int send = 0; - int recv = 0; - int force = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "O&|$ppp:channel_release", kwlist, - channel_id_converter, &cid_data, - &send, &recv, &force)) { - return NULL; - } - cid = cid_data.cid; - if (send == 0 && recv == 0) { - send = 1; - recv = 1; - } - - // XXX Handle force is True. - // XXX Fix implicit release. - - int err = _channel_drop(&_globals.channels, cid, send, recv); - if (handle_channel_error(err, self, cid)) { - return NULL; - } - Py_RETURN_NONE; -} - -PyDoc_STRVAR(channel_release_doc, -"channel_release(cid, *, send=None, recv=None, force=True)\n\ -\n\ -Close the channel for the current interpreter. 'send' and 'recv'\n\ -(bool) may be used to indicate the ends to close. By default both\n\ -ends are closed. Closing an already closed end is a noop."); - -static PyObject * -channel__channel_id(PyObject *self, PyObject *args, PyObject *kwds) -{ - module_state *state = get_module_state(self); - if (state == NULL) { - return NULL; - } - PyTypeObject *cls = state->ChannelIDType; - PyObject *mod = get_module_from_owned_type(cls); - if (mod == NULL) { - return NULL; - } - PyObject *cid = _channelid_new(mod, cls, args, kwds); - Py_DECREF(mod); - return cid; -} - static PyMethodDef module_functions[] = { {"create", _PyCFunction_CAST(interp_create), METH_VARARGS | METH_KEYWORDS, create_doc}, @@ -2941,6 +816,7 @@ static PyMethodDef module_functions[] = { METH_NOARGS, get_current_doc}, {"get_main", interp_get_main, METH_NOARGS, get_main_doc}, + {"is_running", _PyCFunction_CAST(interp_is_running), METH_VARARGS | METH_KEYWORDS, is_running_doc}, {"run_string", _PyCFunction_CAST(interp_run_string), @@ -2949,25 +825,6 @@ static PyMethodDef module_functions[] = { {"is_shareable", _PyCFunction_CAST(object_is_shareable), METH_VARARGS | METH_KEYWORDS, is_shareable_doc}, - {"channel_create", channel_create, - METH_NOARGS, channel_create_doc}, - {"channel_destroy", _PyCFunction_CAST(channel_destroy), - METH_VARARGS | METH_KEYWORDS, channel_destroy_doc}, - {"channel_list_all", channel_list_all, - METH_NOARGS, channel_list_all_doc}, - {"channel_list_interpreters", _PyCFunction_CAST(channel_list_interpreters), - METH_VARARGS | METH_KEYWORDS, channel_list_interpreters_doc}, - {"channel_send", _PyCFunction_CAST(channel_send), - METH_VARARGS | METH_KEYWORDS, channel_send_doc}, - {"channel_recv", _PyCFunction_CAST(channel_recv), - METH_VARARGS | METH_KEYWORDS, channel_recv_doc}, - {"channel_close", _PyCFunction_CAST(channel_close), - METH_VARARGS | METH_KEYWORDS, channel_close_doc}, - {"channel_release", _PyCFunction_CAST(channel_release), - METH_VARARGS | METH_KEYWORDS, channel_release_doc}, - {"_channel_id", _PyCFunction_CAST(channel__channel_id), - METH_VARARGS | METH_KEYWORDS, NULL}, - {NULL, NULL} /* sentinel */ }; @@ -2981,29 +838,8 @@ The 'interpreters' module provides a more convenient interface."); static int module_exec(PyObject *mod) { - if (_globals_init() != 0) { - return -1; - } - - module_state *state = get_module_state(mod); - if (state == NULL) { - goto error; - } - /* Add exception types */ - if (interp_exceptions_init(mod) != 0) { - goto error; - } - if (channel_exceptions_init(mod) != 0) { - goto error; - } - - /* Add other types */ - - // ChannelID - state->ChannelIDType = add_new_type( - mod, &ChannelIDType_spec, _channelid_shared); - if (state->ChannelIDType == NULL) { + if (exceptions_init(mod) != 0) { goto error; } @@ -3015,8 +851,6 @@ module_exec(PyObject *mod) return 0; error: - (void)_PyCrossInterpreterData_UnregisterClass(state->ChannelIDType); - _globals_fini(); return -1; } @@ -3049,7 +883,6 @@ module_free(void *mod) module_state *state = get_module_state(mod); assert(state != NULL); clear_module_state(state); - _globals_fini(); } static struct PyModuleDef moduledef = { diff --git a/PC/config.c b/PC/config.c index 9d900c78e40d001..cdb5db23c4ae498 100644 --- a/PC/config.c +++ b/PC/config.c @@ -37,6 +37,7 @@ extern PyObject* PyInit__weakref(void); /* XXX: These two should really be extracted to standalone extensions. */ extern PyObject* PyInit_xxsubtype(void); extern PyObject* PyInit__xxsubinterpreters(void); +extern PyObject* PyInit__xxinterpchannels(void); extern PyObject* PyInit__random(void); extern PyObject* PyInit_itertools(void); extern PyObject* PyInit__collections(void); @@ -134,6 +135,7 @@ struct _inittab _PyImport_Inittab[] = { {"xxsubtype", PyInit_xxsubtype}, {"_xxsubinterpreters", PyInit__xxsubinterpreters}, + {"_xxinterpchannels", PyInit__xxinterpchannels}, #ifdef _Py_HAVE_ZLIB {"zlib", PyInit_zlib}, #endif diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index d3bd5b378e0dd0e..397d22abe235039 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -418,6 +418,7 @@ + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index c1b531fd818a97a..bcbedcc3235b3ec 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -1322,6 +1322,9 @@ Modules + + Modules + Parser diff --git a/Tools/build/generate_stdlib_module_names.py b/Tools/build/generate_stdlib_module_names.py index c8a23f41fdd4755..d15e5e2d5450d7c 100644 --- a/Tools/build/generate_stdlib_module_names.py +++ b/Tools/build/generate_stdlib_module_names.py @@ -36,6 +36,7 @@ '_testmultiphase', '_testsinglephase', '_xxsubinterpreters', + '_xxinterpchannels', '_xxtestfuzz', 'idlelib.idle_test', 'test', diff --git a/configure b/configure index 8b707cda62129f0..aef8103085bc207 100755 --- a/configure +++ b/configure @@ -752,6 +752,8 @@ MODULE__MULTIPROCESSING_FALSE MODULE__MULTIPROCESSING_TRUE MODULE__ZONEINFO_FALSE MODULE__ZONEINFO_TRUE +MODULE__XXINTERPCHANNELS_FALSE +MODULE__XXINTERPCHANNELS_TRUE MODULE__XXSUBINTERPRETERS_FALSE MODULE__XXSUBINTERPRETERS_TRUE MODULE__TYPING_FALSE @@ -25615,6 +25617,7 @@ case $ac_sys_system in #( py_cv_module__scproxy=n/a py_cv_module__tkinter=n/a py_cv_module__xxsubinterpreters=n/a + py_cv_module__xxinterpchannels=n/a py_cv_module_grp=n/a py_cv_module_nis=n/a py_cv_module_ossaudiodev=n/a @@ -26057,6 +26060,26 @@ fi +fi + + + if test "$py_cv_module__xxinterpchannels" != "n/a"; then : + py_cv_module__xxinterpchannels=yes +fi + if test "$py_cv_module__xxinterpchannels" = yes; then + MODULE__XXINTERPCHANNELS_TRUE= + MODULE__XXINTERPCHANNELS_FALSE='#' +else + MODULE__XXINTERPCHANNELS_TRUE='#' + MODULE__XXINTERPCHANNELS_FALSE= +fi + + as_fn_append MODULE_BLOCK "MODULE__XXINTERPCHANNELS_STATE=$py_cv_module__xxinterpchannels$as_nl" + if test "x$py_cv_module__xxinterpchannels" = xyes; then : + + + + fi @@ -28236,6 +28259,10 @@ if test -z "${MODULE__XXSUBINTERPRETERS_TRUE}" && test -z "${MODULE__XXSUBINTERP as_fn_error $? "conditional \"MODULE__XXSUBINTERPRETERS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__XXINTERPCHANNELS_TRUE}" && test -z "${MODULE__XXINTERPCHANNELS_FALSE}"; then + as_fn_error $? "conditional \"MODULE__XXINTERPCHANNELS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE__ZONEINFO_TRUE}" && test -z "${MODULE__ZONEINFO_FALSE}"; then as_fn_error $? "conditional \"MODULE__ZONEINFO\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index 5eee4586680dbbe..010bca855f00598 100644 --- a/configure.ac +++ b/configure.ac @@ -7017,6 +7017,7 @@ AS_CASE([$ac_sys_system], [_scproxy], [_tkinter], [_xxsubinterpreters], + [_xxinterpchannels], [grp], [nis], [ossaudiodev], @@ -7135,6 +7136,7 @@ PY_STDLIB_MOD_SIMPLE([select]) PY_STDLIB_MOD_SIMPLE([_struct]) PY_STDLIB_MOD_SIMPLE([_typing]) PY_STDLIB_MOD_SIMPLE([_xxsubinterpreters]) +PY_STDLIB_MOD_SIMPLE([_xxinterpchannels]) PY_STDLIB_MOD_SIMPLE([_zoneinfo]) dnl multiprocessing modules From f11a3d1ebe0c78f8c159c63a37022b9b96f720dd Mon Sep 17 00:00:00 2001 From: Max Bachmann Date: Sat, 4 Feb 2023 04:33:28 +0100 Subject: [PATCH 34/74] Add missing `versionadded` directive for `PyCode_Addr2Location` (#101347) --- Doc/c-api/code.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Doc/c-api/code.rst b/Doc/c-api/code.rst index a6eb86f1a0b5140..ae75d68901d7baf 100644 --- a/Doc/c-api/code.rst +++ b/Doc/c-api/code.rst @@ -77,6 +77,8 @@ bound into a function. Returns ``1`` if the function succeeds and 0 otherwise. + .. versionadded:: 3.11 + .. c:function:: PyObject* PyCode_GetCode(PyCodeObject *co) Equivalent to the Python code ``getattr(co, 'co_code')``. From cef9de62b8bf5e2d11d5a074012dfa81dc4ea935 Mon Sep 17 00:00:00 2001 From: Furkan Onder Date: Sat, 4 Feb 2023 03:49:29 +0000 Subject: [PATCH 35/74] GH-56426: Add cross-reference to the documentation for faulthandler, traceback, and pdb. (#101157) Co-authored-by: C.A.M. Gerlach --- Doc/library/faulthandler.rst | 10 +++++++++- Doc/library/pdb.rst | 9 +++++++++ Doc/library/traceback.rst | 9 ++++++++- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/Doc/library/faulthandler.rst b/Doc/library/faulthandler.rst index 07a7489941442bf..f64dfeb5e081c7c 100644 --- a/Doc/library/faulthandler.rst +++ b/Doc/library/faulthandler.rst @@ -43,6 +43,13 @@ Python is deadlocked. The :ref:`Python Development Mode ` calls :func:`faulthandler.enable` at Python startup. +.. seealso:: + + Module :mod:`pdb` + Interactive source code debugger for Python programs. + + Module :mod:`traceback` + Standard interface to extract, format and print stack traces of Python programs. Dumping the traceback --------------------- @@ -52,6 +59,8 @@ Dumping the traceback Dump the tracebacks of all threads into *file*. If *all_threads* is ``False``, dump only the current thread. + .. seealso:: :func:`traceback.print_tb`, which can be used to print a traceback object. + .. versionchanged:: 3.5 Added support for passing file descriptor to this function. @@ -178,4 +187,3 @@ handler: File "/home/python/cpython/Lib/ctypes/__init__.py", line 486 in string_at File "", line 1 in Segmentation fault - diff --git a/Doc/library/pdb.rst b/Doc/library/pdb.rst index 383c3adcf289d5f..4ae12a5d03a78db 100644 --- a/Doc/library/pdb.rst +++ b/Doc/library/pdb.rst @@ -27,6 +27,15 @@ The debugger is extensible -- it is actually defined as the class :class:`Pdb`. This is currently undocumented but easily understood by reading the source. The extension interface uses the modules :mod:`bdb` and :mod:`cmd`. +.. seealso:: + + Module :mod:`faulthandler` + Used to dump Python tracebacks explicitly, on a fault, after a timeout, + or on a user signal. + + Module :mod:`traceback` + Standard interface to extract, format and print stack traces of Python programs. + The debugger's prompt is ``(Pdb)``. Typical usage to run a program under control of the debugger is:: diff --git a/Doc/library/traceback.rst b/Doc/library/traceback.rst index f8c1eabadacf9f2..69818baf184d7cc 100644 --- a/Doc/library/traceback.rst +++ b/Doc/library/traceback.rst @@ -20,8 +20,15 @@ The module uses traceback objects --- this is the object type that is stored in the :data:`sys.last_traceback` variable and returned as the third item from :func:`sys.exc_info`. -The module defines the following functions: +.. seealso:: + + Module :mod:`faulthandler` + Used to dump Python tracebacks explicitly, on a fault, after a timeout, or on a user signal. + Module :mod:`pdb` + Interactive source code debugger for Python programs. + +The module defines the following functions: .. function:: print_tb(tb, limit=None, file=None) From 144aaa74bbd77aee822ee92344744dbb05aa2f30 Mon Sep 17 00:00:00 2001 From: Dong-hee Na Date: Sat, 4 Feb 2023 16:55:31 +0900 Subject: [PATCH 36/74] =?UTF-8?q?gh-101282:=20Update=20BOLT=20--split-func?= =?UTF-8?q?tions=20flag=20not=20to=20use=20deprecated=20u=E2=80=A6=20(gh-1?= =?UTF-8?q?01557)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gh-101282: Update BOLT --split-functions flag not to use deprecated usage --- Makefile.pre.in | 2 +- .../next/Build/2023-02-04-06-59-07.gh-issue-101282.7sQz5l.rst | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Build/2023-02-04-06-59-07.gh-issue-101282.7sQz5l.rst diff --git a/Makefile.pre.in b/Makefile.pre.in index 618bb7b5f7307db..f2f9371e8ac04de 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -647,7 +647,7 @@ bolt-opt: @PREBOLT_RULE@ @LLVM_BOLT@ ./$(BUILDPYTHON) -instrument -instrumentation-file-append-pid -instrumentation-file=$(abspath $(BUILDPYTHON).bolt) -o $(BUILDPYTHON).bolt_inst ./$(BUILDPYTHON).bolt_inst $(PROFILE_TASK) || true @MERGE_FDATA@ $(BUILDPYTHON).*.fdata > $(BUILDPYTHON).fdata - @LLVM_BOLT@ ./$(BUILDPYTHON) -o $(BUILDPYTHON).bolt -data=$(BUILDPYTHON).fdata -update-debug-sections -reorder-blocks=ext-tsp -reorder-functions=hfsort+ -split-functions=3 -icf=1 -inline-all -split-eh -reorder-functions-use-hot-size -peepholes=all -jump-tables=aggressive -inline-ap -indirect-call-promotion=all -dyno-stats -use-gnu-stack -frame-opt=hot + @LLVM_BOLT@ ./$(BUILDPYTHON) -o $(BUILDPYTHON).bolt -data=$(BUILDPYTHON).fdata -update-debug-sections -reorder-blocks=ext-tsp -reorder-functions=hfsort+ -split-functions -icf=1 -inline-all -split-eh -reorder-functions-use-hot-size -peepholes=all -jump-tables=aggressive -inline-ap -indirect-call-promotion=all -dyno-stats -use-gnu-stack -frame-opt=hot rm -f *.fdata rm -f $(BUILDPYTHON).bolt_inst mv $(BUILDPYTHON).bolt $(BUILDPYTHON) diff --git a/Misc/NEWS.d/next/Build/2023-02-04-06-59-07.gh-issue-101282.7sQz5l.rst b/Misc/NEWS.d/next/Build/2023-02-04-06-59-07.gh-issue-101282.7sQz5l.rst new file mode 100644 index 000000000000000..49d485646673493 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2023-02-04-06-59-07.gh-issue-101282.7sQz5l.rst @@ -0,0 +1,2 @@ +Update BOLT configration not to use depreacted usage of ``--split +functions``. Patch by Dong-hee Na. From a89e6713c4de99d4be5a1304b134e57a24ab10ac Mon Sep 17 00:00:00 2001 From: Ruben Vorderman Date: Sat, 4 Feb 2023 21:07:30 +0100 Subject: [PATCH 37/74] gh-101322: Ensure test_zlib.ZlibDecompressorTest runs, fix errors in ZlibDecompressor (#101323) * Ensure test_zlib.ZlibDecompressorTest actually runs, fix errors in ZlibDecompressor. --- Lib/test/test_zlib.py | 9 +++++++-- .../2023-01-26-06-44-35.gh-issue-101323.h8Hk11.rst | 2 ++ Modules/zlibmodule.c | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2023-01-26-06-44-35.gh-issue-101323.h8Hk11.rst diff --git a/Lib/test/test_zlib.py b/Lib/test/test_zlib.py index ae54f6c46891c68..3dac70eb12852cd 100644 --- a/Lib/test/test_zlib.py +++ b/Lib/test/test_zlib.py @@ -944,13 +944,18 @@ def choose_lines(source, number, seed=None, generator=random): """ -class ZlibDecompressorTest(): +class ZlibDecompressorTest(unittest.TestCase): # Test adopted from test_bz2.py TEXT = HAMLET_SCENE DATA = zlib.compress(HAMLET_SCENE) BAD_DATA = b"Not a valid deflate block" + BIG_TEXT = DATA * ((128 * 1024 // len(DATA)) + 1) + BIG_DATA = zlib.compress(BIG_TEXT) + def test_Constructor(self): - self.assertRaises(TypeError, zlib._ZlibDecompressor, 42) + self.assertRaises(TypeError, zlib._ZlibDecompressor, "ASDA") + self.assertRaises(TypeError, zlib._ZlibDecompressor, -15, "notbytes") + self.assertRaises(TypeError, zlib._ZlibDecompressor, -15, b"bytes", 5) def testDecompress(self): zlibd = zlib._ZlibDecompressor() diff --git a/Misc/NEWS.d/next/Library/2023-01-26-06-44-35.gh-issue-101323.h8Hk11.rst b/Misc/NEWS.d/next/Library/2023-01-26-06-44-35.gh-issue-101323.h8Hk11.rst new file mode 100644 index 000000000000000..f8419e130dbcd7c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-01-26-06-44-35.gh-issue-101323.h8Hk11.rst @@ -0,0 +1,2 @@ +Fix a bug where errors where not thrown by zlib._ZlibDecompressor if +encountered during decompressing. diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c index 1cdfd01320288b3..e2f7dbaca87a9f7 100644 --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -1519,6 +1519,7 @@ decompress_buf(ZlibDecompressor *self, Py_ssize_t max_length) } } else if (err != Z_OK && err != Z_BUF_ERROR) { zlib_error(state, self->zst, err, "while decompressing data"); + goto error; } self->avail_in_real += self->zst.avail_in; From 5a2b984568f72f0d7ff7c7b4ee8ce31af9fd1b7e Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Sat, 4 Feb 2023 17:54:44 -0600 Subject: [PATCH 38/74] GH-100485: Create an alternative code path when an accurate fma() implementation is not available (#101567) --- Lib/test/test_math.py | 5 +++++ Modules/mathmodule.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py index 2c84e55ab45c57d..8d849045b2d11f9 100644 --- a/Lib/test/test_math.py +++ b/Lib/test/test_math.py @@ -1450,6 +1450,11 @@ def Trial(dotfunc, c, n): n = 20 # Length of vectors c = 1e30 # Target condition number + # If the following test fails, it means that the C math library + # implementation of fma() is not compliant with the C99 standard + # and is inaccurate. To solve this problem, make a new build + # with the symbol UNRELIABLE_FMA defined. That will enable a + # slower but accurate code path that avoids the fma() call. relative_err = median(Trial(math.sumprod, c, n) for i in range(times)) self.assertLess(relative_err, 1e-16) diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index e6cdb3bae1ecff1..654336d6d9f4bc3 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -2851,6 +2851,8 @@ dl_sum(double a, double b) return (DoubleLength) {x, y}; } +#ifndef UNRELIABLE_FMA + static DoubleLength dl_mul(double x, double y) { @@ -2860,6 +2862,47 @@ dl_mul(double x, double y) return (DoubleLength) {z, zz}; } +#else + +/* + The default implementation of dl_mul() depends on the C math library + having an accurate fma() function as required by § 7.12.13.1 of the + C99 standard. + + The UNRELIABLE_FMA option is provided as a slower but accurate + alternative for builds where the fma() function is found wanting. + The speed penalty may be modest (17% slower on an Apple M1 Max), + so don't hesitate to enable this build option. + + The algorithms are from the T. J. Dekker paper: + A Floating-Point Technique for Extending the Available Precision + https://csclub.uwaterloo.ca/~pbarfuss/dekker1971.pdf +*/ + +static DoubleLength +dl_split(double x) { + // Dekker (5.5) and (5.6). + double t = x * 134217729.0; // Veltkamp constant = 2.0 ** 27 + 1 + double hi = t - (t - x); + double lo = x - hi; + return (DoubleLength) {hi, lo}; +} + +static DoubleLength +dl_mul(double x, double y) +{ + // Dekker (5.12) and mul12() + DoubleLength xx = dl_split(x); + DoubleLength yy = dl_split(y); + double p = xx.hi * yy.hi; + double q = xx.hi * yy.lo + xx.lo * yy.hi; + double z = p + q; + double zz = p - z + q + xx.lo * yy.lo; + return (DoubleLength) {z, zz}; +} + +#endif + typedef struct { double hi; double lo; double tiny; } TripleLength; static const TripleLength tl_zero = {0.0, 0.0, 0.0}; From ddd619cffa457776a22f224b7111bd39de289d66 Mon Sep 17 00:00:00 2001 From: Alexander Belopolsky Date: Sun, 5 Feb 2023 11:14:15 +0400 Subject: [PATCH 39/74] Fix detection of presence of time.tzset (gh-101539) (#101540) Resolves gh-101539 Related to gh-31898 --- Lib/test/datetimetester.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 6a1df174a1b9725..570f803918c1ef5 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -6173,7 +6173,7 @@ def test_gaps(self): self.assertEqual(ldt.fold, 0) @unittest.skipUnless( - hasattr(time, "tzset"), "time module has no attribute tzset" + hasattr(_time, "tzset"), "time module has no attribute tzset" ) def test_system_transitions(self): if ('Riyadh8' in self.zonename or From 6e4a521c2ab84c082ad71e540b045699f0dbbc11 Mon Sep 17 00:00:00 2001 From: alnoki <43892045+alnoki@users.noreply.github.com> Date: Sun, 5 Feb 2023 01:45:07 -0800 Subject: [PATCH 40/74] Add missing preposition in argparse docs (#101548) --- Doc/library/argparse.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index 475cac70291e9a3..dbaa5d0d9b995b9 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -31,7 +31,7 @@ Core Functionality The :mod:`argparse` module's support for command-line interfaces is built around an instance of :class:`argparse.ArgumentParser`. It is a container for -argument specifications and has options that apply the parser as whole:: +argument specifications and has options that apply to the parser as whole:: parser = argparse.ArgumentParser( prog = 'ProgramName', From 9b60ee976a6b66fe96c2d39051612999c26561e5 Mon Sep 17 00:00:00 2001 From: busywhitespace Date: Sun, 5 Feb 2023 10:55:36 +0100 Subject: [PATCH 41/74] gh-101221: Add options in the documentation of timeit command (#101222) --- Doc/library/timeit.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/timeit.rst b/Doc/library/timeit.rst index 5437704cec337b8..32ab565aba0c08b 100644 --- a/Doc/library/timeit.rst +++ b/Doc/library/timeit.rst @@ -206,7 +206,7 @@ Command-Line Interface When called as a program from the command line, the following form is used:: - python -m timeit [-n N] [-r N] [-u U] [-s S] [-h] [statement ...] + python -m timeit [-n N] [-r N] [-u U] [-s S] [-p] [-v] [-h] [statement ...] Where the following options are understood: From 39017e04b55d4c110787551dc9a0cb753f27d700 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sun, 5 Feb 2023 10:02:53 +0000 Subject: [PATCH 42/74] gh-101266: Fix __sizeof__ for subclasses of int (#101394) Fix the behaviour of the `__sizeof__` method (and hence the results returned by `sys.getsizeof`) for subclasses of `int`. Previously, `int` subclasses gave identical results to the `int` base class, ignoring the presence of the instance dictionary. * Issue: gh-101266 --- Lib/test/test_long.py | 39 +++++++++++++++++++ ...-01-28-13-11-52.gh-issue-101266.AxV3OF.rst | 1 + Objects/boolobject.c | 6 ++- Objects/longobject.c | 11 ++---- 4 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-01-28-13-11-52.gh-issue-101266.AxV3OF.rst diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py index 569ab15820e3023..d299c34cec076d0 100644 --- a/Lib/test/test_long.py +++ b/Lib/test/test_long.py @@ -1601,5 +1601,44 @@ def test_square(self): self.assertEqual(n**2, (1 << (2 * bitlen)) - (1 << (bitlen + 1)) + 1) + def test___sizeof__(self): + self.assertEqual(int.__itemsize__, sys.int_info.sizeof_digit) + + # Pairs (test_value, number of allocated digits) + test_values = [ + # We always allocate space for at least one digit, even for + # a value of zero; sys.getsizeof should reflect that. + (0, 1), + (1, 1), + (-1, 1), + (BASE-1, 1), + (1-BASE, 1), + (BASE, 2), + (-BASE, 2), + (BASE*BASE - 1, 2), + (BASE*BASE, 3), + ] + + for value, ndigits in test_values: + with self.subTest(value): + self.assertEqual( + value.__sizeof__(), + int.__basicsize__ + int.__itemsize__ * ndigits + ) + + # Same test for a subclass of int. + class MyInt(int): + pass + + self.assertEqual(MyInt.__itemsize__, sys.int_info.sizeof_digit) + + for value, ndigits in test_values: + with self.subTest(value): + self.assertEqual( + MyInt(value).__sizeof__(), + MyInt.__basicsize__ + MyInt.__itemsize__ * ndigits + ) + + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-01-28-13-11-52.gh-issue-101266.AxV3OF.rst b/Misc/NEWS.d/next/Core and Builtins/2023-01-28-13-11-52.gh-issue-101266.AxV3OF.rst new file mode 100644 index 000000000000000..51999bacb8de079 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-01-28-13-11-52.gh-issue-101266.AxV3OF.rst @@ -0,0 +1 @@ +Fix :func:`sys.getsizeof` reporting for :class:`int` subclasses. diff --git a/Objects/boolobject.c b/Objects/boolobject.c index 55b4a4077ab7831..a035f463323823a 100644 --- a/Objects/boolobject.c +++ b/Objects/boolobject.c @@ -4,6 +4,8 @@ #include "pycore_object.h" // _Py_FatalRefcountError() #include "pycore_runtime.h" // _Py_ID() +#include + /* We define bool_repr to return "False" or "True" */ static PyObject * @@ -153,8 +155,8 @@ bool_dealloc(PyObject* Py_UNUSED(ignore)) PyTypeObject PyBool_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "bool", - sizeof(struct _longobject), - 0, + offsetof(struct _longobject, long_value.ob_digit), /* tp_basicsize */ + sizeof(digit), /* tp_itemsize */ bool_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ diff --git a/Objects/longobject.c b/Objects/longobject.c index 65bf15648b07fb3..8293f133bed2135 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -5882,13 +5882,10 @@ static Py_ssize_t int___sizeof___impl(PyObject *self) /*[clinic end generated code: output=3303f008eaa6a0a5 input=9b51620c76fc4507]*/ { - Py_ssize_t res; - - res = offsetof(PyLongObject, long_value.ob_digit) - /* using Py_MAX(..., 1) because we always allocate space for at least - one digit, even though the integer zero has a Py_SIZE of 0 */ - + Py_MAX(Py_ABS(Py_SIZE(self)), 1)*sizeof(digit); - return res; + /* using Py_MAX(..., 1) because we always allocate space for at least + one digit, even though the integer zero has a Py_SIZE of 0 */ + Py_ssize_t ndigits = Py_MAX(Py_ABS(Py_SIZE(self)), 1); + return Py_TYPE(self)->tp_basicsize + Py_TYPE(self)->tp_itemsize * ndigits; } /*[clinic input] From 19ac43629e6fd73f2dbf9fd5a0b97d791c28acc7 Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Sun, 5 Feb 2023 11:30:44 +0000 Subject: [PATCH 43/74] gh-101570: Update bundled pip version to 23.0 (#101571) Update bundled pip version to 23.0 This is the current latest version of `pip`. --------- Co-authored-by: Pradyun Gedam Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> --- Lib/ensurepip/__init__.py | 2 +- ...none-any.whl => pip-23.0-py3-none-any.whl} | Bin 2051534 -> 2056044 bytes ...-02-04-21-01-49.gh-issue-101570.lbtUsD.rst | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) rename Lib/ensurepip/_bundled/{pip-22.3.1-py3-none-any.whl => pip-23.0-py3-none-any.whl} (73%) create mode 100644 Misc/NEWS.d/next/Library/2023-02-04-21-01-49.gh-issue-101570.lbtUsD.rst diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py index 1a2f57c07ba3418..052b7bca28ddd3f 100644 --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -11,7 +11,7 @@ __all__ = ["version", "bootstrap"] _PACKAGE_NAMES = ('setuptools', 'pip') _SETUPTOOLS_VERSION = "65.5.0" -_PIP_VERSION = "22.3.1" +_PIP_VERSION = "23.0" _PROJECTS = [ ("setuptools", _SETUPTOOLS_VERSION, "py3"), ("pip", _PIP_VERSION, "py3"), diff --git a/Lib/ensurepip/_bundled/pip-22.3.1-py3-none-any.whl b/Lib/ensurepip/_bundled/pip-23.0-py3-none-any.whl similarity index 73% rename from Lib/ensurepip/_bundled/pip-22.3.1-py3-none-any.whl rename to Lib/ensurepip/_bundled/pip-23.0-py3-none-any.whl index c5b7753e757df23620ad5f039050e7dcd49fffb5..bb9aebf474cfe981dbf984bd9e36e23560111288 100644 GIT binary patch delta 520370 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 |%G3#nRz51y3_SSkD3X+Odirs*jJgznSlu-HY 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
    O0OJxAC|60&& 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 delta 515738 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

    ^JImakCpEjkdFidjv0UoaIzd!%~se0(1L-c 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
  1. +Q^5*P!0_7WQXdN9yKOIjhVYaXB7M=zL(hkk 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

    YF)hhqhpo9jr<~1W8vsw` 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

    u#>xo){ zzKMyo{ceU@GT|qOGC3{ewL5Te=zr4~(x3M_Bu#2}kVa`mRN;Y3pUM_p3c_(*N+j3} za%sG%kB@fq3E4j=dSq5h&g|A+2 z-TzLG0flkbVjkWYb9{EUHpv)HGN7~vf+E+&tf_4agCgTANepE2AYq$n&4OBV^Duk> z!ku*niFpP-4I5_Z+A^1?I0f;_R&q(O$RWzdR4{z)!B2vvIV|WNzW0}g{OLM!wBQ

    *nsi@e$hJLi7) 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

    s4$e@L4CjxI$3t(skZ-Ezo}tFOiyMGO_{z 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�UFpG;B ze6nI)Ynm<7WZEHhp6U^gJgDMxe0vEHjSHHU)-U5=@Sc)7U#NBk}nFaDysc_jt%g6 z?)q61h&IBzZ^@AUo*pdbN!EDi`` zLSry^!ehkzd>jx~_2D)k&HZ(ZVHJAd?hKT4Rcd`8(wor|`KBAy_!Ij=@=M-J`@}UZ zQK33tvHBJsHc|V9ti0BqoCJj`dPOM{?`Z&vJOZlQg$@*W)`Vd;uLc}oGo`i{D6N}6 zzQ8M@SHp`A3#m|19I=?hKVsuKxOBq%Xndu7zRPQC;ueM~peFhq@>@Jh9JM}eZxy(I z_P}FmV2}VZM%~>EeJ5i?8mK-R-ayjIop*T|VSib-b8D+GuSXiugP_WC3+J{Q(t~C% zB-E3UyoXtkw!&Qlt0qEn8-D2QF(s8 z9GGL)$gCE67NS&8d=i5S3fh*NgAK@OR)PAeU_di=QTudF@hx&FZxdYX5L+Nc_CZ29?HcyZbP35gkEojNX1 zF|FE5E3{4Vo1(XGT^9m&?!0O8kp&iWW9?ss{{IuoThnC#&=mj0RTMb_(xCqnrU`lh zRR6n}<^>Q!`ER%p38?ySm==`{5c|&I=6$LQ}h*cN}2f%+b=q5<@5f27*BoZPC`}1j~G!mEI*-bftOW zJW`Bq2b?m#&}Qe6c*oQ#o`E(F>%y*IX8A-TuZMpAWkl>Nsky!q)PjeFIUA86MDnG#4I0m^B}p*_~;@~2(D3528pkOr7-e{6J3R?f6z7?-7qGV zJw;$7MX$0mZ~%)t4B`|9Bat%_yxfziT(vl`Gd};KOIKT`Os58h&e>8A>KPu}atN(} zs#jIUK9NoVBJ``|8MI|n^Vu>qAcL_0Ga)1rR@<6}IaDQ2w|w9xo; z+yv|VE#-gqo6+V)Q9m|(ZY--ra2_W_)Ad48qlPM+EcnT=L>EN_dv1xJ&a zs4}jEIBBU=YH|WXHA%Zoqz*Z7#{0|~F{#Jd169Fib=>OlrKn|&plNSTZPs)o?6Rvc z3SNiA#lkT2QhazoH|c$j7hvSIzmIDf#-I$Jb)%!=30Uh8mF}pq)zitfpKZ2}T&PY$ z*CWAjW(7e0Fc7<1W=xQvy*&bvs9oI;rRlt^=tsT3!N6YR2g8jMW|>1hNauc`>QxaJ>rZu;LhHDw+8#E9X(|TVitAmwfdye-+4LKM zuBEdx?^JS{{tW;Cik0Sj10V*HlnWZh^I=*oYPX+>@VAHWo6y^fv=ruS93@`4L@>}N zSwWaXS()a|q3z^_U^oxB)ekII14x1{#VZ?i9z!edH#OZjDnxFw(Sc^bJ?r)B^Y(gL$ zF!zh4tKAbtzP5&;HWT0apc|;PhP!Jy8)VCFn$m@Ld8PmGv~d;{m1aGcPX%6gbrjLM zY>qQLfX`m+t6;XnnTvC&?+TL~1ltm(4nFU17rB?$JSlCq{BIR02M(Eze0J=$r zl!1;_9lI@E0Dg8~;H`oWH(J~cJYXdXpKbEjmg!Dw?{9%>1lVj z05sUQaIOz&Jb~ZUBx#6u08D0ZHnNDKbADcM+yK-eJayC~;w`vFW=;%wcp64k0G7+eAF$cfF}v(>16h!dIESD8ghHw{ zm$Y?nVFkGe-oPLKSC?$rUXwSqz* z{NGI5ijPb13HP6r#>-=@ii`#VGQ;^_M%4eC($XX-2+)BD5)_>jg?Rsr+sHOi3=t-; zA@PZI?5bkuydH_T0zNNw)VAoG>2MM|9vmPis=eLZJotGJ$Z}a$04G|xjw@z;u9%cK z52050$2cBCH|nynl%4Dn(MtHCzR3_y$u!BMSPH}2zwlh{q#w3j#8LrPp02AxzUT9XA_8Qw;>DXfOc4UEDZM*4%>2D;f9 zCzxm-wnD)xMogQ=!feMxlV;zVLL=N|GX2aCWU;_MA+BNB@(s4;tqKb7gov?m0tB4` z*KH>b+b;r-(?&EU0ku|Ow>kYk@(aSD_Rx<9JDE)H(#_Cvogo{?J;7u?`q8F+bHP0} zEs8inK#JU12<$%JoLi?#>VJoA5eN-KXw7g?q_099z^4C(6{+~zaDW%H}=xHs~1tHWuUfuFC zlprsX9vl8!&J6^n9ZwtQ7PP`+?@>QnB@0!|H3AWJ-KWtt9 zbq{qpJjpL(*Fo%7#-Fj<*#yt4Kfbv5y12N20@qE3II+`TtL`(142s5soh0O)r?&k1 z8_TWLBloRy-aGGM;OvgrY>?gqX&blquf8@aT@XAw6dzwoAAYZxlh-YT^aBJ36q9n; zn@LSP@HIry`nKxeP{o1B+7 z;3FcOj??Yil+n#q$BX3mr{D;og2K$#vS81jkAs`<*AqzxuKT~Q?x-IZE?hDDYrmy4 zk30;nPYgKqZSC!DF2C;YH8wuaygzp!Gk@z%S!3JA;2?#5)^deUR{FGz2lImf2l}r2 z$eFJuk?6o7bzbiti%tjt)~4#59t7(2P3BUL!k$97e01r)Hu90qj-IREnv-{#w{SQs z!4ZSZIh2Sx?<+qFmu|XTej@fdokBh>JS{yLE(z=Co4hy9wR4^JT(El;|1{Uge6Prm zd_Y_VM0c?4MEx12q<(J6Wa^&>vZV%IFAIgxs{kKkeNIlUkx>7vyDoD= zMMlrtAuQM~emwcJ?R5+C_c+cdykjZ9_m1hx6P^mH62Iyz^X6jR$6(qr?qxl>p`A!j z*S;1@NBvScXrVG!i=Re4u~9=@%6ftFi%wO}g^Bo@8G%E>8e~qZ-5S^i-pz%3)Z@Q*&vBxBJZCbURi;vpj`&gqk4ltU17)3r|-R^*2+K|=^GucK=k(LJ->a^ z5$!x9ZTs~a${|>~BHIx%X;&+q79$5x{3kLkGE^njx2%OAGWf z{ic)bw}1gpQ^FK$r8yk}_AZ;JQH!PN!v@&(gYp@B=%=Hh&N&Zzu{qnDWA}CR-VK}A znm}h0qpKy)~J$PaMI5*r2Z+eI+1f-n)>G1kyN!~K#lTBrU6efP`+TxEb_PSeB|S;Got z8qmbQw+>JCpo=a?7sE@f4Ek*-=PG5Uls$*UJJm@h%iPCg^xJYal0Ng1fx!18e<2YL zxkwD2TRq|Eoj+wGnE4PrPv}X%#xqki(XhYdJP(Y%qeQ(}Te?(K`!ar?r>GJ!Vi^VZ z3|)o_dX(LVUDntTm@*ZGA%^;=aVj~?#O}QA(ZOf~ky!p?pZr&QYzaj6HWPG^ErT=X zYD^Qo-RR@`pQk_+3!~eNftCjrog7HNg5E)i)QLf9u1TUP!$K$oRKO^k7M%=oOuw$J zE*Bh|3!f{Kq7g#T=rM?eNRU>aaSP2vI3q+rv229tvLWFm@IZhHMLS9b{Et~ulqcqJ zVW?Nm?WJtCuX(=QN^^OH3qnVVv%Q_Rj4ghx3=IUcI&tbFf-6(VIxo3`ADTcbN8Khu z1J;bg{%NcUIjE2!n4uh>7&V3~Gw4wPdm(j6{8X5L>1>^op|l91IY-39s6iNcb_4>2 z-S29=o+uatU_3q@pwn2zK|z-DFnY(QkS-ez?<_xrOjgQJm~Dc%=cR8Q!}Z*k$2Q%9 zZZtVv>T!k-WC6Z35&^=BEtR6x!Oj`NN>~A%W0mQ#V5Z5Q2{qJqKcLx7=+w%0#BYLu zeWBx}gtdy4OQEtMx##ZBPx#`QfAN4YosjDsqOt5> zo23J>BhQbOv)CWuDe{g-0!Tqt?a18yV|UETKyblczY!zG%PBzLHDJ&h<>AnsBn`yK zH2!W7FBHErO$-@|NkK>-ev)pT+873u99x6B4ZKOqKnnI+vS5-4o#Z^6`-x@MqdSy1 zm>V|qwkF;U%2A{(m6tK^Wz<@WC4Pqj{!BR z%_W43VbLx0HZAm3F3a1d5T+=OJ$@NIy5mS{4agovx2xbybJR-O1D4ZMOE3|&1Dm`YQ5 zR_2e4OM~)U7iS`B9kx{*y<>3{eWb1r8d(81a1)e#KPSEx`Vc*l)85a}d)}|AJgvmV zx46DZeXY?h>Xjy^F)w4{nn9{4`-T(9XWP-Fu>rpVLc($R1V5&1_=k*1+y?Rwg))&H z3^|g<-3Y4hno<3NFLnyG>ZyDfu$z)DleGI%2b#;`7;=!5Rj#)xwnS?%fhXvnjG6-S z>AV)~Te8VmXCr(j?F$!*7lb96Jw)V2s~qV3l6kmIn<3PcB$>g@rcRC!ae6)x9j~A0 z>5>vt7y>;jLZANJL&$!7~F!qgqR^%|@hS%G`xI6Co@n2tmS2_=jdEM@sziQVFZ#`%ptq ztnlZtdHn@lrSa)`(NWPN(7ir60xcsrDj@MG>yot!%@y7d@1@4DSCS)o9 zvnve{+$mKEF`Z#Sy~wr;PzcSr~xa>#F7zuhnqOi z4dQkC8@_*`5Q%rk9Ais?wH&PrM}_Ox(cs49pn~7>Pbc#8-n!199S2Js=u55cf*y0P!_kyxLMj< zo@X{x)H7meEL_&8z@K;zgZMf=)H_6ZWqB~|5c`tdlvNvhn@^DUD070XxeQ%maVucc zlpJdA5QG9nRV7^_w2H1icw5it$T`O-1IirFgttOD03<($HRMP}8LAFqGw5iL8ZpOh zDn?2X%z09n`ke4VSkaV_8s|i5C9U}^wFxV=0v(6t z3}FteN+Xa4MXEIj5XuI@#{HY+pfxUJ0A{$4o}1GXv07=_ef_zny$KIk80E()f#0E| zYDNJ&;IM$S(Zpl$Kx}?29^`U6zlL0z-MvtORwi2xt1_%uH;QKs@1d~GGX(gwYsjxO zzTV=5IQpNjjEPcX{Z(U9s$FUdjAp6LmlIlLb}A|7k*3OF)bU+oe>J zmcGTJy$ZrnDb$eQuTo3F!*Z@A$x*T#Y_WU9=)Rxsi^3yx@vR*U@I;OY_l!Y zqi95&+Scc{fgFF^)zR4acL8PB$YLHNxVMIuG?DWr3Cd0M`~10t8`nV%%O0CodEHv% zEr7zHT)@Sq66x!PD6|+SSyThI9)^2vQXJR?t>#Md_eB1}Cur^ToRRCQ;IF%LhMB>e z&}$o3Xj_e&c{i;Tw_Rv&0Cki~`AddYZODTO%*r1ESbu}A0z8ql&%t6NMFw2!0wNRY zRXw;{t00k?%`?m!M5*wog#qQTC(Dm;q+RsO=|F;kVDG#%NvjLLf_B=h zK>jBE8TZAdCC&pVVgkeQ0XRBYlqCwEV>~sjx&oR?HjG_^tcWdt0Fiy9b|UqRoJ^&K zqDRC;9B#vqQ|hE8qf}+fg4UBHO$fx>coazFuiHSBre^dT#r_7-NF0}bf2H!L0)YN) zpEnnTr7s$t?l}U70qth*;*Rolj{|O!-E6Y(Hi%?{Oq4sbD-c#amYvnPfR#djxeM$) zgrVMrweN1H1x|{~J_j zvG_F#4g_=x4+Mn!KZ4RMjqz*%7`S_8o5`f?6Tw?3fx5J{u^EWvbkd5ZM8Zg%QJY5HEb&9u=X+%|byoMppe`WVEatpmQA0*B>IPCHbwBTC}GBhBI zt%1&JgcP01ky0fuu*g$>S5E@UyYeKmcsSC^%V;hEcw1oVVgST)82ehl46<9{!Y>V6 zcSx(-?4RyW4R$hA>pq?K!VJ-H4l+-rOKMmcy(9lDerp~y)#$;=w_qKxz|;&nJ8zS$&^>!Gq;c5W9I#Qq5sA`T?M8Bf56o?``XPgj!IxQ@piuUC+UOET(Y+Vxh$mf|j3>IRQ)orLJUG~>nrql+%=YLCk z4qp$g?8+@$eeL=Ng$tBn<|Ud)8$SNm;3p8dMBrYV45bJ!!X|KiknJ1}+z zNoc0Y{W4;bp7blHR$mRz0cP^^Z)ECp_MikZ#x{#OXn#-vSiV{YRK+Uvsc3M)ilxjP z?)kZZf$d*`L{NK*S*DNSbnQYdDH8{lbfN`fADYQ|EsVw4KxdWQmz5-i6ApXBossq> zs&2IcH)hJ-{V8zxD^I9PXdW5?!QeG1FOEmAS)C%2 zh9a?oTnxs|A!xw0M@)b*MJd2m>NT0U38%pJO4JG(3h4_?VW_iJjnv}z0$gwb@~Oyl z`bGY&xC%sbRto+;W1+iVQ(k53-Vp=`2b-;PyHJUddJon*|d(Eit zH{6r@Ekbq60EfK^nT|GnS7+#_~sRyA2v zQDzz=w$(Xd5Dgn~@NlEH9ud?SY0BkN?5H$%t zCdCCez2XUR`hqI0mEa-ojg-qC(%~;+E3mk|IYtLe8Pzgu2>2zI)FOZI(v{cUp z0Gyr&h8x>P{n^}u`Ub@_j?spl*Z8ir>?eIX+p^uXXFJ}H-MUtxKK0g^H>K?Pm+F3B zv6K?5y~A;uhz=zu=!U3>&Y1hnzlqSB0NbbMA7iws1`C*aS$BGJN-KDyre2y~MQV4q z_lGV{o@|(UdfA(B_JvF^|8I(n2nYxg=)aQrnFW@=&cFQpUkmGhZ{qNO)fSzjqm8$;{LuX>?>_Tg4XJ${YBq}VgB+}F+o>nxuT*i5` zL*yI79)xE=LKy50LPjINvB!J5!d~H38LL$8Go!op0$0&M1tA~ocDYLD7Mxl2*27C* z+0gg!U8?EsdoE1z{L`vnl?PyPq_VeEPPK&?Rc9z6_{KvNR?X~v9R;aoi~Gn}?W6bx zu=X$%=c(#56!Yq@dBlU=Au-!`O~;2qD=$Jah;afI8T?v7 zkQBp}vzws_Kc~zvGPeTWF^F~Qf zn8K*7y?})>^DDT8B_h9*jg=kGCwFblJ`E-}VD$VvgnJ&{_!6pa>2vjNWFihkwp!%7hbO9xR!EJpd3+a@LZ<7jYU9Wd zCCqbY0O{<@{CjrpjRHqM$OR+^tl%F{+&b^n!+I?lRjcD_2xxs1c6n$Hfqp=5{S|eTqdC<_?WBw(Tor&Wt$#Zf3dwD(ylUjFa-9vW z><$LhHRCQ(QyMgcWrk#FVpC1Gs{TdlPhv8#pM@xc!jgE%@eG zG}L7ieJsig#A5D4@BC08B_q1L63skJ8=pvf2l#FQbWi`K+s6lVDP!ROlm+7s9L zTkn18Dul~;oSGdX<&=UC6>mI6jrbFJ1!+w?@@0g)yWe+8t z{;Tet2O$1R1TLDL;hPXr_{L5)XI@l1pkyji_WTJ8{Q-{15abi=n|H%@dBZ+Uy?UYb zuxc_0=g%oAY6tdZtC$`_TrbxZBPTt~CR8k&lLWFs7(lt5{KMARgjGJfn#iBdfO<5l z8UKRQn964=<4G?2w`uD<)oaMnC5z zjek#z8b1|?Nbn7{z9fnM)P-*Ih~BJ6TA&fUVCGZ8&fgv+_wpceI1(V^?m>8F7+ z1SmQ8gh*U1eREU%5S&{c#(*#sy4FLXhea`lJ!U?~px12zynfOOOWU`i35lF=J7hhO zBfiK!y9Cuf$jw0Z`j@_RL;kjl_ z1>-2r*Gf_Ifq}`9k01qnPN;X`VOMt%H})ImWeOH_Y-{rFb~6AY;CuATWSygTw^Z5v;(`ckrqavvwhwI_Cu>-fV67NPD;_H) zCidk44!Fm23jNi*g=X#)19@|e>{(Q-Fjk?1NkA>xVLLfyZ4lp@RJkA%YAgxzu`Mgi!Xj>gt6Xg~$&@a#M8fKvfXwSg%n- zXQ4(&Ik_<(^v)q9TmGZy#7Y>om)+Fljvz5&ilS)8<{sbS{N>D=#7gs?1CSG{#km=a zSs<QGrDRtB%(=63yobh=;;ZCN0QX4|$wHO6vKC5M(%_lyP{^aSgtq*CEpsMZ zJE!Y9Pi?PzJ=1!lV{i4+SMc3uwnVF?*P3s-_Kb`A!My0?4TWDRqpD6V|BPO8-?YK2 z&D=OCi_7W`8T$p(V&DBs7*IT%^vzkS3dQlzs);l;pkEeNoQ)jNYGXJDGQ0wlm!8}n zw0Glo7Q*u?dMEUJxeHBk!PFW}A!RF@Tt(kfCuogHk2}O0!GIN<*0&nM?ZKSOpIJn7 z5k}7lV{r=edqAn+OhOxys%~!jOQt7e9>aABuq~*~p+KP1{*!LIJjZjR5dC>v^c}e1Xiba8Cy@jDI9iMOOy zJ~(>DSA6tWBv^#m24K81h;g5H^K;@G)xEny)Zx&6w3_8$n(Mv|OD7!K%b^mjfx(rm z4}(9QRkIhJd~J{6t=p}|cC4KS0}!H-_X)LP^yW{>ma|!GBcMFc3cW~dMDnJz;0=$mj-5PBrJ0S`E?OlaFI%V$=)9&xu7{&2V!luH-``1n zpzi7MRkhPCwr}HK^-9%|BbR^C>;=P$&$D+-6G$JEAWS=K#@;Ez4UNCqxTF5uD7^L@ zOnn)1iEi&d1H{FJ*>PVk(hd@|f&*C6gLV50h}b@QLLhE#^~KH>jO3>3PKXC$_LFa4 z#D4{DhA&?gp+>t{T$EnY{Hd7u$Wq?yyP_fOt=U0Z0B$o-kCq56Y%=Bqwb>@x*zVfmaA3=mAaS& z>fr|^7AG1k$H@fbztg6z6ZDwn+dpT|^^Lu=lJ)hD6nwT^VKM-Q;JrkzG+N~BGBM|I zFQT|@dz0j#w^F3FQ-)mUsrk4SiQ;YC_N$j^-+|n1zjC zhNnIL4S1CC6~GbQ!R>?jET_uKMX6QJLypa9O*(WEMs#ZPazBsoK7>f}GwEtJwV|YI znLMVQr4{fG02I7f|8Tc^RyT%wvo&&jSkY)MY)U~P$g2gowfe-)>_f{#QKPXUdbxHT z*{;q6dT!hrcQ#Zrb&TplKE{j2C*+$AaNX>A00>O78RT`f7w}KF!ZRy&dinq(tZP+j++Uku)D6Zm(J8TQ~x3m{*;(IY$mF5Rv zn5W>Q?iN)-vj%kb942*0{?8yI0Q3egG7%sef}Eh1(U{kom!3Jtt(5QEO1FijT8~tF zk&|wb>7&AJGfEWjQEre0f#Q$mb_}^Db1Y-UBHl!vmnC>+0Q@;bDN?u>r)hYt^h!PG zIC7s7^fu!vS4lVdbf*jrGlJWR>`V{mbkCwb;yC?6>(yFmLud5fjzEt!Agp*H?$M=M zs%mll9!x0PpfBbk)Na%@#F59mx-F>A-ZTv`Own-8+D6t^2}D$46&^LL0_R3u4k6%H zD%|J(Pm_vD@<1m{-+NmX1vCgxHE%EJ{Z@g0yI01xoq^fKchuV@*kTD>wz#T~5yCqz z+K)>NRe$leZZCM^t?(KKc&Dy-VS8EVY-mg>tVoZ8{FYcGU*gug39g0Glv6;^0Ij1N zKP{dQ<4w9mfc1>?{qE0G99N!~MIWloy4&Aof|d5Ny|FB@bvwk^`rr%enBV1E+OJIz z5$yWg@<@A5(xY9y^VxTkXmOkAD$(;A^*sMioAD4V@+LL*OmXlAP-Po|?%*jQyGfVE zo>{sQ*?oii#-slc2E;++ECUwJ-D!R0!HYiTATV|I=_*Qeqs}sS=t#^g(-Mn|9#VOL zZlExy}CkF62{~mRxz56xK2qSHka!Ju_x2FqAy`8qfxu44G0C4mg zneojWHeMn&cW>MPeiNN-%s16N=Y)HS)1d5(PdKZ0!a4)AH4r^(ar~<{Q zouK%ztRE21E@WZG(?oRaI|RrT{^K3-c35x z6Ts()U6ByD$0<@c=oaBdx@}YWFZs?tYKO?%4NdW0E;0Y!i#XQ!{^1eoNjY#>+Kdk^ zqxJ)DMXtu~ZEj1jKYPNz_qK^pEZffb+%s^JcEAec%a)a}N`I;k!xtV#E2Uns&{}^O zgahslfdkY5q%~b+U;B&ktek}8BH#++(d~w-9}Xc%a<6jlqP~z`G~-54zW)Jvg^cdE zX6)1oKRCC=9G>&p+yjeT0XLW@_wC}IWLQfQ6VfV3*x%>5yDIo`$Je?$dZRZ>W3%EW ziDM}NJjo{X42+Y&8La-L&K^Uefxt40HP(4}zfHmbfxX_)Z$jT{^wj19A!3RIKCIN<6R+|*^82+zN9J3gt8q_`UZJUyMd;AbF6JZalyG{E{%iy=mPZgV%g z+GRhvbg{ie0qi*3w{1w@>|DEJ9_^MWGMcCllChxJTZ<*@JP}s%ea;c;io|oe@{q^H z@s3H?_MLXMFW)kLBuzqH8M3=}BerGvbxs#K!YZnEPY;aNm>HvKE&3^lQW*qz(@wSk zr#}p{?4FE=xEI4biZcdBcL`LB*On&s^_=_|-pDI&B^bZawm|MQG2hf2Ju#2-7;Y9) zDQ$UlHBU+Am{joOU8gG;WK@Al&ZM&bjP){5YEfr zlIX5mL^Uq5l;VB*yoqi2Z0x|_8~vY{`?@3PM~)KtYYH|Z`Xs`f^a5Y2I!qP^LhWzF z;L{?f9`N+Xh7fzBEeh39>++Se8C0GRk0^ZkZHG;4Ylld^AnC-HA$E|UdRs7nwYC~9 z0~q4)xJBB#(=a=q)IL4lll9FoG#XRXZrh72d{o9~hI(R`JtRjfIQZj`qTY=wFrEto zjMwf#`Ns!;=IL%5U?^%7Ot^r8XE~0`D)NeP#|fA5)6i{N5#2;5ptORzY7^&djC(t_ zZ-XB6;)K0=E%K0qzAwwDWoa2e!Ecm8`4b|@1k5<)%9s}ltYoc*pt+lXBYY?Pt`a79 zj&pf|xU;zRd7`Y#8q|5#Se7b?fv6MGbWhQVaY^lS+1?$aUH(~lRhO5t;Rrfj2Dm>% ze3X!#O2u&FJ}FQ^#v1EWDW`O)SY~^0>(Ngg%e>O0L$!q$KXz%)LVlHirzX*ieuRnz zHJ%&>MxrEyly{UXduH(&_*gr}9|QO_z5M3nmo24k2Y`LwPZ08txxao-M)#{B6BQI1 zt56re#OQwH?%yaMS@|O?)PIOwCB+jg<+BTijYxbsCH-G-Vc)`%XMhEAPt3!vUr^%` z+49lR$(Edjn6R|C+zH8m7^w(MGrdC%>ZyvXJVbYj$7-Ql&*&c3WO_%Jn)Za(^u~Oo zc%k7y>iEnGuQa$MT;;xg4~=HCj9ZwmSXrN^u+MsEW?5>k+H$7DVSpTy}0Jxr}^x zPz#HOwD!V@&i=5j`L5Qb93%!fHr-f2=7vb8Ttq~`lNobZ$7oUXoCJI;DZf75@dyg_ zh)(w;_Wx{QKjK>`_TaJoQ=t>!^8`I?K}g{XmsGe0@Ng^wdO=fgQy|xpT%$KjC(r<( zJ6;ri%wHvKrusgP{Nx3W3DU2}FbTFg^-#sKxJ*nES#V2|%DB_on%wkd?`Ki`#yu%T zlxD@oglz-4zU$^FT4@l?joNBpLQnUj;mNx!?>fA4>F+e+J(Y*ltS}8k*lPB-N%V|^ zw3U!gBC|Sx3yZFOf(HK(Q-1=P*>!LWpozky))XhtZs9$9@P9Bv9{0<5U&^%|z4%mv>fJG9TP*l&2Yb)~7>E+{cHq0dJH^J2Ks zl-3u*3kG!M!fM_zos;KPl%`4Qz|Gk#(V?D@>7RVS4_Z{0dFk*9AI&8s9N}UJdY zrX2oJ^C$PvJnZcvnYq72g@B966~u5PLx;8(s+YB3JxVx;d5mWiI{ZdtKa=}Yn|#aO zt^spyMQW*cxbaAZhnN|NR&&bJLM@OJ3R-gK;b?RVI-kYGf8@Yi81{8-lJ_IMdlCiE zS<*(D!%2yU+ZSg!EivPM;bawgG`itc0CxaIWm~>G!yW9ulN7YGSmpIBVGr!i;Wjt> zruyR+t8k-gi|phU&lRL^#!;dKjh}Yx);g6Q?mwL4{A+8zondWnXPO!S-+*~~SUH`c z0Apex`X>^O)Jm$!5LXGxtFjdN$U6Y=i_lMReZOcTp>*2!BJF*Ow((na60-a$KG}t) zKQDU15y+^=SnAWGq`}u+|AKVPszN%W65^8J_9J72e^#ILVa3x>yEs|Xln01VZaB5 z)nYCtfl;AlSq*zT>j-|%Bj=QtwS~)PK;twFmmq;Cno}G)I3NoMY0^Gi1MiiX zE2M>*=hpZx>2b!z(-=kqaHIV$68)HxE~QHkcymUu8{=1m;_rusI(52}ja|UF3fKx@ zb%>;TaOzpTe`)S)6y*&vowLDYywxHV?WLQ%$;1hM)lnC1Jwg&*cs}v#3GwBl};%8SkRX3$a!8r;^IGswz)nVk9tk8ic39P zw{>(i>W*Kp20>9a8E}Ib?10QO61Re&>gu6Wr}Y7sG6KLFBG4=O%SYJf$H))t#BIw5 zk~~8AFQ&1~d%FU%m)y8EYW2q~73w49e(Yly-KNB~_#bEJVq6*QT?g^+RRK zY5(!>{~?OCA4?;keO;Vinrd?-+l&76@Av!Xj1Cay!E9cVHS%Ys%cCzn8N%7$8SU{y z(-%QfkYnGCGItzRkeDk zVq2&bgptFON4v(i+5Wd)>$@U4e|wh;d?>(-lE01#^}WL}jXQTV`E)zm4x}+Re&29V z*vE;S@J;^tgI@Tb&e&W1OBtDV511%qeGLiw-=G*Vi{*;By&=F}-Ow>Ej*7fBUzqJD zFzClMnQlFC*?u5-O0R1Xu-Su47WDF{$#g&gK)aFU*hK;6&mN8_yIRcfOJPrJ9!SYPp9S)QID*@4!uHR zL@s4ec>~?OWP9LRBnbL=otIJl^B5w$YA+Y!sqB`M=PtzEXT>FtJ*3!C^GM^l zG>o|0{3s7&wtzU&cXYFhrvRZ`vZdxjduGlh#>RtXnVSH^2D55<5KVs|&lF$P`0d=U>79-E_b)9d%WLbB zVIpUi+XP>oW9QyilyE0!21ZumqpS}w{u%c30sBVThS;HAxKuCIGLfb0TJ?1iCA-Df zu)aRD?iQng%jcAHn+rg=@ABR6&7RaEph|Hj(ehGTn)>Cm;`aP0&#W}un~A-|QSfk* zGTi-{dk!#xJah-=t(Tj~mFz@3%IWz@91R%g)aOg1@~v0*(^wP*+QymPp3 z@4R^uCXJu;=K|G-x;5_^X&?ZtTXYWTd0sBGghz)P(#HS zxggxqn3Ef-k9`2@g2}g;Bsma^#u)oXF^RU0HF&p~wW~{cPw!eNbomlIQYFnqJR7O% zeZjZ@l4uh|jF%Ki-(oTU($8Dl5uccDcMf*TwKIGJMG$)OYSXBFum-tYmDoPUSP6e87{T!uYt z1BbLfNHhXEK%`8r^3=ok5e0j1DJ^%I+o3A=Sg&aNf^Cy^V0;gIr>!Md+x@v(PExwh zR~rLFxC^cJw)NIc0`?A1z-d0IpoWR=S`0egRR?{pyf=8FoK+yVrk;vR$O-wI)1pB? zyw8d>GY2B)Hq~$z+s&iH@-ZF{FeK4M-?;PQEO`JJSsytk`IyaJ^W}@Nu%6=s@CR!K z`3fC@4mR6G53wW&`;Dr;`+$o*Zv11LX>=9QLb(FnyO+<&ktbm%aAT%dCb1d{R`XTi z1-iWlqeuAj`zU_3JW&_jKnY&@HxUldB@?BNvOSj__1~jm3mx$e5;w=Dt`cx#5)*TXIE~j$7#=mx4LMRTyxJ~j zfBgFzHy-?}(A2MLMyd;uIn#W8s+xWC3}f|IougqEoGI|&+VclB;78gA&!ITo+^4e- z$YxNH(kw^41PRhBFcg}hrvU@|c}j8Xk2(PObc~VX)29wN$}m8wkg&4%pDXucgK}A< z*(vn1i@3#&6}`l%GEmU+H?Y#p?vMpuZb{$??M5HpO*PXiW&b!`TEei^jRy&kWi?BH z+3#K)vo@>XW)z+_dlu2j=4ikJHp8=LobBtkvkPQ{-gf*Fm}g?emfb(@Ld~VfKp9}N zv=x#4NzW}>%HOhS8o zP@ypb_j^s*E4+U3;stA`Hi1uM5l^#no1$|{(-srqK7&VXtx@J2eFLyvn?J8Zq6@)L z>#r(H^;`RoVE%Q63f`jFN%p=|x>%Zu`tQlSn*)SAQhvC*huiax5ix=={!u{N&^!iS z|DgZ7k5v@8LQch#m#OHOApCmKxQv1Lr!UJMclImYz0|Gix=^CYO&X{RZQ8`0lWxLT zVNn(Z>5Dc4DSZ2{RR@T@Ui15x#K+Texn^@) zC)@dRO{?X6NKf*uZFqYbch4us9gXQlCDn-^GyYw-s$^ot+Pgz=X%ax0$e$;93>BnL z!K2xE;LyBA|7p#-xY;gV*agG)Nlf2f*aZ=OPm--r+67F~6;RDPX?$%#XFm)kM0jd` zsxYGoE?g_QQJ&;Dhjr`#fOtad);DV5wD>iuFD;(tJz&IK#PzG@?Ey&RC*YD^)J=xxto5w#*5h=yi32B&L-Hrl)-iSQNem*?1vd=l6> z!$(`dA`ey^jB7mtu4;}#kL*IeuWW8#6VNlm{dmLb55GuwuBQvq@dZZgDDngy znigmi;>~5LSl7u}iZvuyc@`AEt`mm3C4SZp@eQ}G?=T+ln7KnXVp8CR!B`@_9M$T z^ZarFvR4h`Up@KuxM;8Ha{6UdL2MXN%n=*4fgH&}kd~l@=l)w{gTP8(_aqR68)a}? z=$L=^#XDn@(HJ1#O0dkgg^b{ddr=TIZALaIA>PJDJ;;o`p??K6KD3BocmJX@C(3l!@o=SvrcHrlBEzr0;u|R z?a=45BaF!=p1E^9vjBZ1+IYVDc^&8N90qb~PW$1&Np`pD%!Y(&YYlIuuZL=@jB$;U zEZ*`I=elzMKhLpOVVB9B?nCeL1q^7Z`?01vFafA85n(;d8$4cAHO25w!? z4-`c$qULMU9B(5_Y;ztI_^4vJvn@eLdyg9`xN3g-qH*MP&tq8ZbIOv2vV8s&fKT=< zU;%)DM%g5rZ5)x(DNRPdpK2+vM=j*ve7lIWlvt&|)#HmWp(E&a@+(8H7K>?JbeXPZ zd}@cL%#w2HuEq%er#u||^c_mwIRBHz?O-ZAk(>b}5G3UKkC?-$KbU_=E#Y1&jweQa z?^6r=mhmYSb6x7Ov-FY~d&S2EHFa*>HwWOLQojNVVDrk52^42`1_0-d(FlGD_+Ajs zB{q*J^q+fb1VMt?o{XD9Xdm6)E*bWFX(@09C)jlBsly7ON@aVVC2 zP_-Eh7jOI6*RoGJTdA0}t(p3F2vDEZK7KPlZ73=-B(krL?!P0MT{GISdg&m;@Bz+> z64cNxQfA)*gW-`j+%TVgiEU8s+3WbBs+|&W%~z_Ee#wRoaOg9>ACAapQJFcxlP~j~xqwBdG5g{Ktr!a|Aj` znS0V_PJr~e_v(y9FE&W+I$T>Z{s6+VbREZGY9a;IdIWIC3<~Ioy5JG%?Y(_TyW5<4 zFOGsJu^^474y(=fESHqBfNbJbj-NHMT;j-AzA5nHabbO5H|@=h33`Ihd^`_fs?}SM zmnMOOt-OMXt#yDd9JS92c|O=75#6<|!a;T-W_q?iCycf?q_ghO`j&FP@&VXZ=?dQ( z+L3&0Xx;IIf5fU?74bus z+QPQT3u1-i4D2UIT-;?L&j5=3*pxW}z>J;1N<$!Q*QC)B5icXET;gN^Z@z)30{cDR zHS(D;zj@_yZTW9e1LvFgO@)5l%Mz@aR-Y8Y><0YSSjI<1M`zm^|jlYV-6uq@UbWJOweTm0=x#Izl9GI1OEK+`l!noQ2^}P!)XbdjIbP# zfjbfbaQ`dhFai=?;$Lrg368&YlW>1^9?1dX>-A9revY79Xsm5S4L;I~Qj9j;r3kl0 z5LQ_-23+K|B|?*Wfoc;NJlQA<^o3`7eDkw>zVh*Upgm+LzG#G*HL|G1J)$=&;;)_r zMoL}?R53k{F5o7mkW{^XWh@ zT9TZ+JA{XE%G*S(a#ncdP;L<*1O2W-r1xod= z>PNFmJwxJr@8DkON(b-O5%QGo78h-Ige|~}GkPV^ZPW2g#sDr{xrbL+c5o0s311&> zN2|VTOIK#rf0$bDXI_?p+>kTilv(F0t_FlrN9y7hL)?g6e9?vwU&$Q-ak-Sasls9L z+63-GC=hf9Wf*TP&F&QvBdh!Zglo)Z3Pz)5GZA@%Ujr%lmIg2(c<0{A0p>}Bvof93 zO7^M7KK74BH2@MTdkBdLsYN(Xe)v!LuQxmsG;@7(It!|JeD50SSvI)1`MqBElcEK6 zb2(Pe4Z;KGn-j5>zhStrpSG$$zW^PC#CvLNn8W1WA-3LPz% zTzoaWmzNbUt7l*FFFzKL*uU}KKxHnx2g(Jind6puh5;p~FMYQNM&gy~agFdwE}NT- zV4o}-H;jMKVKNtSJBFY*sr9Ul#>cqlj5{SHw&yRRTrU}7^as2q$Pg~8VQM3=PzL$= z4u;vaJ{dA`oLxxU!lZ?-MMKA39^G1bjS}U67izK|gL$dBdd1J#S8%E{SX||njy3Zl zycK_wzX9fp1p6c7gqD$8mN?2|fDh|Q1ME=)0Qoo72dNBA0#x$zDG|22={sZxPN&ae zZEgYfpk`TrVj>{2VW+bagm>j9Us~v`1Z;SQeyM8)*C@fXvo}i`hV`>@whA9hvSL28 ziZe{H=lyzPe$d2t^V*>{qPdL}nh5Gv{?MbNg9k8Ye+o>*@~UcYh}PV4FN$V(zk}G+;^3Li|?^_|_^~LW}0;C>{GXBWu1OmacDtb;{`FReVLi7ldEl-`KZ!YQ1lj5X>zKHc3wF z)Y|dqdIwZk7%Q}8LMIR{W)Cs*_GU-Q`S3A+d_8xKpIl78&YSdLwQ+-+maLe#S_u|l zMot~`;c75i!mtHtwhk}DTL%8XgMOau)B+|(*@l&LMASf*H13;e&L`m@CjUNO+$sRw zP@P@@VQK3Ke@W@?@C{#Bd*BlnRw(X)6=7b_g-29*HVC9mE11G5O~h>!XSC!XwcxRl z^;E#!G=IbNXd2#b9Gf*|hd;>7X%xUSH8~DQ&*bpRLya#IBL+}#E9pv7`A=?r)B|jl zUk4s68~<_rNcul0ozc|;|ULOAqrCmp#P6g+X>iU{J zbL~EnJ&?29KF~`|Bi`Kl8zegC9&*~kakll<t6#!giM74b%W;XI1 zQ4y-d;oQnaz&G}P=(-B9sJ5;>baxHm3?(2^(n=%J3aE%zkPr}%E|DBYL_`G@;~|2u=tG1BLxEeTP80)%fuws6+9PIJb~5)+t)}IbORJ-Is>*88GNrj9 zU)pKu+xh$|67HO?zs>1ftY-c$MDO?P;}VYgg3@57O6x}7qE(MDj{5&5>t3~+&g$sV zlC{wld}+T^b|hqIxqw&jk*`Ag`)Ko@|J8-jQGfnvVLJDxB1nLp;sJ&BfR00rW_ned&vJ`M#`eEl&`G_!_QOt>_`{a zKOxlXYJ=-(!{KeI>ta>n81`X?h)CJZ@W8HUDr-wJie_uk)IXuYRKF@XOM z%6+AFEy!znFZXxe13#H#_ULvN{KwT82M#wAzo zVWf{+q^S)Y4;)V~7=3U)kxA*-bf2%W*GR&nYbR~`Uo#yXyQMn$msF!+(PHo0&bvk} z*e5F8r>n&Gn;xqptBSj=uTomd!==yY`8lZ6N#WVyj#%Nm)~*cXZE2ec?D=;-Ph4*B zTlyP43`#v91exDNvx{rr$AK$GMet^DSSFNjv{yX*##~1D8fPiJHuBf$HOG)bzy@v22ua}LJ%b#|k zL|=Y?C=;aXJHN6fEjs^^4m?>kMtAsGU1hPBXxUAv7RTnmR~_A@R=O8j z&HrSZA-TB?s1=H;8G}rE*G;1i+^~k+AEuiBIHKBIE9nCr?>6zi?9f!uRej~;fkbVV zcj|s(6XkEJi(f3;{670FrMuZCM@ob?(P{x1(Shlh4$C$0c)D8XiB6Av!qjJtpwhHH zqxd`70U2^bX6<1WXRmZ)msKvkajw{1gIOQhmJ6XGp}}s-4JW%txIXUHFyU0 zSd31!Gg3W~`zHVOk7Ignn>u?`lh0AtTQOy9Kl1w>nmra}Xn7teF)^$cYOL{Gy%C|T z8+=t6v+J#W<5}`{_cP^ZITK2$~1Fo!&*-pF4AdTj_of ziyTwBYqA$=?*Z}~&nxvt|M<)Ux z`|VI`;OSeCxz~jL2ZiDN2Q{v% z!mZb6{z+`-@9^pdg)S?hiz~K;)|3tJI(O@Pchs~d>@A@SR&I5bTvR$NGsxOXVMODw z5GNXSoeJ}!>Cc~~E{y*H-l||p$jLXBQ9@dp#NO^o%bgkTB%fAGnV4DxhC;mH^=!g( zuh~CWrZ6dMoXa7hQ%dF+{rm3wGMQy`H|70o8F$S4v-+jskn>(@`$f9w#G6B095urj zbQ0M(G%krslgWqO z?P&e*dFii$XwEY8G94zrEIIpyy)e(8(r7Q6LlT|sB`ggdokv@Z!DuPkYo-?mL#KT;6l|i@7R-yS1st`&_nn`K}_9>8d=oza!>1WXyz< z%tan`=Ke6+@r}kMQt2fpPu&xtrR)+4Q6J@p z=tYDdrt$=gdjGz#oLqDMf=so#X5iW9euHMNtq;N}JtikBqENZ%N0D&X1UI7x+6}iGg7cNwunfXZdN3J@c?60!J^+?p+>n-PQS^QZx9^4-`Xcnc~ z9Qas>GgtYLSmelT(-Qv@)#<-Z;hs#QqB$aq4k9D66s#@hc4v`Z7I{NDGggB5VNWY3 z`s%&TftLsEmN06oE39fE?52Y+q;lFI#G(1Y<9yYt>Q)UhV!3puPEtmZ7a8}FIehxV zs9U|LGw|n-iw67X>0jsTcpvMw#O^veSFWce?)FQs>Li;=;a#5Rma3yx-6MZqy;ky_ ziyDiX%#9ihE>R9l)N9`qm=C;1wNAh0qoc2Oowb~g zVd}z>0`4H=q9*8c`sWT~vH~kziQ6vm6VKnwHk%=Jd;F)E76)#zNszxn7sv?jCvjG# zBvtc1nv4=-yWWNALJF%z-85xM_qjcjfzimTs*-x7m=RJ%x}1?xr=OTh!tGXd@#(7y z88(9pz6ufd*4jKzR75l`7Im)QEPH~!CVdwpbt~hU<3}a)ug~ITr@Wi_1n;+|ol`f? zRP)Q1qW_j6hWz3~w)7xn^&skD*wQQRX*-=Ksam>fKO{A0K4T&t-hJ$l(aa!hWsbey zqN{mAxOzx|iTpzEbxeaLVwtn+?QHzj0A!mv^TGQxLrZ770{;5Y7Ooc;O*&hc(|k+n z?R~K%wV$5FR8#nhu&C-!el5)(xm9^B>dQ}>D)bh44+Qd-J=^PNUSWQ;;c$lVohIs8 zW=+fg)TZBruEwnV##Ht2Tny)U-!5d?evm_1fZ3@#v}b-W@k`Q$w66UM3Rx28|GsWS zn{`(`>3_Or!8LDxw1?FEV+H-^{J1M26P!~ye=LyMoK3&`T_u9s-Kbxy(l$m_hctCR zFIx$GcTtkx5g^K6^*0atfKAROX-KuoVkR=lvorSKyvp5|DwM0*W>ZXU>qiYrCc(2Ii)(7% z3Pyy~k0dJD9J;04Gdz<2?b$GEZ+&{@$9g>j-ht1IIw5uIwdg7OkT1S;=bz>FjJ%6m zLi{cdl@Ew-G0S|kw*<3N=WN8%^Rr#m-D=E}J8J!=jrHv7PuJ`ZN(9Svkc##-aOJQS zwDAqJT+lcfr(Gh&U1RD$`nfH7>0@W*i}p-}G{>OMFW!A(_j1(d`JTvxTFgBvks$Y` zMANm)RJMBeK32eJcAvVOqNJ(t=~WN5^y=f{y-xZEfi+@TBT+;h81T@ssk6Z>KbcPUN)^*V;8EzwRqTCXO${CS;R!#n|M2gn#`SY$wQ) z<~X^EZ0guwf^0BY?EwI!?f@B4VDCjCdj)vbJ>y1)JR zCF#V!5jR&8_@-pZ-Z;PQ3%U1OEA~vf(41zz{~L#kCl?2sdV-ej>kD7Cwz?$gZoH<& zwyO< zi;iE~reg9hnqPeX_UL9n`;yj;zbjwe-R~_YO||Jv`567`d6R$Vj&^B6w0W75h?7k) zZHFvJcCpM-s9c!oLv{OlPKw5Qq*(0FbE~plG~J3Pg^jP>q5D9g9BMq-6Z!18!>0t~ zpD=JF@wU4CoAiSCsBVFCs~B14303Z~CLIltxR%qLveNb4BRA!q9m_L&%Z!|_XIj_O zvHrlG(buuBr#mRFsav7HIhEixkt2k!YdpYA$ zrmD`4xI-W3t&!Br_Y<%0pQU}z#4!f~Ygo!;79iAU#x1JhPx2Tr9g4*R|JoQQJ zSawYMZ9c>eu>+45tvmD7T%MMBpuPk>xHjc-JKd!$c0$91wzW;QThZ_qhA#40zt8u~ z6M6xAm}eEtuF=aLQ#q07!qmp+?q8bP+E!IklssC45=#pt@#RY@vhh(QV|DCgmJv@D zQp}8xOSn#d%@UzitTRN_ky3DO^w|X@i`eUSuR{L}x3A|){-%!{?6f~uOSzvGykf>h zs;BY^`tm4m;gjOy%io3dos}?jsfGtTm;L;i2l>VI=nv06)N;2iE(w$Tsr}~C&-~w& z%*eItmKw|4StCELvwuEE!-%4{Tx2;N+f1XX(tXh?=XO%WxoooIZ#~jvW(?j${!z_)MUrZD`uc~45ntk;^k&y9{fxRbLfNJ5@k9GsazNnOOY)giUb-oy z!Uw;<|77sVZ2G}v$!DeCd7Pe@fBH+PSLf+e&(=hMqmz^{C!u z;GLj4KloABQjLNVab;stJ}Pr%=%$_K0qrky4<%3eKiKu!W!QfIU76n^p)cC!F%@?g zSL(u=Dx)H-Od;75TwfDk3@{XY3BBht?r(oe-!>vGe4t;Z{(R}n@|u)Kb6mr@D)TRR znMf-P8#)TEUp@Zo*OBf({nw9-!^tK^7QX$rS1_3+y{N>Ud?w|R>t6k!BeridjMOyM zYQFE@+d101;P5{FvDt;lgH+{j>#{FoV?sa&#Mir;#W4MePh7T|q*J%^ZZ15cAxq1YNyP5Y^9kJM{8{+oF|w;(cs@(Uk3W~W$i>@NSv;k>zu0D~j` zL6`2FZJ|5L-}Hu)U2uu2Z2t4%Mh(?@%}WOb`zNd-l1>~!`jYNDp>tX+YnO4co256# zVX~wy2i@9@vHLVf9dSt0fs5QJb64_LJoKJGW~j$51*s|Rr2(e$>q1X zHk7yN$U3-B+}4W0{cxkA@`&c!_{?fJ5FS?&FufLDY6_`q8hDd9E zY3RCbb>JX4mOZ`ZAbY|0jGXaE>}$s3N%NSTWDlF+$+RlzE0+F!zITE|X`>bKbj1 zc;#~`uE@|^CO=P~@BY4A_OwK`Kv(@*_0`o^!%dLbRVBA6WTK(?Sga4F)^u&_5f54? z%vd_VQ_}Q%+fx+DmI*OzOn*}2!+tZZ`=p)xO3A{;Ag^+j4atc8BsbC3P;p?2RW?GH zz00lo8&~A5$=s9c7u8QqJ~kwgrFaQ?ia@?>#V4fM%>n&SW0>0u2XpFYT^U}w8nFAigNy_rb(t9tBF&f&ap*WJQUkz{+e;?LE< z5t}c?EXjXks*nlCi}PEOMudhwb0x?vn1y8L1ax$U6be}OXvB^l3d$8+s-sW;GI}j) z*+i<3=G(dV?8?t%I}fKS)aobx_IQ81+F3FBimNw+72CzE`$v8#dW;V667u&-MCI9oSDb)qaQ zW=OvExSXJlvl&n5;$id_tyf7TY!I^xZ7e&&lK-)}NCy*5wS&(44pV0=)2`205)+hMEviVuUsjjfed>!!Su@pxDy8hlGe422<1$0%jz2k;RUT<~D|wf5y6NiA zdp}o0!&dd(b8aXM#c4MzjSGGJqvAgz^-9&|0#(=EFY!J)Iab>5`c6E)5vu&;^@Gv1 z|E9eggdcjJK6_28VBj~EfCvMpN}2k|Ijuhw7QL5hFc;nIE!m;+`g&)_iDMxW6MX4a~KH>X)O)J?FWg7UJ zR-(S;zPqjbyw?4Dw>sygOXVuvDB49-Mnn2ng?F2LcdalI9L&BY2_aNIs673m;C0D7 zfq5$8LQln%yXo8U7aD&30;Hp{7r^@-(USv*QZ?%aFDqiMJRHT2d^nnz@7R@aMcw&B z8C1@ivqvi6>-deZi^rvs#IBuwcvGFfMDFXH1pfrLvN+?|LQvjxY6$5{?A>JFTiObV z0+Ei=Ue}SG$0W22zB8u{^n9IaxbXzd6YVo~2Db|o|sD=;(B@8JS+ub(A&k{ zqPv2;<3n#k;iBeyRdfB~@5%!==vsq=?_P`SxHv%BYeAtnhT*%YI3X?^Q6AVwtEIG* zbFR)@dzwkRiWHLmb%pKZsp`|Fqo%59yIWo{db?qqd(@o1j!v-7b;3HlH1r=EE~-F`tjfY$YsckR-6fSQ1m=_r90ZYz?rA?_KY8n9*EhjgqUl z#ae^*7|i908Zs_1Nsh+|erW%4(7T6n#L?uIQP)5x8|ovgvvA8p@s|PL(=F@!Mc+?K z)cNkY`h}**D`t*o#L_XjMYpH_?1OJeUw0SNWO4@T%sW|iL2A<`xyF+U&!3occf~*^ z&(v---K00fykJ~2c5eSgX;gQ}av><{MH=Yec_pT0$TVR^fINB@+&kU=1 zGw-I7uD-;6%-JT9-T(Xj?wa8exf2j-IrVy3p#O-?DDz`6a@PaTYUvivKcSoy>3 zpU2~#8hOjSQvWT|Jo48)wlTs>(A0sU5!U&p|d&no9_)YS|>c}nmk)u zWm+xakuh*PG`O5orqddQx^#u9v@s^p&=w=L6I}(2efzOTC{^WV3=8%f5i_zwZ1|Q_1Fvr|ik4kFg$@E7D(|?kUxu zXAKVfsd7UzBu^m1MTwWqIAZqlb2|nzW3&3M-pZaohu5^+D)@s&iM>*D#>DfIo$^vL{~DEIkbsQ(pUXl+2R?PCJ+FK7#(OkR zUh}u6{WsRc5C*!puBX@&^7di8%9}4=5tnX2p`%V01=>cRjmW}EyrZWrX6n;MGj@-Y zCw5w%pZ{vl^b(c-?P*Nq()gYM4F}J=>wUir?hJ)^IbF3XWZQ2@Vfe1+@E$+AZ6+Wzlb03nZVrcj$@_raq>tO-n&xaw$&!h!*$Kxd&OrZtb2^zkg-#Q@1?$ zQZqSkN&8@XfN+}UoPu3oc}~9LftQqF=I^_^!e4(rd@ZD|>#|G5g%CN)he1)u@vp*H z-x*vk?HVYl)lR35T8n<0#moCsjo06Xe4+0AH1Esca$(+ALN+tj*}n|G}x%GX6;K@!u(#*qL-f69qn`Y@!X?BH~wlEMz07`8pbp&hZuf;;-c@Nq`S$Ey}{bEOK{c!d&ZH8?ZgXy(#{YPRHX?f}HA9S%Mf#l%Skqj%vAD&vlBlAtB6( zEA^jrO!?;n3p75PVKbjTy(NUX1-=nSh823$Rev=|E~LEhF6+$%K26aJ!XpYLVNHgs z*Z7>wSSpW)F|alX=bW4|75H_zX8(ls2LmDhD}G9O=RAG5dIg&D)Ix84u@v}(d2+}v z*Cu{Urq?~;=lchdI&&X{9wl|ZFv61A@PIerUK@N9>Dc!9*1W2P6Kb`*`TO8K>-mLu z2o%SmpYaFc_~ew9>=4!L<~$Bno$?nJu%UN*R}ziij$@+*d!F{K)vlS3&t3}d9@Vyw zp!aYzQan@>RK`+V*{qg7K$%yva5IoZMfK49M;^~AHIg-|@7#78usJy#cLKc$QHN;%y*)@XOd z1+A{CnK$)gbyuxln!0qjViC`|eJ;_Wrwq7U9bzh8?y4B*9a3n>c{LG;UC?SwOpW{M zB6|4a{$Dj#Pv1$sL^$Tg>9+*V`h9qSQqSJUMRIG(#$sufxpjZV<;V9`O2qrD3Ku7J z1~6g)e8`EmKZ?~eSr&{ah;32!%dl!&)%xumM(d~i6~4NM?wvkn(UK|iJ^mrG;x%)D z^i%Q0((5^UtVbUHoztwMzWH}qtLlc}s?ELL#ZN2G|DqnwlqZC~Y1b{uDx=bGKS`Dt zSF`Vq-Hhjd70|x^$l}D! zbX3i7IP=7=%*fL@VTvwFDKbyoWvM7I)-%1NZR<&rD=}*a-n3>uVpEIx zYWKc_E&PQwPNuwaht)_uDb`g!a>cgg4|vhX-S3L4p6k);pZ8Q)7JkhfGTeg+opVhwR(2xY?G2 zaS?kaVqcy}8NDQ@G$=h)P&Lo6o}6QOUCW$1zXCIm_JYcBPV+$}EBgh8)QZrK?+4G9 zcAs*SnTsi9U1^HSz5EjMb<+3DZ4U>soIu`;Ze5en!~S7hoiArqakB9n)+Mjzh$0etFyn2qbVECAUSD1mQx%fIV`RBr^XBY zHu$2K0Y+CL**T^D^wk(LuejxcU*=zq44dVt>&-i4@s0~phH^IA^yT*3*NxCTXFMws zwJ0ASo!;1lzpN~D+UpsO&+e_bbH-js**X(}AaHln=@FqT$*XwdtSkw}^Ih|#HsZm3ae9~0%b!c|YSDVzP?@Ut>LOQc2 zyVbIe)^i)|Iu0Fi7mqZXG}DR1xl}=GWTrZh*fzP+Y}SwM$}H zM*m@%QkE;GTZa8~bD)uYgZrzcYh9uJ$Tes+xvTQpDJ83H)A<=~jlD6Cqke^k@tqMe z=-w-JfM#!|KVr-|EIECc)NYwG68-Fy&e|SFgzXaM<~nxG$^He!3-O%wTw$5S=f15U z-F8js^ftW{TP`XT8IhqW2>XimFnXTcy)X27>Yw<>r5F}@ceNJGnYNT_(FyH>xyZF~ z&ZF0Vke@8*qE(z`Iuz{ZF}v!}$zeD^`k+f_;EaJ}zC;Vx-)mk!MW5FCCeAG{@h9rJ z=v+CM{rt}7eeLS6P_aSDX9I!-q44KH=P+WI*;Ws&lE|D|&HGx>`L*upQX!46|6KtH zL1S@|rB>)PhT`^}=w}i9QR1HuimqMUZOzhTIp3&ZkdV@M<3zS{=gOaBPGb{@R$e)B5AR+0S!Yt9viK(#(KHYCs(KrXU2O2>TqGeuEMa-7@|FX7?ku^a#XX zQNkOR|B)AAK}8Q!uJLPBNUkt zh_CVp1ZtBKr%1Bk?QlVUiLK0WfVaPH2hMOI5G`heH!c6e6k(a=AeLH`Al-)Qcyp-N zqLAc8SQVo<6RvHnZZ>yI-K9Yw9)dSE<6a&8?<&HcFou$9|7QgpE3Q-8UmwvT5XaF7 zgz!H~@V5vnbmDgNe{FZkH94~=0CkV*Y1496&SH<}oGsc~W+uywE>t@V5w?fd||U^kspmg#)#U>OHuF z8#J)C01Px9fRl2&I+$r2NWFQjY!?`Ktq%eL{%l@F*lH|ZwTtyA)_;b_Nr6)8@rLI~ z!{2VLM{&V!PZMrOJ;dFX!$rgnp`%%X3UUOFJOliLe^VxId`B|zY@HiWY+DU-C%k;U z2{@jXII(X`XX61y4JbyK9<2>{HRoU9Z?89?IAFKYjriMwmEg7@^Hx{H57M1*+xi0@ zozw`Qp4A|P(Mh1TANas6t@ITKxc#?lyQN3(e%coY-ZU-_G7au!N~g;$WBux5;#FJa2fd2r1k&+4;1qbMZeWZJc@47`#{*=1(t;a&I|#7!1iHIzr$Oh zZ3M^f_Wg1CZT@k_ZCjRy}8-U6Cug9HRu#QHA) zaYM~bD2A%P7bur0=XG(8woOq}m$m~5z zbSrUH!*bsMut_H14$nfK3^>l*P|14~{Xf^hXO`CYc%#HJ6YkrxlTg9Tf+Lcob9(&& zB=ZDT;t>|I5@4py{~IC>A!fEa_#v2nDUdkeKJx}iKqNJznEt7bLv(csGg1QcO#~Ao z9_=C^#)uFaWYAA@5G6`7#Dg7CB_LE<{^v3{85TLS(r3VruxNp74!32H0Ra)!f@0jN z)mprHL?l2=gG>!KD32K)A?NGt89)^CI8l4iG8UD<0Je<8IqmyNJdn@d!^Okb&(6(l z2Q;MCil3ElrwMAQogtx?+#0qx5g+{-q*O={h*Q8j;LhrQmISIkMZoblk}f2Q`dZa1(_yJv_9y{GtAK6encW{=YPW zGfF^Ld1WK`-Rb~M;wkpqKxDO}Shh~_U+d4z)}ZWk#Swl=0f@q1McCkIoD7Mr#NYQe z{GJ4nkOYPg_Xoagf^eZ2>HY|x7A<%5zz5)`Lfb^`86+Si zJK!0l&t^?=8CbdE46&t^f8!9lVSat91Mjw;2z0ztU-0CNk#5FHzcDhX0}>BA|+c0$iM5(M@<$c^why}k!0XtOBch|dhi*gFIM zU%<#kU^2{PAhS-C-~LT)se1?K=8p}Mh6Hm+b{5{z{@xD+YRXV0~AhpOgoxF`@W)( z(6cXa-xQDkanJ?WN*L5bVVDetqc{XNlys7mVVi1KFFqM;1wwp5L4hail9M=?)K;sR zQRq2Vf#I`)1_~a|?=1=ANc#G}E)VZg6+l<8NNBMo+@Jai*P0QHHIxO~;y!T4pgjv! zegorF{RVfXXKGSM4M7D@mL{IL;0?sJZ*W^08wi{}0vy8*^h0o4BK&YN;88mPgaU=H z1`xzcT_mO39w=(xQAn~PY#mhb4H))ZG%3S&npi*s81-DiGve`e^!0V|ByPp=HtHf! zhNlulGIzmkB$*p*^9oGSI+$H}N({{)AgsFJ9RhCp0RVr&eZemay48i+yLD1WnsX}z z0qc2Cq2N1y2$39%&E;$|A(E$(@Ij!3!PkMlp(PDbp32LkoQ%dy<_Y zE;v`9ecdQND5)FXe&O{0Hw<_l%j$r%dQk$~I(Oqh;t*{w+(%^#nWbcb$K3-S zw{Mdkmmnqka0unCI{i>()g1<*E(!t*9)URngi%^g>|p<>Cy#2ifL5VEE6{9iUPajN zzX-6HDN^_n73XYv#u5A^K++Ou-K91`IMvP#6JXr4r113w4%Xkz9;^V!apQ-Vsp2uh zY}+o9vTYB7@jm=~D2{IuQ9}~_|68!){r^Zmo+x#43sFoz+@+6E_NkWegH0k(DEGkh zHlE)CTV3C&uB`$Apu;rcB!g-^$=D#tA1LOn1ylOLi<|2#2*iLUaR~78Y(Of6$(Xhk zZv^}L0?xrFbcl1&e_+)FL~%juieyyVaPPXVuIhupWWGjRK<{X7;0_p((L($KM3rA= z06!2OM?BT8ZH%2Chnz=)9hdRb#6fxAd4qAz0K9p|+45hI0hKndBJ5HG8N`2+j0Y-> zCEFnf^8Li?qIzkAYBhF;k>c3>;|?#FfsuHe#I}kgON-^*19n}stch#v+eoPQCrTC; z@O;1US}3M&Xp#2|MF&~`g3s?8gkY~eh!Y1eS8y#Nx8S(8y2M{2+lRKmCD;s!LzpvT zt0?xt|836Toq69NUZL9JEmS;b?d<(LeFAq#E>H}Co}yz5J=6;R=T>c;*qPM@K+$^z zk}arvn^zH*^ZQnu{18z-G#SEcb7^=hmFetG^ZA@W`g3$EY2E@E)Ap!l7{+rInBGci zG7L95PRV~$4=-CC>tv9oDme#qla`!r+x#0|*st*!o~x zShn}2vyW++KqIq%xQP>DP$rKev=lgJP(T1qU)2lHlu=`2Bl-@R!#Tyl@&BOs25l5ejGmI0?r)q$V~pj^Rc zssV+AiENco$J@rm2l>(XK7^RM($RTNYa+>WE=>Z5qbJe(yFf2gH0-KR?!hIV#!u^RccuQq)XLh#!VQH~k`+;}jc6i|VzziZFjHciX|0(PXQ9+RIBerk! zB@hr)8RR>3?DME~ywkaTuWtu%BQipLCIk*A#mqU0GA*o+1O!2>*eTvUPkpttgzB8QTf z$&uSyk`MDgTS)}K^5QaBH^Oof=^{BKFbnrSzrJ#t{|vxm31t!lKa5%q3E9s6Z)X`N zyNpGsP#jFeC-4FOy?GU3-`PPqv#4ELODKtNVlguyYzH5BpCe{Z0h!&U;DH$C;1%qH zTIo$4Fv<47#{8Syap^S3VFO|_hoavq<@Shi)jA;00*fgSK$}+)cIE5_Bzq3Uv=zdl z|EA_Nkb;8=YyxmnRNX0{=^P5Q%nosup^){;1Pp~1Lg^tX__dIPl z_4f^fmWE%Gc!R{rdjpa@4{r{su~nxHK-`@J3x0U|xE--EobFf(MreJWD3LQQ5ITgb zcq-9tUV(~s!XiN$r~%=ydsBJbppV|%V4V1Xf_@t=kwy26EEqN=7&hF#+4nba;|p;6 z#;iqErUDT&-~(^|_#fbhEdU)_Bx;*%7xC)TByJESFQQnt&YAUxIlda81`P;m_$sO< z9S@P-7OdL&%MC|?3ZSbcs+%p3q3|WJ(_yp(??$Bgv-^_)_4+o%=?okKR+iu2eXA~D zM~Zl8O-_^xlrwR}oKVOMiXA$lRUjFJ?_FwY2)l&hfTaJx9r_E83-t^bWgti$@Nyr| zKn>Z&(sDo-{=mZq<7>gUx*sgCgNPyZtQ(M3Dr!2Y?GK7#t5IhM_Xa70d2I#`2M+|2 z!y7myZE6Mx{TD^CHM4Q+Gu*ZWzH|jR65L5Im_n(4Q9MxjA?oc*S}niTHh(a(5iqhn zz{LNqA}sP04koizhJc$=;BC;t)qoTR&mJAtIO1K<^W)Ss+a^8bpx>_hAg+f%;)lz~ zIt!&Pqr`UFZ$L%L@i+iGNCA29(2jP)$>M@oSK#i*$>sj06r_-2z;f{YMM*D$11;!7*SqaK!=CjN3atyH&iSI$qkKy1fcdRlo0vEy@F{y#Y$W88ats zK-TV3GeVQAM5$_>!1z+?1{G!vMInFI$I*L-tc!BLk+8Fn```WtXM+{Uq&2+a3_TkJ z%$?K>+w$6s?Kf^YpnW6IUI;b~6%;gtFsojp-o677`|B1u4fv#uA~9|s%?8eMooKZZ zyN*|gjqe}hb$G%wJkBza0=BJ4Gl*Tn%a{PUOOJ*-yh*M~` zt+7tolTv&cbP?Ik#646Eb_4Mg4ST5JYv|Ht1KKU0coL#ex_FNU+DC@wf&y>Sux+!f z!9mOZ6!4_9Fr0*_(ufsq;LtfVJ1lbDNzk~=Nc(<+Dvboad4K`m`P2{y#0LJc>E1#7 zkiKu;1(215=17Q=)A_Xxocj_D%XWWvCq?7>XgLuGONQozQb>uUR}t>t*4n&J0mZ1$ zZeK=D9iBFd0~2!{m>cd|d8Y|jT{7_Ap)Eb#y%*Js9UwD`f~+M1bH)e<9D)m4J4?HL z8F{BXw?71U0X0}g!eI|w2rvzDH0M@9IjtuTDS$-a=TGbfmhJ?^X)oICPhsTVR=&Xr zQ38)3;ewii2_urAKyz&sbeZmPb2P|00^s2w9Km&ofCwi-_yjFoV*-fBKs|Ud`Wa0? zbWosKx5^0Zi%by&)WcwpR19V{*&74|-5px?Z6(4^JN+CT7>pf1ab-zJBESME(XdTy zGBf9sN?>~Kg57txYD13+h$c$7YL*3YekDMq8SsHG6iz=SAb6tNPMm*kvfRv zh&phJccesCYEGxe`2+{#@s6HuTlKYaB;&sQ9tg}J7I^Xp0|6JrjE0~7y2Xqyyu!JR zcmjEUKbM`(;bcCR9S8$X{ne6q^y>=*B$T>~iFTVxckg)EiWCBs&JwFs%FIMi=_Cu0 zN}eoum5{X?1f`=)J3J97Cr}yAG85QL05)4^_^ng1G9Q@Tpl8IM++G3+u%d-vDbj=$ zFH>}Y1#)9W3vUg#UB}B^RKW-|!3UntFaKnLN{FaY_d2H4z(c#nN@B5Vfch#O>#ptH z$38Z^i~F-cBphfq$d(Q6tBx`YasnV@;*QdRDcHP>qbx+pq<#EC@h8doVcHBD;b5@x!f~hk zabh9@(Ii4fBtylRAS2J0m45pigmK^& z6vF*|LWKLz4A~f|S0<7{F8!Z%$ zB;tJ&iC1t{kw6q+&9;5JK_PC6av0b=8T7jFRzX&s0DJDpw!QGbqH*`V4mRzMsS!J< z<$pMsFf3qF0F$a=*KG)CM`05g7Du5YBcTjR&9RJ*3%j1iVlWAN%$+aQJlRiN7Gvqe1x--eij_ ze`_)jmKV(nxr1GvZA++|Bd+G2z$Wnk3Wps~B*2=5c7PofyyxozAU}Z@!*kWB5)LN5 zwX5NxIpMVeh^5$w3&dSj95Ej>!HcHdiZCjm;|~EoZ3ApA02@pT*v-HV<^UhOqo?X$ zhH#rpYrxz1VTfoQ0wS6Z-fKlXN3-Huq$A)1A40Sd0l~MQeS6z}&NFl56zBy+L01EZ zQ5q9q%>cHoNVanAqfG@iCc&WW(eN!q$31`Cje))haG(M{OW)J+ z5P@wIt6j3h5Dp;h00OtCIDIZ^z{pL+iBJzNddf-5=u7&*b1OwUv~%+3(+hxMj$>e5bI1P1#K7-{b&Z(KgpJAlWbAuBNs20RYd;Zzg27iex!tq7uFPv%;7aML+Jr{yc>)}H^Q{*CGdO+tQ3e%Xwi~v#e zm3H=X-)X5TBj;*x6)e1vk*ozzy|6mjMqmZW`p1vAlMpD$CnP0>4T@< zkP-2A>?X2}=We_%U-CDo##1=9 zf0Lo(&A8JV;C>Hq2X@-LKs)+!14ku7G)S}vp0Pvu27x6Y*gD8(!)IrW08j00ZsJzA z0m&61S`EA>@I*BKkAN0JmvK;T3vTC_e40?;CmFy4;ZwT*D+ewmp`gR{z#cf~h0RT< zC|>R5UwA69ZDsexJ|&9*&_sl{5$}bvpdl?W5EOZ$Xex+a3=R8Y*W;s+8ef6$T7rHS zu8)!-4hB1mpSD_c&KVGX1n~(^zUC%S_#Tk9bHw0lU1|LXS-PMFvfe{*_pF}Gqx zK&*4iA%{`N9j}Y!^ZZ%plxO7B@E_sJ(EAq~4m_1gM{PL4N|z-31ReAl1=a+YbV_ zjT|%P0GLQC;%wEGzJVLL#kGBFT>SZv-~}M>0N59WtEgNFX-NYsHcP@Me?LR39u*1r zdKCD;8=Hw*0>ZYLYx|1WLUW!f5cCuNprFBBQn8)@bCW`Ee*GA~8jqF2uR-S;arcot z4t8FCJ2&i57lHCo51tZYmWH>9$^mD)L%=*V0m1MJqzq2DOA~FEc>-Zz={qq+P|IqG zYx~j{(RdYU2}VN+MgwnkF3u2OQ-8R&KgE|eeSW(FWVLX8;xOQzC&2d0!2O|HQ`T?@ zMDipE9zj^BvC$wQ?-edi=&}sFa7E3Wl8OZoQP6Y4M|*&g0O4|Wbo1J&M;e#G2L~zJ z25bI(@GLs%Uh=&hq~y+M;$c5x-+;L8gQp@^)gG)XaFt?UEx3avsz9mx(4t$jG)g}_ zfk^-?7r@pAocNI127d}!qCIqeS-j41;3zBJ9BYoq?N7JOSdB|@XIX857r@PU+;Ia} z?S|a`G=1dG@@pkf{l8#|!*SAufJ5Rom3LZ2LJV?v#q4e)p?xJtB-EOKq}%=#ywe1# zfI9>#K5!uNyo2n6m$8*IK;AX&FnKHg3#Cwt(RiQppxKL4&FY|%g5UIjGlWfCFm z30c2D%25Uz2yp*&Du%oi&_Y{Rc%k?>I`NLPJFovN6Z1WD!_a5-Z$Z#N?<+c z1%jRbpE}@g5mx^_62kg(vq4Bj_!$C>)I_+1H^>h{q(qR4&qydu5zP%%b|bfEfq}ru zQrrP^G2mHnuM!1&zWdSaP@y9Hi7Va0!vNg(d9*?Ggd@}p2?%8~Zsu)mfI&y`ckuWJ zK?8)r(@pMS0_^E=ZhFX8iD(MFl<=wS@(}`2suH{^b3Pm7Ee6`$2L^^$W%*MCgtQ&^ z_AP{0OutdM7p35y?8Eo$#jNo#IX6$wo$?D;nuTN}06}1D3|`zW+2DX2P?IuT!;z^8 z<9;ykOdt*}O2+|*;D@=i#D4s6tsDu;TkVIh{p;eL1m z_x8PoN0b?A-K5|kGjQ|WK>WW8d@~Dkk6%Y_fJ|>~|;|??k>{djcFfT#R^`IpnPh&oFmB_pG=8+gt&q3QoK~A4kj% zy;DWg!d$0U6>pl(GDtuj+-FjQiUd#@eGrKT?)kSm zycCaeN_E$Ph9wXzAmLer8+=t+1N3_Di4eP3R0O8LJPm@_gYS#;?#ChE;-xh3;&rre zx7eW5KnIwO!wC2NL2ks|&(?r9mVFFVhn9fr)zT2#*d63X9Ky<+hZ~|B3kJbr3RZvcQP-Fd5P7F~wkNssm&B*FfWtKbZQzCH!qH6_IhU_X z(2n~k;{>HJz({NZAFzu13(oJsQ&BufZaBj%X`we?tAp>aS+wyS8-ob`gTehV>>z%8H=hy2W*>wr%2>y7(HEpURp4{*+VVUfk3f3aIXUha z)r>lL&L;{8oYi!QI4k?I;okNm21-1fvtbDyA@619vEwU25MxYcBmCf`QY`T-Qq~Y; zHS56L+eb*>(^3i?Y8fH+Q_&v;gv}u|INJpNv9+&C9S^$72wb}#%q)<%d4ab@Fhc_R zz+C_g{@t{&L-;{c^APT5AA&1#GJg5veh_D#V1D2MvwJrIku1wgcTblndYN_cT;oLv zG#a{au0JcJk-Gp#JMiQZ9w>*z2#87r-W~Q1lQ-B(5{R00;l6zxYpdo5e47WX2jDa0 zD2GF^%h`K+?G)G=3Trt>!6=nLHi3s3voanCS?a-4c$2lQq%`o?RBK|NO*lY6FzNH| z@Wr%pJ-lH^O$bC|dT_%eitY1V03$E}hJh;*c^rq>d^sF0)MLdCU`~N8zVNfe!!7s^ zN6Z0*>7(hk`o}bFhAHmbFu!p|+Vl=w7p>!kN63K<?l3oc+2?S0R9YqW@^C66c z-T-c(ss*aD0{~%}K&%{T91g)I?`L;r$KC1!LLaNvK=g`(bOSq3ZfK5fl*f z6fZdxZit3`-@roKW%>#5>i3Ss4e6mD1Zc37NHxX}Bv%Y~YZru8;@iHkHc`?=T9{IX8{Ks1XBXf zd4mcBgsBc66;yqg$kJ_x@uO(m|9^uhV)jEDc~Dl(hPgVL7r994S<5ckvjhhh?=+nR8v2NzEo!ew*S-o&e##PXvY?YL3)-3D#x?+|yE;T8wQC?!KElonHVQHWxU8hw485 zj}R*_1fj+fF#W(6h^vD*Pyjr*RB*arh`ii%)nK$yLc+|jk z2u_#imc_Ep5V{usM=waF*z^tiWI3nr2}6zUm?@HL)PTu7vmHIFJMd_7#N@buhpR2%Q@NZ#xL)CbzOfvW8%LYo}MnA@|inX_&H%hqOK z3rGcS7bxr|Zi3k6a9Wmix_ktxZEsdR;hzP}JgOLzm#eoRX-hvWi)G(w?RSQw+dkje>=T%wm>H8y5 z8!Sz0P1pYd7APNq)6c*-goAC3?@uH2N))A*U_YWnE(+`oi_=5-}WCE%I|?~Q{bo*9BgZJVwRh}kwZ>arlcq_uecz;2wN#NT`n3t z_}$JeH+|wQS*huv(Wuid)>cU&0>BtNZ;oD!b%;Z>h?N#$s{^L*ftY+%3!==VJTViS z3o0(i7Xr_pVF(7+HmIrVl9Al>dPg}`%=Hj4Ff;yq6Ao|W1Y+JjRjlH=?k^`LbRNq1@hAVcfei-TXUFpBQT@6 z0&|Q4JW4=0=3Af~XmzKqk&&LUp5gSg*rn65!1WtgL_<8NV{t0J}~$n?ZFo0Fbf=W&i*H diff --git a/Misc/NEWS.d/next/Library/2023-02-04-21-01-49.gh-issue-101570.lbtUsD.rst b/Misc/NEWS.d/next/Library/2023-02-04-21-01-49.gh-issue-101570.lbtUsD.rst new file mode 100644 index 000000000000000..599edab6c07117d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-02-04-21-01-49.gh-issue-101570.lbtUsD.rst @@ -0,0 +1 @@ +Upgrade pip wheel bundled with ensurepip (pip 23.0) From 0672a6c23b2b72666e10d9c61fc025e66aad9c2b Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sun, 5 Feb 2023 16:36:33 +0000 Subject: [PATCH 44/74] Revert "gh-89381: Fix invalid signatures of math/cmath.log (#101404)" (#101580) This reverts commit 0ef92d979311ba82d4c41b22ef38e12e1b08b13d. --- Doc/library/cmath.rst | 2 +- Doc/library/math.rst | 9 ++-- Lib/test/test_math.py | 1 - ...3-01-16-10-42-58.gh-issue-89381.lM2WL0.rst | 1 - Modules/clinic/cmathmodule.c.h | 9 ++-- Modules/clinic/mathmodule.c.h | 44 +++++++++++-------- Modules/cmathmodule.c | 9 ++-- Modules/mathmodule.c | 14 +++--- 8 files changed, 47 insertions(+), 42 deletions(-) delete mode 100644 Misc/NEWS.d/next/Library/2023-01-16-10-42-58.gh-issue-89381.lM2WL0.rst diff --git a/Doc/library/cmath.rst b/Doc/library/cmath.rst index c575b90e6461ed8..28cd96b0e12da9c 100644 --- a/Doc/library/cmath.rst +++ b/Doc/library/cmath.rst @@ -89,7 +89,7 @@ Power and logarithmic functions logarithms. -.. function:: log(x, base=None) +.. function:: log(x[, base]) Returns the logarithm of *x* to the given *base*. If the *base* is not specified, returns the natural logarithm of *x*. There is one branch cut, from 0 diff --git a/Doc/library/math.rst b/Doc/library/math.rst index 9da22b6ad0562f5..797f32408eac3d9 100644 --- a/Doc/library/math.rst +++ b/Doc/library/math.rst @@ -393,12 +393,13 @@ Power and logarithmic functions .. versionadded:: 3.2 -.. function:: log(x, base=None) +.. function:: log(x[, base]) - Return the logarithm of *x* to the given *base*. + With one argument, return the natural logarithm of *x* (to base *e*). + + With two arguments, return the logarithm of *x* to the given *base*, + calculated as ``log(x)/log(base)``. - If the *base* is not specified, returns the natural - logarithm (base *e*) of *x*. .. function:: log1p(x) diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py index 8d849045b2d11f9..433161c2dd41458 100644 --- a/Lib/test/test_math.py +++ b/Lib/test/test_math.py @@ -1146,7 +1146,6 @@ def testLog(self): self.ftest('log(1/e)', math.log(1/math.e), -1) self.ftest('log(1)', math.log(1), 0) self.ftest('log(e)', math.log(math.e), 1) - self.ftest('log(e, None)', math.log(math.e, None), 1) self.ftest('log(32,2)', math.log(32,2), 5) self.ftest('log(10**40, 10)', math.log(10**40, 10), 40) self.ftest('log(10**40, 10**20)', math.log(10**40, 10**20), 2) diff --git a/Misc/NEWS.d/next/Library/2023-01-16-10-42-58.gh-issue-89381.lM2WL0.rst b/Misc/NEWS.d/next/Library/2023-01-16-10-42-58.gh-issue-89381.lM2WL0.rst deleted file mode 100644 index 7bffe7d226e38af..000000000000000 --- a/Misc/NEWS.d/next/Library/2023-01-16-10-42-58.gh-issue-89381.lM2WL0.rst +++ /dev/null @@ -1 +0,0 @@ -:func:`~math.log` and :func:`~cmath.log` support default base=None values. diff --git a/Modules/clinic/cmathmodule.c.h b/Modules/clinic/cmathmodule.c.h index bc91c20f373bcdf..b1da9452c61db88 100644 --- a/Modules/clinic/cmathmodule.c.h +++ b/Modules/clinic/cmathmodule.c.h @@ -639,13 +639,12 @@ cmath_tanh(PyObject *module, PyObject *arg) } PyDoc_STRVAR(cmath_log__doc__, -"log($module, z, base=None, /)\n" +"log($module, z, base=, /)\n" "--\n" "\n" "log(z[, base]) -> the logarithm of z to the given base.\n" "\n" -"If the base is not specified or is None, returns the\n" -"natural logarithm (base e) of z."); +"If the base not specified, returns the natural logarithm (base e) of z."); #define CMATH_LOG_METHODDEF \ {"log", _PyCFunction_CAST(cmath_log), METH_FASTCALL, cmath_log__doc__}, @@ -658,7 +657,7 @@ cmath_log(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; Py_complex x; - PyObject *y_obj = Py_None; + PyObject *y_obj = NULL; if (!_PyArg_CheckPositional("log", nargs, 1, 2)) { goto exit; @@ -983,4 +982,4 @@ cmath_isclose(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec exit: return return_value; } -/*[clinic end generated code: output=2630f8740909a8f7 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=0146c656e67f5d5f input=a9049054013a1b77]*/ diff --git a/Modules/clinic/mathmodule.c.h b/Modules/clinic/mathmodule.c.h index 0d61fd1be38ddb8..1f9725883b98202 100644 --- a/Modules/clinic/mathmodule.c.h +++ b/Modules/clinic/mathmodule.c.h @@ -187,37 +187,43 @@ math_modf(PyObject *module, PyObject *arg) } PyDoc_STRVAR(math_log__doc__, -"log($module, x, base=None, /)\n" -"--\n" -"\n" +"log(x, [base=math.e])\n" "Return the logarithm of x to the given base.\n" "\n" -"If the base is not specified or is None, returns the natural\n" -"logarithm (base e) of x."); +"If the base not specified, returns the natural logarithm (base e) of x."); #define MATH_LOG_METHODDEF \ - {"log", _PyCFunction_CAST(math_log), METH_FASTCALL, math_log__doc__}, + {"log", (PyCFunction)math_log, METH_VARARGS, math_log__doc__}, static PyObject * -math_log_impl(PyObject *module, PyObject *x, PyObject *base); +math_log_impl(PyObject *module, PyObject *x, int group_right_1, + PyObject *base); static PyObject * -math_log(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +math_log(PyObject *module, PyObject *args) { PyObject *return_value = NULL; PyObject *x; - PyObject *base = Py_None; + int group_right_1 = 0; + PyObject *base = NULL; - if (!_PyArg_CheckPositional("log", nargs, 1, 2)) { - goto exit; - } - x = args[0]; - if (nargs < 2) { - goto skip_optional; + switch (PyTuple_GET_SIZE(args)) { + case 1: + if (!PyArg_ParseTuple(args, "O:log", &x)) { + goto exit; + } + break; + case 2: + if (!PyArg_ParseTuple(args, "OO:log", &x, &base)) { + goto exit; + } + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "math.log requires 1 to 2 arguments"); + goto exit; } - base = args[1]; -skip_optional: - return_value = math_log_impl(module, x, base); + return_value = math_log_impl(module, x, group_right_1, base); exit: return return_value; @@ -948,4 +954,4 @@ math_ulp(PyObject *module, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=afec63ebb0da709a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=899211ec70e4506c input=a9049054013a1b77]*/ diff --git a/Modules/cmathmodule.c b/Modules/cmathmodule.c index 62caba031eda275..2038ac26e658578 100644 --- a/Modules/cmathmodule.c +++ b/Modules/cmathmodule.c @@ -952,24 +952,23 @@ cmath_tanh_impl(PyObject *module, Py_complex z) cmath.log z as x: Py_complex - base as y_obj: object = None + base as y_obj: object = NULL / log(z[, base]) -> the logarithm of z to the given base. -If the base is not specified or is None, returns the -natural logarithm (base e) of z. +If the base not specified, returns the natural logarithm (base e) of z. [clinic start generated code]*/ static PyObject * cmath_log_impl(PyObject *module, Py_complex x, PyObject *y_obj) -/*[clinic end generated code: output=4effdb7d258e0d94 input=e7db51859ebf70bf]*/ +/*[clinic end generated code: output=4effdb7d258e0d94 input=230ed3a71ecd000a]*/ { Py_complex y; errno = 0; x = c_log(x); - if (y_obj != Py_None) { + if (y_obj != NULL) { y = PyComplex_AsCComplex(y_obj); if (PyErr_Occurred()) { return NULL; diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 654336d6d9f4bc3..992957e675a7a38 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -2366,24 +2366,26 @@ loghelper(PyObject* arg, double (*func)(double)) math.log x: object - base: object = None + [ + base: object(c_default="NULL") = math.e + ] / Return the logarithm of x to the given base. -If the base is not specified or is None, returns the natural -logarithm (base e) of x. +If the base not specified, returns the natural logarithm (base e) of x. [clinic start generated code]*/ static PyObject * -math_log_impl(PyObject *module, PyObject *x, PyObject *base) -/*[clinic end generated code: output=1dead263cbb1e854 input=ef032cc9837943e1]*/ +math_log_impl(PyObject *module, PyObject *x, int group_right_1, + PyObject *base) +/*[clinic end generated code: output=7b5a39e526b73fc9 input=0f62d5726cbfebbd]*/ { PyObject *num, *den; PyObject *ans; num = loghelper(x, m_log); - if (num == NULL || base == Py_None) + if (num == NULL || base == NULL) return num; den = loghelper(base, m_log); From 90d85a9b4136aa1feb02f88aab614a3c29f20ed3 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Sun, 5 Feb 2023 17:10:53 +0000 Subject: [PATCH 45/74] gh-76961: Fix the PEP3118 format string for ctypes.Structure (#5561) The summary of this diff is that it: * adds a `_ctypes_alloc_format_padding` function to append strings like `37x` to a format string to indicate 37 padding bytes * removes the branches that amount to "give up on producing a valid format string if the struct is packed" * combines the resulting adjacent `if (isStruct) {`s now that neither is `if (isStruct && !isPacked) {` * invokes `_ctypes_alloc_format_padding` to add padding between structure fields, and after the last structure field. The computation used for the total size is unchanged from ctypes already used. This patch does not affect any existing aligment computation; all it does is use subtraction to deduce the amount of paddnig introduced by the existing code. --- Without this fix, it would never include padding bytes - an assumption that was only valid in the case when `_pack_` was set - and this case was explicitly not implemented. This should allow conversion from ctypes structs to numpy structs Fixes https://github.com/numpy/numpy/issues/10528 --- Doc/library/ctypes.rst | 1 + Lib/test/test_ctypes/test_pep3118.py | 23 +++- .../2018-02-05-21-54-46.bpo-32780.Dtiz8z.rst | 3 + Modules/_ctypes/stgdict.c | 117 +++++++++++++----- 4 files changed, 111 insertions(+), 33 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2018-02-05-21-54-46.bpo-32780.Dtiz8z.rst diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst index 4de5c820f2c6ac8..0642bbe9f99d0db 100644 --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -2510,6 +2510,7 @@ fields, or any other data types containing pointer type fields. An optional small integer that allows overriding the alignment of structure fields in the instance. :attr:`_pack_` must already be defined when :attr:`_fields_` is assigned, otherwise it will have no effect. + Setting this attribute to 0 is the same as not setting it at all. .. attribute:: _anonymous_ diff --git a/Lib/test/test_ctypes/test_pep3118.py b/Lib/test/test_ctypes/test_pep3118.py index efffc80a66fcb8c..74fdf29fc9ad054 100644 --- a/Lib/test/test_ctypes/test_pep3118.py +++ b/Lib/test/test_ctypes/test_pep3118.py @@ -86,6 +86,20 @@ class PackedPoint(Structure): _pack_ = 2 _fields_ = [("x", c_long), ("y", c_long)] +class PointMidPad(Structure): + _fields_ = [("x", c_byte), ("y", c_uint64)] + +class PackedPointMidPad(Structure): + _pack_ = 2 + _fields_ = [("x", c_byte), ("y", c_uint64)] + +class PointEndPad(Structure): + _fields_ = [("x", c_uint64), ("y", c_byte)] + +class PackedPointEndPad(Structure): + _pack_ = 2 + _fields_ = [("x", c_uint64), ("y", c_byte)] + class Point2(Structure): pass Point2._fields_ = [("x", c_long), ("y", c_long)] @@ -185,10 +199,13 @@ class Complete(Structure): ## structures and unions - (Point, "T{ 0); + + if (padding == 1) { + /* Use x instead of 1x, for brevity */ + return _ctypes_alloc_format_string(prefix, "x"); + } + + int ret = PyOS_snprintf(buf, sizeof(buf), "%zdx", padding); + assert(0 <= ret && ret < sizeof(buf)); + return _ctypes_alloc_format_string(prefix, buf); +} + /* Retrieve the (optional) _pack_ attribute from a type, the _fields_ attribute, and create an StgDictObject. Used for Structure and Union subclasses. @@ -346,11 +369,10 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct { StgDictObject *stgdict, *basedict; Py_ssize_t len, offset, size, align, i; - Py_ssize_t union_size, total_align; + Py_ssize_t union_size, total_align, aligned_size; Py_ssize_t field_size = 0; int bitofs; PyObject *tmp; - int isPacked; int pack; Py_ssize_t ffi_ofs; int big_endian; @@ -374,7 +396,6 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct return -1; } if (tmp) { - isPacked = 1; pack = _PyLong_AsInt(tmp); Py_DECREF(tmp); if (pack < 0) { @@ -389,7 +410,7 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct } } else { - isPacked = 0; + /* Setting `_pack_ = 0` amounts to using the default alignment */ pack = 0; } @@ -470,12 +491,10 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct } assert(stgdict->format == NULL); - if (isStruct && !isPacked) { + if (isStruct) { stgdict->format = _ctypes_alloc_format_string(NULL, "T{"); } else { - /* PEP3118 doesn't support union, or packed structures (well, - only standard packing, but we don't support the pep for - that). Use 'B' for bytes. */ + /* PEP3118 doesn't support union. Use 'B' for bytes. */ stgdict->format = _ctypes_alloc_format_string(NULL, "B"); } if (stgdict->format == NULL) @@ -543,12 +562,14 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct } else bitsize = 0; - if (isStruct && !isPacked) { + if (isStruct) { const char *fieldfmt = dict->format ? dict->format : "B"; const char *fieldname = PyUnicode_AsUTF8(name); char *ptr; Py_ssize_t len; char *buf; + Py_ssize_t last_size = size; + Py_ssize_t padding; if (fieldname == NULL) { @@ -556,11 +577,38 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct return -1; } + /* construct the field now, as `prop->offset` is `offset` with + corrected alignment */ + prop = PyCField_FromDesc(desc, i, + &field_size, bitsize, &bitofs, + &size, &offset, &align, + pack, big_endian); + if (prop == NULL) { + Py_DECREF(pair); + return -1; + } + + /* number of bytes between the end of the last field and the start + of this one */ + padding = ((CFieldObject *)prop)->offset - last_size; + + if (padding > 0) { + ptr = stgdict->format; + stgdict->format = _ctypes_alloc_format_padding(ptr, padding); + PyMem_Free(ptr); + if (stgdict->format == NULL) { + Py_DECREF(pair); + Py_DECREF(prop); + return -1; + } + } + len = strlen(fieldname) + strlen(fieldfmt); buf = PyMem_Malloc(len + 2 + 1); if (buf == NULL) { Py_DECREF(pair); + Py_DECREF(prop); PyErr_NoMemory(); return -1; } @@ -578,15 +626,9 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct if (stgdict->format == NULL) { Py_DECREF(pair); + Py_DECREF(prop); return -1; } - } - - if (isStruct) { - prop = PyCField_FromDesc(desc, i, - &field_size, bitsize, &bitofs, - &size, &offset, &align, - pack, big_endian); } else /* union */ { size = 0; offset = 0; @@ -595,14 +637,14 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct &field_size, bitsize, &bitofs, &size, &offset, &align, pack, big_endian); + if (prop == NULL) { + Py_DECREF(pair); + return -1; + } union_size = max(size, union_size); } total_align = max(align, total_align); - if (!prop) { - Py_DECREF(pair); - return -1; - } if (-1 == PyObject_SetAttr(type, name, prop)) { Py_DECREF(prop); Py_DECREF(pair); @@ -612,26 +654,41 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct Py_DECREF(prop); } - if (isStruct && !isPacked) { - char *ptr = stgdict->format; + if (!isStruct) { + size = union_size; + } + + /* Adjust the size according to the alignment requirements */ + aligned_size = ((size + total_align - 1) / total_align) * total_align; + + if (isStruct) { + char *ptr; + Py_ssize_t padding; + + /* Pad up to the full size of the struct */ + padding = aligned_size - size; + if (padding > 0) { + ptr = stgdict->format; + stgdict->format = _ctypes_alloc_format_padding(ptr, padding); + PyMem_Free(ptr); + if (stgdict->format == NULL) { + return -1; + } + } + + ptr = stgdict->format; stgdict->format = _ctypes_alloc_format_string(stgdict->format, "}"); PyMem_Free(ptr); if (stgdict->format == NULL) return -1; } - if (!isStruct) - size = union_size; - - /* Adjust the size according to the alignment requirements */ - size = ((size + total_align - 1) / total_align) * total_align; - stgdict->ffi_type_pointer.alignment = Py_SAFE_DOWNCAST(total_align, Py_ssize_t, unsigned short); - stgdict->ffi_type_pointer.size = size; + stgdict->ffi_type_pointer.size = aligned_size; - stgdict->size = size; + stgdict->size = aligned_size; stgdict->align = total_align; stgdict->length = len; /* ADD ffi_ofs? */ From f7e9fbacb250ad9df95d0024161b40dfdc9cc39e Mon Sep 17 00:00:00 2001 From: mrh1997 Date: Sun, 5 Feb 2023 18:36:57 +0100 Subject: [PATCH 46/74] bpo-33591: Add support for path like objects to `ctypes.CDLL` (#7032) Co-authored-by: Oleg Iarygin --- Doc/library/ctypes.rst | 16 ++++++++++++++++ Lib/ctypes/__init__.py | 2 ++ Lib/test/test_ctypes/test_loading.py | 18 ++++++++++++++---- Misc/ACKS | 1 + ...18-05-21-17-18-00.gh-issue-77772.Fhg84L.rst | 3 +++ 5 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2018-05-21-17-18-00.gh-issue-77772.Fhg84L.rst diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst index 0642bbe9f99d0db..8fd681286b812dd 100644 --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -1380,6 +1380,10 @@ way is to instantiate one of the following classes: DLLs and determine which one is not found using Windows debugging and tracing tools. + .. versionchanged:: 3.12 + + The *name* parameter can now be a :term:`path-like object`. + .. seealso:: `Microsoft DUMPBIN tool `_ @@ -1398,6 +1402,10 @@ way is to instantiate one of the following classes: .. versionchanged:: 3.3 :exc:`WindowsError` used to be raised. + .. versionchanged:: 3.12 + + The *name* parameter can now be a :term:`path-like object`. + .. class:: WinDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None) @@ -1405,6 +1413,10 @@ way is to instantiate one of the following classes: functions in these libraries use the ``stdcall`` calling convention, and are assumed to return :c:expr:`int` by default. + .. versionchanged:: 3.12 + + The *name* parameter can now be a :term:`path-like object`. + The Python :term:`global interpreter lock` is released before calling any function exported by these libraries, and reacquired afterwards. @@ -1418,6 +1430,10 @@ function exported by these libraries, and reacquired afterwards. Thus, this is only useful to call Python C api functions directly. + .. versionchanged:: 3.12 + + The *name* parameter can now be a :term:`path-like object`. + All these classes can be instantiated by calling them with at least one argument, the pathname of the shared library. If you have an existing handle to an already loaded shared library, it can be passed as the ``handle`` named diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py index 2e9d4c5e7238e95..95353bab26cc71a 100644 --- a/Lib/ctypes/__init__.py +++ b/Lib/ctypes/__init__.py @@ -344,6 +344,8 @@ def __init__(self, name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None): + if name: + name = _os.fspath(name) self._name = name flags = self._func_flags_ if use_errno: diff --git a/Lib/test/test_ctypes/test_loading.py b/Lib/test/test_ctypes/test_loading.py index 15e365ed267d9b6..f2434926a51714b 100644 --- a/Lib/test/test_ctypes/test_loading.py +++ b/Lib/test/test_ctypes/test_loading.py @@ -28,10 +28,20 @@ class LoaderTest(unittest.TestCase): unknowndll = "xxrandomnamexx" def test_load(self): - if libc_name is None: - self.skipTest('could not find libc') - CDLL(libc_name) - CDLL(os.path.basename(libc_name)) + if libc_name is not None: + test_lib = libc_name + else: + if os.name == "nt": + import _ctypes_test + test_lib = _ctypes_test.__file__ + else: + self.skipTest('could not find library to load') + CDLL(test_lib) + CDLL(os.path.basename(test_lib)) + class CTypesTestPathLikeCls: + def __fspath__(self): + return test_lib + CDLL(CTypesTestPathLikeCls()) self.assertRaises(OSError, CDLL, self.unknowndll) def test_load_version(self): diff --git a/Misc/ACKS b/Misc/ACKS index 74abcebe21ea600..d27d60f5b3605e3 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -754,6 +754,7 @@ Tim Hochberg Benjamin Hodgson Joerg-Cyril Hoehle Douwe Hoekstra +Robert Hoelzl Gregor Hoffleit Chris Hoffman Tim Hoffmann diff --git a/Misc/NEWS.d/next/Library/2018-05-21-17-18-00.gh-issue-77772.Fhg84L.rst b/Misc/NEWS.d/next/Library/2018-05-21-17-18-00.gh-issue-77772.Fhg84L.rst new file mode 100644 index 000000000000000..3a7c6d45297ba4f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-21-17-18-00.gh-issue-77772.Fhg84L.rst @@ -0,0 +1,3 @@ +:class:`ctypes.CDLL`, :class:`ctypes.OleDLL`, :class:`ctypes.WinDLL`, +and :class:`ctypes.PyDLL` now accept :term:`path-like objects +` as their ``name`` argument. Patch by Robert Hoelzl. From ffcb8220d7a8c8ca169b467d9e4a752874f68af2 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Sun, 5 Feb 2023 09:44:57 -0800 Subject: [PATCH 47/74] gh-101334: Don't force USTAR format in test_tarfile. (GH-101572) That causes the test to fail when run using a high UID as that ancient format cannot represent it. The current default (PAX) and the old default (GNU) both support high UIDs. --- Lib/test/test_tarfile.py | 5 +++++ .../Tests/2023-02-04-17-24-33.gh-issue-101334._yOqwg.rst | 1 + 2 files changed, 6 insertions(+) create mode 100644 Misc/NEWS.d/next/Tests/2023-02-04-17-24-33.gh-issue-101334._yOqwg.rst diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index 213932069201b96..f15a800976681cf 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -225,6 +225,11 @@ def test_add_dir_getmember(self): self.add_dir_and_getmember('bar') self.add_dir_and_getmember('a'*101) + @unittest.skipIf( + (hasattr(os, 'getuid') and os.getuid() > 0o777_7777) or + (hasattr(os, 'getgid') and os.getgid() > 0o777_7777), + "uid or gid too high for USTAR format." + ) def add_dir_and_getmember(self, name): with os_helper.temp_cwd(): with tarfile.open(tmpname, 'w') as tar: diff --git a/Misc/NEWS.d/next/Tests/2023-02-04-17-24-33.gh-issue-101334._yOqwg.rst b/Misc/NEWS.d/next/Tests/2023-02-04-17-24-33.gh-issue-101334._yOqwg.rst new file mode 100644 index 000000000000000..2a95fd9ae53c868 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2023-02-04-17-24-33.gh-issue-101334._yOqwg.rst @@ -0,0 +1 @@ +``test_tarfile`` has been updated to pass when run as a high UID. From d3e2dd6e71bd8e5482973891926d5df19be687eb Mon Sep 17 00:00:00 2001 From: Matty G Date: Sun, 5 Feb 2023 18:55:37 -0800 Subject: [PATCH 48/74] Trivial Change: Remove unhelpful doc in `datetime.timedelta` (#100164) --- Lib/datetime.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Lib/datetime.py b/Lib/datetime.py index 68746de1cabf85f..637144637485bcd 100644 --- a/Lib/datetime.py +++ b/Lib/datetime.py @@ -587,9 +587,12 @@ class timedelta: returning a timedelta, and addition or subtraction of a datetime and a timedelta giving a datetime. - Representation: (days, seconds, microseconds). Why? Because I - felt like it. + Representation: (days, seconds, microseconds). """ + # The representation of (days, seconds, microseconds) was chosen + # arbitrarily; the exact rationale originally specified in the docstring + # was "Because I felt like it." + __slots__ = '_days', '_seconds', '_microseconds', '_hashcode' def __new__(cls, days=0, seconds=0, microseconds=0, From ef7c2bfcf1fd618438f981ace64499a99ae9fae0 Mon Sep 17 00:00:00 2001 From: Ethan Furman Date: Sun, 5 Feb 2023 19:29:06 -0800 Subject: [PATCH 49/74] gh-101541: [Enum] create flag psuedo-member without calling original __new__ (GH-101590) --- Lib/enum.py | 5 +-- Lib/test/test_enum.py | 40 +++++++++++++++++++ ...-02-05-14-39-49.gh-issue-101541.Mo3ppp.rst | 1 + 3 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2023-02-05-14-39-49.gh-issue-101541.Mo3ppp.rst diff --git a/Lib/enum.py b/Lib/enum.py index adb61519abe942b..d14e91a9b017d14 100644 --- a/Lib/enum.py +++ b/Lib/enum.py @@ -1429,12 +1429,11 @@ def _missing_(cls, value): % (cls.__name__, value, unknown, bin(unknown)) ) # normal Flag? - __new__ = getattr(cls, '__new_member__', None) - if cls._member_type_ is object and not __new__: + if cls._member_type_ is object: # construct a singleton enum pseudo-member pseudo_member = object.__new__(cls) else: - pseudo_member = (__new__ or cls._member_type_.__new__)(cls, value) + pseudo_member = cls._member_type_.__new__(cls, value) if not hasattr(pseudo_member, '_value_'): pseudo_member._value_ = value if member_value: diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py index 1e653e94f6b57ab..0a2e0c14d268af1 100644 --- a/Lib/test/test_enum.py +++ b/Lib/test/test_enum.py @@ -2855,6 +2855,46 @@ class NTEnum(Enum): [TTuple(id=0, a=0, blist=[]), TTuple(id=1, a=2, blist=[4]), TTuple(id=2, a=4, blist=[0, 1, 2])], ) + def test_flag_with_custom_new(self): + class FlagFromChar(IntFlag): + def __new__(cls, c): + value = 1 << c + self = int.__new__(cls, value) + self._value_ = value + return self + # + a = ord('a') + # + self.assertEqual(FlagFromChar.a, 158456325028528675187087900672) + self.assertEqual(FlagFromChar.a|1, 158456325028528675187087900673) + # + # + class FlagFromChar(Flag): + def __new__(cls, c): + value = 1 << c + self = object.__new__(cls) + self._value_ = value + return self + # + a = ord('a') + z = 1 + # + self.assertEqual(FlagFromChar.a.value, 158456325028528675187087900672) + self.assertEqual((FlagFromChar.a|FlagFromChar.z).value, 158456325028528675187087900674) + # + # + class FlagFromChar(int, Flag, boundary=KEEP): + def __new__(cls, c): + value = 1 << c + self = int.__new__(cls, value) + self._value_ = value + return self + # + a = ord('a') + # + self.assertEqual(FlagFromChar.a, 158456325028528675187087900672) + self.assertEqual(FlagFromChar.a|1, 158456325028528675187087900673) + class TestOrder(unittest.TestCase): "test usage of the `_order_` attribute" diff --git a/Misc/NEWS.d/next/Library/2023-02-05-14-39-49.gh-issue-101541.Mo3ppp.rst b/Misc/NEWS.d/next/Library/2023-02-05-14-39-49.gh-issue-101541.Mo3ppp.rst new file mode 100644 index 000000000000000..0f149e80dc54a2a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-02-05-14-39-49.gh-issue-101541.Mo3ppp.rst @@ -0,0 +1 @@ +[Enum] - fix psuedo-flag creation From 9ef7e75434587fc8f167d73eee5dd9bdca62714b Mon Sep 17 00:00:00 2001 From: Dong-hee Na Date: Mon, 6 Feb 2023 13:58:00 +0900 Subject: [PATCH 50/74] =?UTF-8?q?gh-101372:=20Fix=20unicodedata.is=5Fnorma?= =?UTF-8?q?lized=20to=20properly=20handle=20the=20UCD=203=E2=80=A6=20(gh-1?= =?UTF-8?q?01388)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2023-01-28-20-31-42.gh-issue-101372.8BcpCC.rst | 2 ++ Modules/unicodedata.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-01-28-20-31-42.gh-issue-101372.8BcpCC.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-01-28-20-31-42.gh-issue-101372.8BcpCC.rst b/Misc/NEWS.d/next/Core and Builtins/2023-01-28-20-31-42.gh-issue-101372.8BcpCC.rst new file mode 100644 index 000000000000000..65a207e3f7e436d --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-01-28-20-31-42.gh-issue-101372.8BcpCC.rst @@ -0,0 +1,2 @@ +Fix :func:`~unicodedata.is_normalized` to properly handle the UCD 3.2.0 +cases. Patch by Dong-hee Na. diff --git a/Modules/unicodedata.c b/Modules/unicodedata.c index 59fccd4b834dd3c..c108f14871f9463 100644 --- a/Modules/unicodedata.c +++ b/Modules/unicodedata.c @@ -800,7 +800,7 @@ is_normalized_quickcheck(PyObject *self, PyObject *input, bool nfc, bool k, { /* UCD 3.2.0 is requested, quickchecks must be disabled. */ if (UCD_Check(self)) { - return NO; + return MAYBE; } if (PyUnicode_IS_ASCII(input)) { From 46416b9004b687856eaa73e5d48520cd768bbf82 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Mon, 6 Feb 2023 12:25:31 +0000 Subject: [PATCH 51/74] gh-76961: Fix buildbot failures in test_pep3118 (#101587) This PR fixes the buildbot failures introduced by the merge of #5561, by restricting the relevant tests to something that should work on both 32-bit and 64-bit platforms. It also silences some compiler warnings introduced in that PR. --- Lib/test/test_ctypes/test_pep3118.py | 20 ++++++++++---------- Modules/_ctypes/stgdict.c | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Lib/test/test_ctypes/test_pep3118.py b/Lib/test/test_ctypes/test_pep3118.py index 74fdf29fc9ad054..c8a70e3e3356933 100644 --- a/Lib/test/test_ctypes/test_pep3118.py +++ b/Lib/test/test_ctypes/test_pep3118.py @@ -87,14 +87,14 @@ class PackedPoint(Structure): _fields_ = [("x", c_long), ("y", c_long)] class PointMidPad(Structure): - _fields_ = [("x", c_byte), ("y", c_uint64)] + _fields_ = [("x", c_byte), ("y", c_uint)] class PackedPointMidPad(Structure): _pack_ = 2 _fields_ = [("x", c_byte), ("y", c_uint64)] class PointEndPad(Structure): - _fields_ = [("x", c_uint64), ("y", c_byte)] + _fields_ = [("x", c_uint), ("y", c_byte)] class PackedPointEndPad(Structure): _pack_ = 2 @@ -199,14 +199,14 @@ class Complete(Structure): ## structures and unions - (Point2, "T{ Date: Mon, 6 Feb 2023 15:55:32 +0000 Subject: [PATCH 52/74] gh-101543: Ensure Windows registry path is only used when stdlib can't be found (GH-101544) --- ...-02-03-17-53-06.gh-issue-101543.cORAT4.rst | 2 ++ Modules/getpath.py | 31 +++++++------------ 2 files changed, 14 insertions(+), 19 deletions(-) create mode 100644 Misc/NEWS.d/next/Windows/2023-02-03-17-53-06.gh-issue-101543.cORAT4.rst diff --git a/Misc/NEWS.d/next/Windows/2023-02-03-17-53-06.gh-issue-101543.cORAT4.rst b/Misc/NEWS.d/next/Windows/2023-02-03-17-53-06.gh-issue-101543.cORAT4.rst new file mode 100644 index 000000000000000..d4e2c6f23013b6d --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2023-02-03-17-53-06.gh-issue-101543.cORAT4.rst @@ -0,0 +1,2 @@ +Ensure the install path in the registry is only used when the standard +library hasn't been located in any other way. diff --git a/Modules/getpath.py b/Modules/getpath.py index 6a0883878778a57..9913fcba497d308 100644 --- a/Modules/getpath.py +++ b/Modules/getpath.py @@ -582,7 +582,7 @@ def search_up(prefix, *landmarks, test=isfile): # Detect prefix by searching from our executable location for the stdlib_dir if STDLIB_SUBDIR and STDLIB_LANDMARKS and executable_dir and not prefix: prefix = search_up(executable_dir, *STDLIB_LANDMARKS) - if prefix: + if prefix and not stdlib_dir: stdlib_dir = joinpath(prefix, STDLIB_SUBDIR) if PREFIX and not prefix: @@ -631,20 +631,6 @@ def search_up(prefix, *landmarks, test=isfile): warn('Consider setting $PYTHONHOME to [:]') -# If we haven't set [plat]stdlib_dir already, set them now -if not stdlib_dir: - if prefix: - stdlib_dir = joinpath(prefix, STDLIB_SUBDIR) - else: - stdlib_dir = '' - -if not platstdlib_dir: - if exec_prefix: - platstdlib_dir = joinpath(exec_prefix, PLATSTDLIB_LANDMARK) - else: - platstdlib_dir = '' - - # For a venv, update the main prefix/exec_prefix but leave the base ones unchanged # XXX: We currently do not update prefix here, but it happens in site.py #if venv_prefix: @@ -706,8 +692,9 @@ def search_up(prefix, *landmarks, test=isfile): pythonpath.extend(v.split(DELIM)) i += 1 # Paths from the core key get appended last, but only - # when home was not set and we aren't in a build dir - if not home_was_set and not venv_prefix and not build_prefix: + # when home was not set and we haven't found our stdlib + # some other way. + if not home and not stdlib_dir: v = winreg.QueryValue(key, None) if isinstance(v, str): pythonpath.extend(v.split(DELIM)) @@ -722,6 +709,11 @@ def search_up(prefix, *landmarks, test=isfile): pythonpath.append(joinpath(prefix, p)) # Then add stdlib_dir and platstdlib_dir + if not stdlib_dir and prefix: + stdlib_dir = joinpath(prefix, STDLIB_SUBDIR) + if not platstdlib_dir and exec_prefix: + platstdlib_dir = joinpath(exec_prefix, PLATSTDLIB_LANDMARK) + if os_name == 'nt': # QUIRK: Windows generates paths differently if platstdlib_dir: @@ -792,5 +784,6 @@ def search_up(prefix, *landmarks, test=isfile): config['base_exec_prefix'] = base_exec_prefix or exec_prefix config['platlibdir'] = platlibdir -config['stdlib_dir'] = stdlib_dir -config['platstdlib_dir'] = platstdlib_dir +# test_embed expects empty strings, not None +config['stdlib_dir'] = stdlib_dir or '' +config['platstdlib_dir'] = platstdlib_dir or '' From b96b344f251954bb64aeb13c3e0c460350565c2a Mon Sep 17 00:00:00 2001 From: Eclips4 <80244920+Eclips4@users.noreply.github.com> Date: Mon, 6 Feb 2023 22:28:24 +0300 Subject: [PATCH 53/74] gh-101562: typing: add tests for inheritance with NotRequired & Required in parent fields (#101563) --- Lib/test/test_typing.py | 33 +++++++++++++++++++++++++++++++++ Misc/ACKS | 1 + 2 files changed, 34 insertions(+) diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 5aa49bb0e2456de..7a460d94469fe7b 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -4892,6 +4892,18 @@ class NontotalMovie(TypedDict, total=False): title: Required[str] year: int +class ParentNontotalMovie(TypedDict, total=False): + title: Required[str] + +class ChildTotalMovie(ParentNontotalMovie): + year: NotRequired[int] + +class ParentDeeplyAnnotatedMovie(TypedDict): + title: Annotated[Annotated[Required[str], "foobar"], "another level"] + +class ChildDeeplyAnnotatedMovie(ParentDeeplyAnnotatedMovie): + year: NotRequired[Annotated[int, 2000]] + class AnnotatedMovie(TypedDict): title: Annotated[Required[str], "foobar"] year: NotRequired[Annotated[int, 2000]] @@ -5221,6 +5233,17 @@ def test_get_type_hints_typeddict(self): 'a': Annotated[Required[int], "a", "b", "c"] }) + self.assertEqual(get_type_hints(ChildTotalMovie), {"title": str, "year": int}) + self.assertEqual(get_type_hints(ChildTotalMovie, include_extras=True), { + "title": Required[str], "year": NotRequired[int] + }) + + self.assertEqual(get_type_hints(ChildDeeplyAnnotatedMovie), {"title": str, "year": int}) + self.assertEqual(get_type_hints(ChildDeeplyAnnotatedMovie, include_extras=True), { + "title": Annotated[Required[str], "foobar", "another level"], + "year": NotRequired[Annotated[int, 2000]] + }) + def test_get_type_hints_collections_abc_callable(self): # https://github.com/python/cpython/issues/91621 P = ParamSpec('P') @@ -6381,6 +6404,16 @@ def test_required_notrequired_keys(self): self.assertEqual(WeirdlyQuotedMovie.__optional_keys__, frozenset({"year"})) + self.assertEqual(ChildTotalMovie.__required_keys__, + frozenset({"title"})) + self.assertEqual(ChildTotalMovie.__optional_keys__, + frozenset({"year"})) + + self.assertEqual(ChildDeeplyAnnotatedMovie.__required_keys__, + frozenset({"title"})) + self.assertEqual(ChildDeeplyAnnotatedMovie.__optional_keys__, + frozenset({"year"})) + def test_multiple_inheritance(self): class One(TypedDict): one: int diff --git a/Misc/ACKS b/Misc/ACKS index d27d60f5b3605e3..e12cbea0ebd6ed2 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1414,6 +1414,7 @@ Jean-François Piéronne Oleg Plakhotnyuk Anatoliy Platonov Marcel Plch +Kirill Podoprigora Remi Pointel Jon Poler Ariel Poliak From 262003fd3297f7f4ee09cebd1abb225066412ce7 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Tue, 7 Feb 2023 00:05:41 +0300 Subject: [PATCH 54/74] =?UTF-8?q?gh-101609:=20Fix=20"=E2=80=98state?= =?UTF-8?q?=E2=80=99=20may=20be=20used=20uninitialized"=20warning=20in=20`?= =?UTF-8?q?=5Fxxinterpchannelsmodule`=20(GH-101610)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I went with the easiest solution: just removing the offending line. See the issue description with my reasoning. https://github.com/python/cpython/issues/101609 --- Modules/_xxinterpchannelsmodule.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Modules/_xxinterpchannelsmodule.c b/Modules/_xxinterpchannelsmodule.c index 8601a189e87526b..60538c318748647 100644 --- a/Modules/_xxinterpchannelsmodule.c +++ b/Modules/_xxinterpchannelsmodule.c @@ -174,7 +174,9 @@ static int clear_module_state(module_state *state) { /* heap types */ - (void)_PyCrossInterpreterData_UnregisterClass(state->ChannelIDType); + if (state->ChannelIDType != NULL) { + (void)_PyCrossInterpreterData_UnregisterClass(state->ChannelIDType); + } Py_CLEAR(state->ChannelIDType); /* exceptions */ @@ -2269,7 +2271,6 @@ module_exec(PyObject *mod) return 0; error: - (void)_PyCrossInterpreterData_UnregisterClass(state->ChannelIDType); _globals_fini(); return -1; } From 132b3f8302c021ac31e9c1797a127d57faa1afee Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 6 Feb 2023 14:39:25 -0700 Subject: [PATCH 55/74] gh-59956: Partial Fix for GILState API Compatibility with Subinterpreters (gh-101431) The GILState API (PEP 311) implementation from 2003 made the assumption that only one thread state would ever be used for any given OS thread, explicitly disregarding the case of subinterpreters. However, PyThreadState_Swap() still facilitated switching between subinterpreters, meaning the "current" thread state (holding the GIL), and the GILState thread state could end up out of sync, causing problems (including crashes). This change addresses the issue by keeping the two in sync in PyThreadState_Swap(). I verified the fix against gh-99040. Note that the other GILState-subinterpreter incompatibility (with autoInterpreterState) is not resolved here. https://github.com/python/cpython/issues/59956 --- ...3-01-30-11-56-09.gh-issue-59956.7xqnC_.rst | 3 +++ Python/pystate.c | 25 +++---------------- 2 files changed, 7 insertions(+), 21 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-01-30-11-56-09.gh-issue-59956.7xqnC_.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-01-30-11-56-09.gh-issue-59956.7xqnC_.rst b/Misc/NEWS.d/next/Core and Builtins/2023-01-30-11-56-09.gh-issue-59956.7xqnC_.rst new file mode 100644 index 000000000000000..b3c1896b9493e1b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-01-30-11-56-09.gh-issue-59956.7xqnC_.rst @@ -0,0 +1,3 @@ +The GILState API is now partially compatible with subinterpreters. +Previously, ``PyThreadState_GET()`` and ``PyGILState_GetThisThreadState()`` +would get out of sync, causing inconsistent behavior and crashes. diff --git a/Python/pystate.c b/Python/pystate.c index 8bb49d954a81b6e..ed8c2e212a55391 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -266,10 +266,10 @@ unbind_tstate(PyThreadState *tstate) thread state for an OS level thread is when there are multiple interpreters. - The PyGILState_*() APIs don't work with multiple - interpreters (see bpo-10915 and bpo-15751), so this function - sets TSS only once. Thus, the first thread state created for that - given OS level thread will "win", which seems reasonable behaviour. + Before 3.12, the PyGILState_*() APIs didn't work with multiple + interpreters (see bpo-10915 and bpo-15751), so this function used + to set TSS only once. Thus, the first thread state created for that + given OS level thread would "win", which seemed reasonable behaviour. */ static void @@ -286,10 +286,6 @@ bind_gilstate_tstate(PyThreadState *tstate) assert(tstate != tcur); if (tcur != NULL) { - // The original gilstate implementation only respects the - // first thread state set. - // XXX Skipping like this does not play nice with multiple interpreters. - return; tcur->_status.bound_gilstate = 0; } gilstate_tss_set(runtime, tstate); @@ -1738,20 +1734,7 @@ _PyThreadState_Swap(_PyRuntimeState *runtime, PyThreadState *newts) tstate_activate(newts); } - /* It should not be possible for more than one thread state - to be used for a thread. Check this the best we can in debug - builds. - */ - // XXX The above isn't true when multiple interpreters are involved. #if defined(Py_DEBUG) - if (newts && gilstate_tss_initialized(runtime)) { - PyThreadState *check = gilstate_tss_get(runtime); - if (check != newts) { - if (check && check->interp == newts->interp) { - Py_FatalError("Invalid thread state for this thread"); - } - } - } errno = err; #endif return oldts; From 949c58f945b93af5b7bb70c6448e940da669065d Mon Sep 17 00:00:00 2001 From: Mariatta Wijaya Date: Mon, 6 Feb 2023 13:59:45 -0800 Subject: [PATCH 56/74] GH-101616: Mention the Docs Discourse forum in the "reporting docs issues" (GH-101617) Fixes https://github.com/python/cpython/issues/101616 --- Doc/bugs.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Doc/bugs.rst b/Doc/bugs.rst index 69d7c27410d56ae..4f30ef19ee4d8a0 100644 --- a/Doc/bugs.rst +++ b/Doc/bugs.rst @@ -19,6 +19,9 @@ If you find a bug in this documentation or would like to propose an improvement, please submit a bug report on the :ref:`tracker `. If you have a suggestion on how to fix it, include that as well. +You can also open a discussion item on our +`Documentation Discourse forum `_. + If you're short on time, you can also email documentation bug reports to docs@python.org (behavioral bugs can be sent to python-list@python.org). 'docs@' is a mailing list run by volunteers; your request will be noticed, From 38752760c91c87dd67af16d2cee611a22e647567 Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Mon, 6 Feb 2023 22:45:18 +0000 Subject: [PATCH 57/74] gh-98831: rewrite COPY and SWAP in the instruction definition DSL (#101620) --- Python/bytecodes.c | 17 ++++++----------- Python/generated_cases.c.h | 18 +++++++++++------- Python/opcode_metadata.h | 8 ++++---- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 8993567ac82206b..0fc0b3b8280f8ba 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -3098,11 +3098,9 @@ dummy_func( PUSH(result); } - // stack effect: ( -- __0) - inst(COPY) { - assert(oparg != 0); - PyObject *peek = PEEK(oparg); - PUSH(Py_NewRef(peek)); + inst(COPY, (bottom, unused[oparg-1] -- bottom, unused[oparg-1], top)) { + assert(oparg > 0); + top = Py_NewRef(bottom); } inst(BINARY_OP, (unused/1, lhs, rhs -- res)) { @@ -3126,12 +3124,9 @@ dummy_func( ERROR_IF(res == NULL, error); } - // stack effect: ( -- ) - inst(SWAP) { - assert(oparg != 0); - PyObject *top = TOP(); - SET_TOP(PEEK(oparg)); - PEEK(oparg) = top; + inst(SWAP, (bottom, unused[oparg-2], top -- + top, unused[oparg-2], bottom)) { + assert(oparg >= 2); } inst(EXTENDED_ARG, (--)) { diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index e524bfcb99d4700..f0f314a143c2c0f 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -3723,9 +3723,12 @@ } TARGET(COPY) { - assert(oparg != 0); - PyObject *peek = PEEK(oparg); - PUSH(Py_NewRef(peek)); + PyObject *bottom = PEEK(1 + (oparg-1)); + PyObject *top; + assert(oparg > 0); + top = Py_NewRef(bottom); + STACK_GROW(1); + POKE(1, top); DISPATCH(); } @@ -3760,10 +3763,11 @@ } TARGET(SWAP) { - assert(oparg != 0); - PyObject *top = TOP(); - SET_TOP(PEEK(oparg)); - PEEK(oparg) = top; + PyObject *top = PEEK(1); + PyObject *bottom = PEEK(2 + (oparg-2)); + assert(oparg >= 2); + POKE(1, bottom); + POKE(2 + (oparg-2), top); DISPATCH(); } diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index 857526c35aa5b65..948d17519e2709a 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -333,11 +333,11 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) { case FORMAT_VALUE: return -1; case COPY: - return -1; + return (oparg-1) + 1; case BINARY_OP: return 2; case SWAP: - return -1; + return (oparg-2) + 2; case EXTENDED_ARG: return 0; case CACHE: @@ -679,11 +679,11 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { case FORMAT_VALUE: return -1; case COPY: - return -1; + return (oparg-1) + 2; case BINARY_OP: return 1; case SWAP: - return -1; + return (oparg-2) + 2; case EXTENDED_ARG: return 0; case CACHE: From 914f8fd9f7fc5e48b54d938a68c932cc618ef3a6 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 6 Feb 2023 15:53:31 -0700 Subject: [PATCH 58/74] gh-59956: Add a Test to Verify GILState Matches the "Current" Thread State (gh-101625) This test should have been in gh-101431. https://github.com/python/cpython/issues/59956 --- Lib/test/test_capi/test_misc.py | 3 +++ Modules/_testcapimodule.c | 37 +++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py index dace37c362e569f..03e22d7a2d382d1 100644 --- a/Lib/test/test_capi/test_misc.py +++ b/Lib/test/test_capi/test_misc.py @@ -1413,6 +1413,9 @@ def callback(): ret = assert_python_ok('-X', 'tracemalloc', '-c', code) self.assertIn(b'callback called', ret.out) + def test_gilstate_matches_current(self): + _testcapi.test_current_tstate_matches() + class Test_testcapi(unittest.TestCase): locals().update((name, getattr(_testcapi, name)) diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index f0d6e404f54a2f1..5e47f4975a2d54d 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -1534,6 +1534,42 @@ crash_no_current_thread(PyObject *self, PyObject *Py_UNUSED(ignored)) return NULL; } +/* Test that the GILState thread and the "current" thread match. */ +static PyObject * +test_current_tstate_matches(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + PyThreadState *orig_tstate = PyThreadState_Get(); + + if (orig_tstate != PyGILState_GetThisThreadState()) { + PyErr_SetString(PyExc_RuntimeError, + "current thread state doesn't match GILState"); + return NULL; + } + + const char *err = NULL; + PyThreadState_Swap(NULL); + PyThreadState *substate = Py_NewInterpreter(); + + if (substate != PyThreadState_Get()) { + err = "subinterpreter thread state not current"; + goto finally; + } + if (substate != PyGILState_GetThisThreadState()) { + err = "subinterpreter thread state doesn't match GILState"; + goto finally; + } + +finally: + Py_EndInterpreter(substate); + PyThreadState_Swap(orig_tstate); + + if (err != NULL) { + PyErr_SetString(PyExc_RuntimeError, err); + return NULL; + } + Py_RETURN_NONE; +} + /* To run some code in a sub-interpreter. */ static PyObject * run_in_subinterp(PyObject *self, PyObject *args) @@ -3354,6 +3390,7 @@ static PyMethodDef TestMethods[] = { {"make_memoryview_from_NULL_pointer", make_memoryview_from_NULL_pointer, METH_NOARGS}, {"crash_no_current_thread", crash_no_current_thread, METH_NOARGS}, + {"test_current_tstate_matches", test_current_tstate_matches, METH_NOARGS}, {"run_in_subinterp", run_in_subinterp, METH_VARARGS}, {"run_in_subinterp_with_config", _PyCFunction_CAST(run_in_subinterp_with_config), From 1fcc0efdaa84b3602c236391633b70ff36df149b Mon Sep 17 00:00:00 2001 From: Jonathan Protzenko Date: Mon, 6 Feb 2023 18:11:01 -0800 Subject: [PATCH 59/74] gh-99108: Replace SHA2-224 & 256 with verified code from HACL* (#99109) replacing hashlib primitives (for the non-OpenSSL case) with verified implementations from HACL*. This is the first PR in the series, and focuses specifically on SHA2-256 and SHA2-224. This PR imports Hacl_Streaming_SHA2 into the Python tree. This is the HACL* implementation of SHA2, which combines a core implementation of SHA2 along with a layer of buffer management that allows updating the digest with any number of bytes. This supersedes the previous implementation in the tree. @franziskuskiefer was kind enough to benchmark the changes: in addition to being verified (thus providing significant safety and security improvements), this implementation also provides a sizeable performance boost! ``` --------------------------------------------------------------- Benchmark Time CPU Iterations --------------------------------------------------------------- Sha2_256_Streaming 3163 ns 3160 ns 219353 // this PR LibTomCrypt_Sha2_256 5057 ns 5056 ns 136234 // library used by Python currently ``` The changes in this PR are as follows: - import the subset of HACL* that covers SHA2-256/224 into `Modules/_hacl` - rewire sha256module.c to use the HACL* implementation Co-authored-by: Gregory P. Smith [Google LLC] Co-authored-by: Erlend E. Aasland --- Lib/test/test_hashlib.py | 10 + Makefile.pre.in | 2 +- ...2-11-08-12-06-52.gh-issue-99108.4Wrsuh.rst | 4 + Modules/Setup.stdlib.in | 2 +- Modules/_hacl/Hacl_Streaming_SHA2.c | 682 ++++++++++++++++++ Modules/_hacl/Hacl_Streaming_SHA2.h | 136 ++++ Modules/_hacl/README.md | 29 + .../include/krml/FStar_UInt_8_16_32_64.h | 109 +++ Modules/_hacl/include/krml/internal/target.h | 218 ++++++ .../_hacl/include/krml/lowstar_endianness.h | 230 ++++++ .../_hacl/include/python_hacl_namespaces.h | 28 + Modules/_hacl/internal/Hacl_SHA2_Generic.h | 135 ++++ Modules/_hacl/refresh.sh | 132 ++++ Modules/sha256module.c | 398 ++-------- PCbuild/pythoncore.vcxproj | 3 +- PCbuild/pythoncore.vcxproj.filters | 3 + configure | 3 +- configure.ac | 5 +- 18 files changed, 1779 insertions(+), 350 deletions(-) create mode 100644 Misc/NEWS.d/next/Security/2022-11-08-12-06-52.gh-issue-99108.4Wrsuh.rst create mode 100644 Modules/_hacl/Hacl_Streaming_SHA2.c create mode 100644 Modules/_hacl/Hacl_Streaming_SHA2.h create mode 100644 Modules/_hacl/README.md create mode 100644 Modules/_hacl/include/krml/FStar_UInt_8_16_32_64.h create mode 100644 Modules/_hacl/include/krml/internal/target.h create mode 100644 Modules/_hacl/include/krml/lowstar_endianness.h create mode 100644 Modules/_hacl/include/python_hacl_namespaces.h create mode 100644 Modules/_hacl/internal/Hacl_SHA2_Generic.h create mode 100755 Modules/_hacl/refresh.sh diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py index 450dc4933f47f73..9c92b4e9c280dc3 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -22,6 +22,7 @@ from test.support import _4G, bigmemtest from test.support.import_helper import import_fresh_module from test.support import os_helper +from test.support import requires_resource from test.support import threading_helper from test.support import warnings_helper from http.client import HTTPException @@ -354,6 +355,15 @@ def test_large_update(self): self.assertEqual(m1.digest(*args), m4_copy.digest(*args)) self.assertEqual(m4.digest(*args), m4_digest) + @requires_resource('cpu') + def test_sha256_update_over_4gb(self): + zero_1mb = b"\0" * 1024 * 1024 + h = hashlib.sha256() + for i in range(0, 4096): + h.update(zero_1mb) + h.update(b"hello world") + self.assertEqual(h.hexdigest(), "a5364f7a52ebe2e25f1838a4ca715a893b6fd7a23f2a0d9e9762120da8b1bf53") + def check(self, name, data, hexdigest, shake=False, **kwargs): length = len(hexdigest)//2 hexdigest = hexdigest.lower() diff --git a/Makefile.pre.in b/Makefile.pre.in index f2f9371e8ac04de..3641c4eeebeee39 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -2612,7 +2612,7 @@ MODULE__HASHLIB_DEPS=$(srcdir)/Modules/hashlib.h MODULE__IO_DEPS=$(srcdir)/Modules/_io/_iomodule.h MODULE__MD5_DEPS=$(srcdir)/Modules/hashlib.h MODULE__SHA1_DEPS=$(srcdir)/Modules/hashlib.h -MODULE__SHA256_DEPS=$(srcdir)/Modules/hashlib.h +MODULE__SHA256_DEPS=$(srcdir)/Modules/hashlib.h $(srcdir)/Modules/_hacl/include/krml/FStar_UInt_8_16_32_64.h $(srcdir)/Modules/_hacl/include/krml/lowstar_endianness.h $(srcdir)/Modules/_hacl/include/krml/internal/target.h $(srcdir)/Modules/_hacl/Hacl_Streaming_SHA2.h MODULE__SHA3_DEPS=$(srcdir)/Modules/_sha3/sha3.c $(srcdir)/Modules/_sha3/sha3.h $(srcdir)/Modules/hashlib.h MODULE__SHA512_DEPS=$(srcdir)/Modules/hashlib.h MODULE__SOCKET_DEPS=$(srcdir)/Modules/socketmodule.h $(srcdir)/Modules/addrinfo.h $(srcdir)/Modules/getaddrinfo.c $(srcdir)/Modules/getnameinfo.c diff --git a/Misc/NEWS.d/next/Security/2022-11-08-12-06-52.gh-issue-99108.4Wrsuh.rst b/Misc/NEWS.d/next/Security/2022-11-08-12-06-52.gh-issue-99108.4Wrsuh.rst new file mode 100644 index 000000000000000..64acc09c482ecbd --- /dev/null +++ b/Misc/NEWS.d/next/Security/2022-11-08-12-06-52.gh-issue-99108.4Wrsuh.rst @@ -0,0 +1,4 @@ +Replace the builtin :mod:`hashlib` implementations of SHA2-224 and SHA2-256 +originally from LibTomCrypt with formally verified, side-channel resistant +code from the `HACL* `_ project. The +builtins remain a fallback only used when OpenSSL does not provide them. diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 3fd591c70d493f2..f72783810f9415c 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -79,7 +79,7 @@ # hashing builtins, can be disabled with --without-builtin-hashlib-hashes @MODULE__MD5_TRUE@_md5 md5module.c @MODULE__SHA1_TRUE@_sha1 sha1module.c -@MODULE__SHA256_TRUE@_sha256 sha256module.c +@MODULE__SHA256_TRUE@_sha256 sha256module.c _hacl/Hacl_Streaming_SHA2.c @MODULE__SHA512_TRUE@_sha512 sha512module.c @MODULE__SHA3_TRUE@_sha3 _sha3/sha3module.c @MODULE__BLAKE2_TRUE@_blake2 _blake2/blake2module.c _blake2/blake2b_impl.c _blake2/blake2s_impl.c diff --git a/Modules/_hacl/Hacl_Streaming_SHA2.c b/Modules/_hacl/Hacl_Streaming_SHA2.c new file mode 100644 index 000000000000000..84566571792a3c8 --- /dev/null +++ b/Modules/_hacl/Hacl_Streaming_SHA2.c @@ -0,0 +1,682 @@ +/* MIT License + * + * Copyright (c) 2016-2022 INRIA, CMU and Microsoft Corporation + * Copyright (c) 2022-2023 HACL* Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + +#include "Hacl_Streaming_SHA2.h" + +#include "internal/Hacl_SHA2_Generic.h" + + +static inline void sha256_init(uint32_t *hash) +{ + KRML_MAYBE_FOR8(i, + (uint32_t)0U, + (uint32_t)8U, + (uint32_t)1U, + uint32_t *os = hash; + uint32_t x = Hacl_Impl_SHA2_Generic_h256[i]; + os[i] = x;); +} + +static inline void sha256_update0(uint8_t *b, uint32_t *hash) +{ + uint32_t hash_old[8U] = { 0U }; + uint32_t ws[16U] = { 0U }; + memcpy(hash_old, hash, (uint32_t)8U * sizeof (uint32_t)); + uint8_t *b10 = b; + uint32_t u = load32_be(b10); + ws[0U] = u; + uint32_t u0 = load32_be(b10 + (uint32_t)4U); + ws[1U] = u0; + uint32_t u1 = load32_be(b10 + (uint32_t)8U); + ws[2U] = u1; + uint32_t u2 = load32_be(b10 + (uint32_t)12U); + ws[3U] = u2; + uint32_t u3 = load32_be(b10 + (uint32_t)16U); + ws[4U] = u3; + uint32_t u4 = load32_be(b10 + (uint32_t)20U); + ws[5U] = u4; + uint32_t u5 = load32_be(b10 + (uint32_t)24U); + ws[6U] = u5; + uint32_t u6 = load32_be(b10 + (uint32_t)28U); + ws[7U] = u6; + uint32_t u7 = load32_be(b10 + (uint32_t)32U); + ws[8U] = u7; + uint32_t u8 = load32_be(b10 + (uint32_t)36U); + ws[9U] = u8; + uint32_t u9 = load32_be(b10 + (uint32_t)40U); + ws[10U] = u9; + uint32_t u10 = load32_be(b10 + (uint32_t)44U); + ws[11U] = u10; + uint32_t u11 = load32_be(b10 + (uint32_t)48U); + ws[12U] = u11; + uint32_t u12 = load32_be(b10 + (uint32_t)52U); + ws[13U] = u12; + uint32_t u13 = load32_be(b10 + (uint32_t)56U); + ws[14U] = u13; + uint32_t u14 = load32_be(b10 + (uint32_t)60U); + ws[15U] = u14; + KRML_MAYBE_FOR4(i0, + (uint32_t)0U, + (uint32_t)4U, + (uint32_t)1U, + KRML_MAYBE_FOR16(i, + (uint32_t)0U, + (uint32_t)16U, + (uint32_t)1U, + uint32_t k_t = Hacl_Impl_SHA2_Generic_k224_256[(uint32_t)16U * i0 + i]; + uint32_t ws_t = ws[i]; + uint32_t a0 = hash[0U]; + uint32_t b0 = hash[1U]; + uint32_t c0 = hash[2U]; + uint32_t d0 = hash[3U]; + uint32_t e0 = hash[4U]; + uint32_t f0 = hash[5U]; + uint32_t g0 = hash[6U]; + uint32_t h02 = hash[7U]; + uint32_t k_e_t = k_t; + uint32_t + t1 = + h02 + + + ((e0 << (uint32_t)26U | e0 >> (uint32_t)6U) + ^ + ((e0 << (uint32_t)21U | e0 >> (uint32_t)11U) + ^ (e0 << (uint32_t)7U | e0 >> (uint32_t)25U))) + + ((e0 & f0) ^ (~e0 & g0)) + + k_e_t + + ws_t; + uint32_t + t2 = + ((a0 << (uint32_t)30U | a0 >> (uint32_t)2U) + ^ + ((a0 << (uint32_t)19U | a0 >> (uint32_t)13U) + ^ (a0 << (uint32_t)10U | a0 >> (uint32_t)22U))) + + ((a0 & b0) ^ ((a0 & c0) ^ (b0 & c0))); + uint32_t a1 = t1 + t2; + uint32_t b1 = a0; + uint32_t c1 = b0; + uint32_t d1 = c0; + uint32_t e1 = d0 + t1; + uint32_t f1 = e0; + uint32_t g1 = f0; + uint32_t h12 = g0; + hash[0U] = a1; + hash[1U] = b1; + hash[2U] = c1; + hash[3U] = d1; + hash[4U] = e1; + hash[5U] = f1; + hash[6U] = g1; + hash[7U] = h12;); + if (i0 < (uint32_t)3U) + { + KRML_MAYBE_FOR16(i, + (uint32_t)0U, + (uint32_t)16U, + (uint32_t)1U, + uint32_t t16 = ws[i]; + uint32_t t15 = ws[(i + (uint32_t)1U) % (uint32_t)16U]; + uint32_t t7 = ws[(i + (uint32_t)9U) % (uint32_t)16U]; + uint32_t t2 = ws[(i + (uint32_t)14U) % (uint32_t)16U]; + uint32_t + s1 = + (t2 << (uint32_t)15U | t2 >> (uint32_t)17U) + ^ ((t2 << (uint32_t)13U | t2 >> (uint32_t)19U) ^ t2 >> (uint32_t)10U); + uint32_t + s0 = + (t15 << (uint32_t)25U | t15 >> (uint32_t)7U) + ^ ((t15 << (uint32_t)14U | t15 >> (uint32_t)18U) ^ t15 >> (uint32_t)3U); + ws[i] = s1 + t7 + s0 + t16;); + }); + KRML_MAYBE_FOR8(i, + (uint32_t)0U, + (uint32_t)8U, + (uint32_t)1U, + uint32_t *os = hash; + uint32_t x = hash[i] + hash_old[i]; + os[i] = x;); +} + +static inline void sha256_update_nblocks(uint32_t len, uint8_t *b, uint32_t *st) +{ + uint32_t blocks = len / (uint32_t)64U; + for (uint32_t i = (uint32_t)0U; i < blocks; i++) + { + uint8_t *b0 = b; + uint8_t *mb = b0 + i * (uint32_t)64U; + sha256_update0(mb, st); + } +} + +static inline void +sha256_update_last(uint64_t totlen, uint32_t len, uint8_t *b, uint32_t *hash) +{ + uint32_t blocks; + if (len + (uint32_t)8U + (uint32_t)1U <= (uint32_t)64U) + { + blocks = (uint32_t)1U; + } + else + { + blocks = (uint32_t)2U; + } + uint32_t fin = blocks * (uint32_t)64U; + uint8_t last[128U] = { 0U }; + uint8_t totlen_buf[8U] = { 0U }; + uint64_t total_len_bits = totlen << (uint32_t)3U; + store64_be(totlen_buf, total_len_bits); + uint8_t *b0 = b; + memcpy(last, b0, len * sizeof (uint8_t)); + last[len] = (uint8_t)0x80U; + memcpy(last + fin - (uint32_t)8U, totlen_buf, (uint32_t)8U * sizeof (uint8_t)); + uint8_t *last00 = last; + uint8_t *last10 = last + (uint32_t)64U; + uint8_t *l0 = last00; + uint8_t *l1 = last10; + uint8_t *lb0 = l0; + uint8_t *lb1 = l1; + uint8_t *last0 = lb0; + uint8_t *last1 = lb1; + sha256_update0(last0, hash); + if (blocks > (uint32_t)1U) + { + sha256_update0(last1, hash); + return; + } +} + +static inline void sha256_finish(uint32_t *st, uint8_t *h) +{ + uint8_t hbuf[32U] = { 0U }; + KRML_MAYBE_FOR8(i, + (uint32_t)0U, + (uint32_t)8U, + (uint32_t)1U, + store32_be(hbuf + i * (uint32_t)4U, st[i]);); + memcpy(h, hbuf, (uint32_t)32U * sizeof (uint8_t)); +} + +static inline void sha224_init(uint32_t *hash) +{ + KRML_MAYBE_FOR8(i, + (uint32_t)0U, + (uint32_t)8U, + (uint32_t)1U, + uint32_t *os = hash; + uint32_t x = Hacl_Impl_SHA2_Generic_h224[i]; + os[i] = x;); +} + +static inline void sha224_update_nblocks(uint32_t len, uint8_t *b, uint32_t *st) +{ + sha256_update_nblocks(len, b, st); +} + +static void sha224_update_last(uint64_t totlen, uint32_t len, uint8_t *b, uint32_t *st) +{ + sha256_update_last(totlen, len, b, st); +} + +static inline void sha224_finish(uint32_t *st, uint8_t *h) +{ + uint8_t hbuf[32U] = { 0U }; + KRML_MAYBE_FOR8(i, + (uint32_t)0U, + (uint32_t)8U, + (uint32_t)1U, + store32_be(hbuf + i * (uint32_t)4U, st[i]);); + memcpy(h, hbuf, (uint32_t)28U * sizeof (uint8_t)); +} + +/** +Allocate initial state for the SHA2_256 hash. The state is to be freed by +calling `free_256`. +*/ +Hacl_Streaming_SHA2_state_sha2_224 *Hacl_Streaming_SHA2_create_in_256(void) +{ + uint8_t *buf = (uint8_t *)KRML_HOST_CALLOC((uint32_t)64U, sizeof (uint8_t)); + uint32_t *block_state = (uint32_t *)KRML_HOST_CALLOC((uint32_t)8U, sizeof (uint32_t)); + Hacl_Streaming_SHA2_state_sha2_224 + s = { .block_state = block_state, .buf = buf, .total_len = (uint64_t)(uint32_t)0U }; + Hacl_Streaming_SHA2_state_sha2_224 + *p = + (Hacl_Streaming_SHA2_state_sha2_224 *)KRML_HOST_MALLOC(sizeof ( + Hacl_Streaming_SHA2_state_sha2_224 + )); + p[0U] = s; + sha256_init(block_state); + return p; +} + +/** +Copies the state passed as argument into a newly allocated state (deep copy). +The state is to be freed by calling `free_256`. Cloning the state this way is +useful, for instance, if your control-flow diverges and you need to feed +more (different) data into the hash in each branch. +*/ +Hacl_Streaming_SHA2_state_sha2_224 +*Hacl_Streaming_SHA2_copy_256(Hacl_Streaming_SHA2_state_sha2_224 *s0) +{ + Hacl_Streaming_SHA2_state_sha2_224 scrut = *s0; + uint32_t *block_state0 = scrut.block_state; + uint8_t *buf0 = scrut.buf; + uint64_t total_len0 = scrut.total_len; + uint8_t *buf = (uint8_t *)KRML_HOST_CALLOC((uint32_t)64U, sizeof (uint8_t)); + memcpy(buf, buf0, (uint32_t)64U * sizeof (uint8_t)); + uint32_t *block_state = (uint32_t *)KRML_HOST_CALLOC((uint32_t)8U, sizeof (uint32_t)); + memcpy(block_state, block_state0, (uint32_t)8U * sizeof (uint32_t)); + Hacl_Streaming_SHA2_state_sha2_224 + s = { .block_state = block_state, .buf = buf, .total_len = total_len0 }; + Hacl_Streaming_SHA2_state_sha2_224 + *p = + (Hacl_Streaming_SHA2_state_sha2_224 *)KRML_HOST_MALLOC(sizeof ( + Hacl_Streaming_SHA2_state_sha2_224 + )); + p[0U] = s; + return p; +} + +/** +Reset an existing state to the initial hash state with empty data. +*/ +void Hacl_Streaming_SHA2_init_256(Hacl_Streaming_SHA2_state_sha2_224 *s) +{ + Hacl_Streaming_SHA2_state_sha2_224 scrut = *s; + uint8_t *buf = scrut.buf; + uint32_t *block_state = scrut.block_state; + sha256_init(block_state); + Hacl_Streaming_SHA2_state_sha2_224 + tmp = { .block_state = block_state, .buf = buf, .total_len = (uint64_t)(uint32_t)0U }; + s[0U] = tmp; +} + +static inline uint32_t +update_224_256(Hacl_Streaming_SHA2_state_sha2_224 *p, uint8_t *data, uint32_t len) +{ + Hacl_Streaming_SHA2_state_sha2_224 s = *p; + uint64_t total_len = s.total_len; + if ((uint64_t)len > (uint64_t)2305843009213693951U - total_len) + { + return (uint32_t)1U; + } + uint32_t sz; + if (total_len % (uint64_t)(uint32_t)64U == (uint64_t)0U && total_len > (uint64_t)0U) + { + sz = (uint32_t)64U; + } + else + { + sz = (uint32_t)(total_len % (uint64_t)(uint32_t)64U); + } + if (len <= (uint32_t)64U - sz) + { + Hacl_Streaming_SHA2_state_sha2_224 s1 = *p; + uint32_t *block_state1 = s1.block_state; + uint8_t *buf = s1.buf; + uint64_t total_len1 = s1.total_len; + uint32_t sz1; + if (total_len1 % (uint64_t)(uint32_t)64U == (uint64_t)0U && total_len1 > (uint64_t)0U) + { + sz1 = (uint32_t)64U; + } + else + { + sz1 = (uint32_t)(total_len1 % (uint64_t)(uint32_t)64U); + } + uint8_t *buf2 = buf + sz1; + memcpy(buf2, data, len * sizeof (uint8_t)); + uint64_t total_len2 = total_len1 + (uint64_t)len; + *p + = + ( + (Hacl_Streaming_SHA2_state_sha2_224){ + .block_state = block_state1, + .buf = buf, + .total_len = total_len2 + } + ); + } + else if (sz == (uint32_t)0U) + { + Hacl_Streaming_SHA2_state_sha2_224 s1 = *p; + uint32_t *block_state1 = s1.block_state; + uint8_t *buf = s1.buf; + uint64_t total_len1 = s1.total_len; + uint32_t sz1; + if (total_len1 % (uint64_t)(uint32_t)64U == (uint64_t)0U && total_len1 > (uint64_t)0U) + { + sz1 = (uint32_t)64U; + } + else + { + sz1 = (uint32_t)(total_len1 % (uint64_t)(uint32_t)64U); + } + if (!(sz1 == (uint32_t)0U)) + { + sha256_update_nblocks((uint32_t)64U, buf, block_state1); + } + uint32_t ite; + if ((uint64_t)len % (uint64_t)(uint32_t)64U == (uint64_t)0U && (uint64_t)len > (uint64_t)0U) + { + ite = (uint32_t)64U; + } + else + { + ite = (uint32_t)((uint64_t)len % (uint64_t)(uint32_t)64U); + } + uint32_t n_blocks = (len - ite) / (uint32_t)64U; + uint32_t data1_len = n_blocks * (uint32_t)64U; + uint32_t data2_len = len - data1_len; + uint8_t *data1 = data; + uint8_t *data2 = data + data1_len; + sha256_update_nblocks(data1_len, data1, block_state1); + uint8_t *dst = buf; + memcpy(dst, data2, data2_len * sizeof (uint8_t)); + *p + = + ( + (Hacl_Streaming_SHA2_state_sha2_224){ + .block_state = block_state1, + .buf = buf, + .total_len = total_len1 + (uint64_t)len + } + ); + } + else + { + uint32_t diff = (uint32_t)64U - sz; + uint8_t *data1 = data; + uint8_t *data2 = data + diff; + Hacl_Streaming_SHA2_state_sha2_224 s1 = *p; + uint32_t *block_state10 = s1.block_state; + uint8_t *buf0 = s1.buf; + uint64_t total_len10 = s1.total_len; + uint32_t sz10; + if (total_len10 % (uint64_t)(uint32_t)64U == (uint64_t)0U && total_len10 > (uint64_t)0U) + { + sz10 = (uint32_t)64U; + } + else + { + sz10 = (uint32_t)(total_len10 % (uint64_t)(uint32_t)64U); + } + uint8_t *buf2 = buf0 + sz10; + memcpy(buf2, data1, diff * sizeof (uint8_t)); + uint64_t total_len2 = total_len10 + (uint64_t)diff; + *p + = + ( + (Hacl_Streaming_SHA2_state_sha2_224){ + .block_state = block_state10, + .buf = buf0, + .total_len = total_len2 + } + ); + Hacl_Streaming_SHA2_state_sha2_224 s10 = *p; + uint32_t *block_state1 = s10.block_state; + uint8_t *buf = s10.buf; + uint64_t total_len1 = s10.total_len; + uint32_t sz1; + if (total_len1 % (uint64_t)(uint32_t)64U == (uint64_t)0U && total_len1 > (uint64_t)0U) + { + sz1 = (uint32_t)64U; + } + else + { + sz1 = (uint32_t)(total_len1 % (uint64_t)(uint32_t)64U); + } + if (!(sz1 == (uint32_t)0U)) + { + sha256_update_nblocks((uint32_t)64U, buf, block_state1); + } + uint32_t ite; + if + ( + (uint64_t)(len - diff) + % (uint64_t)(uint32_t)64U + == (uint64_t)0U + && (uint64_t)(len - diff) > (uint64_t)0U + ) + { + ite = (uint32_t)64U; + } + else + { + ite = (uint32_t)((uint64_t)(len - diff) % (uint64_t)(uint32_t)64U); + } + uint32_t n_blocks = (len - diff - ite) / (uint32_t)64U; + uint32_t data1_len = n_blocks * (uint32_t)64U; + uint32_t data2_len = len - diff - data1_len; + uint8_t *data11 = data2; + uint8_t *data21 = data2 + data1_len; + sha256_update_nblocks(data1_len, data11, block_state1); + uint8_t *dst = buf; + memcpy(dst, data21, data2_len * sizeof (uint8_t)); + *p + = + ( + (Hacl_Streaming_SHA2_state_sha2_224){ + .block_state = block_state1, + .buf = buf, + .total_len = total_len1 + (uint64_t)(len - diff) + } + ); + } + return (uint32_t)0U; +} + +/** +Feed an arbitrary amount of data into the hash. This function returns 0 for +success, or 1 if the combined length of all of the data passed to `update_256` +(since the last call to `init_256`) exceeds 2^61-1 bytes. + +This function is identical to the update function for SHA2_224. +*/ +uint32_t +Hacl_Streaming_SHA2_update_256( + Hacl_Streaming_SHA2_state_sha2_224 *p, + uint8_t *input, + uint32_t input_len +) +{ + return update_224_256(p, input, input_len); +} + +/** +Write the resulting hash into `dst`, an array of 32 bytes. The state remains +valid after a call to `finish_256`, meaning the user may feed more data into +the hash via `update_256`. (The finish_256 function operates on an internal copy of +the state and therefore does not invalidate the client-held state `p`.) +*/ +void Hacl_Streaming_SHA2_finish_256(Hacl_Streaming_SHA2_state_sha2_224 *p, uint8_t *dst) +{ + Hacl_Streaming_SHA2_state_sha2_224 scrut = *p; + uint32_t *block_state = scrut.block_state; + uint8_t *buf_ = scrut.buf; + uint64_t total_len = scrut.total_len; + uint32_t r; + if (total_len % (uint64_t)(uint32_t)64U == (uint64_t)0U && total_len > (uint64_t)0U) + { + r = (uint32_t)64U; + } + else + { + r = (uint32_t)(total_len % (uint64_t)(uint32_t)64U); + } + uint8_t *buf_1 = buf_; + uint32_t tmp_block_state[8U] = { 0U }; + memcpy(tmp_block_state, block_state, (uint32_t)8U * sizeof (uint32_t)); + uint32_t ite; + if (r % (uint32_t)64U == (uint32_t)0U && r > (uint32_t)0U) + { + ite = (uint32_t)64U; + } + else + { + ite = r % (uint32_t)64U; + } + uint8_t *buf_last = buf_1 + r - ite; + uint8_t *buf_multi = buf_1; + sha256_update_nblocks((uint32_t)0U, buf_multi, tmp_block_state); + uint64_t prev_len_last = total_len - (uint64_t)r; + sha256_update_last(prev_len_last + (uint64_t)r, r, buf_last, tmp_block_state); + sha256_finish(tmp_block_state, dst); +} + +/** +Free a state allocated with `create_in_256`. + +This function is identical to the free function for SHA2_224. +*/ +void Hacl_Streaming_SHA2_free_256(Hacl_Streaming_SHA2_state_sha2_224 *s) +{ + Hacl_Streaming_SHA2_state_sha2_224 scrut = *s; + uint8_t *buf = scrut.buf; + uint32_t *block_state = scrut.block_state; + KRML_HOST_FREE(block_state); + KRML_HOST_FREE(buf); + KRML_HOST_FREE(s); +} + +/** +Hash `input`, of len `input_len`, into `dst`, an array of 32 bytes. +*/ +void Hacl_Streaming_SHA2_sha256(uint8_t *input, uint32_t input_len, uint8_t *dst) +{ + uint8_t *ib = input; + uint8_t *rb = dst; + uint32_t st[8U] = { 0U }; + sha256_init(st); + uint32_t rem = input_len % (uint32_t)64U; + uint64_t len_ = (uint64_t)input_len; + sha256_update_nblocks(input_len, ib, st); + uint32_t rem1 = input_len % (uint32_t)64U; + uint8_t *b0 = ib; + uint8_t *lb = b0 + input_len - rem1; + sha256_update_last(len_, rem, lb, st); + sha256_finish(st, rb); +} + +Hacl_Streaming_SHA2_state_sha2_224 *Hacl_Streaming_SHA2_create_in_224(void) +{ + uint8_t *buf = (uint8_t *)KRML_HOST_CALLOC((uint32_t)64U, sizeof (uint8_t)); + uint32_t *block_state = (uint32_t *)KRML_HOST_CALLOC((uint32_t)8U, sizeof (uint32_t)); + Hacl_Streaming_SHA2_state_sha2_224 + s = { .block_state = block_state, .buf = buf, .total_len = (uint64_t)(uint32_t)0U }; + Hacl_Streaming_SHA2_state_sha2_224 + *p = + (Hacl_Streaming_SHA2_state_sha2_224 *)KRML_HOST_MALLOC(sizeof ( + Hacl_Streaming_SHA2_state_sha2_224 + )); + p[0U] = s; + sha224_init(block_state); + return p; +} + +void Hacl_Streaming_SHA2_init_224(Hacl_Streaming_SHA2_state_sha2_224 *s) +{ + Hacl_Streaming_SHA2_state_sha2_224 scrut = *s; + uint8_t *buf = scrut.buf; + uint32_t *block_state = scrut.block_state; + sha224_init(block_state); + Hacl_Streaming_SHA2_state_sha2_224 + tmp = { .block_state = block_state, .buf = buf, .total_len = (uint64_t)(uint32_t)0U }; + s[0U] = tmp; +} + +uint32_t +Hacl_Streaming_SHA2_update_224( + Hacl_Streaming_SHA2_state_sha2_224 *p, + uint8_t *input, + uint32_t input_len +) +{ + return update_224_256(p, input, input_len); +} + +/** +Write the resulting hash into `dst`, an array of 28 bytes. The state remains +valid after a call to `finish_224`, meaning the user may feed more data into +the hash via `update_224`. +*/ +void Hacl_Streaming_SHA2_finish_224(Hacl_Streaming_SHA2_state_sha2_224 *p, uint8_t *dst) +{ + Hacl_Streaming_SHA2_state_sha2_224 scrut = *p; + uint32_t *block_state = scrut.block_state; + uint8_t *buf_ = scrut.buf; + uint64_t total_len = scrut.total_len; + uint32_t r; + if (total_len % (uint64_t)(uint32_t)64U == (uint64_t)0U && total_len > (uint64_t)0U) + { + r = (uint32_t)64U; + } + else + { + r = (uint32_t)(total_len % (uint64_t)(uint32_t)64U); + } + uint8_t *buf_1 = buf_; + uint32_t tmp_block_state[8U] = { 0U }; + memcpy(tmp_block_state, block_state, (uint32_t)8U * sizeof (uint32_t)); + uint32_t ite; + if (r % (uint32_t)64U == (uint32_t)0U && r > (uint32_t)0U) + { + ite = (uint32_t)64U; + } + else + { + ite = r % (uint32_t)64U; + } + uint8_t *buf_last = buf_1 + r - ite; + uint8_t *buf_multi = buf_1; + sha224_update_nblocks((uint32_t)0U, buf_multi, tmp_block_state); + uint64_t prev_len_last = total_len - (uint64_t)r; + sha224_update_last(prev_len_last + (uint64_t)r, r, buf_last, tmp_block_state); + sha224_finish(tmp_block_state, dst); +} + +void Hacl_Streaming_SHA2_free_224(Hacl_Streaming_SHA2_state_sha2_224 *p) +{ + Hacl_Streaming_SHA2_free_256(p); +} + +/** +Hash `input`, of len `input_len`, into `dst`, an array of 28 bytes. +*/ +void Hacl_Streaming_SHA2_sha224(uint8_t *input, uint32_t input_len, uint8_t *dst) +{ + uint8_t *ib = input; + uint8_t *rb = dst; + uint32_t st[8U] = { 0U }; + sha224_init(st); + uint32_t rem = input_len % (uint32_t)64U; + uint64_t len_ = (uint64_t)input_len; + sha224_update_nblocks(input_len, ib, st); + uint32_t rem1 = input_len % (uint32_t)64U; + uint8_t *b0 = ib; + uint8_t *lb = b0 + input_len - rem1; + sha224_update_last(len_, rem, lb, st); + sha224_finish(st, rb); +} + diff --git a/Modules/_hacl/Hacl_Streaming_SHA2.h b/Modules/_hacl/Hacl_Streaming_SHA2.h new file mode 100644 index 000000000000000..c83a835afe70fd8 --- /dev/null +++ b/Modules/_hacl/Hacl_Streaming_SHA2.h @@ -0,0 +1,136 @@ +/* MIT License + * + * Copyright (c) 2016-2022 INRIA, CMU and Microsoft Corporation + * Copyright (c) 2022-2023 HACL* Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + +#ifndef __Hacl_Streaming_SHA2_H +#define __Hacl_Streaming_SHA2_H + +#if defined(__cplusplus) +extern "C" { +#endif + +#include +#include "python_hacl_namespaces.h" +#include "krml/FStar_UInt_8_16_32_64.h" +#include "krml/lowstar_endianness.h" +#include "krml/internal/target.h" + + + + +typedef struct Hacl_Streaming_SHA2_state_sha2_224_s +{ + uint32_t *block_state; + uint8_t *buf; + uint64_t total_len; +} +Hacl_Streaming_SHA2_state_sha2_224; + +typedef Hacl_Streaming_SHA2_state_sha2_224 Hacl_Streaming_SHA2_state_sha2_256; + +/** +Allocate initial state for the SHA2_256 hash. The state is to be freed by +calling `free_256`. +*/ +Hacl_Streaming_SHA2_state_sha2_224 *Hacl_Streaming_SHA2_create_in_256(void); + +/** +Copies the state passed as argument into a newly allocated state (deep copy). +The state is to be freed by calling `free_256`. Cloning the state this way is +useful, for instance, if your control-flow diverges and you need to feed +more (different) data into the hash in each branch. +*/ +Hacl_Streaming_SHA2_state_sha2_224 +*Hacl_Streaming_SHA2_copy_256(Hacl_Streaming_SHA2_state_sha2_224 *s0); + +/** +Reset an existing state to the initial hash state with empty data. +*/ +void Hacl_Streaming_SHA2_init_256(Hacl_Streaming_SHA2_state_sha2_224 *s); + +/** +Feed an arbitrary amount of data into the hash. This function returns 0 for +success, or 1 if the combined length of all of the data passed to `update_256` +(since the last call to `init_256`) exceeds 2^61-1 bytes. + +This function is identical to the update function for SHA2_224. +*/ +uint32_t +Hacl_Streaming_SHA2_update_256( + Hacl_Streaming_SHA2_state_sha2_224 *p, + uint8_t *input, + uint32_t input_len +); + +/** +Write the resulting hash into `dst`, an array of 32 bytes. The state remains +valid after a call to `finish_256`, meaning the user may feed more data into +the hash via `update_256`. (The finish_256 function operates on an internal copy of +the state and therefore does not invalidate the client-held state `p`.) +*/ +void Hacl_Streaming_SHA2_finish_256(Hacl_Streaming_SHA2_state_sha2_224 *p, uint8_t *dst); + +/** +Free a state allocated with `create_in_256`. + +This function is identical to the free function for SHA2_224. +*/ +void Hacl_Streaming_SHA2_free_256(Hacl_Streaming_SHA2_state_sha2_224 *s); + +/** +Hash `input`, of len `input_len`, into `dst`, an array of 32 bytes. +*/ +void Hacl_Streaming_SHA2_sha256(uint8_t *input, uint32_t input_len, uint8_t *dst); + +Hacl_Streaming_SHA2_state_sha2_224 *Hacl_Streaming_SHA2_create_in_224(void); + +void Hacl_Streaming_SHA2_init_224(Hacl_Streaming_SHA2_state_sha2_224 *s); + +uint32_t +Hacl_Streaming_SHA2_update_224( + Hacl_Streaming_SHA2_state_sha2_224 *p, + uint8_t *input, + uint32_t input_len +); + +/** +Write the resulting hash into `dst`, an array of 28 bytes. The state remains +valid after a call to `finish_224`, meaning the user may feed more data into +the hash via `update_224`. +*/ +void Hacl_Streaming_SHA2_finish_224(Hacl_Streaming_SHA2_state_sha2_224 *p, uint8_t *dst); + +void Hacl_Streaming_SHA2_free_224(Hacl_Streaming_SHA2_state_sha2_224 *p); + +/** +Hash `input`, of len `input_len`, into `dst`, an array of 28 bytes. +*/ +void Hacl_Streaming_SHA2_sha224(uint8_t *input, uint32_t input_len, uint8_t *dst); + +#if defined(__cplusplus) +} +#endif + +#define __Hacl_Streaming_SHA2_H_DEFINED +#endif diff --git a/Modules/_hacl/README.md b/Modules/_hacl/README.md new file mode 100644 index 000000000000000..e6a156a54b3cee5 --- /dev/null +++ b/Modules/_hacl/README.md @@ -0,0 +1,29 @@ +# Algorithm implementations used by the `hashlib` module. + +This code comes from the +[HACL\*](https://github.com/hacl-star/hacl-star/) project. + +HACL\* is a cryptographic library that has been formally verified for memory +safety, functional correctness, and secret independence. + +## Updating HACL* + +Use the `refresh.sh` script in this directory to pull in a new upstream code +version. The upstream git hash used for the most recent code pull is recorded +in the script. Modify the script as needed to bring in more if changes are +needed based on upstream code refactoring. + +Never manually edit HACL\* files. Always add transformation shell code to the +`refresh.sh` script to perform any necessary edits. If there are serious code +changes needed, work with the upstream repository. + +## Local files + +1. `./include/python_hacl_namespaces.h` +1. `./README.md` +1. `./refresh.sh` + +## ACKS + +* Jonathan Protzenko aka [@msprotz on Github](https://github.com/msprotz) +contributed our HACL\* based builtin code. diff --git a/Modules/_hacl/include/krml/FStar_UInt_8_16_32_64.h b/Modules/_hacl/include/krml/FStar_UInt_8_16_32_64.h new file mode 100644 index 000000000000000..3e2e4b32b22f96e --- /dev/null +++ b/Modules/_hacl/include/krml/FStar_UInt_8_16_32_64.h @@ -0,0 +1,109 @@ +/* + Copyright (c) INRIA and Microsoft Corporation. All rights reserved. + Licensed under the Apache 2.0 License. +*/ + + +#ifndef __FStar_UInt_8_16_32_64_H +#define __FStar_UInt_8_16_32_64_H + + + + +#include +#include + +#include "krml/lowstar_endianness.h" +#include "krml/FStar_UInt_8_16_32_64.h" +#include "krml/internal/target.h" +static inline uint64_t FStar_UInt64_eq_mask(uint64_t a, uint64_t b) +{ + uint64_t x = a ^ b; + uint64_t minus_x = ~x + (uint64_t)1U; + uint64_t x_or_minus_x = x | minus_x; + uint64_t xnx = x_or_minus_x >> (uint32_t)63U; + return xnx - (uint64_t)1U; +} + +static inline uint64_t FStar_UInt64_gte_mask(uint64_t a, uint64_t b) +{ + uint64_t x = a; + uint64_t y = b; + uint64_t x_xor_y = x ^ y; + uint64_t x_sub_y = x - y; + uint64_t x_sub_y_xor_y = x_sub_y ^ y; + uint64_t q = x_xor_y | x_sub_y_xor_y; + uint64_t x_xor_q = x ^ q; + uint64_t x_xor_q_ = x_xor_q >> (uint32_t)63U; + return x_xor_q_ - (uint64_t)1U; +} + +static inline uint32_t FStar_UInt32_eq_mask(uint32_t a, uint32_t b) +{ + uint32_t x = a ^ b; + uint32_t minus_x = ~x + (uint32_t)1U; + uint32_t x_or_minus_x = x | minus_x; + uint32_t xnx = x_or_minus_x >> (uint32_t)31U; + return xnx - (uint32_t)1U; +} + +static inline uint32_t FStar_UInt32_gte_mask(uint32_t a, uint32_t b) +{ + uint32_t x = a; + uint32_t y = b; + uint32_t x_xor_y = x ^ y; + uint32_t x_sub_y = x - y; + uint32_t x_sub_y_xor_y = x_sub_y ^ y; + uint32_t q = x_xor_y | x_sub_y_xor_y; + uint32_t x_xor_q = x ^ q; + uint32_t x_xor_q_ = x_xor_q >> (uint32_t)31U; + return x_xor_q_ - (uint32_t)1U; +} + +static inline uint16_t FStar_UInt16_eq_mask(uint16_t a, uint16_t b) +{ + uint16_t x = a ^ b; + uint16_t minus_x = ~x + (uint16_t)1U; + uint16_t x_or_minus_x = x | minus_x; + uint16_t xnx = x_or_minus_x >> (uint32_t)15U; + return xnx - (uint16_t)1U; +} + +static inline uint16_t FStar_UInt16_gte_mask(uint16_t a, uint16_t b) +{ + uint16_t x = a; + uint16_t y = b; + uint16_t x_xor_y = x ^ y; + uint16_t x_sub_y = x - y; + uint16_t x_sub_y_xor_y = x_sub_y ^ y; + uint16_t q = x_xor_y | x_sub_y_xor_y; + uint16_t x_xor_q = x ^ q; + uint16_t x_xor_q_ = x_xor_q >> (uint32_t)15U; + return x_xor_q_ - (uint16_t)1U; +} + +static inline uint8_t FStar_UInt8_eq_mask(uint8_t a, uint8_t b) +{ + uint8_t x = a ^ b; + uint8_t minus_x = ~x + (uint8_t)1U; + uint8_t x_or_minus_x = x | minus_x; + uint8_t xnx = x_or_minus_x >> (uint32_t)7U; + return xnx - (uint8_t)1U; +} + +static inline uint8_t FStar_UInt8_gte_mask(uint8_t a, uint8_t b) +{ + uint8_t x = a; + uint8_t y = b; + uint8_t x_xor_y = x ^ y; + uint8_t x_sub_y = x - y; + uint8_t x_sub_y_xor_y = x_sub_y ^ y; + uint8_t q = x_xor_y | x_sub_y_xor_y; + uint8_t x_xor_q = x ^ q; + uint8_t x_xor_q_ = x_xor_q >> (uint32_t)7U; + return x_xor_q_ - (uint8_t)1U; +} + + +#define __FStar_UInt_8_16_32_64_H_DEFINED +#endif diff --git a/Modules/_hacl/include/krml/internal/target.h b/Modules/_hacl/include/krml/internal/target.h new file mode 100644 index 000000000000000..9ef59859a554b54 --- /dev/null +++ b/Modules/_hacl/include/krml/internal/target.h @@ -0,0 +1,218 @@ +/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved. + Licensed under the Apache 2.0 License. */ + +#ifndef __KRML_TARGET_H +#define __KRML_TARGET_H + +#include +#include +#include +#include +#include +#include +#include + +/* Since KaRaMeL emits the inline keyword unconditionally, we follow the + * guidelines at https://gcc.gnu.org/onlinedocs/gcc/Inline.html and make this + * __inline__ to ensure the code compiles with -std=c90 and earlier. */ +#ifdef __GNUC__ +# define inline __inline__ +#endif + +#ifndef KRML_HOST_MALLOC +# define KRML_HOST_MALLOC malloc +#endif + +#ifndef KRML_HOST_CALLOC +# define KRML_HOST_CALLOC calloc +#endif + +#ifndef KRML_HOST_FREE +# define KRML_HOST_FREE free +#endif + +/* Macros for prettier unrolling of loops */ +#define KRML_LOOP1(i, n, x) { \ + x \ + i += n; \ +} + +#define KRML_LOOP2(i, n, x) \ + KRML_LOOP1(i, n, x) \ + KRML_LOOP1(i, n, x) + +#define KRML_LOOP3(i, n, x) \ + KRML_LOOP2(i, n, x) \ + KRML_LOOP1(i, n, x) + +#define KRML_LOOP4(i, n, x) \ + KRML_LOOP2(i, n, x) \ + KRML_LOOP2(i, n, x) + +#define KRML_LOOP5(i, n, x) \ + KRML_LOOP4(i, n, x) \ + KRML_LOOP1(i, n, x) + +#define KRML_LOOP6(i, n, x) \ + KRML_LOOP4(i, n, x) \ + KRML_LOOP2(i, n, x) + +#define KRML_LOOP7(i, n, x) \ + KRML_LOOP4(i, n, x) \ + KRML_LOOP3(i, n, x) + +#define KRML_LOOP8(i, n, x) \ + KRML_LOOP4(i, n, x) \ + KRML_LOOP4(i, n, x) + +#define KRML_LOOP9(i, n, x) \ + KRML_LOOP8(i, n, x) \ + KRML_LOOP1(i, n, x) + +#define KRML_LOOP10(i, n, x) \ + KRML_LOOP8(i, n, x) \ + KRML_LOOP2(i, n, x) + +#define KRML_LOOP11(i, n, x) \ + KRML_LOOP8(i, n, x) \ + KRML_LOOP3(i, n, x) + +#define KRML_LOOP12(i, n, x) \ + KRML_LOOP8(i, n, x) \ + KRML_LOOP4(i, n, x) + +#define KRML_LOOP13(i, n, x) \ + KRML_LOOP8(i, n, x) \ + KRML_LOOP5(i, n, x) + +#define KRML_LOOP14(i, n, x) \ + KRML_LOOP8(i, n, x) \ + KRML_LOOP6(i, n, x) + +#define KRML_LOOP15(i, n, x) \ + KRML_LOOP8(i, n, x) \ + KRML_LOOP7(i, n, x) + +#define KRML_LOOP16(i, n, x) \ + KRML_LOOP8(i, n, x) \ + KRML_LOOP8(i, n, x) + +#define KRML_UNROLL_FOR(i, z, n, k, x) do { \ + uint32_t i = z; \ + KRML_LOOP##n(i, k, x) \ +} while (0) + +#define KRML_ACTUAL_FOR(i, z, n, k, x) \ + do { \ + for (uint32_t i = z; i < n; i += k) { \ + x \ + } \ + } while (0) + +#ifndef KRML_UNROLL_MAX +#define KRML_UNROLL_MAX 16 +#endif + +/* 1 is the number of loop iterations, i.e. (n - z)/k as evaluated by krml */ +#if 0 <= KRML_UNROLL_MAX +#define KRML_MAYBE_FOR0(i, z, n, k, x) +#else +#define KRML_MAYBE_FOR0(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) +#endif + +#if 1 <= KRML_UNROLL_MAX +#define KRML_MAYBE_FOR1(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 1, k, x) +#else +#define KRML_MAYBE_FOR1(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) +#endif + +#if 2 <= KRML_UNROLL_MAX +#define KRML_MAYBE_FOR2(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 2, k, x) +#else +#define KRML_MAYBE_FOR2(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) +#endif + +#if 3 <= KRML_UNROLL_MAX +#define KRML_MAYBE_FOR3(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 3, k, x) +#else +#define KRML_MAYBE_FOR3(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) +#endif + +#if 4 <= KRML_UNROLL_MAX +#define KRML_MAYBE_FOR4(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 4, k, x) +#else +#define KRML_MAYBE_FOR4(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) +#endif + +#if 5 <= KRML_UNROLL_MAX +#define KRML_MAYBE_FOR5(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 5, k, x) +#else +#define KRML_MAYBE_FOR5(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) +#endif + +#if 6 <= KRML_UNROLL_MAX +#define KRML_MAYBE_FOR6(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 6, k, x) +#else +#define KRML_MAYBE_FOR6(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) +#endif + +#if 7 <= KRML_UNROLL_MAX +#define KRML_MAYBE_FOR7(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 7, k, x) +#else +#define KRML_MAYBE_FOR7(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) +#endif + +#if 8 <= KRML_UNROLL_MAX +#define KRML_MAYBE_FOR8(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 8, k, x) +#else +#define KRML_MAYBE_FOR8(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) +#endif + +#if 9 <= KRML_UNROLL_MAX +#define KRML_MAYBE_FOR9(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 9, k, x) +#else +#define KRML_MAYBE_FOR9(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) +#endif + +#if 10 <= KRML_UNROLL_MAX +#define KRML_MAYBE_FOR10(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 10, k, x) +#else +#define KRML_MAYBE_FOR10(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) +#endif + +#if 11 <= KRML_UNROLL_MAX +#define KRML_MAYBE_FOR11(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 11, k, x) +#else +#define KRML_MAYBE_FOR11(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) +#endif + +#if 12 <= KRML_UNROLL_MAX +#define KRML_MAYBE_FOR12(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 12, k, x) +#else +#define KRML_MAYBE_FOR12(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) +#endif + +#if 13 <= KRML_UNROLL_MAX +#define KRML_MAYBE_FOR13(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 13, k, x) +#else +#define KRML_MAYBE_FOR13(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) +#endif + +#if 14 <= KRML_UNROLL_MAX +#define KRML_MAYBE_FOR14(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 14, k, x) +#else +#define KRML_MAYBE_FOR14(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) +#endif + +#if 15 <= KRML_UNROLL_MAX +#define KRML_MAYBE_FOR15(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 15, k, x) +#else +#define KRML_MAYBE_FOR15(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) +#endif + +#if 16 <= KRML_UNROLL_MAX +#define KRML_MAYBE_FOR16(i, z, n, k, x) KRML_UNROLL_FOR(i, z, 16, k, x) +#else +#define KRML_MAYBE_FOR16(i, z, n, k, x) KRML_ACTUAL_FOR(i, z, n, k, x) +#endif +#endif diff --git a/Modules/_hacl/include/krml/lowstar_endianness.h b/Modules/_hacl/include/krml/lowstar_endianness.h new file mode 100644 index 000000000000000..32a7391e817ebbc --- /dev/null +++ b/Modules/_hacl/include/krml/lowstar_endianness.h @@ -0,0 +1,230 @@ +/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved. + Licensed under the Apache 2.0 License. */ + +#ifndef __LOWSTAR_ENDIANNESS_H +#define __LOWSTAR_ENDIANNESS_H + +#include +#include + +/******************************************************************************/ +/* Implementing C.fst (part 2: endian-ness macros) */ +/******************************************************************************/ + +/* ... for Linux */ +#if defined(__linux__) || defined(__CYGWIN__) || defined (__USE_SYSTEM_ENDIAN_H__) || defined(__GLIBC__) +# include + +/* ... for OSX */ +#elif defined(__APPLE__) +# include +# define htole64(x) OSSwapHostToLittleInt64(x) +# define le64toh(x) OSSwapLittleToHostInt64(x) +# define htobe64(x) OSSwapHostToBigInt64(x) +# define be64toh(x) OSSwapBigToHostInt64(x) + +# define htole16(x) OSSwapHostToLittleInt16(x) +# define le16toh(x) OSSwapLittleToHostInt16(x) +# define htobe16(x) OSSwapHostToBigInt16(x) +# define be16toh(x) OSSwapBigToHostInt16(x) + +# define htole32(x) OSSwapHostToLittleInt32(x) +# define le32toh(x) OSSwapLittleToHostInt32(x) +# define htobe32(x) OSSwapHostToBigInt32(x) +# define be32toh(x) OSSwapBigToHostInt32(x) + +/* ... for Solaris */ +#elif defined(__sun__) +# include +# define htole64(x) LE_64(x) +# define le64toh(x) LE_64(x) +# define htobe64(x) BE_64(x) +# define be64toh(x) BE_64(x) + +# define htole16(x) LE_16(x) +# define le16toh(x) LE_16(x) +# define htobe16(x) BE_16(x) +# define be16toh(x) BE_16(x) + +# define htole32(x) LE_32(x) +# define le32toh(x) LE_32(x) +# define htobe32(x) BE_32(x) +# define be32toh(x) BE_32(x) + +/* ... for the BSDs */ +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) +# include +#elif defined(__OpenBSD__) +# include + +/* ... for Windows (MSVC)... not targeting XBOX 360! */ +#elif defined(_MSC_VER) + +# include +# define htobe16(x) _byteswap_ushort(x) +# define htole16(x) (x) +# define be16toh(x) _byteswap_ushort(x) +# define le16toh(x) (x) + +# define htobe32(x) _byteswap_ulong(x) +# define htole32(x) (x) +# define be32toh(x) _byteswap_ulong(x) +# define le32toh(x) (x) + +# define htobe64(x) _byteswap_uint64(x) +# define htole64(x) (x) +# define be64toh(x) _byteswap_uint64(x) +# define le64toh(x) (x) + +/* ... for Windows (GCC-like, e.g. mingw or clang) */ +#elif (defined(_WIN32) || defined(_WIN64)) && \ + (defined(__GNUC__) || defined(__clang__)) + +# define htobe16(x) __builtin_bswap16(x) +# define htole16(x) (x) +# define be16toh(x) __builtin_bswap16(x) +# define le16toh(x) (x) + +# define htobe32(x) __builtin_bswap32(x) +# define htole32(x) (x) +# define be32toh(x) __builtin_bswap32(x) +# define le32toh(x) (x) + +# define htobe64(x) __builtin_bswap64(x) +# define htole64(x) (x) +# define be64toh(x) __builtin_bswap64(x) +# define le64toh(x) (x) + +/* ... generic big-endian fallback code */ +#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + +/* byte swapping code inspired by: + * https://github.com/rweather/arduinolibs/blob/master/libraries/Crypto/utility/EndianUtil.h + * */ + +# define htobe32(x) (x) +# define be32toh(x) (x) +# define htole32(x) \ + (__extension__({ \ + uint32_t _temp = (x); \ + ((_temp >> 24) & 0x000000FF) | ((_temp >> 8) & 0x0000FF00) | \ + ((_temp << 8) & 0x00FF0000) | ((_temp << 24) & 0xFF000000); \ + })) +# define le32toh(x) (htole32((x))) + +# define htobe64(x) (x) +# define be64toh(x) (x) +# define htole64(x) \ + (__extension__({ \ + uint64_t __temp = (x); \ + uint32_t __low = htobe32((uint32_t)__temp); \ + uint32_t __high = htobe32((uint32_t)(__temp >> 32)); \ + (((uint64_t)__low) << 32) | __high; \ + })) +# define le64toh(x) (htole64((x))) + +/* ... generic little-endian fallback code */ +#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + +# define htole32(x) (x) +# define le32toh(x) (x) +# define htobe32(x) \ + (__extension__({ \ + uint32_t _temp = (x); \ + ((_temp >> 24) & 0x000000FF) | ((_temp >> 8) & 0x0000FF00) | \ + ((_temp << 8) & 0x00FF0000) | ((_temp << 24) & 0xFF000000); \ + })) +# define be32toh(x) (htobe32((x))) + +# define htole64(x) (x) +# define le64toh(x) (x) +# define htobe64(x) \ + (__extension__({ \ + uint64_t __temp = (x); \ + uint32_t __low = htobe32((uint32_t)__temp); \ + uint32_t __high = htobe32((uint32_t)(__temp >> 32)); \ + (((uint64_t)__low) << 32) | __high; \ + })) +# define be64toh(x) (htobe64((x))) + +/* ... couldn't determine endian-ness of the target platform */ +#else +# error "Please define __BYTE_ORDER__!" + +#endif /* defined(__linux__) || ... */ + +/* Loads and stores. These avoid undefined behavior due to unaligned memory + * accesses, via memcpy. */ + +inline static uint16_t load16(uint8_t *b) { + uint16_t x; + memcpy(&x, b, 2); + return x; +} + +inline static uint32_t load32(uint8_t *b) { + uint32_t x; + memcpy(&x, b, 4); + return x; +} + +inline static uint64_t load64(uint8_t *b) { + uint64_t x; + memcpy(&x, b, 8); + return x; +} + +inline static void store16(uint8_t *b, uint16_t i) { + memcpy(b, &i, 2); +} + +inline static void store32(uint8_t *b, uint32_t i) { + memcpy(b, &i, 4); +} + +inline static void store64(uint8_t *b, uint64_t i) { + memcpy(b, &i, 8); +} + +/* Legacy accessors so that this header can serve as an implementation of + * C.Endianness */ +#define load16_le(b) (le16toh(load16(b))) +#define store16_le(b, i) (store16(b, htole16(i))) +#define load16_be(b) (be16toh(load16(b))) +#define store16_be(b, i) (store16(b, htobe16(i))) + +#define load32_le(b) (le32toh(load32(b))) +#define store32_le(b, i) (store32(b, htole32(i))) +#define load32_be(b) (be32toh(load32(b))) +#define store32_be(b, i) (store32(b, htobe32(i))) + +#define load64_le(b) (le64toh(load64(b))) +#define store64_le(b, i) (store64(b, htole64(i))) +#define load64_be(b) (be64toh(load64(b))) +#define store64_be(b, i) (store64(b, htobe64(i))) + +/* Co-existence of LowStar.Endianness and FStar.Endianness generates name + * conflicts, because of course both insist on having no prefixes. Until a + * prefix is added, or until we truly retire FStar.Endianness, solve this issue + * in an elegant way. */ +#define load16_le0 load16_le +#define store16_le0 store16_le +#define load16_be0 load16_be +#define store16_be0 store16_be + +#define load32_le0 load32_le +#define store32_le0 store32_le +#define load32_be0 load32_be +#define store32_be0 store32_be + +#define load64_le0 load64_le +#define store64_le0 store64_le +#define load64_be0 load64_be +#define store64_be0 store64_be + +#define load128_le0 load128_le +#define store128_le0 store128_le +#define load128_be0 load128_be +#define store128_be0 store128_be + +#endif diff --git a/Modules/_hacl/include/python_hacl_namespaces.h b/Modules/_hacl/include/python_hacl_namespaces.h new file mode 100644 index 000000000000000..af390459311fe8b --- /dev/null +++ b/Modules/_hacl/include/python_hacl_namespaces.h @@ -0,0 +1,28 @@ +#ifndef _PYTHON_HACL_NAMESPACES_H +#define _PYTHON_HACL_NAMESPACES_H + +/* + * C's excuse for namespaces: Use globally unique names to avoid linkage + * conflicts with builds linking or dynamically loading other code potentially + * using HACL* libraries. + */ + +#define Hacl_Streaming_SHA2_state_sha2_224_s python_hashlib_Hacl_Streaming_SHA2_state_sha2_224_s +#define Hacl_Streaming_SHA2_state_sha2_224 python_hashlib_Hacl_Streaming_SHA2_state_sha2_224 +#define Hacl_Streaming_SHA2_state_sha2_256 python_hashlib_Hacl_Streaming_SHA2_state_sha2_256 +#define Hacl_Streaming_SHA2_create_in_256 python_hashlib_Hacl_Streaming_SHA2_create_in_256 +#define Hacl_Streaming_SHA2_create_in_224 python_hashlib_Hacl_Streaming_SHA2_create_in_224 +#define Hacl_Streaming_SHA2_copy_256 python_hashlib_Hacl_Streaming_SHA2_copy_256 +#define Hacl_Streaming_SHA2_copy_224 python_hashlib_Hacl_Streaming_SHA2_copy_224 +#define Hacl_Streaming_SHA2_init_256 python_hashlib_Hacl_Streaming_SHA2_init_256 +#define Hacl_Streaming_SHA2_init_224 python_hashlib_Hacl_Streaming_SHA2_init_224 +#define Hacl_Streaming_SHA2_update_256 python_hashlib_Hacl_Streaming_SHA2_update_256 +#define Hacl_Streaming_SHA2_update_224 python_hashlib_Hacl_Streaming_SHA2_update_224 +#define Hacl_Streaming_SHA2_finish_256 python_hashlib_Hacl_Streaming_SHA2_finish_256 +#define Hacl_Streaming_SHA2_finish_224 python_hashlib_Hacl_Streaming_SHA2_finish_224 +#define Hacl_Streaming_SHA2_free_256 python_hashlib_Hacl_Streaming_SHA2_free_256 +#define Hacl_Streaming_SHA2_free_224 python_hashlib_Hacl_Streaming_SHA2_free_224 +#define Hacl_Streaming_SHA2_sha256 python_hashlib_Hacl_Streaming_SHA2_sha256 +#define Hacl_Streaming_SHA2_sha224 python_hashlib_Hacl_Streaming_SHA2_sha224 + +#endif // _PYTHON_HACL_NAMESPACES_H diff --git a/Modules/_hacl/internal/Hacl_SHA2_Generic.h b/Modules/_hacl/internal/Hacl_SHA2_Generic.h new file mode 100644 index 000000000000000..23f7cea1eb3884a --- /dev/null +++ b/Modules/_hacl/internal/Hacl_SHA2_Generic.h @@ -0,0 +1,135 @@ +/* MIT License + * + * Copyright (c) 2016-2022 INRIA, CMU and Microsoft Corporation + * Copyright (c) 2022-2023 HACL* Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + +#ifndef __internal_Hacl_SHA2_Generic_H +#define __internal_Hacl_SHA2_Generic_H + +#if defined(__cplusplus) +extern "C" { +#endif + +#include +#include "krml/FStar_UInt_8_16_32_64.h" +#include "krml/lowstar_endianness.h" +#include "krml/internal/target.h" + + + + +static const +uint32_t +Hacl_Impl_SHA2_Generic_h224[8U] = + { + (uint32_t)0xc1059ed8U, (uint32_t)0x367cd507U, (uint32_t)0x3070dd17U, (uint32_t)0xf70e5939U, + (uint32_t)0xffc00b31U, (uint32_t)0x68581511U, (uint32_t)0x64f98fa7U, (uint32_t)0xbefa4fa4U + }; + +static const +uint32_t +Hacl_Impl_SHA2_Generic_h256[8U] = + { + (uint32_t)0x6a09e667U, (uint32_t)0xbb67ae85U, (uint32_t)0x3c6ef372U, (uint32_t)0xa54ff53aU, + (uint32_t)0x510e527fU, (uint32_t)0x9b05688cU, (uint32_t)0x1f83d9abU, (uint32_t)0x5be0cd19U + }; + +static const +uint64_t +Hacl_Impl_SHA2_Generic_h384[8U] = + { + (uint64_t)0xcbbb9d5dc1059ed8U, (uint64_t)0x629a292a367cd507U, (uint64_t)0x9159015a3070dd17U, + (uint64_t)0x152fecd8f70e5939U, (uint64_t)0x67332667ffc00b31U, (uint64_t)0x8eb44a8768581511U, + (uint64_t)0xdb0c2e0d64f98fa7U, (uint64_t)0x47b5481dbefa4fa4U + }; + +static const +uint64_t +Hacl_Impl_SHA2_Generic_h512[8U] = + { + (uint64_t)0x6a09e667f3bcc908U, (uint64_t)0xbb67ae8584caa73bU, (uint64_t)0x3c6ef372fe94f82bU, + (uint64_t)0xa54ff53a5f1d36f1U, (uint64_t)0x510e527fade682d1U, (uint64_t)0x9b05688c2b3e6c1fU, + (uint64_t)0x1f83d9abfb41bd6bU, (uint64_t)0x5be0cd19137e2179U + }; + +static const +uint32_t +Hacl_Impl_SHA2_Generic_k224_256[64U] = + { + (uint32_t)0x428a2f98U, (uint32_t)0x71374491U, (uint32_t)0xb5c0fbcfU, (uint32_t)0xe9b5dba5U, + (uint32_t)0x3956c25bU, (uint32_t)0x59f111f1U, (uint32_t)0x923f82a4U, (uint32_t)0xab1c5ed5U, + (uint32_t)0xd807aa98U, (uint32_t)0x12835b01U, (uint32_t)0x243185beU, (uint32_t)0x550c7dc3U, + (uint32_t)0x72be5d74U, (uint32_t)0x80deb1feU, (uint32_t)0x9bdc06a7U, (uint32_t)0xc19bf174U, + (uint32_t)0xe49b69c1U, (uint32_t)0xefbe4786U, (uint32_t)0x0fc19dc6U, (uint32_t)0x240ca1ccU, + (uint32_t)0x2de92c6fU, (uint32_t)0x4a7484aaU, (uint32_t)0x5cb0a9dcU, (uint32_t)0x76f988daU, + (uint32_t)0x983e5152U, (uint32_t)0xa831c66dU, (uint32_t)0xb00327c8U, (uint32_t)0xbf597fc7U, + (uint32_t)0xc6e00bf3U, (uint32_t)0xd5a79147U, (uint32_t)0x06ca6351U, (uint32_t)0x14292967U, + (uint32_t)0x27b70a85U, (uint32_t)0x2e1b2138U, (uint32_t)0x4d2c6dfcU, (uint32_t)0x53380d13U, + (uint32_t)0x650a7354U, (uint32_t)0x766a0abbU, (uint32_t)0x81c2c92eU, (uint32_t)0x92722c85U, + (uint32_t)0xa2bfe8a1U, (uint32_t)0xa81a664bU, (uint32_t)0xc24b8b70U, (uint32_t)0xc76c51a3U, + (uint32_t)0xd192e819U, (uint32_t)0xd6990624U, (uint32_t)0xf40e3585U, (uint32_t)0x106aa070U, + (uint32_t)0x19a4c116U, (uint32_t)0x1e376c08U, (uint32_t)0x2748774cU, (uint32_t)0x34b0bcb5U, + (uint32_t)0x391c0cb3U, (uint32_t)0x4ed8aa4aU, (uint32_t)0x5b9cca4fU, (uint32_t)0x682e6ff3U, + (uint32_t)0x748f82eeU, (uint32_t)0x78a5636fU, (uint32_t)0x84c87814U, (uint32_t)0x8cc70208U, + (uint32_t)0x90befffaU, (uint32_t)0xa4506cebU, (uint32_t)0xbef9a3f7U, (uint32_t)0xc67178f2U + }; + +static const +uint64_t +Hacl_Impl_SHA2_Generic_k384_512[80U] = + { + (uint64_t)0x428a2f98d728ae22U, (uint64_t)0x7137449123ef65cdU, (uint64_t)0xb5c0fbcfec4d3b2fU, + (uint64_t)0xe9b5dba58189dbbcU, (uint64_t)0x3956c25bf348b538U, (uint64_t)0x59f111f1b605d019U, + (uint64_t)0x923f82a4af194f9bU, (uint64_t)0xab1c5ed5da6d8118U, (uint64_t)0xd807aa98a3030242U, + (uint64_t)0x12835b0145706fbeU, (uint64_t)0x243185be4ee4b28cU, (uint64_t)0x550c7dc3d5ffb4e2U, + (uint64_t)0x72be5d74f27b896fU, (uint64_t)0x80deb1fe3b1696b1U, (uint64_t)0x9bdc06a725c71235U, + (uint64_t)0xc19bf174cf692694U, (uint64_t)0xe49b69c19ef14ad2U, (uint64_t)0xefbe4786384f25e3U, + (uint64_t)0x0fc19dc68b8cd5b5U, (uint64_t)0x240ca1cc77ac9c65U, (uint64_t)0x2de92c6f592b0275U, + (uint64_t)0x4a7484aa6ea6e483U, (uint64_t)0x5cb0a9dcbd41fbd4U, (uint64_t)0x76f988da831153b5U, + (uint64_t)0x983e5152ee66dfabU, (uint64_t)0xa831c66d2db43210U, (uint64_t)0xb00327c898fb213fU, + (uint64_t)0xbf597fc7beef0ee4U, (uint64_t)0xc6e00bf33da88fc2U, (uint64_t)0xd5a79147930aa725U, + (uint64_t)0x06ca6351e003826fU, (uint64_t)0x142929670a0e6e70U, (uint64_t)0x27b70a8546d22ffcU, + (uint64_t)0x2e1b21385c26c926U, (uint64_t)0x4d2c6dfc5ac42aedU, (uint64_t)0x53380d139d95b3dfU, + (uint64_t)0x650a73548baf63deU, (uint64_t)0x766a0abb3c77b2a8U, (uint64_t)0x81c2c92e47edaee6U, + (uint64_t)0x92722c851482353bU, (uint64_t)0xa2bfe8a14cf10364U, (uint64_t)0xa81a664bbc423001U, + (uint64_t)0xc24b8b70d0f89791U, (uint64_t)0xc76c51a30654be30U, (uint64_t)0xd192e819d6ef5218U, + (uint64_t)0xd69906245565a910U, (uint64_t)0xf40e35855771202aU, (uint64_t)0x106aa07032bbd1b8U, + (uint64_t)0x19a4c116b8d2d0c8U, (uint64_t)0x1e376c085141ab53U, (uint64_t)0x2748774cdf8eeb99U, + (uint64_t)0x34b0bcb5e19b48a8U, (uint64_t)0x391c0cb3c5c95a63U, (uint64_t)0x4ed8aa4ae3418acbU, + (uint64_t)0x5b9cca4f7763e373U, (uint64_t)0x682e6ff3d6b2b8a3U, (uint64_t)0x748f82ee5defb2fcU, + (uint64_t)0x78a5636f43172f60U, (uint64_t)0x84c87814a1f0ab72U, (uint64_t)0x8cc702081a6439ecU, + (uint64_t)0x90befffa23631e28U, (uint64_t)0xa4506cebde82bde9U, (uint64_t)0xbef9a3f7b2c67915U, + (uint64_t)0xc67178f2e372532bU, (uint64_t)0xca273eceea26619cU, (uint64_t)0xd186b8c721c0c207U, + (uint64_t)0xeada7dd6cde0eb1eU, (uint64_t)0xf57d4f7fee6ed178U, (uint64_t)0x06f067aa72176fbaU, + (uint64_t)0x0a637dc5a2c898a6U, (uint64_t)0x113f9804bef90daeU, (uint64_t)0x1b710b35131c471bU, + (uint64_t)0x28db77f523047d84U, (uint64_t)0x32caab7b40c72493U, (uint64_t)0x3c9ebe0a15c9bebcU, + (uint64_t)0x431d67c49c100d4cU, (uint64_t)0x4cc5d4becb3e42b6U, (uint64_t)0x597f299cfc657e2aU, + (uint64_t)0x5fcb6fab3ad6faecU, (uint64_t)0x6c44198c4a475817U + }; + +#if defined(__cplusplus) +} +#endif + +#define __internal_Hacl_SHA2_Generic_H_DEFINED +#endif diff --git a/Modules/_hacl/refresh.sh b/Modules/_hacl/refresh.sh new file mode 100755 index 000000000000000..594873862a2db03 --- /dev/null +++ b/Modules/_hacl/refresh.sh @@ -0,0 +1,132 @@ +#!/usr/bin/env bash +# +# Use this script to update the HACL generated hash algorithm implementation +# code from a local checkout of the upstream hacl-star repository. +# + +set -e +set -o pipefail + +if [[ "${BASH_VERSINFO[0]}" -lt 4 ]]; then + echo "A bash version >= 4 required. Got: $BASH_VERSION" >&2 + exit 1 +fi + +if [[ $1 == "" ]]; then + echo "Usage: $0 path-to-hacl-directory" + echo "" + echo " path-to-hacl-directory should be a local git checkout of a" + echo " https://github.com/hacl-star/hacl-star/ repo." + exit 1 +fi + +# Update this when updating to a new version after verifying that the changes +# the update brings in are good. +expected_hacl_star_rev=94aabbb4cf71347d3779a8db486c761403c6d036 + +hacl_dir="$(realpath "$1")" +cd "$(dirname "$0")" +actual_rev=$(cd "$hacl_dir" && git rev-parse HEAD) + +if [[ "$actual_rev" != "$expected_hacl_star_rev" ]]; then + echo "WARNING: HACL* in '$hacl_dir' is at revision:" >&2 + echo " $actual_rev" >&2 + echo "but expected revision:" >&2 + echo " $expected_hacl_star_rev" >&2 + echo "Edit the expected rev if the changes pulled in are what you want." +fi + +# Step 1: copy files + +declare -a dist_files +dist_files=( + Hacl_Streaming_SHA2.h + internal/Hacl_SHA2_Generic.h + Hacl_Streaming_SHA2.c +) + +declare -a include_files +include_files=( + include/krml/lowstar_endianness.h + include/krml/internal/target.h +) + +declare -a lib_files +lib_files=( + krmllib/dist/minimal/FStar_UInt_8_16_32_64.h +) + +# C files for the algorithms themselves: current directory +(cd "$hacl_dir/dist/gcc-compatible" && tar cf - "${dist_files[@]}") | tar xf - + +# Support header files (e.g. endianness macros): stays in include/ +(cd "$hacl_dir/dist/karamel" && tar cf - "${include_files[@]}") | tar xf - + +# Special treatment: we don't bother with an extra directory and move krmllib +# files to the same include directory +for f in "${lib_files[@]}"; do + cp "$hacl_dir/dist/karamel/$f" include/krml/ +done + +# Step 2: some in-place modifications to keep things simple and minimal + +# This is basic, but refreshes of the vendored HACL code are infrequent, so +# let's not over-engineer this. +if [[ $(uname) == "Darwin" ]]; then + # You're already running with homebrew or macports to satisfy the + # bash>=4 requirement, so requiring GNU sed is entirely reasonable. + sed=gsed +else + sed=sed +fi + +readarray -t all_files < <(find . -name '*.h' -or -name '*.c') + +# types.h is a simple wrapper that defines the uint128 type then proceeds to +# include FStar_UInt_8_16_32_64.h; we jump the types.h step since our current +# selection of algorithms does not necessitate the use of uint128 +$sed -i 's!#include.*types.h"!#include "krml/FStar_UInt_8_16_32_64.h"!g' "${all_files[@]}" +$sed -i 's!#include.*compat.h"!!g' "${all_files[@]}" + +# FStar_UInt_8_16_32_64 contains definitions useful in the general case, but not +# for us; trim! +$sed -i -z 's!\(extern\|typedef\)[^;]*;\n\n!!g' include/krml/FStar_UInt_8_16_32_64.h + +# This contains static inline prototypes that are defined in +# FStar_UInt_8_16_32_64; they are by default repeated for safety of separate +# compilation, but this is not necessary. +$sed -i 's!#include.*Hacl_Krmllib.h"!!g' "${all_files[@]}" + +# This header is useful for *other* algorithms that refer to SHA2, e.g. Ed25519 +# which needs to compute a digest of a message before signing it. Here, since no +# other algorithm builds upon SHA2, this internal header is useless (and is not +# included in $dist_files). +$sed -i 's!#include.*internal/Hacl_Streaming_SHA2.h"!#include "Hacl_Streaming_SHA2.h"!g' "${all_files[@]}" + +# The SHA2 file contains all variants of SHA2. We strip 384 and 512 for the time +# being, to be included later. +# This regexp matches a separator (two new lines), followed by: +# +# * +# ... 384 or 512 ... { +# * +# } +# +# The first non-empty lines are the comment block. The second ... may spill over +# the next following lines if the arguments are printed in one-per-line mode. +$sed -i -z 's/\n\n\([^\n]\+\n\)*[^\n]*\(384\|512\)[^{]*{\n\?\( [^\n]*\n\)*}//g' Hacl_Streaming_SHA2.c + +# Same thing with function prototypes +$sed -i -z 's/\n\n\([^\n]\+\n\)*[^\n]*\(384\|512\)[^;]*;//g' Hacl_Streaming_SHA2.h + +# Use globally unique names for the Hacl_ C APIs to avoid linkage conflicts. +$sed -i -z 's!#include \n!#include \n#include "python_hacl_namespaces.h"\n!' Hacl_Streaming_SHA2.h + +# Finally, we remove a bunch of ifdefs from target.h that are, again, useful in +# the general case, but not exercised by the subset of HACL* that we vendor. +$sed -z -i 's!#ifndef KRML_\(HOST_PRINTF\|HOST_EXIT\|PRE_ALIGN\|POST_ALIGN\|ALIGNED_MALLOC\|ALIGNED_FREE\|HOST_TIME\)\n\(\n\|# [^\n]*\n\|[^#][^\n]*\n\)*#endif\n\n!!g' include/krml/internal/target.h +$sed -z -i 's!\n\n\([^#][^\n]*\n\)*#define KRML_\(EABORT\|EXIT\|CHECK_SIZE\)[^\n]*\(\n [^\n]*\)*!!g' include/krml/internal/target.h +$sed -z -i 's!\n\n\([^#][^\n]*\n\)*#if [^\n]*\n\( [^\n]*\n\)*#define KRML_\(EABORT\|EXIT\|CHECK_SIZE\)[^\n]*\(\n [^\n]*\)*!!g' include/krml/internal/target.h +$sed -z -i 's!\n\n\([^#][^\n]*\n\)*#if [^\n]*\n\( [^\n]*\n\)*# define _\?KRML_\(DEPRECATED\|CHECK_SIZE_PRAGMA\|HOST_EPRINTF\|HOST_SNPRINTF\)[^\n]*\n\([^#][^\n]*\n\|#el[^\n]*\n\|# [^\n]*\n\)*#endif!!g' include/krml/internal/target.h + +echo "Updated; verify all is okay using git diff and git status." diff --git a/Modules/sha256module.c b/Modules/sha256module.c index 17ee86683b7a89b..630e4bf03bbe967 100644 --- a/Modules/sha256module.c +++ b/Modules/sha256module.c @@ -31,29 +31,33 @@ class SHA256Type "SHAobject *" "&PyType_Type" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=71a39174d4f0a744]*/ -/* Some useful types */ -typedef unsigned char SHA_BYTE; -typedef uint32_t SHA_INT32; /* 32-bit integer */ - -/* The SHA block size and message digest sizes, in bytes */ +/* The SHA block size and maximum message digest sizes, in bytes */ #define SHA_BLOCKSIZE 64 -#define SHA_DIGESTSIZE 32 +#define SHA_DIGESTSIZE 32 + +/* The SHA2-224 and SHA2-256 implementations defer to the HACL* verified + * library. */ -/* The structure for storing SHA info */ +#include "_hacl/Hacl_Streaming_SHA2.h" typedef struct { - PyObject_HEAD - SHA_INT32 digest[8]; /* Message digest */ - SHA_INT32 count_lo, count_hi; /* 64-bit bit count */ - SHA_BYTE data[SHA_BLOCKSIZE]; /* SHA data buffer */ - int local; /* unprocessed amount in data */ - int digestsize; + PyObject_HEAD + // Even though one could conceivably perform run-type checks to tell apart a + // sha224_type from a sha256_type (and thus deduce the digest size), we must + // keep this field because it's exposed as a member field on the underlying + // python object. + // TODO: could we transform this into a getter and get rid of the redundant + // field? + int digestsize; + Hacl_Streaming_SHA2_state_sha2_256 *state; } SHAobject; #include "clinic/sha256module.c.h" +/* We shall use run-time type information in the remainder of this module to + * tell apart SHA2-224 and SHA2-256 */ typedef struct { PyTypeObject* sha224_type; PyTypeObject* sha256_type; @@ -67,321 +71,12 @@ _sha256_get_state(PyObject *module) return (_sha256_state *)state; } -/* When run on a little-endian CPU we need to perform byte reversal on an - array of longwords. */ - -#if PY_LITTLE_ENDIAN -static void longReverse(SHA_INT32 *buffer, int byteCount) -{ - byteCount /= sizeof(*buffer); - for (; byteCount--; buffer++) { - *buffer = _Py_bswap32(*buffer); - } -} -#endif - static void SHAcopy(SHAobject *src, SHAobject *dest) { - dest->local = src->local; dest->digestsize = src->digestsize; - dest->count_lo = src->count_lo; - dest->count_hi = src->count_hi; - memcpy(dest->digest, src->digest, sizeof(src->digest)); - memcpy(dest->data, src->data, sizeof(src->data)); -} - - -/* ------------------------------------------------------------------------ - * - * This code for the SHA-256 algorithm was noted as public domain. The - * original headers are pasted below. - * - * Several changes have been made to make it more compatible with the - * Python environment and desired interface. - * - */ - -/* LibTomCrypt, modular cryptographic library -- Tom St Denis - * - * LibTomCrypt is a library that provides various cryptographic - * algorithms in a highly modular and flexible manner. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, https://www.libtom.net - */ - - -/* SHA256 by Tom St Denis */ - -/* Various logical functions */ -#define ROR(x, y)\ -( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | \ -((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) -#define Ch(x,y,z) (z ^ (x & (y ^ z))) -#define Maj(x,y,z) (((x | y) & z) | (x & y)) -#define S(x, n) ROR((x),(n)) -#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) -#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) -#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) -#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) -#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) - - -static void -sha_transform(SHAobject *sha_info) -{ - int i; - SHA_INT32 S[8], W[64], t0, t1; - - memcpy(W, sha_info->data, sizeof(sha_info->data)); -#if PY_LITTLE_ENDIAN - longReverse(W, (int)sizeof(sha_info->data)); -#endif - - for (i = 16; i < 64; ++i) { - W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; - } - for (i = 0; i < 8; ++i) { - S[i] = sha_info->digest[i]; - } - - /* Compress */ -#define RND(a,b,c,d,e,f,g,h,i,ki) \ - t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \ - t1 = Sigma0(a) + Maj(a, b, c); \ - d += t0; \ - h = t0 + t1; - - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2); - -#undef RND - - /* feedback */ - for (i = 0; i < 8; i++) { - sha_info->digest[i] = sha_info->digest[i] + S[i]; - } - -} - - - -/* initialize the SHA digest */ - -static void -sha_init(SHAobject *sha_info) -{ - sha_info->digest[0] = 0x6A09E667L; - sha_info->digest[1] = 0xBB67AE85L; - sha_info->digest[2] = 0x3C6EF372L; - sha_info->digest[3] = 0xA54FF53AL; - sha_info->digest[4] = 0x510E527FL; - sha_info->digest[5] = 0x9B05688CL; - sha_info->digest[6] = 0x1F83D9ABL; - sha_info->digest[7] = 0x5BE0CD19L; - sha_info->count_lo = 0L; - sha_info->count_hi = 0L; - sha_info->local = 0; - sha_info->digestsize = 32; + dest->state = Hacl_Streaming_SHA2_copy_256(src->state); } -static void -sha224_init(SHAobject *sha_info) -{ - sha_info->digest[0] = 0xc1059ed8L; - sha_info->digest[1] = 0x367cd507L; - sha_info->digest[2] = 0x3070dd17L; - sha_info->digest[3] = 0xf70e5939L; - sha_info->digest[4] = 0xffc00b31L; - sha_info->digest[5] = 0x68581511L; - sha_info->digest[6] = 0x64f98fa7L; - sha_info->digest[7] = 0xbefa4fa4L; - sha_info->count_lo = 0L; - sha_info->count_hi = 0L; - sha_info->local = 0; - sha_info->digestsize = 28; -} - - -/* update the SHA digest */ - -static void -sha_update(SHAobject *sha_info, SHA_BYTE *buffer, Py_ssize_t count) -{ - Py_ssize_t i; - SHA_INT32 clo; - - clo = sha_info->count_lo + ((SHA_INT32) count << 3); - if (clo < sha_info->count_lo) { - ++sha_info->count_hi; - } - sha_info->count_lo = clo; - sha_info->count_hi += (SHA_INT32) count >> 29; - if (sha_info->local) { - i = SHA_BLOCKSIZE - sha_info->local; - if (i > count) { - i = count; - } - memcpy(((SHA_BYTE *) sha_info->data) + sha_info->local, buffer, i); - count -= i; - buffer += i; - sha_info->local += (int)i; - if (sha_info->local == SHA_BLOCKSIZE) { - sha_transform(sha_info); - } - else { - return; - } - } - while (count >= SHA_BLOCKSIZE) { - memcpy(sha_info->data, buffer, SHA_BLOCKSIZE); - buffer += SHA_BLOCKSIZE; - count -= SHA_BLOCKSIZE; - sha_transform(sha_info); - } - memcpy(sha_info->data, buffer, count); - sha_info->local = (int)count; -} - -/* finish computing the SHA digest */ - -static void -sha_final(unsigned char digest[SHA_DIGESTSIZE], SHAobject *sha_info) -{ - int count; - SHA_INT32 lo_bit_count, hi_bit_count; - - lo_bit_count = sha_info->count_lo; - hi_bit_count = sha_info->count_hi; - count = (int) ((lo_bit_count >> 3) & 0x3f); - ((SHA_BYTE *) sha_info->data)[count++] = 0x80; - if (count > SHA_BLOCKSIZE - 8) { - memset(((SHA_BYTE *) sha_info->data) + count, 0, - SHA_BLOCKSIZE - count); - sha_transform(sha_info); - memset((SHA_BYTE *) sha_info->data, 0, SHA_BLOCKSIZE - 8); - } - else { - memset(((SHA_BYTE *) sha_info->data) + count, 0, - SHA_BLOCKSIZE - 8 - count); - } - - /* GJS: note that we add the hi/lo in big-endian. sha_transform will - swap these values into host-order. */ - sha_info->data[56] = (hi_bit_count >> 24) & 0xff; - sha_info->data[57] = (hi_bit_count >> 16) & 0xff; - sha_info->data[58] = (hi_bit_count >> 8) & 0xff; - sha_info->data[59] = (hi_bit_count >> 0) & 0xff; - sha_info->data[60] = (lo_bit_count >> 24) & 0xff; - sha_info->data[61] = (lo_bit_count >> 16) & 0xff; - sha_info->data[62] = (lo_bit_count >> 8) & 0xff; - sha_info->data[63] = (lo_bit_count >> 0) & 0xff; - sha_transform(sha_info); - digest[ 0] = (unsigned char) ((sha_info->digest[0] >> 24) & 0xff); - digest[ 1] = (unsigned char) ((sha_info->digest[0] >> 16) & 0xff); - digest[ 2] = (unsigned char) ((sha_info->digest[0] >> 8) & 0xff); - digest[ 3] = (unsigned char) ((sha_info->digest[0] ) & 0xff); - digest[ 4] = (unsigned char) ((sha_info->digest[1] >> 24) & 0xff); - digest[ 5] = (unsigned char) ((sha_info->digest[1] >> 16) & 0xff); - digest[ 6] = (unsigned char) ((sha_info->digest[1] >> 8) & 0xff); - digest[ 7] = (unsigned char) ((sha_info->digest[1] ) & 0xff); - digest[ 8] = (unsigned char) ((sha_info->digest[2] >> 24) & 0xff); - digest[ 9] = (unsigned char) ((sha_info->digest[2] >> 16) & 0xff); - digest[10] = (unsigned char) ((sha_info->digest[2] >> 8) & 0xff); - digest[11] = (unsigned char) ((sha_info->digest[2] ) & 0xff); - digest[12] = (unsigned char) ((sha_info->digest[3] >> 24) & 0xff); - digest[13] = (unsigned char) ((sha_info->digest[3] >> 16) & 0xff); - digest[14] = (unsigned char) ((sha_info->digest[3] >> 8) & 0xff); - digest[15] = (unsigned char) ((sha_info->digest[3] ) & 0xff); - digest[16] = (unsigned char) ((sha_info->digest[4] >> 24) & 0xff); - digest[17] = (unsigned char) ((sha_info->digest[4] >> 16) & 0xff); - digest[18] = (unsigned char) ((sha_info->digest[4] >> 8) & 0xff); - digest[19] = (unsigned char) ((sha_info->digest[4] ) & 0xff); - digest[20] = (unsigned char) ((sha_info->digest[5] >> 24) & 0xff); - digest[21] = (unsigned char) ((sha_info->digest[5] >> 16) & 0xff); - digest[22] = (unsigned char) ((sha_info->digest[5] >> 8) & 0xff); - digest[23] = (unsigned char) ((sha_info->digest[5] ) & 0xff); - digest[24] = (unsigned char) ((sha_info->digest[6] >> 24) & 0xff); - digest[25] = (unsigned char) ((sha_info->digest[6] >> 16) & 0xff); - digest[26] = (unsigned char) ((sha_info->digest[6] >> 8) & 0xff); - digest[27] = (unsigned char) ((sha_info->digest[6] ) & 0xff); - digest[28] = (unsigned char) ((sha_info->digest[7] >> 24) & 0xff); - digest[29] = (unsigned char) ((sha_info->digest[7] >> 16) & 0xff); - digest[30] = (unsigned char) ((sha_info->digest[7] >> 8) & 0xff); - digest[31] = (unsigned char) ((sha_info->digest[7] ) & 0xff); -} - -/* - * End of copied SHA code. - * - * ------------------------------------------------------------------------ - */ - - static SHAobject * newSHA224object(_sha256_state *state) { @@ -409,14 +104,31 @@ SHA_traverse(PyObject *ptr, visitproc visit, void *arg) } static void -SHA_dealloc(PyObject *ptr) +SHA_dealloc(SHAobject *ptr) { + Hacl_Streaming_SHA2_free_256(ptr->state); PyTypeObject *tp = Py_TYPE(ptr); PyObject_GC_UnTrack(ptr); PyObject_GC_Del(ptr); Py_DECREF(tp); } +/* HACL* takes a uint32_t for the length of its parameter, but Py_ssize_t can be + * 64 bits. */ +static void update_256(Hacl_Streaming_SHA2_state_sha2_256 *state, uint8_t *buf, Py_ssize_t len) { + /* Note: we explicitly ignore the error code on the basis that it would take > + * 1 billion years to overflow the maximum admissible length for SHA2-256 + * (namely, 2^61-1 bytes). */ + while (len > UINT32_MAX) { + Hacl_Streaming_SHA2_update_256(state, buf, UINT32_MAX); + len -= UINT32_MAX; + buf += UINT32_MAX; + } + /* Cast to uint32_t is safe: upon exiting the loop, len <= UINT32_MAX, and + * therefore fits in a uint32_t */ + Hacl_Streaming_SHA2_update_256(state, buf, (uint32_t) len); +} + /* External methods for a hash object */ @@ -458,11 +170,10 @@ static PyObject * SHA256Type_digest_impl(SHAobject *self) /*[clinic end generated code: output=46616a5e909fbc3d input=f1f4cfea5cbde35c]*/ { - unsigned char digest[SHA_DIGESTSIZE]; - SHAobject temp; - - SHAcopy(self, &temp); - sha_final(digest, &temp); + uint8_t digest[SHA_DIGESTSIZE]; + // HACL performs copies under the hood so that self->state remains valid + // after this call. + Hacl_Streaming_SHA2_finish_256(self->state, digest); return PyBytes_FromStringAndSize((const char *)digest, self->digestsize); } @@ -476,13 +187,8 @@ static PyObject * SHA256Type_hexdigest_impl(SHAobject *self) /*[clinic end generated code: output=725f8a7041ae97f3 input=0cc4c714693010d1]*/ { - unsigned char digest[SHA_DIGESTSIZE]; - SHAobject temp; - - /* Get the raw (binary) digest value */ - SHAcopy(self, &temp); - sha_final(digest, &temp); - + uint8_t digest[SHA_DIGESTSIZE]; + Hacl_Streaming_SHA2_finish_256(self->state, digest); return _Py_strhex((const char *)digest, self->digestsize); } @@ -503,7 +209,7 @@ SHA256Type_update(SHAobject *self, PyObject *obj) GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); - sha_update(self, buf.buf, buf.len); + update_256(self->state, buf.buf, buf.len); PyBuffer_Release(&buf); Py_RETURN_NONE; @@ -524,12 +230,12 @@ SHA256_get_block_size(PyObject *self, void *closure) } static PyObject * -SHA256_get_name(PyObject *self, void *closure) +SHA256_get_name(SHAobject *self, void *closure) { - if (((SHAobject *)self)->digestsize == 32) - return PyUnicode_FromStringAndSize("sha256", 6); - else + if (self->digestsize == 28) { return PyUnicode_FromStringAndSize("sha224", 6); + } + return PyUnicode_FromStringAndSize("sha256", 6); } static PyGetSetDef SHA_getseters[] = { @@ -606,7 +312,8 @@ _sha256_sha256_impl(PyObject *module, PyObject *string, int usedforsecurity) return NULL; } - sha_init(new); + new->state = Hacl_Streaming_SHA2_create_in_256(); + new->digestsize = 32; if (PyErr_Occurred()) { Py_DECREF(new); @@ -616,7 +323,7 @@ _sha256_sha256_impl(PyObject *module, PyObject *string, int usedforsecurity) return NULL; } if (string) { - sha_update(new, buf.buf, buf.len); + update_256(new->state, buf.buf, buf.len); PyBuffer_Release(&buf); } @@ -651,7 +358,8 @@ _sha256_sha224_impl(PyObject *module, PyObject *string, int usedforsecurity) return NULL; } - sha224_init(new); + new->state = Hacl_Streaming_SHA2_create_in_224(); + new->digestsize = 28; if (PyErr_Occurred()) { Py_DECREF(new); @@ -661,7 +369,7 @@ _sha256_sha224_impl(PyObject *module, PyObject *string, int usedforsecurity) return NULL; } if (string) { - sha_update(new, buf.buf, buf.len); + update_256(new->state, buf.buf, buf.len); PyBuffer_Release(&buf); } diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 397d22abe235039..e8e9ff01e306bc0 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -100,7 +100,7 @@ /Zm200 %(AdditionalOptions) - $(PySourcePath)Python;%(AdditionalIncludeDirectories) + $(PySourcePath)Modules\_hacl\include;$(PySourcePath)Modules\_hacl\internal;$(PySourcePath)Python;%(AdditionalIncludeDirectories) $(zlibDir);%(AdditionalIncludeDirectories) _USRDLL;Py_BUILD_CORE;Py_BUILD_CORE_BUILTIN;Py_ENABLE_SHARED;MS_DLL_ID="$(SysWinVer)";%(PreprocessorDefinitions) _Py_HAVE_ZLIB;%(PreprocessorDefinitions) @@ -407,6 +407,7 @@ + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index bcbedcc3235b3ec..4820db6f2c32dc6 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -866,6 +866,9 @@ Modules + + Modules + Modules diff --git a/configure b/configure index aef8103085bc207..97694c602d1cc8b 100755 --- a/configure +++ b/configure @@ -24426,6 +24426,7 @@ SRCDIRS="\ Modules/_ctypes \ Modules/_decimal \ Modules/_decimal/libmpdec \ + Modules/_hacl \ Modules/_io \ Modules/_multiprocessing \ Modules/_sha3 \ @@ -26966,7 +26967,7 @@ fi as_fn_append MODULE_BLOCK "MODULE__SHA256_STATE=$py_cv_module__sha256$as_nl" if test "x$py_cv_module__sha256" = xyes; then : - + as_fn_append MODULE_BLOCK "MODULE__SHA256_CFLAGS=-I\$(srcdir)/Modules/_hacl/include -I\$(srcdir)/Modules/_hacl/internal -D_BSD_SOURCE -D_DEFAULT_SOURCE$as_nl" fi diff --git a/configure.ac b/configure.ac index 010bca855f00598..09369b985b33f68 100644 --- a/configure.ac +++ b/configure.ac @@ -6508,6 +6508,7 @@ SRCDIRS="\ Modules/_ctypes \ Modules/_decimal \ Modules/_decimal/libmpdec \ + Modules/_hacl \ Modules/_io \ Modules/_multiprocessing \ Modules/_sha3 \ @@ -7197,7 +7198,9 @@ dnl By default we always compile these even when OpenSSL is available dnl (issue #14693). The modules are small. PY_STDLIB_MOD([_md5], [test "$with_builtin_md5" = yes]) PY_STDLIB_MOD([_sha1], [test "$with_builtin_sha1" = yes]) -PY_STDLIB_MOD([_sha256], [test "$with_builtin_sha256" = yes]) +PY_STDLIB_MOD([_sha256], + [test "$with_builtin_sha256" = yes], [], + [-I\$(srcdir)/Modules/_hacl/include -I\$(srcdir)/Modules/_hacl/internal -D_BSD_SOURCE -D_DEFAULT_SOURCE]) PY_STDLIB_MOD([_sha512], [test "$with_builtin_sha512" = yes]) PY_STDLIB_MOD([_sha3], [test "$with_builtin_sha3" = yes]) PY_STDLIB_MOD([_blake2], From 694e346a01f407c7f78138331db006dea79f82a8 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Mon, 6 Feb 2023 21:03:58 -0800 Subject: [PATCH 60/74] gh-98831: Move DSL documentation here from ideas repo (#101629) --- Tools/cases_generator/README.md | 9 +- .../cases_generator/interpreter_definition.md | 409 ++++++++++++++++++ 2 files changed, 415 insertions(+), 3 deletions(-) create mode 100644 Tools/cases_generator/interpreter_definition.md diff --git a/Tools/cases_generator/README.md b/Tools/cases_generator/README.md index dc055ead1941cde..c595a932ac44701 100644 --- a/Tools/cases_generator/README.md +++ b/Tools/cases_generator/README.md @@ -1,5 +1,8 @@ # Tooling to generate interpreters +Documentation for the instruction definitions in `Python/bytecodes.c` +("the DSL") is [here](interpreter_definition.md). + What's currently here: - `lexer.py`: lexer for C, originally written by Mark Shannon @@ -7,10 +10,10 @@ What's currently here: - `parser.py`: Parser for instruction definition DSL; main class `Parser` - `generate_cases.py`: driver script to read `Python/bytecodes.c` and write `Python/generated_cases.c.h` +- `test_generator.py`: tests, require manual running using `pytest` -The DSL for the instruction definitions in `Python/bytecodes.c` is described -[here](https://github.com/faster-cpython/ideas/blob/main/3.12/interpreter_definition.md). -Note that there is some dummy C code at the top and bottom of the file +Note that there is some dummy C code at the top and bottom of +`Python/bytecodes.c` to fool text editors like VS Code into believing this is valid C code. ## A bit about the parser diff --git a/Tools/cases_generator/interpreter_definition.md b/Tools/cases_generator/interpreter_definition.md new file mode 100644 index 000000000000000..c7bd38d32ff4115 --- /dev/null +++ b/Tools/cases_generator/interpreter_definition.md @@ -0,0 +1,409 @@ +# A higher level definition of the bytecode interpreter + +## Abstract + +The CPython interpreter is defined in C, meaning that the semantics of the +bytecode instructions, the dispatching mechanism, error handling, and +tracing and instrumentation are all intermixed. + +This document proposes defining a custom C-like DSL for defining the +instruction semantics and tools for generating the code deriving from +the instruction definitions. + +These tools would be used to: +* Generate the main interpreter (done) +* Generate the tier 2 interpreter +* Generate documentation for instructions +* Generate metadata about instructions, such as stack use (done). + +Having a single definition file ensures that there is a single source +of truth for bytecode semantics. + +Other tools that operate on bytecodes, like `frame.setlineno` +and the `dis` module, will be derived from the common semantic +definition, reducing errors. + +## Motivation + +The bytecode interpreter of CPython has traditionally been defined as standard +C code, but with a lot of macros. +The presence of these macros and the nature of bytecode interpreters means +that the interpreter is effectively defined in a domain specific language (DSL). + +Rather than using an ad-hoc DSL embedded in the C code for the interpreter, +a custom DSL should be defined and the semantics of the bytecode instructions, +and the instructions defined in that DSL. + +Generating the interpreter decouples low-level details of dispatching +and error handling from the semantics of the instructions, resulting +in more maintainable code and a potentially faster interpreter. + +It also provides the ability to create and check optimizers and optimization +passes from the semantic definition, reducing errors. + +## Rationale + +As we improve the performance of CPython, we need to optimize larger regions +of code, use more complex optimizations and, ultimately, translate to machine +code. + +All of these steps introduce the possibility of more bugs, and require more code +to be written. One way to mitigate this is through the use of code generators. +Code generators decouple the debugging of the code (the generator) from checking +the correctness (the DSL input). + +For example, we are likely to want a new interpreter for the tier 2 optimizer +to be added in 3.12. That interpreter will have a different API, a different +set of instructions and potentially different dispatching mechanism. +But the instructions it will interpret will be built from the same building +blocks as the instructions for the tier 1 (PEP 659) interpreter. + +Rewriting all the instructions is tedious and error-prone, and changing the +instructions is a maintenance headache as both versions need to be kept in sync. + +By using a code generator and using a common source for the instructions, or +parts of instructions, we can reduce the potential for errors considerably. + + +## Specification + +This specification is at an early stage and is likely to change considerably. + +Syntax +------ + +Each op definition has a kind, a name, a stack and instruction stream effect, +and a piece of C code describing its semantics:: + +``` + file: + (definition | family)+ + + definition: + "inst" "(" NAME ["," stack_effect] ")" "{" C-code "}" + | + "op" "(" NAME "," stack_effect ")" "{" C-code "}" + | + "macro" "(" NAME ")" "=" uop ("+" uop)* ";" + | + "super" "(" NAME ")" "=" NAME ("+" NAME)* ";" + + stack_effect: + "(" [inputs] "--" [outputs] ")" + + inputs: + input ("," input)* + + outputs: + output ("," output)* + + input: + object | stream | array + + output: + object | array + + uop: + NAME | stream + + object: + NAME [":" type] [ "if" "(" C-expression ")" ] + + type: + NAME + + stream: + NAME "/" size + + size: + INTEGER + + array: + object "[" C-expression "]" + + family: + "family" "(" NAME ")" = "{" NAME ("," NAME)+ "}" ";" +``` + +The following definitions may occur: + +* `inst`: A normal instruction, as previously defined by `TARGET(NAME)` in `ceval.c`. +* `op`: A part instruction from which macros can be constructed. +* `macro`: A bytecode instruction constructed from ops and cache effects. +* `super`: A super-instruction, such as `LOAD_FAST__LOAD_FAST`, constructed from + normal or macro instructions. + +`NAME` can be any ASCII identifier that is a C identifier and not a C or Python keyword. +`foo_1` is legal. `$` is not legal, nor is `struct` or `class`. + +The optional `type` in an `object` is the C type. It defaults to `PyObject *`. +The objects before the "--" are the objects on top of the the stack at the start +of the instruction. Those after the "--" are the objects on top of the the stack +at the end of the instruction. + +An `inst` without `stack_effect` is a transitional form to allow the original C code +definitions to be copied. It lacks information to generate anything other than the +interpreter, but is useful for initial porting of code. + +Stack effect names may be `unused`, indicating the space is to be reserved +but no use of it will be made in the instruction definition. +This is useful to ensure that all instructions in a family have the same +stack effect. + +The number in a `stream` define how many codeunits are consumed from the +instruction stream. It returns a 16, 32 or 64 bit value. +If the name is `unused` the size can be any value and that many codeunits +will be skipped in the instruction stream. + +By convention cache effects (`stream`) must precede the input effects. + +The name `oparg` is pre-defined as a 32 bit value fetched from the instruction stream. + +The C code may include special functions that are understood by the tools as +part of the DSL. + +Those functions include: + +* `DEOPT_IF(cond, instruction)`. Deoptimize if `cond` is met. +* `ERROR_IF(cond, label)`. Jump to error handler if `cond` is true. +* `DECREF_INPUTS()`. Generate `Py_DECREF()` calls for the input stack effects. + +Variables can either be defined in the input, output, or in the C code. +Variables defined in the input may not be assigned in the C code. +If an `ERROR_IF` occurs, all values will be removed from the stack; +they must already be `DECREF`'ed by the code block. +If a `DEOPT_IF` occurs, no values will be removed from the stack or +the instruction stream; no values must have been `DECREF`'ed or created. + +These requirements result in the following constraints on the use of +`DEOPT_IF` and `ERROR_IF` in any instruction's code block: + +1. Until the last `DEOPT_IF`, no objects may be allocated, `INCREF`ed, + or `DECREF`ed. +2. Before the first `ERROR_IF`, all input values must be `DECREF`ed, + and no objects may be allocated or `INCREF`ed, with the exception + of attempting to create an object and checking for success using + `ERROR_IF(result == NULL, label)`. (TODO: Unclear what to do with + intermediate results.) +3. No `DEOPT_IF` may follow an `ERROR_IF` in the same block. + +Semantics +--------- + +The underlying execution model is a stack machine. +Operations pop values from the stack, and push values to the stack. +They also can look at, and consume, values from the instruction stream. + +All members of a family must have the same stack and instruction stream effect. + +Examples +-------- + +(Another source of examples can be found in the [tests](test_generator.py).) + +Some examples: + +### Output stack effect +```C + inst ( LOAD_FAST, (-- value) ) { + value = frame->f_localsplus[oparg]; + Py_INCREF(value); + } +``` +This would generate: +```C + TARGET(LOAD_FAST) { + PyObject *value; + value = frame->f_localsplus[oparg]; + Py_INCREF(value); + PUSH(value); + DISPATCH(); + } +``` + +### Input stack effect +```C + inst ( STORE_FAST, (value --) ) { + SETLOCAL(oparg, value); + } +``` +This would generate: +```C + TARGET(STORE_FAST) { + PyObject *value = PEEK(1); + SETLOCAL(oparg, value); + STACK_SHRINK(1); + DISPATCH(); + } +``` + +### Super-instruction definition + +```C + super ( LOAD_FAST__LOAD_FAST ) = LOAD_FAST + LOAD_FAST ; +``` +This might get translated into the following: +```C + TARGET(LOAD_FAST__LOAD_FAST) { + PyObject *value; + value = frame->f_localsplus[oparg]; + Py_INCREF(value); + PUSH(value); + NEXTOPARG(); + next_instr++; + value = frame->f_localsplus[oparg]; + Py_INCREF(value); + PUSH(value); + DISPATCH(); + } +``` + +### Input stack effect and cache effect +```C + op ( CHECK_OBJECT_TYPE, (owner, type_version/2 -- owner) ) { + PyTypeObject *tp = Py_TYPE(owner); + assert(type_version != 0); + DEOPT_IF(tp->tp_version_tag != type_version); + } +``` +This might become (if it was an instruction): +```C + TARGET(CHECK_OBJECT_TYPE) { + PyObject *owner = PEEK(1); + uint32 type_version = read32(next_instr); + PyTypeObject *tp = Py_TYPE(owner); + assert(type_version != 0); + DEOPT_IF(tp->tp_version_tag != type_version); + next_instr += 2; + DISPATCH(); + } +``` + +### More examples + +For explanations see "Generating the interpreter" below.) +```C + op ( CHECK_HAS_INSTANCE_VALUES, (owner -- owner) ) { + PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); + DEOPT_IF(!_PyDictOrValues_IsValues(dorv)); + } +``` +```C + op ( LOAD_INSTANCE_VALUE, (owner, index/1 -- null if (oparg & 1), res) ) { + res = _PyDictOrValues_GetValues(dorv)->values[index]; + DEOPT_IF(res == NULL); + Py_INCREF(res); + null = NULL; + Py_DECREF(owner); + } +``` +```C + macro ( LOAD_ATTR_INSTANCE_VALUE ) = + counter/1 + CHECK_OBJECT_TYPE + CHECK_HAS_INSTANCE_VALUES + + LOAD_INSTANCE_VALUE + unused/4 ; +``` +```C + op ( LOAD_SLOT, (owner, index/1 -- null if (oparg & 1), res) ) { + char *addr = (char *)owner + index; + res = *(PyObject **)addr; + DEOPT_IF(res == NULL); + Py_INCREF(res); + null = NULL; + Py_DECREF(owner); + } +``` +```C + macro ( LOAD_ATTR_SLOT ) = counter/1 + CHECK_OBJECT_TYPE + LOAD_SLOT + unused/4; +``` +```C + inst ( BUILD_TUPLE, (items[oparg] -- tuple) ) { + tuple = _PyTuple_FromArraySteal(items, oparg); + ERROR_IF(tuple == NULL, error); + } +``` +```C + inst ( PRINT_EXPR ) { + PyObject *value = POP(); + PyObject *hook = _PySys_GetAttr(tstate, &_Py_ID(displayhook)); + PyObject *res; + if (hook == NULL) { + _PyErr_SetString(tstate, PyExc_RuntimeError, + "lost sys.displayhook"); + Py_DECREF(value); + goto error; + } + res = PyObject_CallOneArg(hook, value); + Py_DECREF(value); + ERROR_IF(res == NULL); + Py_DECREF(res); + } +``` + +### Define an instruction family +These opcodes all share the same instruction format): +```C + family(load_attr) = { LOAD_ATTR, LOAD_ATTR_INSTANCE_VALUE, LOAD_SLOT } ; +``` + +Generating the interpreter +========================== + +The generated C code for a single instruction includes a preamble and dispatch at the end +which can be easily inserted. What is more complex is ensuring the correct stack effects +and not generating excess pops and pushes. + +For example, in `CHECK_HAS_INSTANCE_VALUES`, `owner` occurs in the input, so it cannot be +redefined. Thus it doesn't need to written and can be read without adjusting the stack pointer. +The C code generated for `CHECK_HAS_INSTANCE_VALUES` would look something like: + +```C + { + PyObject *owner = stack_pointer[-1]; + PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); + DEOPT_IF(!_PyDictOrValues_IsValues(dorv)); + } +``` + +When combining ops together to form instructions, temporary values should be used, +rather than popping and pushing, such that `LOAD_ATTR_SLOT` would look something like: + +```C + case LOAD_ATTR_SLOT: { + PyObject *s1 = stack_pointer[-1]; + /* CHECK_OBJECT_TYPE */ + { + PyObject *owner = s1; + uint32_t type_version = read32(next_instr + 1); + PyTypeObject *tp = Py_TYPE(owner); + assert(type_version != 0); + if (tp->tp_version_tag != type_version) goto deopt; + } + /* LOAD_SLOT */ + { + PyObject *owner = s1; + uint16_t index = *(next_instr + 1 + 2); + char *addr = (char *)owner + index; + PyObject *null; + PyObject *res = *(PyObject **)addr; + if (res == NULL) goto deopt; + Py_INCREF(res); + null = NULL; + Py_DECREF(owner); + if (oparg & 1) { + stack_pointer[0] = null; + stack_pointer += 1; + } + s1 = res; + } + next_instr += (1 + 1 + 2 + 1 + 4); + stack_pointer[-1] = s1; + DISPATCH(); + } +``` + +Other tools +=========== + +From the instruction definitions we can generate the stack marking code used in `frame.set_lineno()`, +and the tables for use by disassemblers. + From c4de6b1d52304a0a9cdfafc1dad5098993710404 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Tue, 7 Feb 2023 00:25:42 -0500 Subject: [PATCH 61/74] gh-85747: Active voice & suggested edits, 'running/stopping loop' & 'callbacks' subsections of asyncio-eventloop.rst (#100270) Co-authored-by: C.A.M. Gerlach Co-authored-by: Terry Jan Reedy --- Doc/library/asyncio-eventloop.rst | 42 ++++++++++++++++++------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index db63a5dd11ad6ec..f86e784288029c1 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -186,19 +186,24 @@ Running and stopping the loop .. coroutinemethod:: loop.shutdown_default_executor(timeout=None) Schedule the closure of the default executor and wait for it to join all of - the threads in the :class:`ThreadPoolExecutor`. After calling this method, a - :exc:`RuntimeError` will be raised if :meth:`loop.run_in_executor` is called - while using the default executor. + the threads in the :class:`~concurrent.futures.ThreadPoolExecutor`. + Once this method has been called, + using the default executor with :meth:`loop.run_in_executor` + will raise a :exc:`RuntimeError`. - The *timeout* parameter specifies the amount of time the executor will - be given to finish joining. The default value is ``None``, which means the - executor will be given an unlimited amount of time. + The *timeout* parameter specifies the amount of time + (in :class:`float` seconds) the executor will be given to finish joining. + With the default, ``None``, + the executor is allowed an unlimited amount of time. - If the timeout duration is reached, a warning is emitted and executor is - terminated without waiting for its threads to finish joining. + If the *timeout* is reached, a :exc:`RuntimeWarning` is emitted + and the default executor is terminated + without waiting for its threads to finish joining. - Note that there is no need to call this function when - :func:`asyncio.run` is used. + .. note:: + + Do not call this method when using :func:`asyncio.run`, + as the latter handles default executor shutdown automatically. .. versionadded:: 3.9 @@ -213,22 +218,23 @@ Scheduling callbacks Schedule the *callback* :term:`callback` to be called with *args* arguments at the next iteration of the event loop. + Return an instance of :class:`asyncio.Handle`, + which can be used later to cancel the callback. + Callbacks are called in the order in which they are registered. Each callback will be called exactly once. - An optional keyword-only *context* argument allows specifying a + The optional keyword-only *context* argument specifies a custom :class:`contextvars.Context` for the *callback* to run in. - The current context is used when no *context* is provided. - - An instance of :class:`asyncio.Handle` is returned, which can be - used later to cancel the callback. + Callbacks use the current context when no *context* is provided. - This method is not thread-safe. + Unlike :meth:`call_soon_threadsafe`, this method is not thread-safe. .. method:: loop.call_soon_threadsafe(callback, *args, context=None) - A thread-safe variant of :meth:`call_soon`. Must be used to - schedule callbacks *from another thread*. + A thread-safe variant of :meth:`call_soon`. When scheduling callbacks from + another thread, this function *must* be used, since :meth:`call_soon` is not + thread-safe. Raises :exc:`RuntimeError` if called on a loop that's been closed. This can happen on a secondary thread when the main application is From ae62bddaf81176a7e55f95f18d55621c9c46c23d Mon Sep 17 00:00:00 2001 From: Matthieu Dartiailh Date: Tue, 7 Feb 2023 10:34:21 +0100 Subject: [PATCH 62/74] gh-101072: support default and kw default in PyEval_EvalCodeEx for 3.11+ (#101127) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Łukasz Langa --- Lib/test/test_capi/test_eval_code_ex.py | 56 +++++++ ...3-02-06-20-13-36.gh-issue-92173.RQE0mk.rst | 8 + Modules/_testcapimodule.c | 141 +++++++++++++++++- Objects/funcobject.c | 4 +- Python/ceval.c | 3 - 5 files changed, 206 insertions(+), 6 deletions(-) create mode 100644 Lib/test/test_capi/test_eval_code_ex.py create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-02-06-20-13-36.gh-issue-92173.RQE0mk.rst diff --git a/Lib/test/test_capi/test_eval_code_ex.py b/Lib/test/test_capi/test_eval_code_ex.py new file mode 100644 index 000000000000000..2d28e5289eff94d --- /dev/null +++ b/Lib/test/test_capi/test_eval_code_ex.py @@ -0,0 +1,56 @@ +import unittest + +from test.support import import_helper + + +# Skip this test if the _testcapi module isn't available. +_testcapi = import_helper.import_module('_testcapi') + + +class PyEval_EvalCodeExTests(unittest.TestCase): + + def test_simple(self): + def f(): + return a + + self.assertEqual(_testcapi.eval_code_ex(f.__code__, dict(a=1)), 1) + + # Need to force the compiler to use LOAD_NAME + # def test_custom_locals(self): + # def f(): + # return + + def test_with_args(self): + def f(a, b, c): + return a + + self.assertEqual(_testcapi.eval_code_ex(f.__code__, {}, {}, (1, 2, 3)), 1) + + def test_with_kwargs(self): + def f(a, b, c): + return a + + self.assertEqual(_testcapi.eval_code_ex(f.__code__, {}, {}, (), dict(a=1, b=2, c=3)), 1) + + def test_with_default(self): + def f(a): + return a + + self.assertEqual(_testcapi.eval_code_ex(f.__code__, {}, {}, (), {}, (1,)), 1) + + def test_with_kwarg_default(self): + def f(*, a): + return a + + self.assertEqual(_testcapi.eval_code_ex(f.__code__, {}, {}, (), {}, (), dict(a=1)), 1) + + def test_with_closure(self): + a = 1 + def f(): + return a + + self.assertEqual(_testcapi.eval_code_ex(f.__code__, {}, {}, (), {}, (), {}, f.__closure__), 1) + + +if __name__ == "__main__": + unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-02-06-20-13-36.gh-issue-92173.RQE0mk.rst b/Misc/NEWS.d/next/Core and Builtins/2023-02-06-20-13-36.gh-issue-92173.RQE0mk.rst new file mode 100644 index 000000000000000..2d991f6ca21b6f3 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-02-06-20-13-36.gh-issue-92173.RQE0mk.rst @@ -0,0 +1,8 @@ +macOS #.. section: IDLE #.. section: Tools/Demos #.. section: C API + +# Write your Misc/NEWS entry below. It should be a simple ReST paragraph. # +Don't start with "- Issue #: " or "- gh-issue-: " or that sort of +stuff. +########################################################################### + +Fix the ``defs`` and ``kwdefs`` arguments to :c:func:`PyEval_EvalCodeEx`. diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 5e47f4975a2d54d..5a6097ef0ac5a68 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -2237,7 +2237,7 @@ dict_get_version(PyObject *self, PyObject *args) return NULL; _Py_COMP_DIAG_PUSH - _Py_COMP_DIAG_IGNORE_DEPR_DECLS + _Py_COMP_DIAG_IGNORE_DEPR_DECLS version = dict->ma_version_tag; _Py_COMP_DIAG_POP @@ -3064,6 +3064,144 @@ eval_get_func_desc(PyObject *self, PyObject *func) return PyUnicode_FromString(PyEval_GetFuncDesc(func)); } +static PyObject * +eval_eval_code_ex(PyObject *mod, PyObject *pos_args) +{ + PyObject *result = NULL; + PyObject *code; + PyObject *globals; + PyObject *locals = NULL; + PyObject *args = NULL; + PyObject *kwargs = NULL; + PyObject *defaults = NULL; + PyObject *kw_defaults = NULL; + PyObject *closure = NULL; + + PyObject **c_kwargs = NULL; + + if (!PyArg_UnpackTuple(pos_args, + "eval_code_ex", + 2, + 8, + &code, + &globals, + &locals, + &args, + &kwargs, + &defaults, + &kw_defaults, + &closure)) + { + goto exit; + } + + if (!PyCode_Check(code)) { + PyErr_SetString(PyExc_TypeError, + "code must be a Python code object"); + goto exit; + } + + if (!PyDict_Check(globals)) { + PyErr_SetString(PyExc_TypeError, "globals must be a dict"); + goto exit; + } + + if (locals && !PyMapping_Check(locals)) { + PyErr_SetString(PyExc_TypeError, "locals must be a mapping"); + goto exit; + } + if (locals == Py_None) { + locals = NULL; + } + + PyObject **c_args = NULL; + Py_ssize_t c_args_len = 0; + + if (args) + { + if (!PyTuple_Check(args)) { + PyErr_SetString(PyExc_TypeError, "args must be a tuple"); + goto exit; + } else { + c_args = &PyTuple_GET_ITEM(args, 0); + c_args_len = PyTuple_Size(args); + } + } + + Py_ssize_t c_kwargs_len = 0; + + if (kwargs) + { + if (!PyDict_Check(kwargs)) { + PyErr_SetString(PyExc_TypeError, "keywords must be a dict"); + goto exit; + } else { + c_kwargs_len = PyDict_Size(kwargs); + if (c_kwargs_len > 0) { + c_kwargs = PyMem_NEW(PyObject*, 2 * c_kwargs_len); + if (!c_kwargs) { + PyErr_NoMemory(); + goto exit; + } + + Py_ssize_t i = 0; + Py_ssize_t pos = 0; + + while (PyDict_Next(kwargs, + &pos, + &c_kwargs[i], + &c_kwargs[i + 1])) + { + i += 2; + } + c_kwargs_len = i / 2; + /* XXX This is broken if the caller deletes dict items! */ + } + } + } + + + PyObject **c_defaults = NULL; + Py_ssize_t c_defaults_len = 0; + + if (defaults && PyTuple_Check(defaults)) { + c_defaults = &PyTuple_GET_ITEM(defaults, 0); + c_defaults_len = PyTuple_Size(defaults); + } + + if (kw_defaults && !PyDict_Check(kw_defaults)) { + PyErr_SetString(PyExc_TypeError, "kw_defaults must be a dict"); + goto exit; + } + + if (closure && !PyTuple_Check(closure)) { + PyErr_SetString(PyExc_TypeError, "closure must be a tuple of cells"); + goto exit; + } + + + result = PyEval_EvalCodeEx( + code, + globals, + locals, + c_args, + c_args_len, + c_kwargs, + c_kwargs_len, + c_defaults, + c_defaults_len, + kw_defaults, + closure + ); + +exit: + if (c_kwargs) { + PyMem_DEL(c_kwargs); + } + + return result; +} + static PyObject * get_feature_macros(PyObject *self, PyObject *Py_UNUSED(args)) { @@ -3385,6 +3523,7 @@ static PyMethodDef TestMethods[] = { {"set_exc_info", test_set_exc_info, METH_VARARGS}, {"argparsing", argparsing, METH_VARARGS}, {"code_newempty", code_newempty, METH_VARARGS}, + {"eval_code_ex", eval_eval_code_ex, METH_VARARGS}, {"make_exception_with_doc", _PyCFunction_CAST(make_exception_with_doc), METH_VARARGS | METH_KEYWORDS}, {"make_memoryview_from_NULL_pointer", make_memoryview_from_NULL_pointer, diff --git a/Objects/funcobject.c b/Objects/funcobject.c index baa360381a77242..91a6b3dd40a2324 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -87,8 +87,8 @@ _PyFunction_FromConstructor(PyFrameConstructor *constr) op->func_name = Py_NewRef(constr->fc_name); op->func_qualname = Py_NewRef(constr->fc_qualname); op->func_code = Py_NewRef(constr->fc_code); - op->func_defaults = NULL; - op->func_kwdefaults = NULL; + op->func_defaults = Py_XNewRef(constr->fc_defaults); + op->func_kwdefaults = Py_XNewRef(constr->fc_kwdefaults); op->func_closure = Py_XNewRef(constr->fc_closure); op->func_doc = Py_NewRef(Py_None); op->func_dict = NULL; diff --git a/Python/ceval.c b/Python/ceval.c index 2e6fed580dede4b..ecb5bf9655553ed 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1761,9 +1761,6 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals, } allargs = newargs; } - for (int i = 0; i < kwcount; i++) { - PyTuple_SET_ITEM(kwnames, i, Py_NewRef(kws[2*i])); - } PyFrameConstructor constr = { .fc_globals = globals, .fc_builtins = builtins, From 79903240480429a6e545177416a7b782b0e5b9bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Langa?= Date: Tue, 7 Feb 2023 10:50:39 +0100 Subject: [PATCH 63/74] [gh-101072] Fix Blurb for GH-101127 --- .../2023-02-06-20-13-36.gh-issue-92173.RQE0mk.rst | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-02-06-20-13-36.gh-issue-92173.RQE0mk.rst b/Misc/NEWS.d/next/Core and Builtins/2023-02-06-20-13-36.gh-issue-92173.RQE0mk.rst index 2d991f6ca21b6f3..6b98aac2a465459 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2023-02-06-20-13-36.gh-issue-92173.RQE0mk.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2023-02-06-20-13-36.gh-issue-92173.RQE0mk.rst @@ -1,8 +1,2 @@ -macOS #.. section: IDLE #.. section: Tools/Demos #.. section: C API - -# Write your Misc/NEWS entry below. It should be a simple ReST paragraph. # -Don't start with "- Issue #: " or "- gh-issue-: " or that sort of -stuff. -########################################################################### - -Fix the ``defs`` and ``kwdefs`` arguments to :c:func:`PyEval_EvalCodeEx`. +Fix the ``defs`` and ``kwdefs`` arguments to :c:func:`PyEval_EvalCodeEx` +and a reference leak in that function. From 3c67ec394faac79d260804d569a18fab43018af0 Mon Sep 17 00:00:00 2001 From: Thomas Wouters Date: Tue, 7 Feb 2023 13:17:26 +0100 Subject: [PATCH 64/74] Python 3.12.0a5 --- Include/patchlevel.h | 4 +- Lib/pydoc_data/topics.py | 14 +- Misc/NEWS.d/3.12.0a5.rst | 664 ++++++++++++++++++ ...2-08-30-10-16-31.gh-issue-96305.274i8B.rst | 2 - ...2-10-25-11-53-55.gh-issue-98636.e0RPAr.rst | 2 - ...2-10-27-09-57-12.gh-issue-98705.H11XmR.rst | 2 - ...-01-15-11-22-15.gh-issue-101060.0mYk9E.rst | 3 - ...-01-17-21-32-51.gh-issue-100340.i9zRGM.rst | 2 - ...-01-21-10-31-35.gh-issue-101152.xvM8pL.rst | 3 - ...3-01-26-19-02-11.gh-issue-77532.cXD8bg.rst | 1 - ...-02-02-23-43-46.gh-issue-101522.lnUDta.rst | 2 - ...-02-04-06-59-07.gh-issue-101282.7sQz5l.rst | 2 - .../2018-02-05-21-54-46.bpo-32780.Dtiz8z.rst | 3 - ...-01-03-14-33-23.gh-issue-100712.po6xyB.rst | 1 - ...-01-03-20-59-20.gh-issue-100726.W9huFl.rst | 1 - ...3-01-06-09-22-21.gh-issue-91351.iq2vZ_.rst | 5 - ...-01-10-14-11-17.gh-issue-100892.qfBVYI.rst | 1 - ...-01-10-16-59-33.gh-issue-100923.ypJAX-.rst | 2 - ...-01-11-22-52-19.gh-issue-100942.ontOy_.rst | 2 - ...-01-12-13-46-49.gh-issue-100982.mJ234s.rst | 4 - ...-01-13-12-56-20.gh-issue-100762.YvHaQJ.rst | 3 - ...-01-14-17-03-08.gh-issue-101037.9ATNuf.rst | 2 - ...-01-15-03-26-04.gh-issue-101046.g2CM4S.rst | 2 - ...-01-24-17-13-32.gh-issue-101291.Yr6u_c.rst | 2 - ...-01-28-13-11-52.gh-issue-101266.AxV3OF.rst | 1 - ...-01-28-20-31-42.gh-issue-101372.8BcpCC.rst | 2 - ...-01-30-08-59-47.gh-issue-101400.Di_ZFm.rst | 2 - ...3-01-30-11-56-09.gh-issue-59956.7xqnC_.rst | 3 - ...3-02-06-20-13-36.gh-issue-92173.RQE0mk.rst | 2 - ...2-06-19-22-04-47.gh-issue-88324.GHhSQ1.rst | 3 - ...8-05-21-17-18-00.gh-issue-77772.Fhg84L.rst | 3 - .../2020-04-18-17-45-03.bpo-29847.Uxtbq0.rst | 1 - .../2020-11-20-21-06-08.bpo-40077.M-iZq3.rst | 1 - .../2022-02-05-12-01-58.bpo-38941.8IhvyG.rst | 4 - ...2-07-22-13-38-37.gh-issue-94518._ZP0cz.rst | 2 - ...2-09-26-21-18-47.gh-issue-60580.0hBgde.rst | 3 - ...2-11-14-03-06-03.gh-issue-88597.EYJA-Q.rst | 1 - ...2-11-15-23-30-39.gh-issue-86682.gK9i1N.rst | 2 - ...2-11-24-21-52-31.gh-issue-99266.88GcV9.rst | 1 - ...2-12-10-15-30-17.gh-issue-67790.P9YUZM.rst | 2 - ...2-12-11-14-38-59.gh-issue-99952.IYGLzr.rst | 2 - ...2-12-19-23-19-26.gh-issue-96290.qFjsi6.rst | 5 - ...-12-21-17-49-50.gh-issue-100160.N0NHRj.rst | 3 - ...-01-04-14-42-59.gh-issue-100750.iFJs5Y.rst | 1 - ...3-01-08-00-12-44.gh-issue-39615.gn4PhB.rst | 3 - ...-01-12-01-18-13.gh-issue-100573.KDskqo.rst | 1 - ...-01-12-21-22-20.gh-issue-101000.wz4Xgc.rst | 3 - ...-01-14-12-58-21.gh-issue-101015.stWFid.rst | 2 - ...3-01-15-09-11-30.gh-issue-94518.jvxtxm.rst | 3 - ...-01-18-17-58-50.gh-issue-101144.FHd8Un.rst | 4 - ...-01-20-10-46-59.gh-issue-101143.hJo8hu.rst | 2 - ...-01-21-16-50-22.gh-issue-100795.NPMZf7.rst | 3 - ...3-01-24-12-53-59.gh-issue-92123.jf6TO5.rst | 2 - ...-01-25-18-07-20.gh-issue-101326.KL4SFv.rst | 1 - ...-01-26-01-25-56.gh-issue-101317.vWaS1x.rst | 2 - ...-01-26-06-44-35.gh-issue-101323.h8Hk11.rst | 2 - ...-02-04-21-01-49.gh-issue-101570.lbtUsD.rst | 1 - ...-02-05-14-39-49.gh-issue-101541.Mo3ppp.rst | 1 - ...2-11-08-12-06-52.gh-issue-99108.4Wrsuh.rst | 4 - ...-02-04-17-24-33.gh-issue-101334._yOqwg.rst | 1 - ...-01-11-14-42-11.gh-issue-100247.YfEmSz.rst | 2 - ...-01-11-16-28-09.gh-issue-100320.2DU2it.rst | 3 - ...3-01-17-18-17-58.gh-issue-82052.mWyysT.rst | 1 - ...-01-18-18-25-18.gh-issue-101135.HF9VlG.rst | 3 - ...3-01-25-00-23-31.gh-issue-99834.WN41lc.rst | 1 - ...-01-31-16-50-07.gh-issue-101467.ye9t-L.rst | 3 - ...-02-03-17-53-06.gh-issue-101543.cORAT4.rst | 2 - README.rst | 2 +- 68 files changed, 680 insertions(+), 145 deletions(-) create mode 100644 Misc/NEWS.d/3.12.0a5.rst delete mode 100644 Misc/NEWS.d/next/Build/2022-08-30-10-16-31.gh-issue-96305.274i8B.rst delete mode 100644 Misc/NEWS.d/next/Build/2022-10-25-11-53-55.gh-issue-98636.e0RPAr.rst delete mode 100644 Misc/NEWS.d/next/Build/2022-10-27-09-57-12.gh-issue-98705.H11XmR.rst delete mode 100644 Misc/NEWS.d/next/Build/2023-01-15-11-22-15.gh-issue-101060.0mYk9E.rst delete mode 100644 Misc/NEWS.d/next/Build/2023-01-17-21-32-51.gh-issue-100340.i9zRGM.rst delete mode 100644 Misc/NEWS.d/next/Build/2023-01-21-10-31-35.gh-issue-101152.xvM8pL.rst delete mode 100644 Misc/NEWS.d/next/Build/2023-01-26-19-02-11.gh-issue-77532.cXD8bg.rst delete mode 100644 Misc/NEWS.d/next/Build/2023-02-02-23-43-46.gh-issue-101522.lnUDta.rst delete mode 100644 Misc/NEWS.d/next/Build/2023-02-04-06-59-07.gh-issue-101282.7sQz5l.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2018-02-05-21-54-46.bpo-32780.Dtiz8z.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-01-03-14-33-23.gh-issue-100712.po6xyB.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-01-03-20-59-20.gh-issue-100726.W9huFl.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-01-06-09-22-21.gh-issue-91351.iq2vZ_.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-01-10-14-11-17.gh-issue-100892.qfBVYI.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-01-10-16-59-33.gh-issue-100923.ypJAX-.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-01-11-22-52-19.gh-issue-100942.ontOy_.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-01-12-13-46-49.gh-issue-100982.mJ234s.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-01-13-12-56-20.gh-issue-100762.YvHaQJ.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-01-14-17-03-08.gh-issue-101037.9ATNuf.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-01-15-03-26-04.gh-issue-101046.g2CM4S.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-01-24-17-13-32.gh-issue-101291.Yr6u_c.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-01-28-13-11-52.gh-issue-101266.AxV3OF.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-01-28-20-31-42.gh-issue-101372.8BcpCC.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-01-30-08-59-47.gh-issue-101400.Di_ZFm.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-01-30-11-56-09.gh-issue-59956.7xqnC_.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-02-06-20-13-36.gh-issue-92173.RQE0mk.rst delete mode 100644 Misc/NEWS.d/next/Documentation/2022-06-19-22-04-47.gh-issue-88324.GHhSQ1.rst delete mode 100644 Misc/NEWS.d/next/Library/2018-05-21-17-18-00.gh-issue-77772.Fhg84L.rst delete mode 100644 Misc/NEWS.d/next/Library/2020-04-18-17-45-03.bpo-29847.Uxtbq0.rst delete mode 100644 Misc/NEWS.d/next/Library/2020-11-20-21-06-08.bpo-40077.M-iZq3.rst delete mode 100644 Misc/NEWS.d/next/Library/2022-02-05-12-01-58.bpo-38941.8IhvyG.rst delete mode 100644 Misc/NEWS.d/next/Library/2022-07-22-13-38-37.gh-issue-94518._ZP0cz.rst delete mode 100644 Misc/NEWS.d/next/Library/2022-09-26-21-18-47.gh-issue-60580.0hBgde.rst delete mode 100644 Misc/NEWS.d/next/Library/2022-11-14-03-06-03.gh-issue-88597.EYJA-Q.rst delete mode 100644 Misc/NEWS.d/next/Library/2022-11-15-23-30-39.gh-issue-86682.gK9i1N.rst delete mode 100644 Misc/NEWS.d/next/Library/2022-11-24-21-52-31.gh-issue-99266.88GcV9.rst delete mode 100644 Misc/NEWS.d/next/Library/2022-12-10-15-30-17.gh-issue-67790.P9YUZM.rst delete mode 100644 Misc/NEWS.d/next/Library/2022-12-11-14-38-59.gh-issue-99952.IYGLzr.rst delete mode 100644 Misc/NEWS.d/next/Library/2022-12-19-23-19-26.gh-issue-96290.qFjsi6.rst delete mode 100644 Misc/NEWS.d/next/Library/2022-12-21-17-49-50.gh-issue-100160.N0NHRj.rst delete mode 100644 Misc/NEWS.d/next/Library/2023-01-04-14-42-59.gh-issue-100750.iFJs5Y.rst delete mode 100644 Misc/NEWS.d/next/Library/2023-01-08-00-12-44.gh-issue-39615.gn4PhB.rst delete mode 100644 Misc/NEWS.d/next/Library/2023-01-12-01-18-13.gh-issue-100573.KDskqo.rst delete mode 100644 Misc/NEWS.d/next/Library/2023-01-12-21-22-20.gh-issue-101000.wz4Xgc.rst delete mode 100644 Misc/NEWS.d/next/Library/2023-01-14-12-58-21.gh-issue-101015.stWFid.rst delete mode 100644 Misc/NEWS.d/next/Library/2023-01-15-09-11-30.gh-issue-94518.jvxtxm.rst delete mode 100644 Misc/NEWS.d/next/Library/2023-01-18-17-58-50.gh-issue-101144.FHd8Un.rst delete mode 100644 Misc/NEWS.d/next/Library/2023-01-20-10-46-59.gh-issue-101143.hJo8hu.rst delete mode 100644 Misc/NEWS.d/next/Library/2023-01-21-16-50-22.gh-issue-100795.NPMZf7.rst delete mode 100644 Misc/NEWS.d/next/Library/2023-01-24-12-53-59.gh-issue-92123.jf6TO5.rst delete mode 100644 Misc/NEWS.d/next/Library/2023-01-25-18-07-20.gh-issue-101326.KL4SFv.rst delete mode 100644 Misc/NEWS.d/next/Library/2023-01-26-01-25-56.gh-issue-101317.vWaS1x.rst delete mode 100644 Misc/NEWS.d/next/Library/2023-01-26-06-44-35.gh-issue-101323.h8Hk11.rst delete mode 100644 Misc/NEWS.d/next/Library/2023-02-04-21-01-49.gh-issue-101570.lbtUsD.rst delete mode 100644 Misc/NEWS.d/next/Library/2023-02-05-14-39-49.gh-issue-101541.Mo3ppp.rst delete mode 100644 Misc/NEWS.d/next/Security/2022-11-08-12-06-52.gh-issue-99108.4Wrsuh.rst delete mode 100644 Misc/NEWS.d/next/Tests/2023-02-04-17-24-33.gh-issue-101334._yOqwg.rst delete mode 100644 Misc/NEWS.d/next/Windows/2023-01-11-14-42-11.gh-issue-100247.YfEmSz.rst delete mode 100644 Misc/NEWS.d/next/Windows/2023-01-11-16-28-09.gh-issue-100320.2DU2it.rst delete mode 100644 Misc/NEWS.d/next/Windows/2023-01-17-18-17-58.gh-issue-82052.mWyysT.rst delete mode 100644 Misc/NEWS.d/next/Windows/2023-01-18-18-25-18.gh-issue-101135.HF9VlG.rst delete mode 100644 Misc/NEWS.d/next/Windows/2023-01-25-00-23-31.gh-issue-99834.WN41lc.rst delete mode 100644 Misc/NEWS.d/next/Windows/2023-01-31-16-50-07.gh-issue-101467.ye9t-L.rst delete mode 100644 Misc/NEWS.d/next/Windows/2023-02-03-17-53-06.gh-issue-101543.cORAT4.rst diff --git a/Include/patchlevel.h b/Include/patchlevel.h index 3a3e40c2e09229b..df6098be8bbcc95 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -20,10 +20,10 @@ #define PY_MINOR_VERSION 12 #define PY_MICRO_VERSION 0 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_ALPHA -#define PY_RELEASE_SERIAL 4 +#define PY_RELEASE_SERIAL 5 /* Version as a string */ -#define PY_VERSION "3.12.0a4+" +#define PY_VERSION "3.12.0a5" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py index 11b75037e78b464..e7f403d3ffbf124 100644 --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Tue Jan 10 13:08:32 2023 +# Autogenerated by Sphinx on Tue Feb 7 13:18:04 2023 topics = {'assert': 'The "assert" statement\n' '**********************\n' '\n' @@ -4647,6 +4647,18 @@ 'the source. The extension interface uses the modules "bdb" and ' '"cmd".\n' '\n' + 'See also:\n' + '\n' + ' Module "faulthandler"\n' + ' Used to dump Python tracebacks explicitly, on a fault, ' + 'after a\n' + ' timeout, or on a user signal.\n' + '\n' + ' Module "traceback"\n' + ' Standard interface to extract, format and print stack ' + 'traces of\n' + ' Python programs.\n' + '\n' 'The debugger’s prompt is "(Pdb)". Typical usage to run a program ' 'under\n' 'control of the debugger is:\n' diff --git a/Misc/NEWS.d/3.12.0a5.rst b/Misc/NEWS.d/3.12.0a5.rst new file mode 100644 index 000000000000000..f6f8de46cf70d9e --- /dev/null +++ b/Misc/NEWS.d/3.12.0a5.rst @@ -0,0 +1,664 @@ +.. date: 2022-11-08-12-06-52 +.. gh-issue: 99108 +.. nonce: 4Wrsuh +.. release date: 2023-02-07 +.. section: Security + +Replace the builtin :mod:`hashlib` implementations of SHA2-224 and SHA2-256 +originally from LibTomCrypt with formally verified, side-channel resistant +code from the `HACL* `_ project. +The builtins remain a fallback only used when OpenSSL does not provide them. + +.. + +.. date: 2023-02-06-20-13-36 +.. gh-issue: 92173 +.. nonce: RQE0mk +.. section: Core and Builtins + +Fix the ``defs`` and ``kwdefs`` arguments to :c:func:`PyEval_EvalCodeEx` and +a reference leak in that function. + +.. + +.. date: 2023-01-30-11-56-09 +.. gh-issue: 59956 +.. nonce: 7xqnC_ +.. section: Core and Builtins + +The GILState API is now partially compatible with subinterpreters. +Previously, ``PyThreadState_GET()`` and ``PyGILState_GetThisThreadState()`` +would get out of sync, causing inconsistent behavior and crashes. + +.. + +.. date: 2023-01-30-08-59-47 +.. gh-issue: 101400 +.. nonce: Di_ZFm +.. section: Core and Builtins + +Fix wrong lineno in exception message on :keyword:`continue` or +:keyword:`break` which are not in a loop. Patch by Dong-hee Na. + +.. + +.. date: 2023-01-28-20-31-42 +.. gh-issue: 101372 +.. nonce: 8BcpCC +.. section: Core and Builtins + +Fix :func:`~unicodedata.is_normalized` to properly handle the UCD 3.2.0 +cases. Patch by Dong-hee Na. + +.. + +.. date: 2023-01-28-13-11-52 +.. gh-issue: 101266 +.. nonce: AxV3OF +.. section: Core and Builtins + +Fix :func:`sys.getsizeof` reporting for :class:`int` subclasses. + +.. + +.. date: 2023-01-24-17-13-32 +.. gh-issue: 101291 +.. nonce: Yr6u_c +.. section: Core and Builtins + +Refactor the ``PyLongObject`` struct into a normal Python object header and +a ``PyLongValue`` struct. + +.. + +.. date: 2023-01-15-03-26-04 +.. gh-issue: 101046 +.. nonce: g2CM4S +.. section: Core and Builtins + +Fix a possible memory leak in the parser when raising :exc:`MemoryError`. +Patch by Pablo Galindo + +.. + +.. date: 2023-01-14-17-03-08 +.. gh-issue: 101037 +.. nonce: 9ATNuf +.. section: Core and Builtins + +Fix potential memory underallocation issue for instances of :class:`int` +subclasses with value zero. + +.. + +.. date: 2023-01-13-12-56-20 +.. gh-issue: 100762 +.. nonce: YvHaQJ +.. section: Core and Builtins + +Record the (virtual) exception block depth in the oparg of +:opcode:`YIELD_VALUE`. Use this to avoid the expensive ``throw()`` when +closing generators (and coroutines) that can be closed trivially. + +.. + +.. date: 2023-01-12-13-46-49 +.. gh-issue: 100982 +.. nonce: mJ234s +.. section: Core and Builtins + +Adds a new :opcode:`COMPARE_AND_BRANCH` instruction. This is a bit more +efficient when performing a comparison immediately followed by a branch, and +restores the design intent of PEP 659 that specializations are local to a +single instruction. + +.. + +.. date: 2023-01-11-22-52-19 +.. gh-issue: 100942 +.. nonce: ontOy_ +.. section: Core and Builtins + +Fixed segfault in property.getter/setter/deleter that occurred when a +property subclass overrode the ``__new__`` method to return a non-property +instance. + +.. + +.. date: 2023-01-10-16-59-33 +.. gh-issue: 100923 +.. nonce: ypJAX- +.. section: Core and Builtins + +Remove the ``mask`` cache entry for the :opcode:`COMPARE_OP` instruction and +embed the mask into the oparg. + +.. + +.. date: 2023-01-10-14-11-17 +.. gh-issue: 100892 +.. nonce: qfBVYI +.. section: Core and Builtins + +Fix race while iterating over thread states in clearing +:class:`threading.local`. Patch by Kumar Aditya. + +.. + +.. date: 2023-01-06-09-22-21 +.. gh-issue: 91351 +.. nonce: iq2vZ_ +.. section: Core and Builtins + +Fix a case where re-entrant imports could corrupt the import deadlock +detection code and cause a :exc:`KeyError` to be raised out of +:mod:`importlib/_bootstrap`. In addition to the straightforward cases, this +could also happen when garbage collection leads to a warning being emitted +-- as happens when it collects an open socket or file) + +.. + +.. date: 2023-01-03-20-59-20 +.. gh-issue: 100726 +.. nonce: W9huFl +.. section: Core and Builtins + +Optimize construction of ``range`` object for medium size integers. + +.. + +.. date: 2023-01-03-14-33-23 +.. gh-issue: 100712 +.. nonce: po6xyB +.. section: Core and Builtins + +Added option to build cpython with specialization disabled, by setting +``ENABLE_SPECIALIZATION=False`` in :mod:`opcode`, followed by ``make +regen-all``. + +.. + +.. bpo: 32780 +.. date: 2018-02-05-21-54-46 +.. nonce: Dtiz8z +.. section: Core and Builtins + +Inter-field padding is now inserted into the PEP3118 format strings obtained +from :class:`ctypes.Structure` objects, reflecting their true representation +in memory. + +.. + +.. date: 2023-02-05-14-39-49 +.. gh-issue: 101541 +.. nonce: Mo3ppp +.. section: Library + +[Enum] - fix psuedo-flag creation + +.. + +.. date: 2023-02-04-21-01-49 +.. gh-issue: 101570 +.. nonce: lbtUsD +.. section: Library + +Upgrade pip wheel bundled with ensurepip (pip 23.0) + +.. + +.. date: 2023-01-26-06-44-35 +.. gh-issue: 101323 +.. nonce: h8Hk11 +.. section: Library + +Fix a bug where errors where not thrown by zlib._ZlibDecompressor if +encountered during decompressing. + +.. + +.. date: 2023-01-26-01-25-56 +.. gh-issue: 101317 +.. nonce: vWaS1x +.. section: Library + +Add *ssl_shutdown_timeout* parameter for +:meth:`asyncio.StreamWriter.start_tls`. + +.. + +.. date: 2023-01-25-18-07-20 +.. gh-issue: 101326 +.. nonce: KL4SFv +.. section: Library + +Fix regression when passing ``None`` as second or third argument to +``FutureIter.throw``. + +.. + +.. date: 2023-01-24-12-53-59 +.. gh-issue: 92123 +.. nonce: jf6TO5 +.. section: Library + +Adapt the ``_elementtree`` extension module to multi-phase init +(:pep:`489`). Patches by Erlend E. Aasland. + +.. + +.. date: 2023-01-21-16-50-22 +.. gh-issue: 100795 +.. nonce: NPMZf7 +.. section: Library + +Avoid potential unexpected ``freeaddrinfo`` call (double free) in +:mod:`socket` when when a libc ``getaddrinfo()`` implementation leaves +garbage in an output pointer when returning an error. Original patch by +Sergey G. Brester. + +.. + +.. date: 2023-01-20-10-46-59 +.. gh-issue: 101143 +.. nonce: hJo8hu +.. section: Library + +Remove unused references to :class:`~asyncio.TimerHandle` in +``asyncio.base_events.BaseEventLoop._add_callback``. + +.. + +.. date: 2023-01-18-17-58-50 +.. gh-issue: 101144 +.. nonce: FHd8Un +.. section: Library + +Make :func:`zipfile.Path.open` and :func:`zipfile.Path.read_text` also +accept ``encoding`` as a positional argument. This was the behavior in +Python 3.9 and earlier. 3.10 introduced a regression where supplying it as +a positional argument would lead to a :exc:`TypeError`. + +.. + +.. date: 2023-01-15-09-11-30 +.. gh-issue: 94518 +.. nonce: jvxtxm +.. section: Library + +Group-related variables of ``_posixsubprocess`` module are renamed to stress +that supplimentary group affinity is added to a fork, not replace the +inherited ones. Patch by Oleg Iarygin. + +.. + +.. date: 2023-01-14-12-58-21 +.. gh-issue: 101015 +.. nonce: stWFid +.. section: Library + +Fix :func:`typing.get_type_hints` on ``'*tuple[...]'`` and ``*tuple[...]``. +It must not drop the ``Unpack`` part. + +.. + +.. date: 2023-01-12-21-22-20 +.. gh-issue: 101000 +.. nonce: wz4Xgc +.. section: Library + +Add :func:`os.path.splitroot()`, which splits a path into a 3-item tuple +``(drive, root, tail)``. This new function is used by :mod:`pathlib` to +improve the performance of path construction by up to a third. + +.. + +.. date: 2023-01-12-01-18-13 +.. gh-issue: 100573 +.. nonce: KDskqo +.. section: Library + +Fix a Windows :mod:`asyncio` bug with named pipes where a client doing +``os.stat()`` on the pipe would cause an error in the server that disabled +serving future requests. + +.. + +.. date: 2023-01-08-00-12-44 +.. gh-issue: 39615 +.. nonce: gn4PhB +.. section: Library + +:func:`warnings.warn` now has the ability to skip stack frames based on code +filename prefix rather than only a numeric ``stacklevel`` via the new +``skip_file_prefixes`` keyword argument. + +.. + +.. date: 2023-01-04-14-42-59 +.. gh-issue: 100750 +.. nonce: iFJs5Y +.. section: Library + +pass encoding kwarg to subprocess in platform + +.. + +.. date: 2022-12-21-17-49-50 +.. gh-issue: 100160 +.. nonce: N0NHRj +.. section: Library + +Emit a deprecation warning in +:meth:`asyncio.DefaultEventLoopPolicy.get_event_loop` if there is no current +event loop set and it decides to create one. + +.. + +.. date: 2022-12-19-23-19-26 +.. gh-issue: 96290 +.. nonce: qFjsi6 +.. section: Library + +Fix handling of partial and invalid UNC drives in ``ntpath.splitdrive()``, +and in ``ntpath.normpath()`` on non-Windows systems. Paths such as +'\\server' and '\\' are now considered by ``splitdrive()`` to contain only a +drive, and consequently are not modified by ``normpath()`` on non-Windows +systems. The behaviour of ``normpath()`` on Windows systems is unaffected, +as native OS APIs are used. Patch by Eryk Sun, with contributions by Barney +Gale. + +.. + +.. date: 2022-12-11-14-38-59 +.. gh-issue: 99952 +.. nonce: IYGLzr +.. section: Library + +Fix a reference undercounting issue in :class:`ctypes.Structure` with +``from_param()`` results larger than a C pointer. + +.. + +.. date: 2022-12-10-15-30-17 +.. gh-issue: 67790 +.. nonce: P9YUZM +.. section: Library + +Add float-style formatting support for :class:`fractions.Fraction` +instances. + +.. + +.. date: 2022-11-24-21-52-31 +.. gh-issue: 99266 +.. nonce: 88GcV9 +.. section: Library + +Preserve more detailed error messages in :mod:`ctypes`. + +.. + +.. date: 2022-11-15-23-30-39 +.. gh-issue: 86682 +.. nonce: gK9i1N +.. section: Library + +Ensure runtime-created collections have the correct module name using the +newly added (internal) :func:`sys._getframemodulename`. + +.. + +.. date: 2022-11-14-03-06-03 +.. gh-issue: 88597 +.. nonce: EYJA-Q +.. section: Library + +:mod:`uuid` now has a command line interface. Try ``python -m uuid -h``. + +.. + +.. date: 2022-09-26-21-18-47 +.. gh-issue: 60580 +.. nonce: 0hBgde +.. section: Library + +:data:`ctypes.wintypes.BYTE` definition changed from :data:`~ctypes.c_byte` +to :data:`~ctypes.c_ubyte` to match Windows SDK. Patch by Anatoly Techtonik +and Oleg Iarygin. + +.. + +.. date: 2022-07-22-13-38-37 +.. gh-issue: 94518 +.. nonce: _ZP0cz +.. section: Library + +``_posixsubprocess`` now initializes all UID and GID variables using a +reserved ``-1`` value instead of a separate flag. Patch by Oleg Iarygin. + +.. + +.. bpo: 38941 +.. date: 2022-02-05-12-01-58 +.. nonce: 8IhvyG +.. section: Library + +The :mod:`xml.etree.ElementTree` module now emits :exc:`DeprecationWarning` +when testing the truth value of an :class:`xml.etree.ElementTree.Element`. +Before, the Python implementation emitted :exc:`FutureWarning`, and the C +implementation emitted nothing. + +.. + +.. bpo: 40077 +.. date: 2020-11-20-21-06-08 +.. nonce: M-iZq3 +.. section: Library + +Convert :mod:`elementtree` types to heap types. Patch by Erlend E. Aasland. + +.. + +.. bpo: 29847 +.. date: 2020-04-18-17-45-03 +.. nonce: Uxtbq0 +.. section: Library + +Fix a bug where :class:`pathlib.Path` accepted and ignored keyword +arguments. Patch provided by Yurii Karabas. + +.. + +.. date: 2018-05-21-17-18-00 +.. gh-issue: 77772 +.. nonce: Fhg84L +.. section: Library + +:class:`ctypes.CDLL`, :class:`ctypes.OleDLL`, :class:`ctypes.WinDLL`, and +:class:`ctypes.PyDLL` now accept :term:`path-like objects ` as their ``name`` argument. Patch by Robert Hoelzl. + +.. + +.. date: 2022-06-19-22-04-47 +.. gh-issue: 88324 +.. nonce: GHhSQ1 +.. section: Documentation + +Reword :mod:`subprocess` to emphasize default behavior of *stdin*, *stdout*, +and *stderr* arguments. Remove inaccurate statement about child file handle +inheritance. + +.. + +.. date: 2023-02-04-17-24-33 +.. gh-issue: 101334 +.. nonce: _yOqwg +.. section: Tests + +``test_tarfile`` has been updated to pass when run as a high UID. + +.. + +.. date: 2023-02-04-06-59-07 +.. gh-issue: 101282 +.. nonce: 7sQz5l +.. section: Build + +Update BOLT configration not to use depreacted usage of ``--split +functions``. Patch by Dong-hee Na. + +.. + +.. date: 2023-02-02-23-43-46 +.. gh-issue: 101522 +.. nonce: lnUDta +.. section: Build + +Allow overriding Windows dependencies versions and paths using MSBuild +properties. + +.. + +.. date: 2023-01-26-19-02-11 +.. gh-issue: 77532 +.. nonce: cXD8bg +.. section: Build + +Minor fixes to allow building with ``PlatformToolset=ClangCL`` on Windows. + +.. + +.. date: 2023-01-21-10-31-35 +.. gh-issue: 101152 +.. nonce: xvM8pL +.. section: Build + +In accordance with :PEP:`699`, the ``ma_version_tag`` field in +:c:type:`PyDictObject` is deprecated for extension modules. Accessing this +field will generate a compiler warning at compile time. This field will be +removed in Python 3.14. + +.. + +.. date: 2023-01-17-21-32-51 +.. gh-issue: 100340 +.. nonce: i9zRGM +.. section: Build + +Allows -Wno-int-conversion for wasm-sdk 17 and onwards, thus enables +building WASI builds once against the latest sdk. + +.. + +.. date: 2023-01-15-11-22-15 +.. gh-issue: 101060 +.. nonce: 0mYk9E +.. section: Build + +Conditionally add ``-fno-reorder-blocks-and-partition`` in configure. +Effectively fixes ``--enable-bolt`` when using Clang, as this appears to be +a GCC-only flag. + +.. + +.. date: 2022-10-27-09-57-12 +.. gh-issue: 98705 +.. nonce: H11XmR +.. section: Build + +``__bool__`` is defined in AIX system header files which breaks the build in +AIX, so undefine it. + +.. + +.. date: 2022-10-25-11-53-55 +.. gh-issue: 98636 +.. nonce: e0RPAr +.. section: Build + +Fix a regression in detecting ``gdbm_compat`` library for the ``_gdbm`` +module build. + +.. + +.. date: 2022-08-30-10-16-31 +.. gh-issue: 96305 +.. nonce: 274i8B +.. section: Build + +``_aix_support`` now uses a simple code to get platform details rather than +the now non-existent ``_bootsubprocess`` during bootstrap. + +.. + +.. date: 2023-02-03-17-53-06 +.. gh-issue: 101543 +.. nonce: cORAT4 +.. section: Windows + +Ensure the install path in the registry is only used when the standard +library hasn't been located in any other way. + +.. + +.. date: 2023-01-31-16-50-07 +.. gh-issue: 101467 +.. nonce: ye9t-L +.. section: Windows + +The ``py.exe`` launcher now correctly filters when only a single runtime is +installed. It also correctly handles prefix matches on tags so that ``-3.1`` +does not match ``3.11``, but would still match ``3.1-32``. + +.. + +.. date: 2023-01-25-00-23-31 +.. gh-issue: 99834 +.. nonce: WN41lc +.. section: Windows + +Updates bundled copy of Tcl/Tk to 8.6.13.0 + +.. + +.. date: 2023-01-18-18-25-18 +.. gh-issue: 101135 +.. nonce: HF9VlG +.. section: Windows + +Restore ability to launch older 32-bit versions from the :file:`py.exe` +launcher when both 32-bit and 64-bit installs of the same version are +available. + +.. + +.. date: 2023-01-17-18-17-58 +.. gh-issue: 82052 +.. nonce: mWyysT +.. section: Windows + +Fixed an issue where writing more than 32K of Unicode output to the console +screen in one go can result in mojibake. + +.. + +.. date: 2023-01-11-16-28-09 +.. gh-issue: 100320 +.. nonce: 2DU2it +.. section: Windows + +Ensures the ``PythonPath`` registry key from an install is used when +launching from a different copy of Python that relies on an existing install +to provide a copy of its modules and standard library. + +.. + +.. date: 2023-01-11-14-42-11 +.. gh-issue: 100247 +.. nonce: YfEmSz +.. section: Windows + +Restores support for the :file:`py.exe` launcher finding shebang commands in +its configuration file using the full command name. diff --git a/Misc/NEWS.d/next/Build/2022-08-30-10-16-31.gh-issue-96305.274i8B.rst b/Misc/NEWS.d/next/Build/2022-08-30-10-16-31.gh-issue-96305.274i8B.rst deleted file mode 100644 index 64a48da658f21f7..000000000000000 --- a/Misc/NEWS.d/next/Build/2022-08-30-10-16-31.gh-issue-96305.274i8B.rst +++ /dev/null @@ -1,2 +0,0 @@ -``_aix_support`` now uses a simple code to get platform details rather than -the now non-existent ``_bootsubprocess`` during bootstrap. diff --git a/Misc/NEWS.d/next/Build/2022-10-25-11-53-55.gh-issue-98636.e0RPAr.rst b/Misc/NEWS.d/next/Build/2022-10-25-11-53-55.gh-issue-98636.e0RPAr.rst deleted file mode 100644 index 26a7cc8acaf2434..000000000000000 --- a/Misc/NEWS.d/next/Build/2022-10-25-11-53-55.gh-issue-98636.e0RPAr.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix a regression in detecting ``gdbm_compat`` library for the ``_gdbm`` -module build. diff --git a/Misc/NEWS.d/next/Build/2022-10-27-09-57-12.gh-issue-98705.H11XmR.rst b/Misc/NEWS.d/next/Build/2022-10-27-09-57-12.gh-issue-98705.H11XmR.rst deleted file mode 100644 index 4519853cdbadd1d..000000000000000 --- a/Misc/NEWS.d/next/Build/2022-10-27-09-57-12.gh-issue-98705.H11XmR.rst +++ /dev/null @@ -1,2 +0,0 @@ -``__bool__`` is defined in AIX system header files which breaks the build in -AIX, so undefine it. diff --git a/Misc/NEWS.d/next/Build/2023-01-15-11-22-15.gh-issue-101060.0mYk9E.rst b/Misc/NEWS.d/next/Build/2023-01-15-11-22-15.gh-issue-101060.0mYk9E.rst deleted file mode 100644 index bebbf8c898d547b..000000000000000 --- a/Misc/NEWS.d/next/Build/2023-01-15-11-22-15.gh-issue-101060.0mYk9E.rst +++ /dev/null @@ -1,3 +0,0 @@ -Conditionally add ``-fno-reorder-blocks-and-partition`` in configure. -Effectively fixes ``--enable-bolt`` when using Clang, as this appears to be -a GCC-only flag. diff --git a/Misc/NEWS.d/next/Build/2023-01-17-21-32-51.gh-issue-100340.i9zRGM.rst b/Misc/NEWS.d/next/Build/2023-01-17-21-32-51.gh-issue-100340.i9zRGM.rst deleted file mode 100644 index 3a37f798dc6c6d1..000000000000000 --- a/Misc/NEWS.d/next/Build/2023-01-17-21-32-51.gh-issue-100340.i9zRGM.rst +++ /dev/null @@ -1,2 +0,0 @@ -Allows -Wno-int-conversion for wasm-sdk 17 and onwards, thus enables -building WASI builds once against the latest sdk. diff --git a/Misc/NEWS.d/next/Build/2023-01-21-10-31-35.gh-issue-101152.xvM8pL.rst b/Misc/NEWS.d/next/Build/2023-01-21-10-31-35.gh-issue-101152.xvM8pL.rst deleted file mode 100644 index e35b6178aa4cf9a..000000000000000 --- a/Misc/NEWS.d/next/Build/2023-01-21-10-31-35.gh-issue-101152.xvM8pL.rst +++ /dev/null @@ -1,3 +0,0 @@ -In accordance with :PEP:`699`, the ``ma_version_tag`` field in :c:type:`PyDictObject` -is deprecated for extension modules. Accessing this field will generate a compiler -warning at compile time. This field will be removed in Python 3.14. diff --git a/Misc/NEWS.d/next/Build/2023-01-26-19-02-11.gh-issue-77532.cXD8bg.rst b/Misc/NEWS.d/next/Build/2023-01-26-19-02-11.gh-issue-77532.cXD8bg.rst deleted file mode 100644 index 5a746dca2e7d8d1..000000000000000 --- a/Misc/NEWS.d/next/Build/2023-01-26-19-02-11.gh-issue-77532.cXD8bg.rst +++ /dev/null @@ -1 +0,0 @@ -Minor fixes to allow building with ``PlatformToolset=ClangCL`` on Windows. diff --git a/Misc/NEWS.d/next/Build/2023-02-02-23-43-46.gh-issue-101522.lnUDta.rst b/Misc/NEWS.d/next/Build/2023-02-02-23-43-46.gh-issue-101522.lnUDta.rst deleted file mode 100644 index 2e7f9029e9ee546..000000000000000 --- a/Misc/NEWS.d/next/Build/2023-02-02-23-43-46.gh-issue-101522.lnUDta.rst +++ /dev/null @@ -1,2 +0,0 @@ -Allow overriding Windows dependencies versions and paths using MSBuild -properties. diff --git a/Misc/NEWS.d/next/Build/2023-02-04-06-59-07.gh-issue-101282.7sQz5l.rst b/Misc/NEWS.d/next/Build/2023-02-04-06-59-07.gh-issue-101282.7sQz5l.rst deleted file mode 100644 index 49d485646673493..000000000000000 --- a/Misc/NEWS.d/next/Build/2023-02-04-06-59-07.gh-issue-101282.7sQz5l.rst +++ /dev/null @@ -1,2 +0,0 @@ -Update BOLT configration not to use depreacted usage of ``--split -functions``. Patch by Dong-hee Na. diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-02-05-21-54-46.bpo-32780.Dtiz8z.rst b/Misc/NEWS.d/next/Core and Builtins/2018-02-05-21-54-46.bpo-32780.Dtiz8z.rst deleted file mode 100644 index 8996d471159a649..000000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2018-02-05-21-54-46.bpo-32780.Dtiz8z.rst +++ /dev/null @@ -1,3 +0,0 @@ -Inter-field padding is now inserted into the PEP3118 format strings obtained -from :class:`ctypes.Structure` objects, reflecting their true representation in -memory. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-01-03-14-33-23.gh-issue-100712.po6xyB.rst b/Misc/NEWS.d/next/Core and Builtins/2023-01-03-14-33-23.gh-issue-100712.po6xyB.rst deleted file mode 100644 index 3ebee0dd2aa48ff..000000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-01-03-14-33-23.gh-issue-100712.po6xyB.rst +++ /dev/null @@ -1 +0,0 @@ -Added option to build cpython with specialization disabled, by setting ``ENABLE_SPECIALIZATION=False`` in :mod:`opcode`, followed by ``make regen-all``. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-01-03-20-59-20.gh-issue-100726.W9huFl.rst b/Misc/NEWS.d/next/Core and Builtins/2023-01-03-20-59-20.gh-issue-100726.W9huFl.rst deleted file mode 100644 index 2c93098b347a7f5..000000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-01-03-20-59-20.gh-issue-100726.W9huFl.rst +++ /dev/null @@ -1 +0,0 @@ -Optimize construction of ``range`` object for medium size integers. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-01-06-09-22-21.gh-issue-91351.iq2vZ_.rst b/Misc/NEWS.d/next/Core and Builtins/2023-01-06-09-22-21.gh-issue-91351.iq2vZ_.rst deleted file mode 100644 index 19de1f8d0fb31eb..000000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-01-06-09-22-21.gh-issue-91351.iq2vZ_.rst +++ /dev/null @@ -1,5 +0,0 @@ -Fix a case where re-entrant imports could corrupt the import deadlock -detection code and cause a :exc:`KeyError` to be raised out of -:mod:`importlib/_bootstrap`. In addition to the straightforward cases, this -could also happen when garbage collection leads to a warning being emitted -- -as happens when it collects an open socket or file) diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-01-10-14-11-17.gh-issue-100892.qfBVYI.rst b/Misc/NEWS.d/next/Core and Builtins/2023-01-10-14-11-17.gh-issue-100892.qfBVYI.rst deleted file mode 100644 index f2576becc2fcfc5..000000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-01-10-14-11-17.gh-issue-100892.qfBVYI.rst +++ /dev/null @@ -1 +0,0 @@ -Fix race while iterating over thread states in clearing :class:`threading.local`. Patch by Kumar Aditya. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-01-10-16-59-33.gh-issue-100923.ypJAX-.rst b/Misc/NEWS.d/next/Core and Builtins/2023-01-10-16-59-33.gh-issue-100923.ypJAX-.rst deleted file mode 100644 index b6b3f1d0c58f8e0..000000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-01-10-16-59-33.gh-issue-100923.ypJAX-.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove the ``mask`` cache entry for the :opcode:`COMPARE_OP` instruction and -embed the mask into the oparg. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-01-11-22-52-19.gh-issue-100942.ontOy_.rst b/Misc/NEWS.d/next/Core and Builtins/2023-01-11-22-52-19.gh-issue-100942.ontOy_.rst deleted file mode 100644 index daccea255b16269..000000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-01-11-22-52-19.gh-issue-100942.ontOy_.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed segfault in property.getter/setter/deleter that occurred when a property -subclass overrode the ``__new__`` method to return a non-property instance. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-01-12-13-46-49.gh-issue-100982.mJ234s.rst b/Misc/NEWS.d/next/Core and Builtins/2023-01-12-13-46-49.gh-issue-100982.mJ234s.rst deleted file mode 100644 index 4f43e783cd6a193..000000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-01-12-13-46-49.gh-issue-100982.mJ234s.rst +++ /dev/null @@ -1,4 +0,0 @@ -Adds a new :opcode:`COMPARE_AND_BRANCH` instruction. This is a bit more -efficient when performing a comparison immediately followed by a branch, and -restores the design intent of PEP 659 that specializations are local to a -single instruction. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-01-13-12-56-20.gh-issue-100762.YvHaQJ.rst b/Misc/NEWS.d/next/Core and Builtins/2023-01-13-12-56-20.gh-issue-100762.YvHaQJ.rst deleted file mode 100644 index 2f6b121439a9857..000000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-01-13-12-56-20.gh-issue-100762.YvHaQJ.rst +++ /dev/null @@ -1,3 +0,0 @@ -Record the (virtual) exception block depth in the oparg of -:opcode:`YIELD_VALUE`. Use this to avoid the expensive ``throw()`` when -closing generators (and coroutines) that can be closed trivially. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-01-14-17-03-08.gh-issue-101037.9ATNuf.rst b/Misc/NEWS.d/next/Core and Builtins/2023-01-14-17-03-08.gh-issue-101037.9ATNuf.rst deleted file mode 100644 index a48756657a29d30..000000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-01-14-17-03-08.gh-issue-101037.9ATNuf.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix potential memory underallocation issue for instances of :class:`int` -subclasses with value zero. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-01-15-03-26-04.gh-issue-101046.g2CM4S.rst b/Misc/NEWS.d/next/Core and Builtins/2023-01-15-03-26-04.gh-issue-101046.g2CM4S.rst deleted file mode 100644 index f600473620f1098..000000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-01-15-03-26-04.gh-issue-101046.g2CM4S.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix a possible memory leak in the parser when raising :exc:`MemoryError`. -Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-01-24-17-13-32.gh-issue-101291.Yr6u_c.rst b/Misc/NEWS.d/next/Core and Builtins/2023-01-24-17-13-32.gh-issue-101291.Yr6u_c.rst deleted file mode 100644 index b585ff5a817edff..000000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-01-24-17-13-32.gh-issue-101291.Yr6u_c.rst +++ /dev/null @@ -1,2 +0,0 @@ -Refactor the ``PyLongObject`` struct into a normal Python object header and -a ``PyLongValue`` struct. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-01-28-13-11-52.gh-issue-101266.AxV3OF.rst b/Misc/NEWS.d/next/Core and Builtins/2023-01-28-13-11-52.gh-issue-101266.AxV3OF.rst deleted file mode 100644 index 51999bacb8de079..000000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-01-28-13-11-52.gh-issue-101266.AxV3OF.rst +++ /dev/null @@ -1 +0,0 @@ -Fix :func:`sys.getsizeof` reporting for :class:`int` subclasses. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-01-28-20-31-42.gh-issue-101372.8BcpCC.rst b/Misc/NEWS.d/next/Core and Builtins/2023-01-28-20-31-42.gh-issue-101372.8BcpCC.rst deleted file mode 100644 index 65a207e3f7e436d..000000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-01-28-20-31-42.gh-issue-101372.8BcpCC.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix :func:`~unicodedata.is_normalized` to properly handle the UCD 3.2.0 -cases. Patch by Dong-hee Na. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-01-30-08-59-47.gh-issue-101400.Di_ZFm.rst b/Misc/NEWS.d/next/Core and Builtins/2023-01-30-08-59-47.gh-issue-101400.Di_ZFm.rst deleted file mode 100644 index f3dd783c01e7c0d..000000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-01-30-08-59-47.gh-issue-101400.Di_ZFm.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix wrong lineno in exception message on :keyword:`continue` or -:keyword:`break` which are not in a loop. Patch by Dong-hee Na. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-01-30-11-56-09.gh-issue-59956.7xqnC_.rst b/Misc/NEWS.d/next/Core and Builtins/2023-01-30-11-56-09.gh-issue-59956.7xqnC_.rst deleted file mode 100644 index b3c1896b9493e1b..000000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-01-30-11-56-09.gh-issue-59956.7xqnC_.rst +++ /dev/null @@ -1,3 +0,0 @@ -The GILState API is now partially compatible with subinterpreters. -Previously, ``PyThreadState_GET()`` and ``PyGILState_GetThisThreadState()`` -would get out of sync, causing inconsistent behavior and crashes. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-02-06-20-13-36.gh-issue-92173.RQE0mk.rst b/Misc/NEWS.d/next/Core and Builtins/2023-02-06-20-13-36.gh-issue-92173.RQE0mk.rst deleted file mode 100644 index 6b98aac2a465459..000000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-02-06-20-13-36.gh-issue-92173.RQE0mk.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix the ``defs`` and ``kwdefs`` arguments to :c:func:`PyEval_EvalCodeEx` -and a reference leak in that function. diff --git a/Misc/NEWS.d/next/Documentation/2022-06-19-22-04-47.gh-issue-88324.GHhSQ1.rst b/Misc/NEWS.d/next/Documentation/2022-06-19-22-04-47.gh-issue-88324.GHhSQ1.rst deleted file mode 100644 index 6c8d192daa79555..000000000000000 --- a/Misc/NEWS.d/next/Documentation/2022-06-19-22-04-47.gh-issue-88324.GHhSQ1.rst +++ /dev/null @@ -1,3 +0,0 @@ -Reword :mod:`subprocess` to emphasize default behavior of *stdin*, *stdout*, -and *stderr* arguments. Remove inaccurate statement about child file handle -inheritance. diff --git a/Misc/NEWS.d/next/Library/2018-05-21-17-18-00.gh-issue-77772.Fhg84L.rst b/Misc/NEWS.d/next/Library/2018-05-21-17-18-00.gh-issue-77772.Fhg84L.rst deleted file mode 100644 index 3a7c6d45297ba4f..000000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-21-17-18-00.gh-issue-77772.Fhg84L.rst +++ /dev/null @@ -1,3 +0,0 @@ -:class:`ctypes.CDLL`, :class:`ctypes.OleDLL`, :class:`ctypes.WinDLL`, -and :class:`ctypes.PyDLL` now accept :term:`path-like objects -` as their ``name`` argument. Patch by Robert Hoelzl. diff --git a/Misc/NEWS.d/next/Library/2020-04-18-17-45-03.bpo-29847.Uxtbq0.rst b/Misc/NEWS.d/next/Library/2020-04-18-17-45-03.bpo-29847.Uxtbq0.rst deleted file mode 100644 index 010d775a0d98ee7..000000000000000 --- a/Misc/NEWS.d/next/Library/2020-04-18-17-45-03.bpo-29847.Uxtbq0.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a bug where :class:`pathlib.Path` accepted and ignored keyword arguments. Patch provided by Yurii Karabas. diff --git a/Misc/NEWS.d/next/Library/2020-11-20-21-06-08.bpo-40077.M-iZq3.rst b/Misc/NEWS.d/next/Library/2020-11-20-21-06-08.bpo-40077.M-iZq3.rst deleted file mode 100644 index 8a74477a4b359dc..000000000000000 --- a/Misc/NEWS.d/next/Library/2020-11-20-21-06-08.bpo-40077.M-iZq3.rst +++ /dev/null @@ -1 +0,0 @@ -Convert :mod:`elementtree` types to heap types. Patch by Erlend E. Aasland. diff --git a/Misc/NEWS.d/next/Library/2022-02-05-12-01-58.bpo-38941.8IhvyG.rst b/Misc/NEWS.d/next/Library/2022-02-05-12-01-58.bpo-38941.8IhvyG.rst deleted file mode 100644 index 5f996042260d098..000000000000000 --- a/Misc/NEWS.d/next/Library/2022-02-05-12-01-58.bpo-38941.8IhvyG.rst +++ /dev/null @@ -1,4 +0,0 @@ -The :mod:`xml.etree.ElementTree` module now emits :exc:`DeprecationWarning` -when testing the truth value of an :class:`xml.etree.ElementTree.Element`. -Before, the Python implementation emitted :exc:`FutureWarning`, and the C -implementation emitted nothing. diff --git a/Misc/NEWS.d/next/Library/2022-07-22-13-38-37.gh-issue-94518._ZP0cz.rst b/Misc/NEWS.d/next/Library/2022-07-22-13-38-37.gh-issue-94518._ZP0cz.rst deleted file mode 100644 index a9d6d69f7effac3..000000000000000 --- a/Misc/NEWS.d/next/Library/2022-07-22-13-38-37.gh-issue-94518._ZP0cz.rst +++ /dev/null @@ -1,2 +0,0 @@ -``_posixsubprocess`` now initializes all UID and GID variables using a -reserved ``-1`` value instead of a separate flag. Patch by Oleg Iarygin. diff --git a/Misc/NEWS.d/next/Library/2022-09-26-21-18-47.gh-issue-60580.0hBgde.rst b/Misc/NEWS.d/next/Library/2022-09-26-21-18-47.gh-issue-60580.0hBgde.rst deleted file mode 100644 index 630e56cd2f7b875..000000000000000 --- a/Misc/NEWS.d/next/Library/2022-09-26-21-18-47.gh-issue-60580.0hBgde.rst +++ /dev/null @@ -1,3 +0,0 @@ -:data:`ctypes.wintypes.BYTE` definition changed from -:data:`~ctypes.c_byte` to :data:`~ctypes.c_ubyte` to match Windows -SDK. Patch by Anatoly Techtonik and Oleg Iarygin. diff --git a/Misc/NEWS.d/next/Library/2022-11-14-03-06-03.gh-issue-88597.EYJA-Q.rst b/Misc/NEWS.d/next/Library/2022-11-14-03-06-03.gh-issue-88597.EYJA-Q.rst deleted file mode 100644 index a98e1ab4d15734f..000000000000000 --- a/Misc/NEWS.d/next/Library/2022-11-14-03-06-03.gh-issue-88597.EYJA-Q.rst +++ /dev/null @@ -1 +0,0 @@ -:mod:`uuid` now has a command line interface. Try ``python -m uuid -h``. diff --git a/Misc/NEWS.d/next/Library/2022-11-15-23-30-39.gh-issue-86682.gK9i1N.rst b/Misc/NEWS.d/next/Library/2022-11-15-23-30-39.gh-issue-86682.gK9i1N.rst deleted file mode 100644 index 64ef42a9a1c0b25..000000000000000 --- a/Misc/NEWS.d/next/Library/2022-11-15-23-30-39.gh-issue-86682.gK9i1N.rst +++ /dev/null @@ -1,2 +0,0 @@ -Ensure runtime-created collections have the correct module name using -the newly added (internal) :func:`sys._getframemodulename`. diff --git a/Misc/NEWS.d/next/Library/2022-11-24-21-52-31.gh-issue-99266.88GcV9.rst b/Misc/NEWS.d/next/Library/2022-11-24-21-52-31.gh-issue-99266.88GcV9.rst deleted file mode 100644 index 97e9569e40a9bf7..000000000000000 --- a/Misc/NEWS.d/next/Library/2022-11-24-21-52-31.gh-issue-99266.88GcV9.rst +++ /dev/null @@ -1 +0,0 @@ -Preserve more detailed error messages in :mod:`ctypes`. diff --git a/Misc/NEWS.d/next/Library/2022-12-10-15-30-17.gh-issue-67790.P9YUZM.rst b/Misc/NEWS.d/next/Library/2022-12-10-15-30-17.gh-issue-67790.P9YUZM.rst deleted file mode 100644 index ba0db774f8b318e..000000000000000 --- a/Misc/NEWS.d/next/Library/2022-12-10-15-30-17.gh-issue-67790.P9YUZM.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add float-style formatting support for :class:`fractions.Fraction` -instances. diff --git a/Misc/NEWS.d/next/Library/2022-12-11-14-38-59.gh-issue-99952.IYGLzr.rst b/Misc/NEWS.d/next/Library/2022-12-11-14-38-59.gh-issue-99952.IYGLzr.rst deleted file mode 100644 index 09ec961249534fd..000000000000000 --- a/Misc/NEWS.d/next/Library/2022-12-11-14-38-59.gh-issue-99952.IYGLzr.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix a reference undercounting issue in :class:`ctypes.Structure` with ``from_param()`` -results larger than a C pointer. diff --git a/Misc/NEWS.d/next/Library/2022-12-19-23-19-26.gh-issue-96290.qFjsi6.rst b/Misc/NEWS.d/next/Library/2022-12-19-23-19-26.gh-issue-96290.qFjsi6.rst deleted file mode 100644 index 33f98602bd1b718..000000000000000 --- a/Misc/NEWS.d/next/Library/2022-12-19-23-19-26.gh-issue-96290.qFjsi6.rst +++ /dev/null @@ -1,5 +0,0 @@ -Fix handling of partial and invalid UNC drives in ``ntpath.splitdrive()``, and in -``ntpath.normpath()`` on non-Windows systems. Paths such as '\\server' and '\\' are now considered -by ``splitdrive()`` to contain only a drive, and consequently are not modified by ``normpath()`` on -non-Windows systems. The behaviour of ``normpath()`` on Windows systems is unaffected, as native -OS APIs are used. Patch by Eryk Sun, with contributions by Barney Gale. diff --git a/Misc/NEWS.d/next/Library/2022-12-21-17-49-50.gh-issue-100160.N0NHRj.rst b/Misc/NEWS.d/next/Library/2022-12-21-17-49-50.gh-issue-100160.N0NHRj.rst deleted file mode 100644 index d5cc785722d7fd1..000000000000000 --- a/Misc/NEWS.d/next/Library/2022-12-21-17-49-50.gh-issue-100160.N0NHRj.rst +++ /dev/null @@ -1,3 +0,0 @@ -Emit a deprecation warning in -:meth:`asyncio.DefaultEventLoopPolicy.get_event_loop` if there is no current -event loop set and it decides to create one. diff --git a/Misc/NEWS.d/next/Library/2023-01-04-14-42-59.gh-issue-100750.iFJs5Y.rst b/Misc/NEWS.d/next/Library/2023-01-04-14-42-59.gh-issue-100750.iFJs5Y.rst deleted file mode 100644 index be351532822c4b1..000000000000000 --- a/Misc/NEWS.d/next/Library/2023-01-04-14-42-59.gh-issue-100750.iFJs5Y.rst +++ /dev/null @@ -1 +0,0 @@ -pass encoding kwarg to subprocess in platform diff --git a/Misc/NEWS.d/next/Library/2023-01-08-00-12-44.gh-issue-39615.gn4PhB.rst b/Misc/NEWS.d/next/Library/2023-01-08-00-12-44.gh-issue-39615.gn4PhB.rst deleted file mode 100644 index 1d04cc2cd54b1ed..000000000000000 --- a/Misc/NEWS.d/next/Library/2023-01-08-00-12-44.gh-issue-39615.gn4PhB.rst +++ /dev/null @@ -1,3 +0,0 @@ -:func:`warnings.warn` now has the ability to skip stack frames based on code -filename prefix rather than only a numeric ``stacklevel`` via the new -``skip_file_prefixes`` keyword argument. diff --git a/Misc/NEWS.d/next/Library/2023-01-12-01-18-13.gh-issue-100573.KDskqo.rst b/Misc/NEWS.d/next/Library/2023-01-12-01-18-13.gh-issue-100573.KDskqo.rst deleted file mode 100644 index 97b95d18d1e4261..000000000000000 --- a/Misc/NEWS.d/next/Library/2023-01-12-01-18-13.gh-issue-100573.KDskqo.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a Windows :mod:`asyncio` bug with named pipes where a client doing ``os.stat()`` on the pipe would cause an error in the server that disabled serving future requests. diff --git a/Misc/NEWS.d/next/Library/2023-01-12-21-22-20.gh-issue-101000.wz4Xgc.rst b/Misc/NEWS.d/next/Library/2023-01-12-21-22-20.gh-issue-101000.wz4Xgc.rst deleted file mode 100644 index 2082361c41d6979..000000000000000 --- a/Misc/NEWS.d/next/Library/2023-01-12-21-22-20.gh-issue-101000.wz4Xgc.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add :func:`os.path.splitroot()`, which splits a path into a 3-item tuple -``(drive, root, tail)``. This new function is used by :mod:`pathlib` to -improve the performance of path construction by up to a third. diff --git a/Misc/NEWS.d/next/Library/2023-01-14-12-58-21.gh-issue-101015.stWFid.rst b/Misc/NEWS.d/next/Library/2023-01-14-12-58-21.gh-issue-101015.stWFid.rst deleted file mode 100644 index b9d73ff9855236c..000000000000000 --- a/Misc/NEWS.d/next/Library/2023-01-14-12-58-21.gh-issue-101015.stWFid.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix :func:`typing.get_type_hints` on ``'*tuple[...]'`` and ``*tuple[...]``. -It must not drop the ``Unpack`` part. diff --git a/Misc/NEWS.d/next/Library/2023-01-15-09-11-30.gh-issue-94518.jvxtxm.rst b/Misc/NEWS.d/next/Library/2023-01-15-09-11-30.gh-issue-94518.jvxtxm.rst deleted file mode 100644 index 77563090464dbc8..000000000000000 --- a/Misc/NEWS.d/next/Library/2023-01-15-09-11-30.gh-issue-94518.jvxtxm.rst +++ /dev/null @@ -1,3 +0,0 @@ -Group-related variables of ``_posixsubprocess`` module are renamed to -stress that supplimentary group affinity is added to a fork, not -replace the inherited ones. Patch by Oleg Iarygin. diff --git a/Misc/NEWS.d/next/Library/2023-01-18-17-58-50.gh-issue-101144.FHd8Un.rst b/Misc/NEWS.d/next/Library/2023-01-18-17-58-50.gh-issue-101144.FHd8Un.rst deleted file mode 100644 index 297652259949fc4..000000000000000 --- a/Misc/NEWS.d/next/Library/2023-01-18-17-58-50.gh-issue-101144.FHd8Un.rst +++ /dev/null @@ -1,4 +0,0 @@ -Make :func:`zipfile.Path.open` and :func:`zipfile.Path.read_text` also accept -``encoding`` as a positional argument. This was the behavior in Python 3.9 and -earlier. 3.10 introduced a regression where supplying it as a positional -argument would lead to a :exc:`TypeError`. diff --git a/Misc/NEWS.d/next/Library/2023-01-20-10-46-59.gh-issue-101143.hJo8hu.rst b/Misc/NEWS.d/next/Library/2023-01-20-10-46-59.gh-issue-101143.hJo8hu.rst deleted file mode 100644 index d14b9e25a691fc5..000000000000000 --- a/Misc/NEWS.d/next/Library/2023-01-20-10-46-59.gh-issue-101143.hJo8hu.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove unused references to :class:`~asyncio.TimerHandle` in -``asyncio.base_events.BaseEventLoop._add_callback``. diff --git a/Misc/NEWS.d/next/Library/2023-01-21-16-50-22.gh-issue-100795.NPMZf7.rst b/Misc/NEWS.d/next/Library/2023-01-21-16-50-22.gh-issue-100795.NPMZf7.rst deleted file mode 100644 index 4cb56ea0f0e58d5..000000000000000 --- a/Misc/NEWS.d/next/Library/2023-01-21-16-50-22.gh-issue-100795.NPMZf7.rst +++ /dev/null @@ -1,3 +0,0 @@ -Avoid potential unexpected ``freeaddrinfo`` call (double free) in :mod:`socket` -when when a libc ``getaddrinfo()`` implementation leaves garbage in an output -pointer when returning an error. Original patch by Sergey G. Brester. diff --git a/Misc/NEWS.d/next/Library/2023-01-24-12-53-59.gh-issue-92123.jf6TO5.rst b/Misc/NEWS.d/next/Library/2023-01-24-12-53-59.gh-issue-92123.jf6TO5.rst deleted file mode 100644 index 4b4443a55fdb1ab..000000000000000 --- a/Misc/NEWS.d/next/Library/2023-01-24-12-53-59.gh-issue-92123.jf6TO5.rst +++ /dev/null @@ -1,2 +0,0 @@ -Adapt the ``_elementtree`` extension module to multi-phase init (:pep:`489`). -Patches by Erlend E. Aasland. diff --git a/Misc/NEWS.d/next/Library/2023-01-25-18-07-20.gh-issue-101326.KL4SFv.rst b/Misc/NEWS.d/next/Library/2023-01-25-18-07-20.gh-issue-101326.KL4SFv.rst deleted file mode 100644 index 54b69b9430910de..000000000000000 --- a/Misc/NEWS.d/next/Library/2023-01-25-18-07-20.gh-issue-101326.KL4SFv.rst +++ /dev/null @@ -1 +0,0 @@ -Fix regression when passing ``None`` as second or third argument to ``FutureIter.throw``. diff --git a/Misc/NEWS.d/next/Library/2023-01-26-01-25-56.gh-issue-101317.vWaS1x.rst b/Misc/NEWS.d/next/Library/2023-01-26-01-25-56.gh-issue-101317.vWaS1x.rst deleted file mode 100644 index f1ce0e0a5276611..000000000000000 --- a/Misc/NEWS.d/next/Library/2023-01-26-01-25-56.gh-issue-101317.vWaS1x.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add *ssl_shutdown_timeout* parameter for :meth:`asyncio.StreamWriter.start_tls`. - diff --git a/Misc/NEWS.d/next/Library/2023-01-26-06-44-35.gh-issue-101323.h8Hk11.rst b/Misc/NEWS.d/next/Library/2023-01-26-06-44-35.gh-issue-101323.h8Hk11.rst deleted file mode 100644 index f8419e130dbcd7c..000000000000000 --- a/Misc/NEWS.d/next/Library/2023-01-26-06-44-35.gh-issue-101323.h8Hk11.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix a bug where errors where not thrown by zlib._ZlibDecompressor if -encountered during decompressing. diff --git a/Misc/NEWS.d/next/Library/2023-02-04-21-01-49.gh-issue-101570.lbtUsD.rst b/Misc/NEWS.d/next/Library/2023-02-04-21-01-49.gh-issue-101570.lbtUsD.rst deleted file mode 100644 index 599edab6c07117d..000000000000000 --- a/Misc/NEWS.d/next/Library/2023-02-04-21-01-49.gh-issue-101570.lbtUsD.rst +++ /dev/null @@ -1 +0,0 @@ -Upgrade pip wheel bundled with ensurepip (pip 23.0) diff --git a/Misc/NEWS.d/next/Library/2023-02-05-14-39-49.gh-issue-101541.Mo3ppp.rst b/Misc/NEWS.d/next/Library/2023-02-05-14-39-49.gh-issue-101541.Mo3ppp.rst deleted file mode 100644 index 0f149e80dc54a2a..000000000000000 --- a/Misc/NEWS.d/next/Library/2023-02-05-14-39-49.gh-issue-101541.Mo3ppp.rst +++ /dev/null @@ -1 +0,0 @@ -[Enum] - fix psuedo-flag creation diff --git a/Misc/NEWS.d/next/Security/2022-11-08-12-06-52.gh-issue-99108.4Wrsuh.rst b/Misc/NEWS.d/next/Security/2022-11-08-12-06-52.gh-issue-99108.4Wrsuh.rst deleted file mode 100644 index 64acc09c482ecbd..000000000000000 --- a/Misc/NEWS.d/next/Security/2022-11-08-12-06-52.gh-issue-99108.4Wrsuh.rst +++ /dev/null @@ -1,4 +0,0 @@ -Replace the builtin :mod:`hashlib` implementations of SHA2-224 and SHA2-256 -originally from LibTomCrypt with formally verified, side-channel resistant -code from the `HACL* `_ project. The -builtins remain a fallback only used when OpenSSL does not provide them. diff --git a/Misc/NEWS.d/next/Tests/2023-02-04-17-24-33.gh-issue-101334._yOqwg.rst b/Misc/NEWS.d/next/Tests/2023-02-04-17-24-33.gh-issue-101334._yOqwg.rst deleted file mode 100644 index 2a95fd9ae53c868..000000000000000 --- a/Misc/NEWS.d/next/Tests/2023-02-04-17-24-33.gh-issue-101334._yOqwg.rst +++ /dev/null @@ -1 +0,0 @@ -``test_tarfile`` has been updated to pass when run as a high UID. diff --git a/Misc/NEWS.d/next/Windows/2023-01-11-14-42-11.gh-issue-100247.YfEmSz.rst b/Misc/NEWS.d/next/Windows/2023-01-11-14-42-11.gh-issue-100247.YfEmSz.rst deleted file mode 100644 index 7bfcbd7ddecf5f9..000000000000000 --- a/Misc/NEWS.d/next/Windows/2023-01-11-14-42-11.gh-issue-100247.YfEmSz.rst +++ /dev/null @@ -1,2 +0,0 @@ -Restores support for the :file:`py.exe` launcher finding shebang commands in -its configuration file using the full command name. diff --git a/Misc/NEWS.d/next/Windows/2023-01-11-16-28-09.gh-issue-100320.2DU2it.rst b/Misc/NEWS.d/next/Windows/2023-01-11-16-28-09.gh-issue-100320.2DU2it.rst deleted file mode 100644 index c206fc8520a5d93..000000000000000 --- a/Misc/NEWS.d/next/Windows/2023-01-11-16-28-09.gh-issue-100320.2DU2it.rst +++ /dev/null @@ -1,3 +0,0 @@ -Ensures the ``PythonPath`` registry key from an install is used when -launching from a different copy of Python that relies on an existing install -to provide a copy of its modules and standard library. diff --git a/Misc/NEWS.d/next/Windows/2023-01-17-18-17-58.gh-issue-82052.mWyysT.rst b/Misc/NEWS.d/next/Windows/2023-01-17-18-17-58.gh-issue-82052.mWyysT.rst deleted file mode 100644 index 4f7ab200b85cba1..000000000000000 --- a/Misc/NEWS.d/next/Windows/2023-01-17-18-17-58.gh-issue-82052.mWyysT.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed an issue where writing more than 32K of Unicode output to the console screen in one go can result in mojibake. diff --git a/Misc/NEWS.d/next/Windows/2023-01-18-18-25-18.gh-issue-101135.HF9VlG.rst b/Misc/NEWS.d/next/Windows/2023-01-18-18-25-18.gh-issue-101135.HF9VlG.rst deleted file mode 100644 index 2e6d6371340d89e..000000000000000 --- a/Misc/NEWS.d/next/Windows/2023-01-18-18-25-18.gh-issue-101135.HF9VlG.rst +++ /dev/null @@ -1,3 +0,0 @@ -Restore ability to launch older 32-bit versions from the :file:`py.exe` -launcher when both 32-bit and 64-bit installs of the same version are -available. diff --git a/Misc/NEWS.d/next/Windows/2023-01-25-00-23-31.gh-issue-99834.WN41lc.rst b/Misc/NEWS.d/next/Windows/2023-01-25-00-23-31.gh-issue-99834.WN41lc.rst deleted file mode 100644 index d3894fa4ea3012f..000000000000000 --- a/Misc/NEWS.d/next/Windows/2023-01-25-00-23-31.gh-issue-99834.WN41lc.rst +++ /dev/null @@ -1 +0,0 @@ -Updates bundled copy of Tcl/Tk to 8.6.13.0 diff --git a/Misc/NEWS.d/next/Windows/2023-01-31-16-50-07.gh-issue-101467.ye9t-L.rst b/Misc/NEWS.d/next/Windows/2023-01-31-16-50-07.gh-issue-101467.ye9t-L.rst deleted file mode 100644 index 4d4da05afa2d161..000000000000000 --- a/Misc/NEWS.d/next/Windows/2023-01-31-16-50-07.gh-issue-101467.ye9t-L.rst +++ /dev/null @@ -1,3 +0,0 @@ -The ``py.exe`` launcher now correctly filters when only a single runtime is -installed. It also correctly handles prefix matches on tags so that ``-3.1`` -does not match ``3.11``, but would still match ``3.1-32``. diff --git a/Misc/NEWS.d/next/Windows/2023-02-03-17-53-06.gh-issue-101543.cORAT4.rst b/Misc/NEWS.d/next/Windows/2023-02-03-17-53-06.gh-issue-101543.cORAT4.rst deleted file mode 100644 index d4e2c6f23013b6d..000000000000000 --- a/Misc/NEWS.d/next/Windows/2023-02-03-17-53-06.gh-issue-101543.cORAT4.rst +++ /dev/null @@ -1,2 +0,0 @@ -Ensure the install path in the registry is only used when the standard -library hasn't been located in any other way. diff --git a/README.rst b/README.rst index 814efef83a357a9..b1756e20c141ab0 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -This is Python version 3.12.0 alpha 4 +This is Python version 3.12.0 alpha 5 ===================================== .. image:: https://github.com/python/cpython/workflows/Tests/badge.svg From a757d721271974c45e2feacef739af4e86ec7350 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Tue, 7 Feb 2023 15:59:26 +0200 Subject: [PATCH 65/74] Doctest: Pin sphinxext-opengraph==0.7.5 to prevent importing NumPy (#101642) --- Doc/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/requirements.txt b/Doc/requirements.txt index 134f39d6d7b3d4a..71d3cd61e53877e 100644 --- a/Doc/requirements.txt +++ b/Doc/requirements.txt @@ -8,7 +8,7 @@ sphinx==4.5.0 blurb sphinx-lint==0.6.7 -sphinxext-opengraph>=0.7.1 +sphinxext-opengraph==0.7.5 # The theme used by the documentation is stored separately, so we need # to install that as well. From a687ae9eb5c0aea06c52de1e426904b79f767f4e Mon Sep 17 00:00:00 2001 From: Oleg Iarygin Date: Tue, 7 Feb 2023 18:54:47 +0400 Subject: [PATCH 66/74] Fix nesting of 'Pending Removal in Python 3.14' (#101637) --- Doc/whatsnew/3.12.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index 0c5a70b64574efc..b723b70154f08d0 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -479,7 +479,7 @@ APIs: * :class:`webbrowser.MacOSX` (:gh:`86421`) Pending Removal in Python 3.14 -============================== +------------------------------ * Deprecated the following :mod:`importlib.abc` classes, scheduled for removal in Python 3.14: From d54b8d8fbd76c05e9006175ab26d737c4b055dfb Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Tue, 7 Feb 2023 08:28:28 -0800 Subject: [PATCH 67/74] gh-98831: Modernize the FOR_ITER family of instructions (#101626) Co-authored-by: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> --- Python/bytecodes.c | 83 +++++++++++++++++++++----------------- Python/generated_cases.c.h | 66 +++++++++++++++++++----------- Python/opcode_metadata.h | 30 +++++++------- 3 files changed, 104 insertions(+), 75 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 0fc0b3b8280f8ba..ec0439af98e6326 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -2066,27 +2066,35 @@ dummy_func( PREDICT(LOAD_CONST); } - // stack effect: ( -- __0) - inst(FOR_ITER) { + // Most members of this family are "secretly" super-instructions. + // When the loop is exhausted, they jump, and the jump target is + // always END_FOR, which pops two values off the stack. + // This is optimized by skipping that instruction and combining + // its effect (popping 'iter' instead of pushing 'next'.) + + family(for_iter, INLINE_CACHE_ENTRIES_FOR_ITER) = { + FOR_ITER, + FOR_ITER_LIST, + FOR_ITER_TUPLE, + FOR_ITER_RANGE, + FOR_ITER_GEN, + }; + + inst(FOR_ITER, (unused/1, iter -- iter, next)) { #if ENABLE_SPECIALIZATION _PyForIterCache *cache = (_PyForIterCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { assert(cframe.use_tracing == 0); next_instr--; - _Py_Specialize_ForIter(TOP(), next_instr, oparg); + _Py_Specialize_ForIter(iter, next_instr, oparg); DISPATCH_SAME_OPARG(); } STAT_INC(FOR_ITER, deferred); DECREMENT_ADAPTIVE_COUNTER(cache->counter); #endif /* ENABLE_SPECIALIZATION */ - /* before: [iter]; after: [iter, iter()] *or* [] */ - PyObject *iter = TOP(); - PyObject *next = (*Py_TYPE(iter)->tp_iternext)(iter); - if (next != NULL) { - PUSH(next); - JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER); - } - else { + /* before: [iter]; after: [iter, iter()] *or* [] (and jump over END_FOR.) */ + next = (*Py_TYPE(iter)->tp_iternext)(iter); + if (next == NULL) { if (_PyErr_Occurred(tstate)) { if (!_PyErr_ExceptionMatches(tstate, PyExc_StopIteration)) { goto error; @@ -2098,63 +2106,66 @@ dummy_func( } /* iterator ended normally */ assert(_Py_OPCODE(next_instr[INLINE_CACHE_ENTRIES_FOR_ITER + oparg]) == END_FOR); - STACK_SHRINK(1); Py_DECREF(iter); - /* Skip END_FOR */ + STACK_SHRINK(1); + /* Jump forward oparg, then skip following END_FOR instruction */ JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1); + DISPATCH(); } + // Common case: no jump, leave it to the code generator } - // stack effect: ( -- __0) - inst(FOR_ITER_LIST) { + inst(FOR_ITER_LIST, (unused/1, iter -- iter, next)) { assert(cframe.use_tracing == 0); - _PyListIterObject *it = (_PyListIterObject *)TOP(); - DEOPT_IF(Py_TYPE(it) != &PyListIter_Type, FOR_ITER); + DEOPT_IF(Py_TYPE(iter) != &PyListIter_Type, FOR_ITER); + _PyListIterObject *it = (_PyListIterObject *)iter; STAT_INC(FOR_ITER, hit); PyListObject *seq = it->it_seq; if (seq) { if (it->it_index < PyList_GET_SIZE(seq)) { - PyObject *next = PyList_GET_ITEM(seq, it->it_index++); - PUSH(Py_NewRef(next)); - JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER); + next = Py_NewRef(PyList_GET_ITEM(seq, it->it_index++)); goto end_for_iter_list; // End of this instruction } it->it_seq = NULL; Py_DECREF(seq); } + Py_DECREF(iter); STACK_SHRINK(1); - Py_DECREF(it); + /* Jump forward oparg, then skip following END_FOR instruction */ JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1); + DISPATCH(); end_for_iter_list: + // Common case: no jump, leave it to the code generator } - // stack effect: ( -- __0) - inst(FOR_ITER_TUPLE) { + inst(FOR_ITER_TUPLE, (unused/1, iter -- iter, next)) { assert(cframe.use_tracing == 0); - _PyTupleIterObject *it = (_PyTupleIterObject *)TOP(); + _PyTupleIterObject *it = (_PyTupleIterObject *)iter; DEOPT_IF(Py_TYPE(it) != &PyTupleIter_Type, FOR_ITER); STAT_INC(FOR_ITER, hit); PyTupleObject *seq = it->it_seq; if (seq) { if (it->it_index < PyTuple_GET_SIZE(seq)) { - PyObject *next = PyTuple_GET_ITEM(seq, it->it_index++); - PUSH(Py_NewRef(next)); - JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER); + next = Py_NewRef(PyTuple_GET_ITEM(seq, it->it_index++)); goto end_for_iter_tuple; // End of this instruction } it->it_seq = NULL; Py_DECREF(seq); } + Py_DECREF(iter); STACK_SHRINK(1); - Py_DECREF(it); + /* Jump forward oparg, then skip following END_FOR instruction */ JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1); + DISPATCH(); end_for_iter_tuple: + // Common case: no jump, leave it to the code generator } - // stack effect: ( -- __0) - inst(FOR_ITER_RANGE) { + // This is slightly different, when the loop isn't terminated we + // jump over the immediately following STORE_FAST instruction. + inst(FOR_ITER_RANGE, (unused/1, iter -- iter, unused)) { assert(cframe.use_tracing == 0); - _PyRangeIterObject *r = (_PyRangeIterObject *)TOP(); + _PyRangeIterObject *r = (_PyRangeIterObject *)iter; DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type, FOR_ITER); STAT_INC(FOR_ITER, hit); _Py_CODEUNIT next = next_instr[INLINE_CACHE_ENTRIES_FOR_ITER]; @@ -2162,6 +2173,7 @@ dummy_func( if (r->len <= 0) { STACK_SHRINK(1); Py_DECREF(r); + // Jump over END_FOR instruction. JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1); } else { @@ -2174,11 +2186,13 @@ dummy_func( // The STORE_FAST is already done. JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + 1); } + DISPATCH(); } - inst(FOR_ITER_GEN) { + // This is *not* a super-instruction, unique in the family. + inst(FOR_ITER_GEN, (unused/1, iter -- iter, unused)) { assert(cframe.use_tracing == 0); - PyGenObject *gen = (PyGenObject *)TOP(); + PyGenObject *gen = (PyGenObject *)iter; DEOPT_IF(Py_TYPE(gen) != &PyGen_Type, FOR_ITER); DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING, FOR_ITER); STAT_INC(FOR_ITER, hit); @@ -3168,9 +3182,6 @@ family(call, INLINE_CACHE_ENTRIES_CALL) = { CALL_NO_KW_LIST_APPEND, CALL_NO_KW_METHOD_DESCRIPTOR_FAST, CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS, CALL_NO_KW_METHOD_DESCRIPTOR_O, CALL_NO_KW_STR_1, CALL_NO_KW_TUPLE_1, CALL_NO_KW_TYPE_1 }; -family(for_iter, INLINE_CACHE_ENTRIES_FOR_ITER) = { - FOR_ITER, FOR_ITER_LIST, - FOR_ITER_RANGE }; family(store_fast) = { STORE_FAST, STORE_FAST__LOAD_FAST, STORE_FAST__STORE_FAST }; family(unpack_sequence, INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE) = { UNPACK_SEQUENCE, UNPACK_SEQUENCE_LIST, diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index f0f314a143c2c0f..4e511f43d950286 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -2619,25 +2619,23 @@ TARGET(FOR_ITER) { PREDICTED(FOR_ITER); + static_assert(INLINE_CACHE_ENTRIES_FOR_ITER == 1, "incorrect cache size"); + PyObject *iter = PEEK(1); + PyObject *next; #if ENABLE_SPECIALIZATION _PyForIterCache *cache = (_PyForIterCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { assert(cframe.use_tracing == 0); next_instr--; - _Py_Specialize_ForIter(TOP(), next_instr, oparg); + _Py_Specialize_ForIter(iter, next_instr, oparg); DISPATCH_SAME_OPARG(); } STAT_INC(FOR_ITER, deferred); DECREMENT_ADAPTIVE_COUNTER(cache->counter); #endif /* ENABLE_SPECIALIZATION */ - /* before: [iter]; after: [iter, iter()] *or* [] */ - PyObject *iter = TOP(); - PyObject *next = (*Py_TYPE(iter)->tp_iternext)(iter); - if (next != NULL) { - PUSH(next); - JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER); - } - else { + /* before: [iter]; after: [iter, iter()] *or* [] (and jump over END_FOR.) */ + next = (*Py_TYPE(iter)->tp_iternext)(iter); + if (next == NULL) { if (_PyErr_Occurred(tstate)) { if (!_PyErr_ExceptionMatches(tstate, PyExc_StopIteration)) { goto error; @@ -2649,63 +2647,81 @@ } /* iterator ended normally */ assert(_Py_OPCODE(next_instr[INLINE_CACHE_ENTRIES_FOR_ITER + oparg]) == END_FOR); - STACK_SHRINK(1); Py_DECREF(iter); - /* Skip END_FOR */ + STACK_SHRINK(1); + /* Jump forward oparg, then skip following END_FOR instruction */ JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1); + DISPATCH(); } + // Common case: no jump, leave it to the code generator + STACK_GROW(1); + POKE(1, next); + JUMPBY(1); DISPATCH(); } TARGET(FOR_ITER_LIST) { + PyObject *iter = PEEK(1); + PyObject *next; assert(cframe.use_tracing == 0); - _PyListIterObject *it = (_PyListIterObject *)TOP(); - DEOPT_IF(Py_TYPE(it) != &PyListIter_Type, FOR_ITER); + DEOPT_IF(Py_TYPE(iter) != &PyListIter_Type, FOR_ITER); + _PyListIterObject *it = (_PyListIterObject *)iter; STAT_INC(FOR_ITER, hit); PyListObject *seq = it->it_seq; if (seq) { if (it->it_index < PyList_GET_SIZE(seq)) { - PyObject *next = PyList_GET_ITEM(seq, it->it_index++); - PUSH(Py_NewRef(next)); - JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER); + next = Py_NewRef(PyList_GET_ITEM(seq, it->it_index++)); goto end_for_iter_list; // End of this instruction } it->it_seq = NULL; Py_DECREF(seq); } + Py_DECREF(iter); STACK_SHRINK(1); - Py_DECREF(it); + /* Jump forward oparg, then skip following END_FOR instruction */ JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1); + DISPATCH(); end_for_iter_list: + // Common case: no jump, leave it to the code generator + STACK_GROW(1); + POKE(1, next); + JUMPBY(1); DISPATCH(); } TARGET(FOR_ITER_TUPLE) { + PyObject *iter = PEEK(1); + PyObject *next; assert(cframe.use_tracing == 0); - _PyTupleIterObject *it = (_PyTupleIterObject *)TOP(); + _PyTupleIterObject *it = (_PyTupleIterObject *)iter; DEOPT_IF(Py_TYPE(it) != &PyTupleIter_Type, FOR_ITER); STAT_INC(FOR_ITER, hit); PyTupleObject *seq = it->it_seq; if (seq) { if (it->it_index < PyTuple_GET_SIZE(seq)) { - PyObject *next = PyTuple_GET_ITEM(seq, it->it_index++); - PUSH(Py_NewRef(next)); - JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER); + next = Py_NewRef(PyTuple_GET_ITEM(seq, it->it_index++)); goto end_for_iter_tuple; // End of this instruction } it->it_seq = NULL; Py_DECREF(seq); } + Py_DECREF(iter); STACK_SHRINK(1); - Py_DECREF(it); + /* Jump forward oparg, then skip following END_FOR instruction */ JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1); + DISPATCH(); end_for_iter_tuple: + // Common case: no jump, leave it to the code generator + STACK_GROW(1); + POKE(1, next); + JUMPBY(1); DISPATCH(); } TARGET(FOR_ITER_RANGE) { + PyObject *iter = PEEK(1); assert(cframe.use_tracing == 0); - _PyRangeIterObject *r = (_PyRangeIterObject *)TOP(); + _PyRangeIterObject *r = (_PyRangeIterObject *)iter; DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type, FOR_ITER); STAT_INC(FOR_ITER, hit); _Py_CODEUNIT next = next_instr[INLINE_CACHE_ENTRIES_FOR_ITER]; @@ -2713,6 +2729,7 @@ if (r->len <= 0) { STACK_SHRINK(1); Py_DECREF(r); + // Jump over END_FOR instruction. JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1); } else { @@ -2729,8 +2746,9 @@ } TARGET(FOR_ITER_GEN) { + PyObject *iter = PEEK(1); assert(cframe.use_tracing == 0); - PyGenObject *gen = (PyGenObject *)TOP(); + PyGenObject *gen = (PyGenObject *)iter; DEOPT_IF(Py_TYPE(gen) != &PyGen_Type, FOR_ITER); DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING, FOR_ITER); STAT_INC(FOR_ITER, hit); diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index 948d17519e2709a..ed26ff00c7b1829 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -261,15 +261,15 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) { case GET_YIELD_FROM_ITER: return 1; case FOR_ITER: - return -1; + return 1; case FOR_ITER_LIST: - return -1; + return 1; case FOR_ITER_TUPLE: - return -1; + return 1; case FOR_ITER_RANGE: - return -1; + return 1; case FOR_ITER_GEN: - return -1; + return 1; case BEFORE_ASYNC_WITH: return 1; case BEFORE_WITH: @@ -607,15 +607,15 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { case GET_YIELD_FROM_ITER: return 1; case FOR_ITER: - return -1; + return 2; case FOR_ITER_LIST: - return -1; + return 2; case FOR_ITER_TUPLE: - return -1; + return 2; case FOR_ITER_RANGE: - return -1; + return 2; case FOR_ITER_GEN: - return -1; + return 2; case BEFORE_ASYNC_WITH: return 2; case BEFORE_WITH: @@ -829,11 +829,11 @@ struct opcode_metadata { [MATCH_KEYS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, [GET_ITER] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, [GET_YIELD_FROM_ITER] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, - [FOR_ITER] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, - [FOR_ITER_LIST] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, - [FOR_ITER_TUPLE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, - [FOR_ITER_RANGE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, - [FOR_ITER_GEN] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, + [FOR_ITER] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC }, + [FOR_ITER_LIST] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC }, + [FOR_ITER_TUPLE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC }, + [FOR_ITER_RANGE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC }, + [FOR_ITER_GEN] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC }, [BEFORE_ASYNC_WITH] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, [BEFORE_WITH] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, [WITH_EXCEPT_START] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, From 6fd5eb640af19b535f4f2ba27b1b61b8d17f02e9 Mon Sep 17 00:00:00 2001 From: Zachary Ware Date: Tue, 7 Feb 2023 11:22:58 -0600 Subject: [PATCH 68/74] Make use of TESTFN_ASCII in test_fileio (GH-101645) testBytesOpen requires an ASCII filename, but TESTFN usually isn't ASCII. Automerge-Triggered-By: GH:zware --- Lib/test/test_fileio.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py index 2263604ed1f97da..ebfcffd18291746 100644 --- a/Lib/test/test_fileio.py +++ b/Lib/test/test_fileio.py @@ -12,7 +12,9 @@ from test.support import ( cpython_only, swap_attr, gc_collect, is_emscripten, is_wasi ) -from test.support.os_helper import (TESTFN, TESTFN_UNICODE, make_bad_fd) +from test.support.os_helper import ( + TESTFN, TESTFN_ASCII, TESTFN_UNICODE, make_bad_fd, + ) from test.support.warnings_helper import check_warnings from collections import UserList @@ -431,18 +433,15 @@ def testUnicodeOpen(self): def testBytesOpen(self): # Opening a bytes filename - try: - fn = TESTFN.encode("ascii") - except UnicodeEncodeError: - self.skipTest('could not encode %r to ascii' % TESTFN) + fn = TESTFN_ASCII.encode("ascii") f = self.FileIO(fn, "w") try: f.write(b"abc") f.close() - with open(TESTFN, "rb") as f: + with open(TESTFN_ASCII, "rb") as f: self.assertEqual(f.read(), b"abc") finally: - os.unlink(TESTFN) + os.unlink(TESTFN_ASCII) @unittest.skipIf(sys.getfilesystemencoding() != 'utf-8', "test only works for utf-8 filesystems") From f87f6e23964d7a4c38b655089cda65538a24ec36 Mon Sep 17 00:00:00 2001 From: Oleg Iarygin Date: Tue, 7 Feb 2023 22:04:31 +0400 Subject: [PATCH 69/74] gh-97725: Fix documentation for the default file of `asyncio.Task.print_stack` (#101652) --- Doc/library/asyncio-task.rst | 2 +- .../Documentation/2023-02-07-21-43-24.gh-issue-97725.cuY7Cd.rst | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Documentation/2023-02-07-21-43-24.gh-issue-97725.cuY7Cd.rst diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 39112580285cc0c..9b9842432822683 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -1097,7 +1097,7 @@ Task Object The *limit* argument is passed to :meth:`get_stack` directly. The *file* argument is an I/O stream to which the output - is written; by default output is written to :data:`sys.stderr`. + is written; by default output is written to :data:`sys.stdout`. .. method:: get_coro() diff --git a/Misc/NEWS.d/next/Documentation/2023-02-07-21-43-24.gh-issue-97725.cuY7Cd.rst b/Misc/NEWS.d/next/Documentation/2023-02-07-21-43-24.gh-issue-97725.cuY7Cd.rst new file mode 100644 index 000000000000000..fd9ea049c239687 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2023-02-07-21-43-24.gh-issue-97725.cuY7Cd.rst @@ -0,0 +1,2 @@ +Fix :meth:`asyncio.Task.print_stack` description for ``file=None``. +Patch by Oleg Iarygin. From dec1ab03879e959f7efb910a723caf4a9ce453cf Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Tue, 7 Feb 2023 20:37:43 +0000 Subject: [PATCH 70/74] gh-98831: rewrite UNPACK_EX, UNPACK_SEQUENCE, UNPACK_SEQUENCE_TWO_TUPLE in the instruction definition DSL (#101641) --- Python/bytecodes.c | 37 ++++++++++------------------------ Python/generated_cases.c.h | 41 +++++++++++++++++++------------------- Python/opcode_metadata.h | 16 +++++++-------- 3 files changed, 40 insertions(+), 54 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index ec0439af98e6326..b43625fd283cc3d 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -859,13 +859,11 @@ dummy_func( } } - // stack effect: (__0 -- __array[oparg]) - inst(UNPACK_SEQUENCE) { + inst(UNPACK_SEQUENCE, (unused/1, seq -- unused[oparg])) { #if ENABLE_SPECIALIZATION _PyUnpackSequenceCache *cache = (_PyUnpackSequenceCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { assert(cframe.use_tracing == 0); - PyObject *seq = TOP(); next_instr--; _Py_Specialize_UnpackSequence(seq, next_instr, oparg); DISPATCH_SAME_OPARG(); @@ -873,27 +871,19 @@ dummy_func( STAT_INC(UNPACK_SEQUENCE, deferred); DECREMENT_ADAPTIVE_COUNTER(cache->counter); #endif /* ENABLE_SPECIALIZATION */ - PyObject *seq = POP(); - PyObject **top = stack_pointer + oparg; - if (!unpack_iterable(tstate, seq, oparg, -1, top)) { - Py_DECREF(seq); - goto error; - } - STACK_GROW(oparg); + PyObject **top = stack_pointer + oparg - 1; + int res = unpack_iterable(tstate, seq, oparg, -1, top); Py_DECREF(seq); - JUMPBY(INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE); + ERROR_IF(res == 0, error); } - // stack effect: (__0 -- __array[oparg]) - inst(UNPACK_SEQUENCE_TWO_TUPLE) { - PyObject *seq = TOP(); + inst(UNPACK_SEQUENCE_TWO_TUPLE, (unused/1, seq -- v1, v0)) { DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE); DEOPT_IF(PyTuple_GET_SIZE(seq) != 2, UNPACK_SEQUENCE); STAT_INC(UNPACK_SEQUENCE, hit); - SET_TOP(Py_NewRef(PyTuple_GET_ITEM(seq, 1))); - PUSH(Py_NewRef(PyTuple_GET_ITEM(seq, 0))); + v1 = Py_NewRef(PyTuple_GET_ITEM(seq, 1)); + v0 = Py_NewRef(PyTuple_GET_ITEM(seq, 0)); Py_DECREF(seq); - JUMPBY(INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE); } // stack effect: (__0 -- __array[oparg]) @@ -926,17 +916,12 @@ dummy_func( JUMPBY(INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE); } - // error: UNPACK_EX has irregular stack effect - inst(UNPACK_EX) { + inst(UNPACK_EX, (seq -- unused[oparg & 0xFF], unused, unused[oparg >> 8])) { int totalargs = 1 + (oparg & 0xFF) + (oparg >> 8); - PyObject *seq = POP(); - PyObject **top = stack_pointer + totalargs; - if (!unpack_iterable(tstate, seq, oparg & 0xFF, oparg >> 8, top)) { - Py_DECREF(seq); - goto error; - } - STACK_GROW(totalargs); + PyObject **top = stack_pointer + totalargs - 1; + int res = unpack_iterable(tstate, seq, oparg & 0xFF, oparg >> 8, top); Py_DECREF(seq); + ERROR_IF(res == 0, error); } family(store_attr, INLINE_CACHE_ENTRIES_STORE_ATTR) = { diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 4e511f43d950286..ab19f431710644b 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -1108,11 +1108,11 @@ TARGET(UNPACK_SEQUENCE) { PREDICTED(UNPACK_SEQUENCE); + PyObject *seq = PEEK(1); #if ENABLE_SPECIALIZATION _PyUnpackSequenceCache *cache = (_PyUnpackSequenceCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { assert(cframe.use_tracing == 0); - PyObject *seq = TOP(); next_instr--; _Py_Specialize_UnpackSequence(seq, next_instr, oparg); DISPATCH_SAME_OPARG(); @@ -1120,27 +1120,30 @@ STAT_INC(UNPACK_SEQUENCE, deferred); DECREMENT_ADAPTIVE_COUNTER(cache->counter); #endif /* ENABLE_SPECIALIZATION */ - PyObject *seq = POP(); - PyObject **top = stack_pointer + oparg; - if (!unpack_iterable(tstate, seq, oparg, -1, top)) { - Py_DECREF(seq); - goto error; - } - STACK_GROW(oparg); + PyObject **top = stack_pointer + oparg - 1; + int res = unpack_iterable(tstate, seq, oparg, -1, top); Py_DECREF(seq); - JUMPBY(INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE); + if (res == 0) goto pop_1_error; + STACK_SHRINK(1); + STACK_GROW(oparg); + JUMPBY(1); DISPATCH(); } TARGET(UNPACK_SEQUENCE_TWO_TUPLE) { - PyObject *seq = TOP(); + PyObject *seq = PEEK(1); + PyObject *v1; + PyObject *v0; DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE); DEOPT_IF(PyTuple_GET_SIZE(seq) != 2, UNPACK_SEQUENCE); STAT_INC(UNPACK_SEQUENCE, hit); - SET_TOP(Py_NewRef(PyTuple_GET_ITEM(seq, 1))); - PUSH(Py_NewRef(PyTuple_GET_ITEM(seq, 0))); + v1 = Py_NewRef(PyTuple_GET_ITEM(seq, 1)); + v0 = Py_NewRef(PyTuple_GET_ITEM(seq, 0)); Py_DECREF(seq); - JUMPBY(INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE); + STACK_GROW(1); + POKE(1, v0); + POKE(2, v1); + JUMPBY(1); DISPATCH(); } @@ -1175,15 +1178,13 @@ } TARGET(UNPACK_EX) { + PyObject *seq = PEEK(1); int totalargs = 1 + (oparg & 0xFF) + (oparg >> 8); - PyObject *seq = POP(); - PyObject **top = stack_pointer + totalargs; - if (!unpack_iterable(tstate, seq, oparg & 0xFF, oparg >> 8, top)) { - Py_DECREF(seq); - goto error; - } - STACK_GROW(totalargs); + PyObject **top = stack_pointer + totalargs - 1; + int res = unpack_iterable(tstate, seq, oparg & 0xFF, oparg >> 8, top); Py_DECREF(seq); + if (res == 0) goto pop_1_error; + STACK_GROW((oparg & 0xFF) + (oparg >> 8)); DISPATCH(); } diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index ed26ff00c7b1829..d2585351f69fd2f 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -121,15 +121,15 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) { case DELETE_NAME: return 0; case UNPACK_SEQUENCE: - return -1; + return 1; case UNPACK_SEQUENCE_TWO_TUPLE: - return -1; + return 1; case UNPACK_SEQUENCE_TUPLE: return -1; case UNPACK_SEQUENCE_LIST: return -1; case UNPACK_EX: - return -1; + return 1; case STORE_ATTR: return 2; case DELETE_ATTR: @@ -467,15 +467,15 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { case DELETE_NAME: return 0; case UNPACK_SEQUENCE: - return -1; + return oparg; case UNPACK_SEQUENCE_TWO_TUPLE: - return -1; + return 2; case UNPACK_SEQUENCE_TUPLE: return -1; case UNPACK_SEQUENCE_LIST: return -1; case UNPACK_EX: - return -1; + return (oparg & 0xFF) + (oparg >> 8) + 1; case STORE_ATTR: return 0; case DELETE_ATTR: @@ -759,8 +759,8 @@ struct opcode_metadata { [LOAD_BUILD_CLASS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, [STORE_NAME] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [DELETE_NAME] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, - [UNPACK_SEQUENCE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, - [UNPACK_SEQUENCE_TWO_TUPLE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, + [UNPACK_SEQUENCE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC }, + [UNPACK_SEQUENCE_TWO_TUPLE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC }, [UNPACK_SEQUENCE_TUPLE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [UNPACK_SEQUENCE_LIST] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [UNPACK_EX] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, From acc2f3b19d28d4bf3f8fb32357f581cba5ba24c7 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Wed, 8 Feb 2023 00:43:33 +0300 Subject: [PATCH 71/74] gh-101656: Fix "conversion from Py_ssize_t to int" warning in `_testcapimodule` (#101657) --- Modules/_testcapimodule.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 5a6097ef0ac5a68..8b2ce1a2cfd4bd8 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -3185,11 +3185,11 @@ eval_eval_code_ex(PyObject *mod, PyObject *pos_args) globals, locals, c_args, - c_args_len, + (int)c_args_len, c_kwargs, - c_kwargs_len, + (int)c_kwargs_len, c_defaults, - c_defaults_len, + (int)c_defaults_len, kw_defaults, closure ); From 46f461be56ab90891d2d43240d80a0e19d100ba9 Mon Sep 17 00:00:00 2001 From: Thomas Wouters Date: Tue, 7 Feb 2023 23:13:10 +0100 Subject: [PATCH 72/74] Post 3.12.0a5 --- Include/patchlevel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h index df6098be8bbcc95..7957220ed7cf9f0 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -23,7 +23,7 @@ #define PY_RELEASE_SERIAL 5 /* Version as a string */ -#define PY_VERSION "3.12.0a5" +#define PY_VERSION "3.12.0a5+" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. From 753fc8a5d64369cd228c3e43fef1811ac3cfde83 Mon Sep 17 00:00:00 2001 From: penguin_wwy <940375606@qq.com> Date: Wed, 8 Feb 2023 06:32:21 +0800 Subject: [PATCH 73/74] gh-101632: Add the new RETURN_CONST opcode (#101633) --- Doc/library/dis.rst | 7 + Include/internal/pycore_opcode.h | 10 +- Include/opcode.h | 16 +- Lib/dis.py | 3 +- Lib/importlib/_bootstrap_external.py | 3 +- Lib/opcode.py | 2 + Lib/test/test_ast.py | 2 +- Lib/test/test_code.py | 1 + Lib/test/test_compile.py | 18 +- Lib/test/test_dis.py | 155 ++++++++---------- Lib/test/test_peepholer.py | 6 +- ...-02-07-14-56-43.gh-issue-101632.Fd1yxk.rst | 1 + Objects/frameobject.c | 2 + Programs/test_frozenmain.h | 50 +++--- Python/bytecodes.c | 17 ++ Python/compile.c | 17 +- Python/generated_cases.c.h | 17 ++ Python/opcode_metadata.h | 5 + Python/opcode_targets.h | 8 +- 19 files changed, 186 insertions(+), 154 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-02-07-14-56-43.gh-issue-101632.Fd1yxk.rst diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 1fe2d5d6227d615..b1e61d7e77b2f5c 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -694,6 +694,13 @@ iterations of the loop. Returns with ``STACK[-1]`` to the caller of the function. +.. opcode:: RETURN_CONST (consti) + + Returns with ``co_consts[consti]`` to the caller of the function. + + .. versionadded:: 3.12 + + .. opcode:: YIELD_VALUE Yields ``STACK.pop()`` from a :term:`generator`. diff --git a/Include/internal/pycore_opcode.h b/Include/internal/pycore_opcode.h index 05c0485b0641d85..47c847213351960 100644 --- a/Include/internal/pycore_opcode.h +++ b/Include/internal/pycore_opcode.h @@ -192,6 +192,7 @@ const uint8_t _PyOpcode_Deopt[256] = { [RAISE_VARARGS] = RAISE_VARARGS, [RERAISE] = RERAISE, [RESUME] = RESUME, + [RETURN_CONST] = RETURN_CONST, [RETURN_GENERATOR] = RETURN_GENERATOR, [RETURN_VALUE] = RETURN_VALUE, [SEND] = SEND, @@ -349,7 +350,7 @@ static const char *const _PyOpcode_OpName[263] = { [CONTAINS_OP] = "CONTAINS_OP", [RERAISE] = "RERAISE", [COPY] = "COPY", - [STORE_FAST__LOAD_FAST] = "STORE_FAST__LOAD_FAST", + [RETURN_CONST] = "RETURN_CONST", [BINARY_OP] = "BINARY_OP", [SEND] = "SEND", [LOAD_FAST] = "LOAD_FAST", @@ -371,7 +372,7 @@ static const char *const _PyOpcode_OpName[263] = { [JUMP_BACKWARD] = "JUMP_BACKWARD", [COMPARE_AND_BRANCH] = "COMPARE_AND_BRANCH", [CALL_FUNCTION_EX] = "CALL_FUNCTION_EX", - [STORE_FAST__STORE_FAST] = "STORE_FAST__STORE_FAST", + [STORE_FAST__LOAD_FAST] = "STORE_FAST__LOAD_FAST", [EXTENDED_ARG] = "EXTENDED_ARG", [LIST_APPEND] = "LIST_APPEND", [SET_ADD] = "SET_ADD", @@ -381,15 +382,15 @@ static const char *const _PyOpcode_OpName[263] = { [YIELD_VALUE] = "YIELD_VALUE", [RESUME] = "RESUME", [MATCH_CLASS] = "MATCH_CLASS", + [STORE_FAST__STORE_FAST] = "STORE_FAST__STORE_FAST", [STORE_SUBSCR_DICT] = "STORE_SUBSCR_DICT", - [STORE_SUBSCR_LIST_INT] = "STORE_SUBSCR_LIST_INT", [FORMAT_VALUE] = "FORMAT_VALUE", [BUILD_CONST_KEY_MAP] = "BUILD_CONST_KEY_MAP", [BUILD_STRING] = "BUILD_STRING", + [STORE_SUBSCR_LIST_INT] = "STORE_SUBSCR_LIST_INT", [UNPACK_SEQUENCE_LIST] = "UNPACK_SEQUENCE_LIST", [UNPACK_SEQUENCE_TUPLE] = "UNPACK_SEQUENCE_TUPLE", [UNPACK_SEQUENCE_TWO_TUPLE] = "UNPACK_SEQUENCE_TWO_TUPLE", - [161] = "<161>", [LIST_EXTEND] = "LIST_EXTEND", [SET_UPDATE] = "SET_UPDATE", [DICT_MERGE] = "DICT_MERGE", @@ -495,7 +496,6 @@ static const char *const _PyOpcode_OpName[263] = { #endif #define EXTRA_CASES \ - case 161: \ case 166: \ case 167: \ case 168: \ diff --git a/Include/opcode.h b/Include/opcode.h index 827f9931beb3e63..77ad7c22440d72e 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -76,6 +76,7 @@ extern "C" { #define CONTAINS_OP 118 #define RERAISE 119 #define COPY 120 +#define RETURN_CONST 121 #define BINARY_OP 122 #define SEND 123 #define LOAD_FAST 124 @@ -179,13 +180,13 @@ extern "C" { #define STORE_ATTR_INSTANCE_VALUE 86 #define STORE_ATTR_SLOT 87 #define STORE_ATTR_WITH_HINT 113 -#define STORE_FAST__LOAD_FAST 121 -#define STORE_FAST__STORE_FAST 143 -#define STORE_SUBSCR_DICT 153 -#define STORE_SUBSCR_LIST_INT 154 -#define UNPACK_SEQUENCE_LIST 158 -#define UNPACK_SEQUENCE_TUPLE 159 -#define UNPACK_SEQUENCE_TWO_TUPLE 160 +#define STORE_FAST__LOAD_FAST 143 +#define STORE_FAST__STORE_FAST 153 +#define STORE_SUBSCR_DICT 154 +#define STORE_SUBSCR_LIST_INT 158 +#define UNPACK_SEQUENCE_LIST 159 +#define UNPACK_SEQUENCE_TUPLE 160 +#define UNPACK_SEQUENCE_TWO_TUPLE 161 #define DO_TRACING 255 #define HAS_ARG(op) ((((op) >= HAVE_ARGUMENT) && (!IS_PSEUDO_OPCODE(op)))\ @@ -196,6 +197,7 @@ extern "C" { #define HAS_CONST(op) (false\ || ((op) == LOAD_CONST) \ + || ((op) == RETURN_CONST) \ || ((op) == KW_NAMES) \ ) diff --git a/Lib/dis.py b/Lib/dis.py index 72ab9536a2bf6a9..a6921008d9d0e5e 100644 --- a/Lib/dis.py +++ b/Lib/dis.py @@ -34,6 +34,7 @@ MAKE_FUNCTION_FLAGS = ('defaults', 'kwdefaults', 'annotations', 'closure') LOAD_CONST = opmap['LOAD_CONST'] +RETURN_CONST = opmap['RETURN_CONST'] LOAD_GLOBAL = opmap['LOAD_GLOBAL'] BINARY_OP = opmap['BINARY_OP'] JUMP_BACKWARD = opmap['JUMP_BACKWARD'] @@ -363,7 +364,7 @@ def _get_const_value(op, arg, co_consts): assert op in hasconst argval = UNKNOWN - if op == LOAD_CONST: + if op == LOAD_CONST or op == RETURN_CONST: if co_consts is not None: argval = co_consts[arg] return argval diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index e760fbb15759d4f..933c8c7d7e05908 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -431,6 +431,7 @@ def _write_atomic(path, data, mode=0o666): # Python 3.12a5 3515 (Embed jump mask in COMPARE_OP oparg) # Python 3.12a5 3516 (Add COMPARE_AND_BRANCH instruction) # Python 3.12a5 3517 (Change YIELD_VALUE oparg to exception block depth) +# Python 3.12a5 3518 (Add RETURN_CONST instruction) # Python 3.13 will start with 3550 @@ -443,7 +444,7 @@ def _write_atomic(path, data, mode=0o666): # Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array # in PC/launcher.c must also be updated. -MAGIC_NUMBER = (3517).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3518).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c diff --git a/Lib/opcode.py b/Lib/opcode.py index c317e23beae62b8..5f163d2ccb80df2 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -164,6 +164,8 @@ def pseudo_op(name, op, real_ops): def_op('CONTAINS_OP', 118) def_op('RERAISE', 119) def_op('COPY', 120) +def_op('RETURN_CONST', 121) +hasconst.append(121) def_op('BINARY_OP', 122) jrel_op('SEND', 123) # Number of bytes to skip def_op('LOAD_FAST', 124) # Local variable number, no null check diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index 98d9b603bbc1cb2..7c9a57c685df753 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -1900,7 +1900,7 @@ def get_load_const(self, tree): co = compile(tree, '', 'exec') consts = [] for instr in dis.get_instructions(co): - if instr.opname == 'LOAD_CONST': + if instr.opname == 'LOAD_CONST' or instr.opname == 'RETURN_CONST': consts.append(instr.argval) return consts diff --git a/Lib/test/test_code.py b/Lib/test/test_code.py index 67ed1694205cd64..9c2ac83e1b69e35 100644 --- a/Lib/test/test_code.py +++ b/Lib/test/test_code.py @@ -723,6 +723,7 @@ def f(): pass PY_CODE_LOCATION_INFO_NO_COLUMNS = 13 f.__code__ = f.__code__.replace( + co_stacksize=1, co_firstlineno=42, co_code=bytes( [ diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index 05a5ed1fa9a637f..90b067bcf309127 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -741,7 +741,7 @@ def unused_code_at_end(): # RETURN_VALUE opcode. This does not always crash an interpreter. # When you build with the clang memory sanitizer it reliably aborts. self.assertEqual( - 'RETURN_VALUE', + 'RETURN_CONST', list(dis.get_instructions(unused_code_at_end))[-1].opname) def test_dont_merge_constants(self): @@ -822,10 +822,9 @@ def unused_block_while_else(): for func in funcs: opcodes = list(dis.get_instructions(func)) - self.assertLessEqual(len(opcodes), 4) - self.assertEqual('LOAD_CONST', opcodes[-2].opname) - self.assertEqual(None, opcodes[-2].argval) - self.assertEqual('RETURN_VALUE', opcodes[-1].opname) + self.assertLessEqual(len(opcodes), 3) + self.assertEqual('RETURN_CONST', opcodes[-1].opname) + self.assertEqual(None, opcodes[-1].argval) def test_false_while_loop(self): def break_in_while(): @@ -841,10 +840,9 @@ def continue_in_while(): # Check that we did not raise but we also don't generate bytecode for func in funcs: opcodes = list(dis.get_instructions(func)) - self.assertEqual(3, len(opcodes)) - self.assertEqual('LOAD_CONST', opcodes[1].opname) + self.assertEqual(2, len(opcodes)) + self.assertEqual('RETURN_CONST', opcodes[1].opname) self.assertEqual(None, opcodes[1].argval) - self.assertEqual('RETURN_VALUE', opcodes[2].opname) def test_consts_in_conditionals(self): def and_true(x): @@ -1311,7 +1309,7 @@ def test_multiline_generator_expression(self): line=1, end_line=2, column=1, end_column=8, occurrence=1) self.assertOpcodeSourcePositionIs(compiled_code, 'JUMP_BACKWARD', line=1, end_line=2, column=1, end_column=8, occurrence=1) - self.assertOpcodeSourcePositionIs(compiled_code, 'RETURN_VALUE', + self.assertOpcodeSourcePositionIs(compiled_code, 'RETURN_CONST', line=1, end_line=6, column=0, end_column=32, occurrence=1) def test_multiline_async_generator_expression(self): @@ -1328,7 +1326,7 @@ def test_multiline_async_generator_expression(self): self.assertIsInstance(compiled_code, types.CodeType) self.assertOpcodeSourcePositionIs(compiled_code, 'YIELD_VALUE', line=1, end_line=2, column=1, end_column=8, occurrence=2) - self.assertOpcodeSourcePositionIs(compiled_code, 'RETURN_VALUE', + self.assertOpcodeSourcePositionIs(compiled_code, 'RETURN_CONST', line=1, end_line=6, column=0, end_column=32, occurrence=1) def test_multiline_list_comprehension(self): diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index bdf48c15309296c..1050b15e16eaaa9 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -49,8 +49,7 @@ def cm(cls, x): COMPARE_OP 32 (==) LOAD_FAST 0 (self) STORE_ATTR 0 (x) - LOAD_CONST 0 (None) - RETURN_VALUE + RETURN_CONST 0 (None) """ % (_C.__init__.__code__.co_firstlineno, _C.__init__.__code__.co_firstlineno + 1,) dis_c_instance_method_bytes = """\ @@ -60,8 +59,7 @@ def cm(cls, x): COMPARE_OP 32 (==) LOAD_FAST 0 STORE_ATTR 0 - LOAD_CONST 0 - RETURN_VALUE + RETURN_CONST 0 """ dis_c_class_method = """\ @@ -72,8 +70,7 @@ def cm(cls, x): COMPARE_OP 32 (==) LOAD_FAST 0 (cls) STORE_ATTR 0 (x) - LOAD_CONST 0 (None) - RETURN_VALUE + RETURN_CONST 0 (None) """ % (_C.cm.__code__.co_firstlineno, _C.cm.__code__.co_firstlineno + 2,) dis_c_static_method = """\ @@ -83,8 +80,7 @@ def cm(cls, x): LOAD_CONST 1 (1) COMPARE_OP 32 (==) STORE_FAST 0 (x) - LOAD_CONST 0 (None) - RETURN_VALUE + RETURN_CONST 0 (None) """ % (_C.sm.__code__.co_firstlineno, _C.sm.__code__.co_firstlineno + 2,) # Class disassembling info has an extra newline at end. @@ -111,8 +107,7 @@ def _f(a): CALL 1 POP_TOP -%3d LOAD_CONST 1 (1) - RETURN_VALUE +%3d RETURN_CONST 1 (1) """ % (_f.__code__.co_firstlineno, _f.__code__.co_firstlineno + 1, _f.__code__.co_firstlineno + 2) @@ -124,8 +119,7 @@ def _f(a): LOAD_FAST 0 CALL 1 POP_TOP - LOAD_CONST 1 - RETURN_VALUE + RETURN_CONST 1 """ @@ -150,8 +144,7 @@ def bug708901(): %3d JUMP_BACKWARD 4 (to 30) %3d >> END_FOR - LOAD_CONST 0 (None) - RETURN_VALUE + RETURN_CONST 0 (None) """ % (bug708901.__code__.co_firstlineno, bug708901.__code__.co_firstlineno + 1, bug708901.__code__.co_firstlineno + 2, @@ -198,8 +191,7 @@ def bug42562(): dis_bug42562 = """\ RESUME 0 - LOAD_CONST 0 (None) - RETURN_VALUE + RETURN_CONST 0 (None) """ # Extended arg followed by NOP @@ -240,8 +232,7 @@ def bug42562(): %3d LOAD_GLOBAL 0 (spam) POP_TOP - LOAD_CONST 0 (None) - RETURN_VALUE + RETURN_CONST 0 (None) """ _BIG_LINENO_FORMAT2 = """\ @@ -249,20 +240,17 @@ def bug42562(): %4d LOAD_GLOBAL 0 (spam) POP_TOP - LOAD_CONST 0 (None) - RETURN_VALUE + RETURN_CONST 0 (None) """ dis_module_expected_results = """\ Disassembly of f: 4 RESUME 0 - LOAD_CONST 0 (None) - RETURN_VALUE + RETURN_CONST 0 (None) Disassembly of g: 5 RESUME 0 - LOAD_CONST 0 (None) - RETURN_VALUE + RETURN_CONST 0 (None) """ @@ -286,8 +274,7 @@ def bug42562(): LOAD_CONST 0 (1) BINARY_OP 0 (+) STORE_NAME 0 (x) - LOAD_CONST 1 (None) - RETURN_VALUE + RETURN_CONST 1 (None) """ annot_stmt_str = """\ @@ -326,8 +313,7 @@ def bug42562(): STORE_SUBSCR LOAD_NAME 1 (int) POP_TOP - LOAD_CONST 4 (None) - RETURN_VALUE + RETURN_CONST 4 (None) """ compound_stmt_str = """\ @@ -447,12 +433,11 @@ def _with(c): %3d LOAD_CONST 2 (2) STORE_FAST 2 (y) - LOAD_CONST 0 (None) - RETURN_VALUE + RETURN_CONST 0 (None) %3d >> PUSH_EXC_INFO WITH_EXCEPT_START - POP_JUMP_IF_TRUE 1 (to 46) + POP_JUMP_IF_TRUE 1 (to 44) RERAISE 2 >> POP_TOP POP_EXCEPT @@ -461,8 +446,7 @@ def _with(c): %3d LOAD_CONST 2 (2) STORE_FAST 2 (y) - LOAD_CONST 0 (None) - RETURN_VALUE + RETURN_CONST 0 (None) >> COPY 3 POP_EXCEPT RERAISE 1 @@ -514,23 +498,22 @@ async def _asyncwith(c): %3d LOAD_CONST 2 (2) STORE_FAST 2 (y) - LOAD_CONST 0 (None) - RETURN_VALUE + RETURN_CONST 0 (None) %3d >> CLEANUP_THROW - JUMP_BACKWARD 24 (to 22) + JUMP_BACKWARD 23 (to 22) >> CLEANUP_THROW - JUMP_BACKWARD 9 (to 56) + JUMP_BACKWARD 8 (to 56) >> PUSH_EXC_INFO WITH_EXCEPT_START GET_AWAITABLE 2 LOAD_CONST 0 (None) - >> SEND 4 (to 92) + >> SEND 4 (to 90) YIELD_VALUE 3 RESUME 3 - JUMP_BACKWARD_NO_INTERRUPT 4 (to 82) + JUMP_BACKWARD_NO_INTERRUPT 4 (to 80) >> CLEANUP_THROW - >> POP_JUMP_IF_TRUE 1 (to 96) + >> POP_JUMP_IF_TRUE 1 (to 94) RERAISE 2 >> POP_TOP POP_EXCEPT @@ -539,8 +522,7 @@ async def _asyncwith(c): %3d LOAD_CONST 2 (2) STORE_FAST 2 (y) - LOAD_CONST 0 (None) - RETURN_VALUE + RETURN_CONST 0 (None) >> COPY 3 POP_EXCEPT RERAISE 1 @@ -610,8 +592,7 @@ def _tryfinallyconst(b): LOAD_FAST 0 (b) CALL 0 POP_TOP - LOAD_CONST 1 (1) - RETURN_VALUE + RETURN_CONST 1 (1) PUSH_EXC_INFO PUSH_NULL LOAD_FAST 0 (b) @@ -754,8 +735,7 @@ def loop_test(): JUMP_BACKWARD 17 (to 16) %3d >> END_FOR - LOAD_CONST 0 (None) - RETURN_VALUE + RETURN_CONST 0 (None) """ % (loop_test.__code__.co_firstlineno, loop_test.__code__.co_firstlineno + 1, loop_test.__code__.co_firstlineno + 2, @@ -772,8 +752,7 @@ def extended_arg_quick(): 6 UNPACK_EX 256 8 STORE_FAST 0 (_) 10 STORE_FAST 0 (_) - 12 LOAD_CONST 0 (None) - 14 RETURN_VALUE + 12 RETURN_CONST 0 (None) """% (extended_arg_quick.__code__.co_firstlineno, extended_arg_quick.__code__.co_firstlineno + 1,) @@ -1549,8 +1528,7 @@ def _prepare_test_cases(): Instruction(opname='LOAD_FAST', opcode=124, arg=1, argval='f', argrepr='f', offset=26, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='CALL', opcode=171, arg=6, argval=6, argrepr='', offset=28, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=38, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=40, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=42, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RETURN_CONST', opcode=121, arg=0, argval=None, argrepr='None', offset=40, starts_line=None, is_jump_target=False, positions=None) ] expected_opinfo_jumpy = [ @@ -1630,52 +1608,50 @@ def _prepare_test_cases(): Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=286, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=288, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=298, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=300, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=302, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=304, starts_line=25, is_jump_target=False, positions=None), - Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=306, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=1, argval=312, argrepr='to 312', offset=308, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=2, argval=2, argrepr='', offset=310, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=312, starts_line=None, is_jump_target=True, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=314, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RETURN_CONST', opcode=121, arg=0, argval=None, argrepr='None', offset=300, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=302, starts_line=25, is_jump_target=False, positions=None), + Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=304, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=1, argval=310, argrepr='to 310', offset=306, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=2, argval=2, argrepr='', offset=308, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=310, starts_line=None, is_jump_target=True, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=312, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=314, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=316, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=318, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_BACKWARD', opcode=140, arg=24, argval=274, argrepr='to 274', offset=320, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=322, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=324, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=326, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=328, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=330, starts_line=22, is_jump_target=False, positions=None), - Instruction(opname='CHECK_EXC_MATCH', opcode=36, arg=None, argval=None, argrepr='', offset=342, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=16, argval=378, argrepr='to 378', offset=344, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=346, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=348, starts_line=23, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=360, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=362, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=372, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=374, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_BACKWARD', opcode=140, arg=52, argval=274, argrepr='to 274', offset=376, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=378, starts_line=22, is_jump_target=True, positions=None), - Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=380, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=382, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=384, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=386, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=388, starts_line=28, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=400, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=402, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=412, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=414, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=416, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=418, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=420, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_BACKWARD', opcode=140, arg=23, argval=274, argrepr='to 274', offset=318, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=320, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=322, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=324, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=326, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=328, starts_line=22, is_jump_target=False, positions=None), + Instruction(opname='CHECK_EXC_MATCH', opcode=36, arg=None, argval=None, argrepr='', offset=340, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=16, argval=376, argrepr='to 376', offset=342, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=344, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=346, starts_line=23, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=358, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=360, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=370, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=372, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_BACKWARD', opcode=140, arg=51, argval=274, argrepr='to 274', offset=374, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=376, starts_line=22, is_jump_target=True, positions=None), + Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=378, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=380, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=382, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=384, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=386, starts_line=28, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=398, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=400, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=410, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=412, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=414, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=416, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=418, starts_line=None, is_jump_target=False, positions=None) ] # One last piece of inspect fodder to check the default line number handling def simple(): pass expected_opinfo_simple = [ Instruction(opname='RESUME', opcode=151, arg=0, argval=0, argrepr='', offset=0, starts_line=simple.__code__.co_firstlineno, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=2, starts_line=None, is_jump_target=False), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=4, starts_line=None, is_jump_target=False) + Instruction(opname='RETURN_CONST', opcode=121, arg=0, argval=None, argrepr='None', offset=2, starts_line=None, is_jump_target=False), ] @@ -1736,7 +1712,6 @@ def test_co_positions(self): (2, 2, 8, 9), (1, 3, 0, 1), (1, 3, 0, 1), - (1, 3, 0, 1), (1, 3, 0, 1) ] self.assertEqual(positions, expected) diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py index 239c9d03fd9d1f2..707ff821b31a8a9 100644 --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -117,7 +117,7 @@ def f(): return None self.assertNotInBytecode(f, 'LOAD_GLOBAL') - self.assertInBytecode(f, 'LOAD_CONST', None) + self.assertInBytecode(f, 'RETURN_CONST', None) self.check_lnotab(f) def test_while_one(self): @@ -134,7 +134,7 @@ def f(): def test_pack_unpack(self): for line, elem in ( - ('a, = a,', 'LOAD_CONST',), + ('a, = a,', 'RETURN_CONST',), ('a, b = a, b', 'SWAP',), ('a, b, c = a, b, c', 'SWAP',), ): @@ -165,7 +165,7 @@ def test_folding_of_tuples_of_constants(self): # One LOAD_CONST for the tuple, one for the None return value load_consts = [instr for instr in dis.get_instructions(code) if instr.opname == 'LOAD_CONST'] - self.assertEqual(len(load_consts), 2) + self.assertEqual(len(load_consts), 1) self.check_lnotab(code) # Bug 1053819: Tuple of constants misidentified when presented with: diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-02-07-14-56-43.gh-issue-101632.Fd1yxk.rst b/Misc/NEWS.d/next/Core and Builtins/2023-02-07-14-56-43.gh-issue-101632.Fd1yxk.rst new file mode 100644 index 000000000000000..136909ca6999030 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-02-07-14-56-43.gh-issue-101632.Fd1yxk.rst @@ -0,0 +1 @@ +Adds a new :opcode:`RETURN_CONST` instruction. diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 6bc04bc8e848fc2..0e52a3e2399c061 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -397,6 +397,8 @@ mark_stacks(PyCodeObject *code_obj, int len) assert(pop_value(next_stack) == EMPTY_STACK); assert(top_of_stack(next_stack) == Object); break; + case RETURN_CONST: + break; case RAISE_VARARGS: break; case RERAISE: diff --git a/Programs/test_frozenmain.h b/Programs/test_frozenmain.h index 95f78b19e65eb6c..8e5055bd7bceb10 100644 --- a/Programs/test_frozenmain.h +++ b/Programs/test_frozenmain.h @@ -1,7 +1,7 @@ // Auto-generated by Programs/freeze_test_frozenmain.py unsigned char M_test_frozenmain[] = { 227,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0, - 0,0,0,0,0,243,184,0,0,0,151,0,100,0,100,1, + 0,0,0,0,0,243,182,0,0,0,151,0,100,0,100,1, 108,0,90,0,100,0,100,1,108,1,90,1,2,0,101,2, 100,2,171,1,0,0,0,0,0,0,0,0,1,0,2,0, 101,2,100,3,101,0,106,6,0,0,0,0,0,0,0,0, @@ -12,28 +12,28 @@ unsigned char M_test_frozenmain[] = { 0,0,0,0,90,5,100,5,68,0,93,23,0,0,90,6, 2,0,101,2,100,6,101,6,155,0,100,7,101,5,101,6, 25,0,0,0,0,0,0,0,0,0,155,0,157,4,171,1, - 0,0,0,0,0,0,0,0,1,0,140,25,4,0,100,1, - 83,0,41,8,233,0,0,0,0,78,122,18,70,114,111,122, - 101,110,32,72,101,108,108,111,32,87,111,114,108,100,122,8, - 115,121,115,46,97,114,103,118,218,6,99,111,110,102,105,103, - 41,5,218,12,112,114,111,103,114,97,109,95,110,97,109,101, - 218,10,101,120,101,99,117,116,97,98,108,101,218,15,117,115, - 101,95,101,110,118,105,114,111,110,109,101,110,116,218,17,99, - 111,110,102,105,103,117,114,101,95,99,95,115,116,100,105,111, - 218,14,98,117,102,102,101,114,101,100,95,115,116,100,105,111, - 122,7,99,111,110,102,105,103,32,122,2,58,32,41,7,218, - 3,115,121,115,218,17,95,116,101,115,116,105,110,116,101,114, - 110,97,108,99,97,112,105,218,5,112,114,105,110,116,218,4, - 97,114,103,118,218,11,103,101,116,95,99,111,110,102,105,103, - 115,114,3,0,0,0,218,3,107,101,121,169,0,243,0,0, - 0,0,250,18,116,101,115,116,95,102,114,111,122,101,110,109, - 97,105,110,46,112,121,250,8,60,109,111,100,117,108,101,62, - 114,18,0,0,0,1,0,0,0,115,100,0,0,0,240,3, - 1,1,1,243,8,0,1,11,219,0,24,225,0,5,208,6, - 26,213,0,27,217,0,5,128,106,144,35,151,40,145,40,213, - 0,27,216,9,38,208,9,26,215,9,38,209,9,38,212,9, - 40,168,24,212,9,50,128,6,240,2,6,12,2,242,0,7, - 1,42,128,67,241,14,0,5,10,208,10,40,144,67,209,10, - 40,152,54,160,35,156,59,209,10,40,214,4,41,242,15,7, - 1,42,114,16,0,0,0, + 0,0,0,0,0,0,0,0,1,0,140,25,4,0,121,1, + 41,8,233,0,0,0,0,78,122,18,70,114,111,122,101,110, + 32,72,101,108,108,111,32,87,111,114,108,100,122,8,115,121, + 115,46,97,114,103,118,218,6,99,111,110,102,105,103,41,5, + 218,12,112,114,111,103,114,97,109,95,110,97,109,101,218,10, + 101,120,101,99,117,116,97,98,108,101,218,15,117,115,101,95, + 101,110,118,105,114,111,110,109,101,110,116,218,17,99,111,110, + 102,105,103,117,114,101,95,99,95,115,116,100,105,111,218,14, + 98,117,102,102,101,114,101,100,95,115,116,100,105,111,122,7, + 99,111,110,102,105,103,32,122,2,58,32,41,7,218,3,115, + 121,115,218,17,95,116,101,115,116,105,110,116,101,114,110,97, + 108,99,97,112,105,218,5,112,114,105,110,116,218,4,97,114, + 103,118,218,11,103,101,116,95,99,111,110,102,105,103,115,114, + 3,0,0,0,218,3,107,101,121,169,0,243,0,0,0,0, + 250,18,116,101,115,116,95,102,114,111,122,101,110,109,97,105, + 110,46,112,121,250,8,60,109,111,100,117,108,101,62,114,18, + 0,0,0,1,0,0,0,115,100,0,0,0,240,3,1,1, + 1,243,8,0,1,11,219,0,24,225,0,5,208,6,26,213, + 0,27,217,0,5,128,106,144,35,151,40,145,40,213,0,27, + 216,9,38,208,9,26,215,9,38,209,9,38,212,9,40,168, + 24,212,9,50,128,6,240,2,6,12,2,242,0,7,1,42, + 128,67,241,14,0,5,10,208,10,40,144,67,209,10,40,152, + 54,160,35,156,59,209,10,40,214,4,41,241,15,7,1,42, + 114,16,0,0,0, }; diff --git a/Python/bytecodes.c b/Python/bytecodes.c index b43625fd283cc3d..0d7d922816ce918 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -555,6 +555,23 @@ dummy_func( goto resume_frame; } + inst(RETURN_CONST, (--)) { + PyObject *retval = GETITEM(consts, oparg); + Py_INCREF(retval); + assert(EMPTY()); + _PyFrame_SetStackPointer(frame, stack_pointer); + TRACE_FUNCTION_EXIT(); + DTRACE_FUNCTION_EXIT(); + _Py_LeaveRecursiveCallPy(tstate); + assert(frame != &entry_frame); + // GH-99729: We need to unlink the frame *before* clearing it: + _PyInterpreterFrame *dying = frame; + frame = cframe.current_frame = dying->previous; + _PyEvalFrameClearAndPop(tstate, dying); + _PyFrame_StackPush(frame, retval); + goto resume_frame; + } + inst(GET_AITER, (obj -- iter)) { unaryfunc getter = NULL; PyTypeObject *type = Py_TYPE(obj); diff --git a/Python/compile.c b/Python/compile.c index d9ec68958972b5f..df2dffb95bbd7ee 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -124,6 +124,7 @@ #define IS_SCOPE_EXIT_OPCODE(opcode) \ ((opcode) == RETURN_VALUE || \ + (opcode) == RETURN_CONST || \ (opcode) == RAISE_VARARGS || \ (opcode) == RERAISE) @@ -354,7 +355,7 @@ basicblock_last_instr(const basicblock *b) { static inline int basicblock_returns(const basicblock *b) { struct instr *last = basicblock_last_instr(b); - return last && last->i_opcode == RETURN_VALUE; + return last && (last->i_opcode == RETURN_VALUE || last->i_opcode == RETURN_CONST); } static inline int @@ -1119,6 +1120,8 @@ stack_effect(int opcode, int oparg, int jump) case RETURN_VALUE: return -1; + case RETURN_CONST: + return 0; case SETUP_ANNOTATIONS: return 0; case YIELD_VALUE: @@ -9261,6 +9264,10 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts) } Py_DECREF(cnt); break; + case RETURN_VALUE: + INSTR_SET_OP1(inst, RETURN_CONST, oparg); + INSTR_SET_OP0(&bb->b_instr[i + 1], NOP); + break; } break; } @@ -9723,9 +9730,7 @@ remove_unused_consts(basicblock *entryblock, PyObject *consts) /* mark used consts */ for (basicblock *b = entryblock; b != NULL; b = b->b_next) { for (int i = 0; i < b->b_iused; i++) { - if (b->b_instr[i].i_opcode == LOAD_CONST || - b->b_instr[i].i_opcode == KW_NAMES) { - + if (HAS_CONST(b->b_instr[i].i_opcode)) { int index = b->b_instr[i].i_oparg; index_map[index] = index; } @@ -9780,9 +9785,7 @@ remove_unused_consts(basicblock *entryblock, PyObject *consts) for (basicblock *b = entryblock; b != NULL; b = b->b_next) { for (int i = 0; i < b->b_iused; i++) { - if (b->b_instr[i].i_opcode == LOAD_CONST || - b->b_instr[i].i_opcode == KW_NAMES) { - + if (HAS_CONST(b->b_instr[i].i_opcode)) { int index = b->b_instr[i].i_oparg; assert(reverse_index_map[index] >= 0); assert(reverse_index_map[index] < n_used_consts); diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index ab19f431710644b..de98b1a4f2ed727 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -742,6 +742,23 @@ goto resume_frame; } + TARGET(RETURN_CONST) { + PyObject *retval = GETITEM(consts, oparg); + Py_INCREF(retval); + assert(EMPTY()); + _PyFrame_SetStackPointer(frame, stack_pointer); + TRACE_FUNCTION_EXIT(); + DTRACE_FUNCTION_EXIT(); + _Py_LeaveRecursiveCallPy(tstate); + assert(frame != &entry_frame); + // GH-99729: We need to unlink the frame *before* clearing it: + _PyInterpreterFrame *dying = frame; + frame = cframe.current_frame = dying->previous; + _PyEvalFrameClearAndPop(tstate, dying); + _PyFrame_StackPush(frame, retval); + goto resume_frame; + } + TARGET(GET_AITER) { PyObject *obj = PEEK(1); PyObject *iter; diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index d2585351f69fd2f..bae5492c0496e64 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -92,6 +92,8 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) { return 1; case RETURN_VALUE: return 1; + case RETURN_CONST: + return 0; case GET_AITER: return 1; case GET_ANEXT: @@ -438,6 +440,8 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { return 0; case RETURN_VALUE: return 0; + case RETURN_CONST: + return 0; case GET_AITER: return 1; case GET_ANEXT: @@ -745,6 +749,7 @@ struct opcode_metadata { [RAISE_VARARGS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [INTERPRETER_EXIT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, [RETURN_VALUE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, + [RETURN_CONST] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [GET_AITER] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, [GET_ANEXT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, [GET_AWAITABLE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index f1c3f3e0c4ee175..eceb246fac4909e 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -120,7 +120,7 @@ static void *opcode_targets[256] = { &&TARGET_CONTAINS_OP, &&TARGET_RERAISE, &&TARGET_COPY, - &&TARGET_STORE_FAST__LOAD_FAST, + &&TARGET_RETURN_CONST, &&TARGET_BINARY_OP, &&TARGET_SEND, &&TARGET_LOAD_FAST, @@ -142,7 +142,7 @@ static void *opcode_targets[256] = { &&TARGET_JUMP_BACKWARD, &&TARGET_COMPARE_AND_BRANCH, &&TARGET_CALL_FUNCTION_EX, - &&TARGET_STORE_FAST__STORE_FAST, + &&TARGET_STORE_FAST__LOAD_FAST, &&TARGET_EXTENDED_ARG, &&TARGET_LIST_APPEND, &&TARGET_SET_ADD, @@ -152,15 +152,15 @@ static void *opcode_targets[256] = { &&TARGET_YIELD_VALUE, &&TARGET_RESUME, &&TARGET_MATCH_CLASS, + &&TARGET_STORE_FAST__STORE_FAST, &&TARGET_STORE_SUBSCR_DICT, - &&TARGET_STORE_SUBSCR_LIST_INT, &&TARGET_FORMAT_VALUE, &&TARGET_BUILD_CONST_KEY_MAP, &&TARGET_BUILD_STRING, + &&TARGET_STORE_SUBSCR_LIST_INT, &&TARGET_UNPACK_SEQUENCE_LIST, &&TARGET_UNPACK_SEQUENCE_TUPLE, &&TARGET_UNPACK_SEQUENCE_TWO_TUPLE, - &&_unknown_opcode, &&TARGET_LIST_EXTEND, &&TARGET_SET_UPDATE, &&TARGET_DICT_MERGE, From aacbdb0c650492756738b044e6ddf8b72f89a1a2 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Tue, 7 Feb 2023 15:44:37 -0800 Subject: [PATCH 74/74] gh-98831: Finish the UNPACK_SEQUENCE family (#101666) New generator feature: Generate useful glue for output arrays, so you can just write values to the output array (no bounds checking). Rewrote UNPACK_SEQUENCE_TWO_TUPLE to use this, and also UNPACK_SEQUENCE_{TUPLE,LIST}. --- Python/bytecodes.c | 37 +++++++++++------------- Python/generated_cases.c.h | 38 ++++++++++++++----------- Python/opcode_metadata.h | 16 +++++------ Tools/cases_generator/generate_cases.py | 25 +++++++++++----- Tools/cases_generator/test_generator.py | 19 ++++++------- 5 files changed, 72 insertions(+), 63 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 0d7d922816ce918..c6c00a7ab9b0cf0 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -876,6 +876,13 @@ dummy_func( } } + family(unpack_sequence, INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE) = { + UNPACK_SEQUENCE, + UNPACK_SEQUENCE_TWO_TUPLE, + UNPACK_SEQUENCE_TUPLE, + UNPACK_SEQUENCE_LIST, + }; + inst(UNPACK_SEQUENCE, (unused/1, seq -- unused[oparg])) { #if ENABLE_SPECIALIZATION _PyUnpackSequenceCache *cache = (_PyUnpackSequenceCache *)next_instr; @@ -894,43 +901,36 @@ dummy_func( ERROR_IF(res == 0, error); } - inst(UNPACK_SEQUENCE_TWO_TUPLE, (unused/1, seq -- v1, v0)) { + inst(UNPACK_SEQUENCE_TWO_TUPLE, (unused/1, seq -- values[oparg])) { DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE); DEOPT_IF(PyTuple_GET_SIZE(seq) != 2, UNPACK_SEQUENCE); + assert(oparg == 2); STAT_INC(UNPACK_SEQUENCE, hit); - v1 = Py_NewRef(PyTuple_GET_ITEM(seq, 1)); - v0 = Py_NewRef(PyTuple_GET_ITEM(seq, 0)); + values[0] = Py_NewRef(PyTuple_GET_ITEM(seq, 1)); + values[1] = Py_NewRef(PyTuple_GET_ITEM(seq, 0)); Py_DECREF(seq); } - // stack effect: (__0 -- __array[oparg]) - inst(UNPACK_SEQUENCE_TUPLE) { - PyObject *seq = TOP(); + inst(UNPACK_SEQUENCE_TUPLE, (unused/1, seq -- values[oparg])) { DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE); DEOPT_IF(PyTuple_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE); STAT_INC(UNPACK_SEQUENCE, hit); - STACK_SHRINK(1); PyObject **items = _PyTuple_ITEMS(seq); - while (oparg--) { - PUSH(Py_NewRef(items[oparg])); + for (int i = oparg; --i >= 0; ) { + *values++ = Py_NewRef(items[i]); } Py_DECREF(seq); - JUMPBY(INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE); } - // stack effect: (__0 -- __array[oparg]) - inst(UNPACK_SEQUENCE_LIST) { - PyObject *seq = TOP(); + inst(UNPACK_SEQUENCE_LIST, (unused/1, seq -- values[oparg])) { DEOPT_IF(!PyList_CheckExact(seq), UNPACK_SEQUENCE); DEOPT_IF(PyList_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE); STAT_INC(UNPACK_SEQUENCE, hit); - STACK_SHRINK(1); PyObject **items = _PyList_ITEMS(seq); - while (oparg--) { - PUSH(Py_NewRef(items[oparg])); + for (int i = oparg; --i >= 0; ) { + *values++ = Py_NewRef(items[i]); } Py_DECREF(seq); - JUMPBY(INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE); } inst(UNPACK_EX, (seq -- unused[oparg & 0xFF], unused, unused[oparg >> 8])) { @@ -3185,6 +3185,3 @@ family(call, INLINE_CACHE_ENTRIES_CALL) = { CALL_NO_KW_METHOD_DESCRIPTOR_O, CALL_NO_KW_STR_1, CALL_NO_KW_TUPLE_1, CALL_NO_KW_TYPE_1 }; family(store_fast) = { STORE_FAST, STORE_FAST__LOAD_FAST, STORE_FAST__STORE_FAST }; -family(unpack_sequence, INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE) = { - UNPACK_SEQUENCE, UNPACK_SEQUENCE_LIST, - UNPACK_SEQUENCE_TUPLE, UNPACK_SEQUENCE_TWO_TUPLE }; diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index de98b1a4f2ed727..ded68d011c6ba1d 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -1125,6 +1125,7 @@ TARGET(UNPACK_SEQUENCE) { PREDICTED(UNPACK_SEQUENCE); + static_assert(INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE == 1, "incorrect cache size"); PyObject *seq = PEEK(1); #if ENABLE_SPECIALIZATION _PyUnpackSequenceCache *cache = (_PyUnpackSequenceCache *)next_instr; @@ -1149,48 +1150,51 @@ TARGET(UNPACK_SEQUENCE_TWO_TUPLE) { PyObject *seq = PEEK(1); - PyObject *v1; - PyObject *v0; + PyObject **values = stack_pointer - (1); DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE); DEOPT_IF(PyTuple_GET_SIZE(seq) != 2, UNPACK_SEQUENCE); + assert(oparg == 2); STAT_INC(UNPACK_SEQUENCE, hit); - v1 = Py_NewRef(PyTuple_GET_ITEM(seq, 1)); - v0 = Py_NewRef(PyTuple_GET_ITEM(seq, 0)); + values[0] = Py_NewRef(PyTuple_GET_ITEM(seq, 1)); + values[1] = Py_NewRef(PyTuple_GET_ITEM(seq, 0)); Py_DECREF(seq); - STACK_GROW(1); - POKE(1, v0); - POKE(2, v1); + STACK_SHRINK(1); + STACK_GROW(oparg); JUMPBY(1); DISPATCH(); } TARGET(UNPACK_SEQUENCE_TUPLE) { - PyObject *seq = TOP(); + PyObject *seq = PEEK(1); + PyObject **values = stack_pointer - (1); DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE); DEOPT_IF(PyTuple_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE); STAT_INC(UNPACK_SEQUENCE, hit); - STACK_SHRINK(1); PyObject **items = _PyTuple_ITEMS(seq); - while (oparg--) { - PUSH(Py_NewRef(items[oparg])); + for (int i = oparg; --i >= 0; ) { + *values++ = Py_NewRef(items[i]); } Py_DECREF(seq); - JUMPBY(INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE); + STACK_SHRINK(1); + STACK_GROW(oparg); + JUMPBY(1); DISPATCH(); } TARGET(UNPACK_SEQUENCE_LIST) { - PyObject *seq = TOP(); + PyObject *seq = PEEK(1); + PyObject **values = stack_pointer - (1); DEOPT_IF(!PyList_CheckExact(seq), UNPACK_SEQUENCE); DEOPT_IF(PyList_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE); STAT_INC(UNPACK_SEQUENCE, hit); - STACK_SHRINK(1); PyObject **items = _PyList_ITEMS(seq); - while (oparg--) { - PUSH(Py_NewRef(items[oparg])); + for (int i = oparg; --i >= 0; ) { + *values++ = Py_NewRef(items[i]); } Py_DECREF(seq); - JUMPBY(INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE); + STACK_SHRINK(1); + STACK_GROW(oparg); + JUMPBY(1); DISPATCH(); } diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index bae5492c0496e64..c1e12a4bbede895 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -127,9 +127,9 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) { case UNPACK_SEQUENCE_TWO_TUPLE: return 1; case UNPACK_SEQUENCE_TUPLE: - return -1; + return 1; case UNPACK_SEQUENCE_LIST: - return -1; + return 1; case UNPACK_EX: return 1; case STORE_ATTR: @@ -473,11 +473,11 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { case UNPACK_SEQUENCE: return oparg; case UNPACK_SEQUENCE_TWO_TUPLE: - return 2; + return oparg; case UNPACK_SEQUENCE_TUPLE: - return -1; + return oparg; case UNPACK_SEQUENCE_LIST: - return -1; + return oparg; case UNPACK_EX: return (oparg & 0xFF) + (oparg >> 8) + 1; case STORE_ATTR: @@ -765,9 +765,9 @@ struct opcode_metadata { [STORE_NAME] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [DELETE_NAME] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [UNPACK_SEQUENCE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC }, - [UNPACK_SEQUENCE_TWO_TUPLE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC }, - [UNPACK_SEQUENCE_TUPLE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, - [UNPACK_SEQUENCE_LIST] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, + [UNPACK_SEQUENCE_TWO_TUPLE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC }, + [UNPACK_SEQUENCE_TUPLE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC }, + [UNPACK_SEQUENCE_LIST] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC }, [UNPACK_EX] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [STORE_ATTR] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC000 }, [DELETE_ATTR] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, diff --git a/Tools/cases_generator/generate_cases.py b/Tools/cases_generator/generate_cases.py index 3925583b40e728e..4f94b48d114de86 100644 --- a/Tools/cases_generator/generate_cases.py +++ b/Tools/cases_generator/generate_cases.py @@ -180,11 +180,8 @@ def assign(self, dst: StackEffect, src: StackEffect): stmt = f"if ({src.cond}) {{ {stmt} }}" self.emit(stmt) elif m := re.match(r"^&PEEK\(.*\)$", dst.name): - # NOTE: MOVE_ITEMS() does not actually exist. - # The only supported output array forms are: - # - unused[...] - # - X[...] where X[...] matches an input array exactly - self.emit(f"MOVE_ITEMS({dst.name}, {src.name}, {src.size});") + # The user code is responsible for writing to the output array. + pass elif m := re.match(r"^REG\(oparg(\d+)\)$", dst.name): self.emit(f"Py_XSETREF({dst.name}, {cast}{src.name});") else: @@ -309,10 +306,24 @@ def write(self, out: Formatter) -> None: out.declare(ieffect, src) # Write output stack effect variable declarations + isize = string_effect_size(list_effect_size(self.input_effects)) input_names = {ieffect.name for ieffect in self.input_effects} - for oeffect in self.output_effects: + for i, oeffect in enumerate(self.output_effects): if oeffect.name not in input_names: - out.declare(oeffect, None) + if oeffect.size: + osize = string_effect_size( + list_effect_size([oeff for oeff in self.output_effects[:i]]) + ) + offset = "stack_pointer" + if isize != osize: + if isize != "0": + offset += f" - ({isize})" + if osize != "0": + offset += f" + {osize}" + src = StackEffect(offset, "PyObject **") + out.declare(oeffect, src) + else: + out.declare(oeffect, None) # out.emit(f"JUMPBY(OPSIZE({self.inst.name}) - 1);") diff --git a/Tools/cases_generator/test_generator.py b/Tools/cases_generator/test_generator.py index 9df97d24ab6f43a..0c3d04b45dd959f 100644 --- a/Tools/cases_generator/test_generator.py +++ b/Tools/cases_generator/test_generator.py @@ -424,20 +424,18 @@ def test_array_input(): def test_array_output(): input = """ - inst(OP, (-- below, values[oparg*3], above)) { - spam(); + inst(OP, (unused, unused -- below, values[oparg*3], above)) { + spam(values, oparg); } """ output = """ TARGET(OP) { PyObject *below; - PyObject **values; + PyObject **values = stack_pointer - (2) + 1; PyObject *above; - spam(); - STACK_GROW(2); + spam(values, oparg); STACK_GROW(oparg*3); POKE(1, above); - MOVE_ITEMS(&PEEK(1 + oparg*3), values, oparg*3); POKE(2 + oparg*3, below); DISPATCH(); } @@ -446,18 +444,17 @@ def test_array_output(): def test_array_input_output(): input = """ - inst(OP, (below, values[oparg] -- values[oparg], above)) { - spam(); + inst(OP, (values[oparg] -- values[oparg], above)) { + spam(values, oparg); } """ output = """ TARGET(OP) { PyObject **values = &PEEK(oparg); - PyObject *below = PEEK(1 + oparg); PyObject *above; - spam(); + spam(values, oparg); + STACK_GROW(1); POKE(1, above); - MOVE_ITEMS(&PEEK(1 + oparg), values, oparg); DISPATCH(); } """

    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

  2. AebyOey!w1)WzE3EK13 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