From webhook-mailer at python.org Wed Dec 1 07:09:42 2021 From: webhook-mailer at python.org (markshannon) Date: Wed, 01 Dec 2021 12:09:42 -0000 Subject: [Python-checkins] bpo-45753: Interpreter internal tweaks (GH-29575) Message-ID: https://github.com/python/cpython/commit/49444fb807ecb396462c8e5f547eeb5c6bc5d4de commit: 49444fb807ecb396462c8e5f547eeb5c6bc5d4de branch: main author: Mark Shannon committer: markshannon date: 2021-12-01T12:09:36Z summary: bpo-45753: Interpreter internal tweaks (GH-29575) * Split exit paths into exceptional and non-exceptional. * Move exit tracing code to individual bytecodes. * Wrap all trace entry and exit events in macros to make them clearer and easier to enhance. * Move return sequence into RETURN_VALUE, YIELD_VALUE and YIELD_FROM. Distinguish between normal trace events and dtrace events. files: M Include/internal/pycore_code.h M Include/internal/pycore_frame.h M Python/ceval.c diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index 194af46a3a274..d4d1392d05bde 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -137,24 +137,25 @@ _GetSpecializedCacheEntryForInstruction(const _Py_CODEUNIT *first_instr, int nex #define QUICKENING_INITIAL_WARMUP_VALUE (-QUICKENING_WARMUP_DELAY) #define QUICKENING_WARMUP_COLDEST 1 -static inline void -PyCodeObject_IncrementWarmup(PyCodeObject * co) -{ - co->co_warmup++; -} +int _Py_Quicken(PyCodeObject *code); -/* Used by the interpreter to determine when a code object should be quickened */ +/* Returns 1 if quickening occurs. + * -1 if an error occurs + * 0 otherwise */ static inline int -PyCodeObject_IsWarmedUp(PyCodeObject * co) +_Py_IncrementCountAndMaybeQuicken(PyCodeObject *code) { - return (co->co_warmup == 0); + if (code->co_warmup != 0) { + code->co_warmup++; + if (code->co_warmup == 0) { + return _Py_Quicken(code) ? -1 : 1; + } + } + return 0; } -int _Py_Quicken(PyCodeObject *code); - extern Py_ssize_t _Py_QuickenedCount; - /* "Locals plus" for a code object is the set of locals + cell vars + * free vars. This relates to variable names as well as offsets into * the "fast locals" storage array of execution frames. The compiler diff --git a/Include/internal/pycore_frame.h b/Include/internal/pycore_frame.h index 0015de8f8fcb4..b0e51a6ddc461 100644 --- a/Include/internal/pycore_frame.h +++ b/Include/internal/pycore_frame.h @@ -19,6 +19,11 @@ enum _framestate { typedef signed char PyFrameState; +/* + frame->f_lasti refers to the index of the last instruction, + unless it's -1 in which case next_instr should be first_instr. +*/ + typedef struct _interpreter_frame { PyFunctionObject *f_func; /* Strong reference */ PyObject *f_globals; /* Borrowed reference */ diff --git a/Python/ceval.c b/Python/ceval.c index c5477b30f7e56..97c684479abdc 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -102,8 +102,8 @@ static InterpreterFrame * _PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func, PyObject *locals, PyObject* const* args, size_t argcount, PyObject *kwnames); -static int -_PyEvalFrameClearAndPop(PyThreadState *tstate, InterpreterFrame * frame); +static void +_PyEvalFrameClearAndPop(PyThreadState *tstate, InterpreterFrame *frame); #define NAME_ERROR_MSG \ "name '%.200s' is not defined" @@ -1390,7 +1390,7 @@ eval_frame_handle_pending(PyThreadState *tstate) /* Get opcode and oparg from original instructions, not quickened form. */ #define TRACING_NEXTOPARG() do { \ - _Py_CODEUNIT word = ((_Py_CODEUNIT *)PyBytes_AS_STRING(co->co_code))[INSTR_OFFSET()]; \ + _Py_CODEUNIT word = ((_Py_CODEUNIT *)PyBytes_AS_STRING(frame->f_code->co_code))[INSTR_OFFSET()]; \ opcode = _Py_OPCODE(word); \ oparg = _Py_OPARG(word); \ } while (0) @@ -1462,20 +1462,20 @@ eval_frame_handle_pending(PyThreadState *tstate) #ifdef LLTRACE #define PUSH(v) { (void)(BASIC_PUSH(v), \ lltrace && prtrace(tstate, TOP(), "push")); \ - assert(STACK_LEVEL() <= co->co_stacksize); } + assert(STACK_LEVEL() <= frame->f_code->co_stacksize); } #define POP() ((void)(lltrace && prtrace(tstate, TOP(), "pop")), \ BASIC_POP()) #define STACK_GROW(n) do { \ assert(n >= 0); \ (void)(BASIC_STACKADJ(n), \ lltrace && prtrace(tstate, TOP(), "stackadj")); \ - assert(STACK_LEVEL() <= co->co_stacksize); \ + assert(STACK_LEVEL() <= frame->f_code->co_stacksize); \ } while (0) #define STACK_SHRINK(n) do { \ assert(n >= 0); \ (void)(lltrace && prtrace(tstate, TOP(), "stackadj")); \ (void)(BASIC_STACKADJ(-(n))); \ - assert(STACK_LEVEL() <= co->co_stacksize); \ + assert(STACK_LEVEL() <= frame->f_code->co_stacksize); \ } while (0) #define EXT_POP(STACK_POINTER) ((void)(lltrace && \ prtrace(tstate, (STACK_POINTER)[-1], "ext_pop")), \ @@ -1537,6 +1537,40 @@ eval_frame_handle_pending(PyThreadState *tstate) STAT_INC(LOAD_##attr_or_method, hit); \ Py_INCREF(res); +#define TRACE_FUNCTION_EXIT() \ + if (cframe.use_tracing) { \ + if (trace_function_exit(tstate, frame, retval)) { \ + Py_DECREF(retval); \ + goto exit_unwind; \ + } \ + } + +#define DTRACE_FUNCTION_EXIT() \ + if (PyDTrace_FUNCTION_RETURN_ENABLED()) { \ + dtrace_function_return(frame); \ + } + +#define TRACE_FUNCTION_UNWIND() \ + if (cframe.use_tracing) { \ + /* Since we are already unwinding, \ + * we dont't care if this raises */ \ + trace_function_exit(tstate, frame, NULL); \ + } + +#define TRACE_FUNCTION_ENTRY() \ + if (cframe.use_tracing) { \ + if (trace_function_entry(tstate, frame)) { \ + goto exit_unwind; \ + } \ + } + +#define DTRACE_FUNCTION_ENTRY() \ + if (PyDTrace_FUNCTION_ENTRY_ENABLED()) { \ + dtrace_function_entry(frame); \ + } + + + static int trace_function_entry(PyThreadState *tstate, InterpreterFrame *frame) { @@ -1576,6 +1610,24 @@ trace_function_entry(PyThreadState *tstate, InterpreterFrame *frame) return 0; } +static int +trace_function_exit(PyThreadState *tstate, InterpreterFrame *frame, PyObject *retval) +{ + if (tstate->c_tracefunc) { + if (call_trace_protected(tstate->c_tracefunc, tstate->c_traceobj, + tstate, frame, PyTrace_RETURN, retval)) { + return -1; + } + } + if (tstate->c_profilefunc) { + if (call_trace_protected(tstate->c_profilefunc, tstate->c_profileobj, + tstate, frame, PyTrace_RETURN, retval)) { + return -1; + } + } + return 0; +} + static PyObject * make_coro(PyThreadState *tstate, PyFunctionObject *func, PyObject *locals, @@ -1583,7 +1635,8 @@ make_coro(PyThreadState *tstate, PyFunctionObject *func, PyObject *kwnames); static int -skip_backwards_over_extended_args(PyCodeObject *code, int offset) { +skip_backwards_over_extended_args(PyCodeObject *code, int offset) +{ _Py_CODEUNIT *instrs = (_Py_CODEUNIT *)PyBytes_AS_STRING(code->co_code); while (offset > 0 && _Py_OPCODE(instrs[offset-1]) == EXTENDED_ARG) { offset--; @@ -1591,6 +1644,14 @@ skip_backwards_over_extended_args(PyCodeObject *code, int offset) { return offset; } +static InterpreterFrame * +pop_frame(PyThreadState *tstate, InterpreterFrame *frame) +{ + InterpreterFrame *prev_frame = frame->previous; + _PyEvalFrameClearAndPop(tstate, frame); + return prev_frame; +} + PyObject* _Py_HOT_FUNCTION _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int throwflag) { @@ -1606,7 +1667,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr #endif int opcode; /* Current opcode */ int oparg; /* Current opcode argument, if any */ - PyObject *retval = NULL; /* Return value */ _Py_atomic_int * const eval_breaker = &tstate->interp->ceval.eval_breaker; CFrame cframe; @@ -1625,82 +1685,77 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr frame->previous = prev_cframe->current_frame; cframe.current_frame = frame; + /* support for generator.throw() */ + if (throwflag) { + if (_Py_EnterRecursiveCall(tstate, "")) { + tstate->recursion_remaining--; + goto exit_unwind; + } + TRACE_FUNCTION_ENTRY(); + DTRACE_FUNCTION_ENTRY(); + goto resume_with_error; + } + + /* Local "register" variables. + * These are cached values from the frame and code object. */ + + PyObject *names; + PyObject *consts; + _Py_CODEUNIT *first_instr; + _Py_CODEUNIT *next_instr; + PyObject **stack_pointer; + +/* Sets the above local variables from the frame */ +#define SET_LOCALS_FROM_FRAME() \ + { \ + PyCodeObject *co = frame->f_code; \ + names = co->co_names; \ + consts = co->co_consts; \ + first_instr = co->co_firstinstr; \ + } \ + assert(frame->f_lasti >= -1); \ + next_instr = first_instr + frame->f_lasti + 1; \ + stack_pointer = _PyFrame_GetStackPointer(frame); \ + /* Set stackdepth to -1. \ + Update when returning or calling trace function. \ + Having stackdepth <= 0 ensures that invalid \ + values are not visible to the cycle GC. \ + We choose -1 rather than 0 to assist debugging. \ + */ \ + frame->stacktop = -1; + + start_frame: if (_Py_EnterRecursiveCall(tstate, "")) { tstate->recursion_remaining--; - goto exit_eval_frame; + goto exit_unwind; } assert(tstate->cframe == &cframe); assert(frame == cframe.current_frame); - if (cframe.use_tracing) { - if (trace_function_entry(tstate, frame)) { - goto exit_eval_frame; - } - } - - if (PyDTrace_FUNCTION_ENTRY_ENABLED()) - dtrace_function_entry(frame); + TRACE_FUNCTION_ENTRY(); + DTRACE_FUNCTION_ENTRY(); - PyCodeObject *co = frame->f_code; - /* Increment the warmup counter and quicken if warm enough - * _Py_Quicken is idempotent so we don't worry about overflow */ - if (!PyCodeObject_IsWarmedUp(co)) { - PyCodeObject_IncrementWarmup(co); - if (PyCodeObject_IsWarmedUp(co)) { - if (_Py_Quicken(co)) { - goto exit_eval_frame; - } - } + if (_Py_IncrementCountAndMaybeQuicken(frame->f_code) < 0) { + goto exit_unwind; } + frame->f_state = FRAME_EXECUTING; resume_frame: - co = frame->f_code; - PyObject *names = co->co_names; - PyObject *consts = co->co_consts; - _Py_CODEUNIT *first_instr = co->co_firstinstr; - /* - frame->f_lasti refers to the index of the last instruction, - unless it's -1 in which case next_instr should be first_instr. - - YIELD_FROM sets frame->f_lasti to itself, in order to repeatedly yield - multiple values. - - When the PREDICT() macros are enabled, some opcode pairs follow in - direct succession. A successful prediction effectively links the two - codes together as if they were a single new opcode, but the value - of frame->f_lasti is correctly updated so potential inlined calls - or lookups of frame->f_lasti are aways correct when the macros are used. - */ - assert(frame->f_lasti >= -1); - _Py_CODEUNIT *next_instr = first_instr + frame->f_lasti + 1; - PyObject **stack_pointer = _PyFrame_GetStackPointer(frame); - /* Set stackdepth to -1. - * Update when returning or calling trace function. - Having stackdepth <= 0 ensures that invalid - values are not visible to the cycle GC. - We choose -1 rather than 0 to assist debugging. - */ - frame->stacktop = -1; - frame->f_state = FRAME_EXECUTING; + SET_LOCALS_FROM_FRAME(); #ifdef LLTRACE _Py_IDENTIFIER(__ltrace__); { int r = _PyDict_ContainsId(GLOBALS(), &PyId___ltrace__); if (r < 0) { - goto exit_eval_frame; + goto exit_unwind; } lltrace = r; } #endif - if (throwflag) { /* support for generator.throw() */ - throwflag = 0; - goto error; - } - #ifdef Py_DEBUG /* _PyEval_EvalFrameDefault() must not be called with an exception set, because it can clear it (directly or indirectly) and so the @@ -1711,7 +1766,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr check_eval_breaker: { assert(STACK_LEVEL() >= 0); /* else underflow */ - assert(STACK_LEVEL() <= co->co_stacksize); /* else overflow */ + assert(STACK_LEVEL() <= frame->f_code->co_stacksize); /* else overflow */ assert(!_PyErr_Occurred(tstate)); /* Do periodic things. Doing this every time through @@ -2418,11 +2473,24 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr } TARGET(RETURN_VALUE) { - retval = POP(); + PyObject *retval = POP(); assert(EMPTY()); frame->f_state = FRAME_RETURNED; _PyFrame_SetStackPointer(frame, stack_pointer); - goto exiting; + TRACE_FUNCTION_EXIT(); + DTRACE_FUNCTION_EXIT(); + _Py_LeaveRecursiveCall(tstate); + if (frame->depth) { + frame = cframe.current_frame = pop_frame(tstate, frame); + _PyFrame_StackPush(frame, retval); + goto resume_frame; + } + /* Restore previous cframe and return. */ + tstate->cframe = cframe.previous; + tstate->cframe->use_tracing = cframe.use_tracing; + assert(tstate->cframe->current_frame == frame->previous); + assert(!_PyErr_Occurred(tstate)); + return retval; } TARGET(GET_AITER) { @@ -2562,9 +2630,11 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr } TARGET(YIELD_FROM) { + assert(frame->depth == 0); PyObject *v = POP(); PyObject *receiver = TOP(); PySendResult gen_status; + PyObject *retval; if (tstate->c_tracefunc == NULL) { gen_status = PyIter_Send(receiver, v, &retval); } else { @@ -2610,13 +2680,22 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr frame->f_lasti -= 1; frame->f_state = FRAME_SUSPENDED; _PyFrame_SetStackPointer(frame, stack_pointer); - goto exiting; + TRACE_FUNCTION_EXIT(); + DTRACE_FUNCTION_EXIT(); + _Py_LeaveRecursiveCall(tstate); + /* Restore previous cframe and return. */ + tstate->cframe = cframe.previous; + tstate->cframe->use_tracing = cframe.use_tracing; + assert(tstate->cframe->current_frame == frame->previous); + assert(!_PyErr_Occurred(tstate)); + return retval; } TARGET(YIELD_VALUE) { - retval = POP(); + assert(frame->depth == 0); + PyObject *retval = POP(); - if (co->co_flags & CO_ASYNC_GENERATOR) { + if (frame->f_code->co_flags & CO_ASYNC_GENERATOR) { PyObject *w = _PyAsyncGenValueWrapperNew(retval); Py_DECREF(retval); if (w == NULL) { @@ -2627,7 +2706,15 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr } frame->f_state = FRAME_SUSPENDED; _PyFrame_SetStackPointer(frame, stack_pointer); - goto exiting; + TRACE_FUNCTION_EXIT(); + DTRACE_FUNCTION_EXIT(); + _Py_LeaveRecursiveCall(tstate); + /* Restore previous cframe and return. */ + tstate->cframe = cframe.previous; + tstate->cframe->use_tracing = cframe.use_tracing; + assert(tstate->cframe->current_frame == frame->previous); + assert(!_PyErr_Occurred(tstate)); + return retval; } TARGET(GEN_START) { @@ -3100,7 +3187,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr format_exc_check_arg( tstate, PyExc_UnboundLocalError, UNBOUNDLOCAL_ERROR_MSG, - PyTuple_GetItem(co->co_localsplusnames, oparg) + PyTuple_GetItem(frame->f_code->co_localsplusnames, oparg) ); goto error; } @@ -3125,15 +3212,15 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr Py_DECREF(oldobj); DISPATCH(); } - format_exc_unbound(tstate, co, oparg); + format_exc_unbound(tstate, frame->f_code, oparg); goto error; } TARGET(LOAD_CLASSDEREF) { PyObject *name, *value, *locals = LOCALS(); assert(locals); - assert(oparg >= 0 && oparg < co->co_nlocalsplus); - name = PyTuple_GET_ITEM(co->co_localsplusnames, oparg); + assert(oparg >= 0 && oparg < frame->f_code->co_nlocalsplus); + name = PyTuple_GET_ITEM(frame->f_code->co_localsplusnames, oparg); if (PyDict_CheckExact(locals)) { value = PyDict_GetItemWithError(locals, name); if (value != NULL) { @@ -3156,7 +3243,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr PyObject *cell = GETLOCAL(oparg); value = PyCell_GET(cell); if (value == NULL) { - format_exc_unbound(tstate, co, oparg); + format_exc_unbound(tstate, frame->f_code, oparg); goto error; } Py_INCREF(value); @@ -3169,7 +3256,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr PyObject *cell = GETLOCAL(oparg); PyObject *value = PyCell_GET(cell); if (value == NULL) { - format_exc_unbound(tstate, co, oparg); + format_exc_unbound(tstate, frame->f_code, oparg); goto error; } Py_INCREF(value); @@ -3918,18 +4005,15 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr TARGET(JUMP_ABSOLUTE) { PREDICTED(JUMP_ABSOLUTE); assert(oparg < INSTR_OFFSET()); - /* Increment the warmup counter and quicken if warm enough - * _Py_Quicken is idempotent so we don't worry about overflow */ - if (!PyCodeObject_IsWarmedUp(co)) { - PyCodeObject_IncrementWarmup(co); - if (PyCodeObject_IsWarmedUp(co)) { - if (_Py_Quicken(co)) { - goto error; - } - int nexti = INSTR_OFFSET(); - first_instr = co->co_firstinstr; - next_instr = first_instr + nexti; + int err = _Py_IncrementCountAndMaybeQuicken(frame->f_code); + if (err) { + if (err < 0) { + goto error; } + /* Update first_instr and next_instr to point to newly quickened code */ + int nexti = INSTR_OFFSET(); + first_instr = frame->f_code->co_firstinstr; + next_instr = first_instr + nexti; } JUMPTO(oparg); CHECK_EVAL_BREAKER(); @@ -4036,7 +4120,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr PyObject *iter; if (PyCoro_CheckExact(iterable)) { /* `iterable` is a coroutine */ - if (!(co->co_flags & (CO_COROUTINE | CO_ITERABLE_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); @@ -4906,7 +4990,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr #else case DO_TRACING: { #endif - int instr_prev = skip_backwards_over_extended_args(co, frame->f_lasti); + int instr_prev = skip_backwards_over_extended_args(frame->f_code, frame->f_lasti); frame->f_lasti = INSTR_OFFSET(); TRACING_NEXTOPARG(); if (PyDTrace_LINE_ENABLED()) { @@ -5016,7 +5100,7 @@ MISS_WITH_OPARG_COUNTER(STORE_SUBSCR) { format_exc_check_arg(tstate, PyExc_UnboundLocalError, UNBOUNDLOCAL_ERROR_MSG, - PyTuple_GetItem(co->co_localsplusnames, oparg) + PyTuple_GetItem(frame->f_code->co_localsplusnames, oparg) ); goto error; } @@ -5039,8 +5123,7 @@ MISS_WITH_OPARG_COUNTER(STORE_SUBSCR) } if (tstate->c_tracefunc != NULL) { - /* Make sure state is set to FRAME_EXECUTING for tracing */ - assert(frame->f_state == FRAME_EXECUTING); + /* Make sure state is set to FRAME_UNWINDING for tracing */ frame->f_state = FRAME_UNWINDING; call_exc_trace(tstate->c_tracefunc, tstate->c_traceobj, tstate, frame); @@ -5051,9 +5134,8 @@ MISS_WITH_OPARG_COUNTER(STORE_SUBSCR) /* We can't use frame->f_lasti here, as RERAISE may have set it */ int offset = INSTR_OFFSET()-1; int level, handler, lasti; - if (get_exception_handler(co, offset, &level, &handler, &lasti) == 0) { + if (get_exception_handler(frame->f_code, offset, &level, &handler, &lasti) == 0) { // No handlers, so exit. - assert(retval == NULL); assert(_PyErr_Occurred(tstate)); /* Pop remaining stack entries. */ @@ -5065,7 +5147,9 @@ MISS_WITH_OPARG_COUNTER(STORE_SUBSCR) assert(STACK_LEVEL() == 0); _PyFrame_SetStackPointer(frame, stack_pointer); frame->f_state = FRAME_RAISED; - goto exiting; + TRACE_FUNCTION_UNWIND(); + DTRACE_FUNCTION_EXIT(); + goto exit_unwind; } assert(STACK_LEVEL() >= level); @@ -5106,48 +5190,22 @@ MISS_WITH_OPARG_COUNTER(STORE_SUBSCR) DISPATCH(); } -exiting: - if (cframe.use_tracing) { - if (tstate->c_tracefunc) { - if (call_trace_protected(tstate->c_tracefunc, tstate->c_traceobj, - tstate, frame, PyTrace_RETURN, retval)) { - Py_CLEAR(retval); - } - } - if (tstate->c_profilefunc) { - if (call_trace_protected(tstate->c_profilefunc, tstate->c_profileobj, - tstate, frame, PyTrace_RETURN, retval)) { - Py_CLEAR(retval); - } - } - } - - /* pop frame */ -exit_eval_frame: - if (PyDTrace_FUNCTION_RETURN_ENABLED()) - dtrace_function_return(frame); +exit_unwind: + assert(_PyErr_Occurred(tstate)); _Py_LeaveRecursiveCall(tstate); - - if (frame->depth) { - cframe.current_frame = frame->previous; - _PyFrame_StackPush(cframe.current_frame, retval); - if (_PyEvalFrameClearAndPop(tstate, frame)) { - retval = NULL; - } - frame = cframe.current_frame; - if (retval == NULL) { - assert(_PyErr_Occurred(tstate)); - throwflag = 1; - } - retval = NULL; - goto resume_frame; + if (frame->depth == 0) { + /* Restore previous cframe and exit */ + tstate->cframe = cframe.previous; + tstate->cframe->use_tracing = cframe.use_tracing; + assert(tstate->cframe->current_frame == frame->previous); + return NULL; } + frame = cframe.current_frame = pop_frame(tstate, frame); + +resume_with_error: + SET_LOCALS_FROM_FRAME(); + goto error; - /* Restore previous cframe. */ - tstate->cframe = cframe.previous; - tstate->cframe->use_tracing = cframe.use_tracing; - assert(tstate->cframe->current_frame == frame->previous); - return _Py_CheckFunctionResult(tstate, NULL, retval, __func__); } static void @@ -5770,15 +5828,14 @@ _PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func, return NULL; } -static int +static void _PyEvalFrameClearAndPop(PyThreadState *tstate, InterpreterFrame * frame) { - --tstate->recursion_remaining; + tstate->recursion_remaining--; assert(frame->frame_obj == NULL || frame->frame_obj->f_owns_frame == 0); _PyFrame_Clear(frame); - ++tstate->recursion_remaining; + tstate->recursion_remaining++; _PyThreadState_PopFrame(tstate, frame); - return 0; } PyObject * @@ -5812,9 +5869,7 @@ _PyEval_Vector(PyThreadState *tstate, PyFunctionObject *func, } PyObject *retval = _PyEval_EvalFrame(tstate, frame, 0); assert(_PyFrame_GetStackPointer(frame) == _PyFrame_Stackbase(frame)); - if (_PyEvalFrameClearAndPop(tstate, frame)) { - retval = NULL; - } + _PyEvalFrameClearAndPop(tstate, frame); return retval; } From webhook-mailer at python.org Wed Dec 1 07:24:55 2021 From: webhook-mailer at python.org (asvetlov) Date: Wed, 01 Dec 2021 12:24:55 -0000 Subject: [Python-checkins] bpo-45896: Fix docs default asyncio event loop on Windows (GH-29857) Message-ID: https://github.com/python/cpython/commit/f27bef30438d2f07f19de91e021f34b77ccc4b20 commit: f27bef30438d2f07f19de91e021f34b77ccc4b20 branch: main author: Rob committer: asvetlov date: 2021-12-01T14:24:46+02:00 summary: bpo-45896: Fix docs default asyncio event loop on Windows (GH-29857) files: M Doc/library/asyncio-eventloop.rst diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index 5a3369415a745..497128ee17f37 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -1243,9 +1243,10 @@ async/await code consider using the high-level .. note:: - The default asyncio event loop on **Windows** does not support - subprocesses. See :ref:`Subprocess Support on Windows - ` for details. + On Windows, the default event loop :class:`ProactorEventLoop` supports + subprocesses, whereas :class:`SelectorEventLoop` does not. See + :ref:`Subprocess Support on Windows ` for + details. .. coroutinemethod:: loop.subprocess_exec(protocol_factory, *args, \ stdin=subprocess.PIPE, stdout=subprocess.PIPE, \ From webhook-mailer at python.org Wed Dec 1 10:40:59 2021 From: webhook-mailer at python.org (asvetlov) Date: Wed, 01 Dec 2021 15:40:59 -0000 Subject: [Python-checkins] bpo-45896: Fix docs default asyncio event loop on Windows (GH-29857) (GH-29878) Message-ID: https://github.com/python/cpython/commit/4203a5d1918ca874e305806b787e3c8c6fc35e3e commit: 4203a5d1918ca874e305806b787e3c8c6fc35e3e branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: asvetlov date: 2021-12-01T17:40:50+02:00 summary: bpo-45896: Fix docs default asyncio event loop on Windows (GH-29857) (GH-29878) (cherry picked from commit f27bef30438d2f07f19de91e021f34b77ccc4b20) Co-authored-by: Rob Co-authored-by: Rob files: M Doc/library/asyncio-eventloop.rst diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index d70aeae766ae3..73799d005c157 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -1239,9 +1239,10 @@ async/await code consider using the high-level .. note:: - The default asyncio event loop on **Windows** does not support - subprocesses. See :ref:`Subprocess Support on Windows - ` for details. + On Windows, the default event loop :class:`ProactorEventLoop` supports + subprocesses, whereas :class:`SelectorEventLoop` does not. See + :ref:`Subprocess Support on Windows ` for + details. .. coroutinemethod:: loop.subprocess_exec(protocol_factory, *args, \ stdin=subprocess.PIPE, stdout=subprocess.PIPE, \ From webhook-mailer at python.org Wed Dec 1 10:44:18 2021 From: webhook-mailer at python.org (asvetlov) Date: Wed, 01 Dec 2021 15:44:18 -0000 Subject: [Python-checkins] bpo-45896: Fix docs default asyncio event loop on Windows (GH-29857) (GH-29877) Message-ID: https://github.com/python/cpython/commit/e99c5e039b380199843db4e06974883d9f3ddad0 commit: e99c5e039b380199843db4e06974883d9f3ddad0 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: asvetlov date: 2021-12-01T17:44:09+02:00 summary: bpo-45896: Fix docs default asyncio event loop on Windows (GH-29857) (GH-29877) (cherry picked from commit f27bef30438d2f07f19de91e021f34b77ccc4b20) Co-authored-by: Rob files: M Doc/library/asyncio-eventloop.rst diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index 44798dc3e23cb..252fb426e5b39 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -1247,9 +1247,10 @@ async/await code consider using the high-level .. note:: - The default asyncio event loop on **Windows** does not support - subprocesses. See :ref:`Subprocess Support on Windows - ` for details. + On Windows, the default event loop :class:`ProactorEventLoop` supports + subprocesses, whereas :class:`SelectorEventLoop` does not. See + :ref:`Subprocess Support on Windows ` for + details. .. coroutinemethod:: loop.subprocess_exec(protocol_factory, *args, \ stdin=subprocess.PIPE, stdout=subprocess.PIPE, \ From webhook-mailer at python.org Wed Dec 1 13:20:37 2021 From: webhook-mailer at python.org (ericsnowcurrently) Date: Wed, 01 Dec 2021 18:20:37 -0000 Subject: [Python-checkins] bpo-45952: Get the C analyzer tool working again. (gh-29882) Message-ID: https://github.com/python/cpython/commit/ee94aa0850191712e6adfc1f4a9df08ec3240195 commit: ee94aa0850191712e6adfc1f4a9df08ec3240195 branch: main author: Eric Snow committer: ericsnowcurrently date: 2021-12-01T11:20:20-07:00 summary: bpo-45952: Get the C analyzer tool working again. (gh-29882) There wasn't much that needed to be done. Mostly it was just a few new files that got added. https://bugs.python.org/issue45952 files: M Tools/c-analyzer/TODO M Tools/c-analyzer/c_parser/__init__.py M Tools/c-analyzer/c_parser/parser/__init__.py M Tools/c-analyzer/c_parser/preprocessor/__main__.py M Tools/c-analyzer/cpython/__main__.py M Tools/c-analyzer/cpython/_parser.py diff --git a/Tools/c-analyzer/TODO b/Tools/c-analyzer/TODO index 1fd8052268be0..4b9b2857e1d1e 100644 --- a/Tools/c-analyzer/TODO +++ b/Tools/c-analyzer/TODO @@ -1,3 +1,11 @@ +# For up-to-date results, run: +# ./python Tools/c-analyzer/c-analyzer.py check --format summary +# or +# ./python Tools/c-analyzer/c-analyzer.py analyze + + +####################################### +# non-PyObject (61) # allocator (16) Objects/obmalloc.c:_PyMem static PyMemAllocatorEx _PyMem @@ -32,12 +40,7 @@ Objects/dictobject.c:empty_keys_struct static PyDictKe Python/fileutils.c:_Py_open_cloexec_works int _Py_open_cloexec_works -# freelists -Objects/dictobject.c:keys_free_list static PyDictKeysObject *keys_free_list[PyDict_MAXFREELIST] -Objects/dictobject.c:numfreekeys static int numfreekeys - - -# other non-object (43) +# other non-object (40) Modules/_tracemalloc.c:allocators static struct { PyMemAllocatorEx mem; PyMemAllocatorEx raw; PyMemAllocatorEx obj; } allocators Modules/_tracemalloc.c:tables_lock static PyThread_type_lock tables_lock Modules/_tracemalloc.c:tracemalloc_filenames static _Py_hashtable_t *tracemalloc_filenames @@ -81,30 +84,7 @@ Python/pylifecycle.c:fatal_error():reentrant static int reen ####################################### -# PyObject (960) - -# freelists (10 + 10) -Modules/_collectionsmodule.c:freeblocks static block *freeblocks[MAXFREEBLOCKS] -Modules/_collectionsmodule.c:numfreeblocks static Py_ssize_t numfreeblocks -Objects/dictobject.c:free_list static PyDictObject *free_list[PyDict_MAXFREELIST] -Objects/dictobject.c:numfree static int numfree -Objects/exceptions.c:memerrors_freelist static PyBaseExceptionObject *memerrors_freelist -Objects/exceptions.c:memerrors_numfree static int memerrors_numfree -Objects/floatobject.c:free_list static PyFloatObject *free_list -Objects/floatobject.c:numfree static int numfree -Objects/frameobject.c:free_list static PyFrameObject *free_list -Objects/frameobject.c:numfree static int numfree -Objects/genobject.c:ag_asend_freelist static PyAsyncGenASend *ag_asend_freelist[_PyAsyncGen_MAXFREELIST] -Objects/genobject.c:ag_asend_freelist_free static int ag_asend_freelist_free -Objects/genobject.c:ag_value_freelist static _PyAsyncGenWrappedValue *ag_value_freelist[_PyAsyncGen_MAXFREELIST] -Objects/genobject.c:ag_value_freelist_free static int ag_value_freelist_free -Objects/listobject.c:free_list static PyListObject *free_list[PyList_MAXFREELIST] -Objects/listobject.c:numfree static int numfree -Objects/tupleobject.c:free_list static PyTupleObject *free_list[PyTuple_MAXSAVESIZE] -Objects/tupleobject.c:numfree static int numfree[PyTuple_MAXSAVESIZE] -Python/context.c:ctx_freelist static PyContext *ctx_freelist -Python/context.c:ctx_freelist_len static int ctx_freelist_len - +# PyObject (919) # singletons (7) Objects/boolobject.c:_Py_FalseStruct static struct _longobject _Py_FalseStruct @@ -116,16 +96,8 @@ Objects/object.c:_Py_NotImplementedStruct PyObject _Py_No Objects/sliceobject.c:_Py_EllipsisObject PyObject _Py_EllipsisObject -# module vars (9) -Modules/_functoolsmodule.c:kwd_mark static PyObject *kwd_mark -Modules/_localemodule.c:Error static PyObject *Error -Modules/_threadmodule.c:ThreadError static PyObject *ThreadError +# module vars (1) Modules/_tracemalloc.c:unknown_filename static PyObject *unknown_filename -Modules/signalmodule.c:DefaultHandler static PyObject *DefaultHandler -Modules/signalmodule.c:IgnoreHandler static PyObject *IgnoreHandler -Modules/signalmodule.c:IntHandler static PyObject *IntHandler -Modules/signalmodule.c:ItimerError static PyObject *ItimerError -Objects/exceptions.c:errnomap static PyObject *errnomap # other (non-cache) (5) @@ -136,26 +108,15 @@ Modules/signalmodule.c:Handlers static volatile Objects/setobject.c:_dummy_struct static PyObject _dummy_struct -# caches (5) -Modules/posixmodule.c:posix_putenv_garbage static PyObject *posix_putenv_garbage -Objects/sliceobject.c:slice_cache static PySliceObject *slice_cache -Objects/typeobject.c:method_cache static struct method_cache_entry method_cache[1 << MCACHE_SIZE_EXP] -Objects/unicodeobject.c:interned static PyObject *interned +# caches (1) Python/import.c:extensions static PyObject *extensions -# cached constants - non-str (15) +# cached constants - non-str (6) Modules/_io/_iomodule.c:_PyIO_empty_bytes PyObject *_PyIO_empty_bytes Modules/_io/bufferedio.c:_PyIO_trap_eintr():eintr_int static PyObject *eintr_int -Modules/posixmodule.c:billion static PyObject *billion -Modules/posixmodule.c:wait_helper():struct_rusage static PyObject *struct_rusage -Objects/bytesobject.c:characters static PyBytesObject *characters[UCHAR_MAX + 1] -Objects/bytesobject.c:nullstring static PyBytesObject *nullstring -Objects/codeobject.c:PyCode_NewEmpty():nulltuple static PyObject *nulltuple -Objects/dictobject.c:empty_values static PyObject *empty_values[1] +Objects/dictobject.c:empty_values_struct static PyDictValues Objects/listobject.c:indexerr static PyObject *indexerr -Objects/longobject.c:small_ints static PyLongObject small_ints[NSMALLNEGINTS + NSMALLPOSINTS] -Objects/setobject.c:emptyfrozenset static PyObject *emptyfrozenset Python/context.c:_token_missing static PyObject *_token_missing Python/hamt.c:_empty_hamt static PyHamtObject *_empty_hamt @@ -662,15 +623,6 @@ Modules/itertoolsmodule.c:takewhile_type static PyTypeOb Modules/itertoolsmodule.c:tee_type static PyTypeObject tee_type Modules/itertoolsmodule.c:teedataobject_type static PyTypeObject teedataobject_type Modules/itertoolsmodule.c:ziplongest_type static PyTypeObject ziplongest_type -Modules/posixmodule.c:DirEntryType static PyTypeObject DirEntryType -Modules/posixmodule.c:ScandirIteratorType static PyTypeObject ScandirIteratorType -Modules/posixmodule.c:SchedParamType static PyTypeObject* SchedParamType -Modules/posixmodule.c:StatResultType static PyTypeObject* StatResultType -Modules/posixmodule.c:StatVFSResultType static PyTypeObject* StatVFSResultType -Modules/posixmodule.c:TerminalSizeType static PyTypeObject* TerminalSizeType -Modules/posixmodule.c:TimesResultType static PyTypeObject* TimesResultType -Modules/posixmodule.c:UnameResultType static PyTypeObject* UnameResultType -Modules/posixmodule.c:WaitidResultType static PyTypeObject* WaitidResultType Modules/signalmodule.c:SiginfoType static PyTypeObject SiginfoType Modules/timemodule.c:StructTimeType static PyTypeObject StructTimeType Modules/xxsubtype.c:spamdict_type static PyTypeObject spamdict_type diff --git a/Tools/c-analyzer/c_parser/__init__.py b/Tools/c-analyzer/c_parser/__init__.py index 39455ddbf1a0c..fc10aff94505d 100644 --- a/Tools/c-analyzer/c_parser/__init__.py +++ b/Tools/c-analyzer/c_parser/__init__.py @@ -1,3 +1,4 @@ +from c_common.fsutil import match_glob as _match_glob from .parser import parse as _parse from .preprocessor import get_preprocessor as _get_preprocessor @@ -5,23 +6,32 @@ def parse_file(filename, *, match_kind=None, get_file_preprocessor=None, + file_maxsizes=None, ): if get_file_preprocessor is None: get_file_preprocessor = _get_preprocessor() - yield from _parse_file(filename, match_kind, get_file_preprocessor) + yield from _parse_file( + filename, match_kind, get_file_preprocessor, file_maxsizes) def parse_files(filenames, *, match_kind=None, get_file_preprocessor=None, + file_maxsizes=None, ): if get_file_preprocessor is None: get_file_preprocessor = _get_preprocessor() for filename in filenames: - yield from _parse_file(filename, match_kind, get_file_preprocessor) + yield from _parse_file( + filename, match_kind, get_file_preprocessor, file_maxsizes) -def _parse_file(filename, match_kind, get_file_preprocessor): +def _parse_file(filename, match_kind, get_file_preprocessor, maxsizes): + srckwargs = {} + maxsize = _resolve_max_size(filename, maxsizes) + if maxsize: + srckwargs['maxtext'], srckwargs['maxlines'] = maxsize + # Preprocess the file. preprocess = get_file_preprocessor(filename) preprocessed = preprocess() @@ -30,7 +40,7 @@ def _parse_file(filename, match_kind, get_file_preprocessor): # Parse the lines. srclines = ((l.file, l.data) for l in preprocessed if l.kind == 'source') - for item in _parse(srclines): + for item in _parse(srclines, **srckwargs): if match_kind is not None and not match_kind(item.kind): continue if not item.filename: @@ -38,6 +48,22 @@ def _parse_file(filename, match_kind, get_file_preprocessor): yield item +def _resolve_max_size(filename, maxsizes): + for pattern, maxsize in (maxsizes.items() if maxsizes else ()): + if _match_glob(filename, pattern): + break + else: + return None + if not maxsize: + return None, None + maxtext, maxlines = maxsize + if maxtext is not None: + maxtext = int(maxtext) + if maxlines is not None: + maxlines = int(maxlines) + return maxtext, maxlines + + def parse_signature(text): raise NotImplementedError diff --git a/Tools/c-analyzer/c_parser/parser/__init__.py b/Tools/c-analyzer/c_parser/parser/__init__.py index df70aae66b776..b5eae2ed92d0d 100644 --- a/Tools/c-analyzer/c_parser/parser/__init__.py +++ b/Tools/c-analyzer/c_parser/parser/__init__.py @@ -120,12 +120,12 @@ from ._info import SourceInfo -def parse(srclines): +def parse(srclines, **srckwargs): if isinstance(srclines, str): # a filename raise NotImplementedError anon_name = anonymous_names() - for result in _parse(srclines, anon_name): + for result in _parse(srclines, anon_name, **srckwargs): yield ParsedItem.from_raw(result) @@ -152,17 +152,19 @@ def anon_name(prefix='anon-'): _logger = logging.getLogger(__name__) -def _parse(srclines, anon_name): +def _parse(srclines, anon_name, **srckwargs): from ._global import parse_globals - source = _iter_source(srclines) - #source = _iter_source(srclines, showtext=True) + source = _iter_source(srclines, **srckwargs) for result in parse_globals(source, anon_name): # XXX Handle blocks here instead of in parse_globals(). yield result -def _iter_source(lines, *, maxtext=20_000, maxlines=700, showtext=False): +# We use defaults that cover most files. Files with bigger declarations +# are covered elsewhere (MAX_SIZES in cpython/_parser.py). + +def _iter_source(lines, *, maxtext=10_000, maxlines=200, showtext=False): maxtext = maxtext if maxtext and maxtext > 0 else None maxlines = maxlines if maxlines and maxlines > 0 else None filestack = [] diff --git a/Tools/c-analyzer/c_parser/preprocessor/__main__.py b/Tools/c-analyzer/c_parser/preprocessor/__main__.py index bfc61949a76e4..55aa8752dce72 100644 --- a/Tools/c-analyzer/c_parser/preprocessor/__main__.py +++ b/Tools/c-analyzer/c_parser/preprocessor/__main__.py @@ -43,7 +43,7 @@ def add_common_cli(parser, *, get_preprocessor=_get_preprocessor): def process_args(args, *, argv): ns = vars(args) - process_fail_arg(args, argv) + process_fail_arg(args, argv=argv) ignore_exc = ns.pop('ignore_exc') # We later pass ignore_exc to _get_preprocessor(). diff --git a/Tools/c-analyzer/cpython/__main__.py b/Tools/c-analyzer/cpython/__main__.py index 06ec871ba75e3..be331d50427d5 100644 --- a/Tools/c-analyzer/cpython/__main__.py +++ b/Tools/c-analyzer/cpython/__main__.py @@ -111,6 +111,7 @@ def cmd_parse(filenames=None, **kwargs): c_parser.cmd_parse( filenames, relroot=REPO_ROOT, + file_maxsizes=_parser.MAX_SIZES, **kwargs ) @@ -127,6 +128,7 @@ def cmd_check(filenames=None, **kwargs): relroot=REPO_ROOT, _analyze=_analyzer.analyze, _CHECKS=CHECKS, + file_maxsizes=_parser.MAX_SIZES, **kwargs ) @@ -141,6 +143,7 @@ def cmd_analyze(filenames=None, **kwargs): relroot=REPO_ROOT, _analyze=_analyzer.analyze, formats=formats, + file_maxsizes=_parser.MAX_SIZES, **kwargs ) diff --git a/Tools/c-analyzer/cpython/_parser.py b/Tools/c-analyzer/cpython/_parser.py index 8526b2af15a23..90b470c8196c0 100644 --- a/Tools/c-analyzer/cpython/_parser.py +++ b/Tools/c-analyzer/cpython/_parser.py @@ -14,6 +14,10 @@ GLOB_ALL = '**/*' +def _abs(relfile): + return os.path.join(REPO_ROOT, relfile) + + def clean_lines(text): """Clear out comments, blank lines, and leading/trailing whitespace.""" lines = (line.strip() for line in text.splitlines()) @@ -22,7 +26,7 @@ def clean_lines(text): if line and not line.startswith('#')) glob_all = f'{GLOB_ALL} ' lines = (re.sub(r'^[*] ', glob_all, line) for line in lines) - lines = (os.path.join(REPO_ROOT, line) for line in lines) + lines = (_abs(line) for line in lines) return list(lines) @@ -55,26 +59,31 @@ def clean_lines(text): # Windows Modules/_winapi.c # windows.h +Modules/expat/winconfig.h Modules/overlapped.c # winsock.h Python/dynload_win.c # windows.h -Modules/expat/winconfig.h Python/thread_nt.h # other OS-dependent +Python/dynload_aix.c # sys/ldr.h Python/dynload_dl.c # dl.h Python/dynload_hpux.c # dl.h -Python/dynload_aix.c # sys/ldr.h Python/thread_pthread.h # only huge constants (safe but parsing is slow) +Modules/_blake2/impl/blake2-kat.h Modules/_ssl_data.h +Modules/_ssl_data_300.h +Modules/_ssl_data_111.h +Modules/cjkcodecs/mappings_*.h Modules/unicodedata_db.h Modules/unicodename_db.h -Modules/cjkcodecs/mappings_*.h Objects/unicodetype_db.h -Python/importlib.h -Python/importlib_external.h -Python/importlib_zipimport.h + +# generated +Python/frozen_modules/*.h +Python/opcode_targets.h +Python/stdlib_module_names.h # @end=conf@ ''') @@ -126,35 +135,40 @@ def clean_lines(text): Parser/**/*.c Py_BUILD_CORE 1 Objects/**/*.c Py_BUILD_CORE 1 -Modules/faulthandler.c Py_BUILD_CORE 1 +Modules/_asynciomodule.c Py_BUILD_CORE 1 +Modules/_collectionsmodule.c Py_BUILD_CORE 1 +Modules/_ctypes/_ctypes.c Py_BUILD_CORE 1 +Modules/_ctypes/cfield.c Py_BUILD_CORE 1 +Modules/_cursesmodule.c Py_BUILD_CORE 1 +Modules/_datetimemodule.c Py_BUILD_CORE 1 Modules/_functoolsmodule.c Py_BUILD_CORE 1 -Modules/gcmodule.c Py_BUILD_CORE 1 -Modules/getpath.c Py_BUILD_CORE 1 +Modules/_heapqmodule.c Py_BUILD_CORE 1 Modules/_io/*.c Py_BUILD_CORE 1 -Modules/itertoolsmodule.c Py_BUILD_CORE 1 Modules/_localemodule.c Py_BUILD_CORE 1 -Modules/main.c Py_BUILD_CORE 1 -Modules/posixmodule.c Py_BUILD_CORE 1 -Modules/signalmodule.c Py_BUILD_CORE 1 +Modules/_operator.c Py_BUILD_CORE 1 +Modules/_posixsubprocess.c Py_BUILD_CORE 1 +Modules/_sre.c Py_BUILD_CORE 1 Modules/_threadmodule.c Py_BUILD_CORE 1 Modules/_tracemalloc.c Py_BUILD_CORE 1 -Modules/_asynciomodule.c Py_BUILD_CORE 1 -Modules/mathmodule.c Py_BUILD_CORE 1 -Modules/cmathmodule.c Py_BUILD_CORE 1 Modules/_weakref.c Py_BUILD_CORE 1 +Modules/_zoneinfo.c Py_BUILD_CORE 1 +Modules/atexitmodule.c Py_BUILD_CORE 1 +Modules/cmathmodule.c Py_BUILD_CORE 1 +Modules/faulthandler.c Py_BUILD_CORE 1 +Modules/gcmodule.c Py_BUILD_CORE 1 +Modules/getpath.c Py_BUILD_CORE 1 +Modules/itertoolsmodule.c Py_BUILD_CORE 1 +Modules/main.c Py_BUILD_CORE 1 +Modules/mathmodule.c Py_BUILD_CORE 1 +Modules/posixmodule.c Py_BUILD_CORE 1 Modules/sha256module.c Py_BUILD_CORE 1 Modules/sha512module.c Py_BUILD_CORE 1 -Modules/_datetimemodule.c Py_BUILD_CORE 1 -Modules/_ctypes/cfield.c Py_BUILD_CORE 1 -Modules/_heapqmodule.c Py_BUILD_CORE 1 -Modules/_posixsubprocess.c Py_BUILD_CORE 1 -Modules/_sre.c Py_BUILD_CORE 1 -Modules/_collectionsmodule.c Py_BUILD_CORE 1 -Modules/_zoneinfo.c Py_BUILD_CORE 1 +Modules/signalmodule.c Py_BUILD_CORE 1 +Modules/symtablemodule.c Py_BUILD_CORE 1 +Modules/timemodule.c Py_BUILD_CORE 1 Modules/unicodedata.c Py_BUILD_CORE 1 -Modules/_cursesmodule.c Py_BUILD_CORE 1 -Modules/_ctypes/_ctypes.c Py_BUILD_CORE 1 Objects/stringlib/codecs.h Py_BUILD_CORE 1 +Objects/stringlib/unicode_format.h Py_BUILD_CORE 1 Python/ceval_gil.h Py_BUILD_CORE 1 Python/condvar.h Py_BUILD_CORE 1 @@ -244,6 +258,7 @@ def clean_lines(text): Modules/sre_lib.h LOCAL(type) static inline type Modules/sre_lib.h SRE(F) sre_ucs2_##F Objects/stringlib/codecs.h STRINGLIB_IS_UNICODE 1 +Include/internal/pycore_bitutils.h _Py__has_builtin(B) 0 # @end=tsv@ ''')[1:] @@ -264,6 +279,18 @@ def clean_lines(text): './Include/cpython/', ] +MAX_SIZES = { + _abs('Include/**/*.h'): (5_000, 500), + _abs('Modules/_ctypes/ctypes.h'): (5_000, 500), + _abs('Modules/_datetimemodule.c'): (20_000, 300), + _abs('Modules/posixmodule.c'): (20_000, 500), + _abs('Modules/termios.c'): (10_000, 800), + _abs('Modules/_testcapimodule.c'): (20_000, 400), + _abs('Modules/expat/expat.h'): (10_000, 400), + _abs('Objects/stringlib/unicode_format.h'): (10_000, 400), + _abs('Objects/typeobject.c'): (20_000, 200), +} + def get_preprocessor(*, file_macros=None, @@ -298,6 +325,7 @@ def parse_file(filename, *, filename, match_kind=match_kind, get_file_preprocessor=get_file_preprocessor, + file_maxsizes=MAX_SIZES, ) @@ -317,5 +345,6 @@ def parse_files(filenames=None, *, filenames, match_kind=match_kind, get_file_preprocessor=get_file_preprocessor, + file_maxsizes=MAX_SIZES, **file_kwargs ) From webhook-mailer at python.org Wed Dec 1 14:23:51 2021 From: webhook-mailer at python.org (DinoV) Date: Wed, 01 Dec 2021 19:23:51 -0000 Subject: [Python-checkins] bpo-30533: Add docs for `inspect.getmembers_static` (#29874) Message-ID: https://github.com/python/cpython/commit/c2bb29ce9ae4adb6a8123285ad3585907cd4cc73 commit: c2bb29ce9ae4adb6a8123285ad3585907cd4cc73 branch: main author: Weipeng Hong committer: DinoV date: 2021-12-01T11:23:46-08:00 summary: bpo-30533: Add docs for `inspect.getmembers_static` (#29874) * Add docs for `inspect.getmembers_static` * update files: M Doc/library/inspect.rst M Doc/whatsnew/3.11.rst diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index 1074f977184bb..711f510d7dcb0 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -275,6 +275,24 @@ attributes: listed in the metaclass' custom :meth:`__dir__`. +.. function:: getmembers_static(object[, predicate]) + + Return all the members of an object in a list of ``(name, value)`` + pairs sorted by name without triggering dynamic lookup via the descriptor + protocol, __getattr__ or __getattribute__. Optionally, only return members + that satisfy a given predicate. + + .. note:: + + :func:`getmembers_static` may not be able to retrieve all members + that getmembers can fetch (like dynamically created attributes) + and may find members that getmembers can't (like descriptors + that raise AttributeError). It can also return descriptor objects + instead of instance members in some cases. + + .. versionadded:: 3.11 + + .. function:: getmodulename(path) Return the name of the module named by the file *path*, without including the diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 6853c04143512..345b2df43f403 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -207,6 +207,13 @@ fractions (Contributed by Mark Dickinson in :issue:`44547`.) +inspect +------- +* Add :func:`inspect.getmembers_static`: return all members without + triggering dynamic lookup via the descriptor protocol. (Contributed by + Weipeng Hong in :issue:`30533`.) + + math ---- * Add :func:`math.exp2`: return 2 raised to the power of x. From webhook-mailer at python.org Wed Dec 1 14:43:34 2021 From: webhook-mailer at python.org (tiran) Date: Wed, 01 Dec 2021 19:43:34 -0000 Subject: [Python-checkins] bpo-40280: Emscripten defaults to --with-ensurepip=no (GH-29873) Message-ID: https://github.com/python/cpython/commit/9deb83468c56c7484645e6e3a6d0183cd6a0afd7 commit: 9deb83468c56c7484645e6e3a6d0183cd6a0afd7 branch: main author: Christian Heimes committer: tiran date: 2021-12-01T20:43:07+01:00 summary: bpo-40280: Emscripten defaults to --with-ensurepip=no (GH-29873) files: M configure M configure.ac diff --git a/configure b/configure index 382e030974727..4dfd4a565d14e 100755 --- a/configure +++ b/configure @@ -20268,7 +20268,15 @@ $as_echo_n "checking for ensurepip... " >&6; } if test "${with_ensurepip+set}" = set; then : withval=$with_ensurepip; else - with_ensurepip=upgrade + + case $ac_sys_system in #( + Emscripten) : + $with_ensurepip=no ;; #( + *) : + with_ensurepip=upgrade + ;; +esac + fi case $with_ensurepip in #( diff --git a/configure.ac b/configure.ac index 1e5fef337ca5d..38f943fa9d77c 100644 --- a/configure.ac +++ b/configure.ac @@ -5871,7 +5871,12 @@ AC_ARG_WITH(ensurepip, [AS_HELP_STRING([--with-ensurepip@<:@=install|upgrade|no@:>@], ["install" or "upgrade" using bundled pip (default is upgrade)])], [], - [with_ensurepip=upgrade]) + [ + AS_CASE([$ac_sys_system], + [Emscripten], [$with_ensurepip=no], + [with_ensurepip=upgrade] + ) + ]) AS_CASE($with_ensurepip, [yes|upgrade],[ENSUREPIP=upgrade], [install],[ENSUREPIP=install], From webhook-mailer at python.org Wed Dec 1 17:16:36 2021 From: webhook-mailer at python.org (tiran) Date: Wed, 01 Dec 2021 22:16:36 -0000 Subject: [Python-checkins] bpo-40280: Emscripten with_ensurepip=no, second attempt (GH-29884) Message-ID: https://github.com/python/cpython/commit/309110f37cdfc78d160ed08ae8faa6f6160ba87e commit: 309110f37cdfc78d160ed08ae8faa6f6160ba87e branch: main author: Christian Heimes committer: tiran date: 2021-12-01T23:16:27+01:00 summary: bpo-40280: Emscripten with_ensurepip=no, second attempt (GH-29884) files: M configure M configure.ac diff --git a/configure b/configure index 4dfd4a565d14e..0aceffb35065a 100755 --- a/configure +++ b/configure @@ -20271,7 +20271,7 @@ else case $ac_sys_system in #( Emscripten) : - $with_ensurepip=no ;; #( + with_ensurepip=no ;; #( *) : with_ensurepip=upgrade ;; diff --git a/configure.ac b/configure.ac index 38f943fa9d77c..99fa94d102909 100644 --- a/configure.ac +++ b/configure.ac @@ -5873,7 +5873,7 @@ AC_ARG_WITH(ensurepip, [], [ AS_CASE([$ac_sys_system], - [Emscripten], [$with_ensurepip=no], + [Emscripten], [with_ensurepip=no], [with_ensurepip=upgrade] ) ]) From webhook-mailer at python.org Thu Dec 2 03:52:42 2021 From: webhook-mailer at python.org (asvetlov) Date: Thu, 02 Dec 2021 08:52:42 -0000 Subject: [Python-checkins] docs: Improve example for urlparse() (GH-29816) Message-ID: https://github.com/python/cpython/commit/226d22ff2d209495621550eb78e81ed4c0fe0152 commit: 226d22ff2d209495621550eb78e81ed4c0fe0152 branch: main author: Christian Clauss committer: asvetlov date: 2021-12-02T10:52:32+02:00 summary: docs: Improve example for urlparse() (GH-29816) files: M Doc/library/urllib.parse.rst diff --git a/Doc/library/urllib.parse.rst b/Doc/library/urllib.parse.rst index a060cc9ba7fdd..1478b34bc9551 100644 --- a/Doc/library/urllib.parse.rst +++ b/Doc/library/urllib.parse.rst @@ -48,17 +48,29 @@ or on combining URL components into a URL string. result, except for a leading slash in the *path* component, which is retained if present. For example: + .. doctest:: + :options: +NORMALIZE_WHITESPACE + >>> from urllib.parse import urlparse - >>> o = urlparse('http://www.cwi.nl:80/%7Eguido/Python.html') - >>> o # doctest: +NORMALIZE_WHITESPACE - ParseResult(scheme='http', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html', - params='', query='', fragment='') + >>> urlparse("scheme://netloc/path;parameters?query#fragment") + ParseResult(scheme='scheme', netloc='netloc', path='/path;parameters', params='', + query='query', fragment='fragment') + >>> o = urlparse("http://docs.python.org:80/3/library/urllib.parse.html?" + ... "highlight=params#url-parsing") + >>> o + ParseResult(scheme='http', netloc='docs.python.org:80', + path='/3/library/urllib.parse.html', params='', + query='highlight=params', fragment='url-parsing') >>> o.scheme 'http' + >>> o.netloc + 'docs.python.org:80' + >>> o.hostname + 'docs.python.org' >>> o.port 80 - >>> o.geturl() - 'http://www.cwi.nl:80/%7Eguido/Python.html' + >>> o._replace(fragment="").geturl() + 'http://docs.python.org:80/3/library/urllib.parse.html?highlight=params' Following the syntax specifications in :rfc:`1808`, urlparse recognizes a netloc only if it is properly introduced by '//'. Otherwise the @@ -92,31 +104,30 @@ or on combining URL components into a URL string. The return value is a :term:`named tuple`, which means that its items can be accessed by index or as named attributes, which are: - +------------------+-------+--------------------------+----------------------+ - | Attribute | Index | Value | Value if not present | - +==================+=======+==========================+======================+ - | :attr:`scheme` | 0 | URL scheme specifier | *scheme* parameter | - +------------------+-------+--------------------------+----------------------+ - | :attr:`netloc` | 1 | Network location part | empty string | - +------------------+-------+--------------------------+----------------------+ - | :attr:`path` | 2 | Hierarchical path | empty string | - +------------------+-------+--------------------------+----------------------+ - | :attr:`params` | 3 | Parameters for last path | empty string | - | | | element | | - +------------------+-------+--------------------------+----------------------+ - | :attr:`query` | 4 | Query component | empty string | - +------------------+-------+--------------------------+----------------------+ - | :attr:`fragment` | 5 | Fragment identifier | empty string | - +------------------+-------+--------------------------+----------------------+ - | :attr:`username` | | User name | :const:`None` | - +------------------+-------+--------------------------+----------------------+ - | :attr:`password` | | Password | :const:`None` | - +------------------+-------+--------------------------+----------------------+ - | :attr:`hostname` | | Host name (lower case) | :const:`None` | - +------------------+-------+--------------------------+----------------------+ - | :attr:`port` | | Port number as integer, | :const:`None` | - | | | if present | | - +------------------+-------+--------------------------+----------------------+ + +------------------+-------+-------------------------+------------------------+ + | Attribute | Index | Value | Value if not present | + +==================+=======+=========================+========================+ + | :attr:`scheme` | 0 | URL scheme specifier | *scheme* parameter | + +------------------+-------+-------------------------+------------------------+ + | :attr:`netloc` | 1 | Network location part | empty string | + +------------------+-------+-------------------------+------------------------+ + | :attr:`path` | 2 | Hierarchical path | empty string | + +------------------+-------+-------------------------+------------------------+ + | :attr:`params` | 3 | No longer used | always an empty string | + +------------------+-------+-------------------------+------------------------+ + | :attr:`query` | 4 | Query component | empty string | + +------------------+-------+-------------------------+------------------------+ + | :attr:`fragment` | 5 | Fragment identifier | empty string | + +------------------+-------+-------------------------+------------------------+ + | :attr:`username` | | User name | :const:`None` | + +------------------+-------+-------------------------+------------------------+ + | :attr:`password` | | Password | :const:`None` | + +------------------+-------+-------------------------+------------------------+ + | :attr:`hostname` | | Host name (lower case) | :const:`None` | + +------------------+-------+-------------------------+------------------------+ + | :attr:`port` | | Port number as integer, | :const:`None` | + | | | if present | | + +------------------+-------+-------------------------+------------------------+ Reading the :attr:`port` attribute will raise a :exc:`ValueError` if an invalid port is specified in the URL. See section From webhook-mailer at python.org Thu Dec 2 04:17:47 2021 From: webhook-mailer at python.org (miss-islington) Date: Thu, 02 Dec 2021 09:17:47 -0000 Subject: [Python-checkins] bpo-40280: Emscripten has no support for subprocesses (GH-29872) Message-ID: https://github.com/python/cpython/commit/cb2b3c8d3566ae46b3b8d0718019e1c98484589e commit: cb2b3c8d3566ae46b3b8d0718019e1c98484589e branch: main author: Christian Heimes committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-02T01:17:37-08:00 summary: bpo-40280: Emscripten has no support for subprocesses (GH-29872) Fixes ``platform`` and ``help()`` on emscripten. Signed-off-by: Christian Heimes Automerge-Triggered-By: GH:tiran files: M Lib/platform.py M Lib/pydoc.py diff --git a/Lib/platform.py b/Lib/platform.py index 9e9b42238fb76..3f3f25a2c92d3 100755 --- a/Lib/platform.py +++ b/Lib/platform.py @@ -607,7 +607,10 @@ def _syscmd_file(target, default=''): # XXX Others too ? return default - import subprocess + try: + import subprocess + except ImportError: + return default target = _follow_symlinks(target) # "file" output is locale dependent: force the usage of the C locale # to get deterministic behavior. @@ -746,7 +749,10 @@ def from_subprocess(): """ Fall back to `uname -p` """ - import subprocess + try: + import subprocess + except ImportError: + return None try: return subprocess.check_output( ['uname', '-p'], diff --git a/Lib/pydoc.py b/Lib/pydoc.py index 3a2ff218f8319..7d52359c9a0ce 100755 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -1556,6 +1556,8 @@ def getpager(): return plainpager if not sys.stdin.isatty() or not sys.stdout.isatty(): return plainpager + if sys.platform == "emscripten": + return plainpager use_pager = os.environ.get('MANPAGER') or os.environ.get('PAGER') if use_pager: if sys.platform == 'win32': # pipes completely broken in Windows From webhook-mailer at python.org Thu Dec 2 05:25:03 2021 From: webhook-mailer at python.org (asvetlov) Date: Thu, 02 Dec 2021 10:25:03 -0000 Subject: [Python-checkins] docs: Improve example for urlparse() (GH-29816) (GH-29889) Message-ID: https://github.com/python/cpython/commit/0003d57e22dc983d85ec734bc5031360b2cfc537 commit: 0003d57e22dc983d85ec734bc5031360b2cfc537 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: asvetlov date: 2021-12-02T12:24:51+02:00 summary: docs: Improve example for urlparse() (GH-29816) (GH-29889) (cherry picked from commit 226d22ff2d209495621550eb78e81ed4c0fe0152) Co-authored-by: Christian Clauss files: M Doc/library/urllib.parse.rst diff --git a/Doc/library/urllib.parse.rst b/Doc/library/urllib.parse.rst index c03765259c3d5..b7430e9d4d670 100644 --- a/Doc/library/urllib.parse.rst +++ b/Doc/library/urllib.parse.rst @@ -48,17 +48,29 @@ or on combining URL components into a URL string. result, except for a leading slash in the *path* component, which is retained if present. For example: + .. doctest:: + :options: +NORMALIZE_WHITESPACE + >>> from urllib.parse import urlparse - >>> o = urlparse('http://www.cwi.nl:80/%7Eguido/Python.html') - >>> o # doctest: +NORMALIZE_WHITESPACE - ParseResult(scheme='http', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html', - params='', query='', fragment='') + >>> urlparse("scheme://netloc/path;parameters?query#fragment") + ParseResult(scheme='scheme', netloc='netloc', path='/path;parameters', params='', + query='query', fragment='fragment') + >>> o = urlparse("http://docs.python.org:80/3/library/urllib.parse.html?" + ... "highlight=params#url-parsing") + >>> o + ParseResult(scheme='http', netloc='docs.python.org:80', + path='/3/library/urllib.parse.html', params='', + query='highlight=params', fragment='url-parsing') >>> o.scheme 'http' + >>> o.netloc + 'docs.python.org:80' + >>> o.hostname + 'docs.python.org' >>> o.port 80 - >>> o.geturl() - 'http://www.cwi.nl:80/%7Eguido/Python.html' + >>> o._replace(fragment="").geturl() + 'http://docs.python.org:80/3/library/urllib.parse.html?highlight=params' Following the syntax specifications in :rfc:`1808`, urlparse recognizes a netloc only if it is properly introduced by '//'. Otherwise the @@ -92,31 +104,30 @@ or on combining URL components into a URL string. The return value is a :term:`named tuple`, which means that its items can be accessed by index or as named attributes, which are: - +------------------+-------+--------------------------+----------------------+ - | Attribute | Index | Value | Value if not present | - +==================+=======+==========================+======================+ - | :attr:`scheme` | 0 | URL scheme specifier | *scheme* parameter | - +------------------+-------+--------------------------+----------------------+ - | :attr:`netloc` | 1 | Network location part | empty string | - +------------------+-------+--------------------------+----------------------+ - | :attr:`path` | 2 | Hierarchical path | empty string | - +------------------+-------+--------------------------+----------------------+ - | :attr:`params` | 3 | Parameters for last path | empty string | - | | | element | | - +------------------+-------+--------------------------+----------------------+ - | :attr:`query` | 4 | Query component | empty string | - +------------------+-------+--------------------------+----------------------+ - | :attr:`fragment` | 5 | Fragment identifier | empty string | - +------------------+-------+--------------------------+----------------------+ - | :attr:`username` | | User name | :const:`None` | - +------------------+-------+--------------------------+----------------------+ - | :attr:`password` | | Password | :const:`None` | - +------------------+-------+--------------------------+----------------------+ - | :attr:`hostname` | | Host name (lower case) | :const:`None` | - +------------------+-------+--------------------------+----------------------+ - | :attr:`port` | | Port number as integer, | :const:`None` | - | | | if present | | - +------------------+-------+--------------------------+----------------------+ + +------------------+-------+-------------------------+------------------------+ + | Attribute | Index | Value | Value if not present | + +==================+=======+=========================+========================+ + | :attr:`scheme` | 0 | URL scheme specifier | *scheme* parameter | + +------------------+-------+-------------------------+------------------------+ + | :attr:`netloc` | 1 | Network location part | empty string | + +------------------+-------+-------------------------+------------------------+ + | :attr:`path` | 2 | Hierarchical path | empty string | + +------------------+-------+-------------------------+------------------------+ + | :attr:`params` | 3 | No longer used | always an empty string | + +------------------+-------+-------------------------+------------------------+ + | :attr:`query` | 4 | Query component | empty string | + +------------------+-------+-------------------------+------------------------+ + | :attr:`fragment` | 5 | Fragment identifier | empty string | + +------------------+-------+-------------------------+------------------------+ + | :attr:`username` | | User name | :const:`None` | + +------------------+-------+-------------------------+------------------------+ + | :attr:`password` | | Password | :const:`None` | + +------------------+-------+-------------------------+------------------------+ + | :attr:`hostname` | | Host name (lower case) | :const:`None` | + +------------------+-------+-------------------------+------------------------+ + | :attr:`port` | | Port number as integer, | :const:`None` | + | | | if present | | + +------------------+-------+-------------------------+------------------------+ Reading the :attr:`port` attribute will raise a :exc:`ValueError` if an invalid port is specified in the URL. See section From webhook-mailer at python.org Thu Dec 2 05:25:18 2021 From: webhook-mailer at python.org (asvetlov) Date: Thu, 02 Dec 2021 10:25:18 -0000 Subject: [Python-checkins] docs: Improve example for urlparse() (GH-29816) (GH-29888) Message-ID: https://github.com/python/cpython/commit/eac07e5ab02474c43aa9924753d4d774f8ff6828 commit: eac07e5ab02474c43aa9924753d4d774f8ff6828 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: asvetlov date: 2021-12-02T12:25:13+02:00 summary: docs: Improve example for urlparse() (GH-29816) (GH-29888) (cherry picked from commit 226d22ff2d209495621550eb78e81ed4c0fe0152) Co-authored-by: Christian Clauss files: M Doc/library/urllib.parse.rst diff --git a/Doc/library/urllib.parse.rst b/Doc/library/urllib.parse.rst index a060cc9ba7fdd..1478b34bc9551 100644 --- a/Doc/library/urllib.parse.rst +++ b/Doc/library/urllib.parse.rst @@ -48,17 +48,29 @@ or on combining URL components into a URL string. result, except for a leading slash in the *path* component, which is retained if present. For example: + .. doctest:: + :options: +NORMALIZE_WHITESPACE + >>> from urllib.parse import urlparse - >>> o = urlparse('http://www.cwi.nl:80/%7Eguido/Python.html') - >>> o # doctest: +NORMALIZE_WHITESPACE - ParseResult(scheme='http', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html', - params='', query='', fragment='') + >>> urlparse("scheme://netloc/path;parameters?query#fragment") + ParseResult(scheme='scheme', netloc='netloc', path='/path;parameters', params='', + query='query', fragment='fragment') + >>> o = urlparse("http://docs.python.org:80/3/library/urllib.parse.html?" + ... "highlight=params#url-parsing") + >>> o + ParseResult(scheme='http', netloc='docs.python.org:80', + path='/3/library/urllib.parse.html', params='', + query='highlight=params', fragment='url-parsing') >>> o.scheme 'http' + >>> o.netloc + 'docs.python.org:80' + >>> o.hostname + 'docs.python.org' >>> o.port 80 - >>> o.geturl() - 'http://www.cwi.nl:80/%7Eguido/Python.html' + >>> o._replace(fragment="").geturl() + 'http://docs.python.org:80/3/library/urllib.parse.html?highlight=params' Following the syntax specifications in :rfc:`1808`, urlparse recognizes a netloc only if it is properly introduced by '//'. Otherwise the @@ -92,31 +104,30 @@ or on combining URL components into a URL string. The return value is a :term:`named tuple`, which means that its items can be accessed by index or as named attributes, which are: - +------------------+-------+--------------------------+----------------------+ - | Attribute | Index | Value | Value if not present | - +==================+=======+==========================+======================+ - | :attr:`scheme` | 0 | URL scheme specifier | *scheme* parameter | - +------------------+-------+--------------------------+----------------------+ - | :attr:`netloc` | 1 | Network location part | empty string | - +------------------+-------+--------------------------+----------------------+ - | :attr:`path` | 2 | Hierarchical path | empty string | - +------------------+-------+--------------------------+----------------------+ - | :attr:`params` | 3 | Parameters for last path | empty string | - | | | element | | - +------------------+-------+--------------------------+----------------------+ - | :attr:`query` | 4 | Query component | empty string | - +------------------+-------+--------------------------+----------------------+ - | :attr:`fragment` | 5 | Fragment identifier | empty string | - +------------------+-------+--------------------------+----------------------+ - | :attr:`username` | | User name | :const:`None` | - +------------------+-------+--------------------------+----------------------+ - | :attr:`password` | | Password | :const:`None` | - +------------------+-------+--------------------------+----------------------+ - | :attr:`hostname` | | Host name (lower case) | :const:`None` | - +------------------+-------+--------------------------+----------------------+ - | :attr:`port` | | Port number as integer, | :const:`None` | - | | | if present | | - +------------------+-------+--------------------------+----------------------+ + +------------------+-------+-------------------------+------------------------+ + | Attribute | Index | Value | Value if not present | + +==================+=======+=========================+========================+ + | :attr:`scheme` | 0 | URL scheme specifier | *scheme* parameter | + +------------------+-------+-------------------------+------------------------+ + | :attr:`netloc` | 1 | Network location part | empty string | + +------------------+-------+-------------------------+------------------------+ + | :attr:`path` | 2 | Hierarchical path | empty string | + +------------------+-------+-------------------------+------------------------+ + | :attr:`params` | 3 | No longer used | always an empty string | + +------------------+-------+-------------------------+------------------------+ + | :attr:`query` | 4 | Query component | empty string | + +------------------+-------+-------------------------+------------------------+ + | :attr:`fragment` | 5 | Fragment identifier | empty string | + +------------------+-------+-------------------------+------------------------+ + | :attr:`username` | | User name | :const:`None` | + +------------------+-------+-------------------------+------------------------+ + | :attr:`password` | | Password | :const:`None` | + +------------------+-------+-------------------------+------------------------+ + | :attr:`hostname` | | Host name (lower case) | :const:`None` | + +------------------+-------+-------------------------+------------------------+ + | :attr:`port` | | Port number as integer, | :const:`None` | + | | | if present | | + +------------------+-------+-------------------------+------------------------+ Reading the :attr:`port` attribute will raise a :exc:`ValueError` if an invalid port is specified in the URL. See section From webhook-mailer at python.org Thu Dec 2 05:43:42 2021 From: webhook-mailer at python.org (vstinner) Date: Thu, 02 Dec 2021 10:43:42 -0000 Subject: [Python-checkins] bpo-45954: Rename PyConfig.no_debug_ranges to code_debug_ranges (GH-29886) Message-ID: https://github.com/python/cpython/commit/a6c3b0faa1d55e36539caf19bd3bcf1dea12df84 commit: a6c3b0faa1d55e36539caf19bd3bcf1dea12df84 branch: main author: Victor Stinner committer: vstinner date: 2021-12-02T11:43:37+01:00 summary: bpo-45954: Rename PyConfig.no_debug_ranges to code_debug_ranges (GH-29886) Rename PyConfig.no_debug_ranges to PyConfig.code_debug_ranges and invert the value. Document -X no_debug_ranges and PYTHONNODEBUGRANGES env var in PyConfig.code_debug_ranges documentation. files: M Doc/c-api/init_config.rst M Include/cpython/initconfig.h M Lib/test/_test_embed_set_config.py M Lib/test/support/__init__.py M Lib/test/test_embed.py M Objects/codeobject.c M Programs/_testembed.c M Python/initconfig.c diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst index 989660caeda06..3642a8bf7fbc7 100644 --- a/Doc/c-api/init_config.rst +++ b/Doc/c-api/init_config.rst @@ -596,13 +596,16 @@ PyConfig .. versionadded:: 3.10 - .. c:member:: int no_debug_ranges + .. c:member:: int code_debug_ranges - If equals to ``1``, disables the inclusion of the end line and column + If equals to ``0``, disables the inclusion of the end line and column mappings in code objects. Also disables traceback printing carets to specific error locations. - Default: ``0``. + Set to ``0`` by the :envvar:`PYTHONNODEBUGRANGES` environment variable + and by the :option:`-X no_debug_ranges <-X>` command line option. + + Default: ``1``. .. versionadded:: 3.11 diff --git a/Include/cpython/initconfig.h b/Include/cpython/initconfig.h index 76f3c5268ee5f..2be4c25ec0b09 100644 --- a/Include/cpython/initconfig.h +++ b/Include/cpython/initconfig.h @@ -143,7 +143,7 @@ typedef struct PyConfig { int faulthandler; int tracemalloc; int import_time; - int no_debug_ranges; + int code_debug_ranges; int show_ref_count; int dump_refs; wchar_t *dump_refs_file; diff --git a/Lib/test/_test_embed_set_config.py b/Lib/test/_test_embed_set_config.py index 23c927e2646bc..d05907ecfe744 100644 --- a/Lib/test/_test_embed_set_config.py +++ b/Lib/test/_test_embed_set_config.py @@ -1,7 +1,7 @@ # bpo-42260: Test _PyInterpreterState_GetConfigCopy() # and _PyInterpreterState_SetConfig(). # -# Test run in a subinterpreter since set_config(get_config()) +# Test run in a subprocess since set_config(get_config()) # does reset sys attributes to their state of the Python startup # (before the site module is run). @@ -61,7 +61,7 @@ def test_set_invalid(self): 'faulthandler', 'tracemalloc', 'import_time', - 'no_debug_ranges', + 'code_debug_ranges', 'show_ref_count', 'dump_refs', 'malloc_stats', diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 6d84a8bea420e..f8faa41ad439c 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -449,7 +449,7 @@ def has_no_debug_ranges(): except ImportError: raise unittest.SkipTest("_testinternalcapi required") config = _testinternalcapi.get_config() - return bool(config['no_debug_ranges']) + return not bool(config['code_debug_ranges']) def requires_debug_ranges(reason='requires co_positions / debug_ranges'): return unittest.skipIf(has_no_debug_ranges(), reason) diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index 94cdd98b2dbba..4781c7f2a9d12 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -386,7 +386,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): 'faulthandler': 0, 'tracemalloc': 0, 'import_time': 0, - 'no_debug_ranges': 0, + 'code_debug_ranges': 1, 'show_ref_count': 0, 'dump_refs': 0, 'malloc_stats': 0, @@ -818,7 +818,7 @@ def test_init_from_config(self): 'hash_seed': 123, 'tracemalloc': 2, 'import_time': 1, - 'no_debug_ranges': 1, + 'code_debug_ranges': 0, 'show_ref_count': 1, 'malloc_stats': 1, @@ -878,7 +878,7 @@ def test_init_compat_env(self): 'hash_seed': 42, 'tracemalloc': 2, 'import_time': 1, - 'no_debug_ranges': 1, + 'code_debug_ranges': 0, 'malloc_stats': 1, 'inspect': 1, 'optimization_level': 2, @@ -908,7 +908,7 @@ def test_init_python_env(self): 'hash_seed': 42, 'tracemalloc': 2, 'import_time': 1, - 'no_debug_ranges': 1, + 'code_debug_ranges': 0, 'malloc_stats': 1, 'inspect': 1, 'optimization_level': 2, diff --git a/Objects/codeobject.c b/Objects/codeobject.c index 5ab8641a17caa..a413b183be8ed 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -381,7 +381,7 @@ _PyCode_New(struct _PyCodeConstructor *con) // Discard the endlinetable and columntable if we are opted out of debug // ranges. - if (_Py_GetConfig()->no_debug_ranges) { + if (!_Py_GetConfig()->code_debug_ranges) { con->endlinetable = Py_None; con->columntable = Py_None; } diff --git a/Programs/_testembed.c b/Programs/_testembed.c index 8077c470c07c5..fc5f44d5eb626 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -531,7 +531,7 @@ static int test_init_from_config(void) config.import_time = 1; putenv("PYTHONNODEBUGRANGES=0"); - config.no_debug_ranges = 1; + config.code_debug_ranges = 0; config.show_ref_count = 1; /* FIXME: test dump_refs: bpo-34223 */ diff --git a/Python/initconfig.c b/Python/initconfig.c index c916e2f7c0714..53b624fdd72ec 100644 --- a/Python/initconfig.c +++ b/Python/initconfig.c @@ -614,7 +614,7 @@ config_check_consistency(const PyConfig *config) assert(config->faulthandler >= 0); assert(config->tracemalloc >= 0); assert(config->import_time >= 0); - assert(config->no_debug_ranges >= 0); + assert(config->code_debug_ranges >= 0); assert(config->show_ref_count >= 0); assert(config->dump_refs >= 0); assert(config->malloc_stats >= 0); @@ -740,6 +740,7 @@ _PyConfig_InitCompatConfig(PyConfig *config) config->legacy_windows_stdio = -1; #endif config->use_frozen_modules = -1; + config->code_debug_ranges = 1; } @@ -904,7 +905,7 @@ _PyConfig_Copy(PyConfig *config, const PyConfig *config2) COPY_ATTR(faulthandler); COPY_ATTR(tracemalloc); COPY_ATTR(import_time); - COPY_ATTR(no_debug_ranges); + COPY_ATTR(code_debug_ranges); COPY_ATTR(show_ref_count); COPY_ATTR(dump_refs); COPY_ATTR(dump_refs_file); @@ -1012,7 +1013,7 @@ _PyConfig_AsDict(const PyConfig *config) SET_ITEM_INT(faulthandler); SET_ITEM_INT(tracemalloc); SET_ITEM_INT(import_time); - SET_ITEM_INT(no_debug_ranges); + SET_ITEM_INT(code_debug_ranges); SET_ITEM_INT(show_ref_count); SET_ITEM_INT(dump_refs); SET_ITEM_INT(malloc_stats); @@ -1291,7 +1292,7 @@ _PyConfig_FromDict(PyConfig *config, PyObject *dict) GET_UINT(faulthandler); GET_UINT(tracemalloc); GET_UINT(import_time); - GET_UINT(no_debug_ranges); + GET_UINT(code_debug_ranges); GET_UINT(show_ref_count); GET_UINT(dump_refs); GET_UINT(malloc_stats); @@ -1853,7 +1854,7 @@ config_read_complex_options(PyConfig *config) if (config_get_env(config, "PYTHONNODEBUGRANGES") || config_get_xoption(config, L"no_debug_ranges")) { - config->no_debug_ranges = 1; + config->code_debug_ranges = 0; } PyStatus status; From webhook-mailer at python.org Thu Dec 2 06:19:35 2021 From: webhook-mailer at python.org (tiran) Date: Thu, 02 Dec 2021 11:19:35 -0000 Subject: [Python-checkins] bpo-40280: Optimize ints and and startup on wasm (GH-29887) Message-ID: https://github.com/python/cpython/commit/cb8f491f46e262549f6c447b31625cab7c20a60a commit: cb8f491f46e262549f6c447b31625cab7c20a60a branch: main author: Christian Heimes committer: tiran date: 2021-12-02T12:19:30+01:00 summary: bpo-40280: Optimize ints and and startup on wasm (GH-29887) files: M Include/pyport.h M Python/pylifecycle.c diff --git a/Include/pyport.h b/Include/pyport.h index 953f75c970d83..81b1bde841e08 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -87,13 +87,17 @@ Used in: Py_SAFE_DOWNCAST /* If PYLONG_BITS_IN_DIGIT is not defined then we'll use 30-bit digits if all the necessary integer types are available, and we're on a 64-bit platform - (as determined by SIZEOF_VOID_P); otherwise we use 15-bit digits. */ + (as determined by SIZEOF_VOID_P); otherwise we use 15-bit digits. + + From pyodide: WASM has 32 bit pointers but has native 64 bit arithmetic + so it is more efficient to use 30 bit digits. + */ #ifndef PYLONG_BITS_IN_DIGIT -#if SIZEOF_VOID_P >= 8 -#define PYLONG_BITS_IN_DIGIT 30 +#if SIZEOF_VOID_P >= 8 || defined(__wasm__) +# define PYLONG_BITS_IN_DIGIT 30 #else -#define PYLONG_BITS_IN_DIGIT 15 +# define PYLONG_BITS_IN_DIGIT 15 #endif #endif diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 74d269b7a5646..c6b2a1eb96148 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -2145,7 +2145,11 @@ is_valid_fd(int fd) if (fd < 0) { return 0; } -#if defined(F_GETFD) && (defined(__linux__) || defined(__APPLE__) || defined(MS_WINDOWS)) +#if defined(F_GETFD) && ( \ + defined(__linux__) || \ + defined(__APPLE__) || \ + defined(MS_WINDOWS) || \ + defined(__wasm__)) int res; _Py_BEGIN_SUPPRESS_IPH res = fcntl(fd, F_GETFD); From webhook-mailer at python.org Thu Dec 2 11:50:07 2021 From: webhook-mailer at python.org (ethanfurman) Date: Thu, 02 Dec 2021 16:50:07 -0000 Subject: [Python-checkins] bpo-45535: Improve output of Enum ``dir()`` (GH-29316) Message-ID: https://github.com/python/cpython/commit/b2afdc95cc8f4e9228148730949a43cef0323f15 commit: b2afdc95cc8f4e9228148730949a43cef0323f15 branch: main author: Alex Waygood committer: ethanfurman date: 2021-12-02T08:49:52-08:00 summary: bpo-45535: Improve output of Enum ``dir()`` (GH-29316) Modify the ``EnumType.__dir__()`` and ``Enum.__dir__()`` to ensure that user-defined methods and methods inherited from mixin classes always show up in the output of `help()`. This change also makes it easier for IDEs to provide auto-completion. files: A Misc/NEWS.d/next/Library/2021-10-29-16-28-06.bpo-45535.n8NiOE.rst M Doc/howto/enum.rst M Doc/library/enum.rst M Lib/enum.py M Lib/test/test_enum.py diff --git a/Doc/howto/enum.rst b/Doc/howto/enum.rst index b0b17b1669f1a..91bef218b9299 100644 --- a/Doc/howto/enum.rst +++ b/Doc/howto/enum.rst @@ -997,11 +997,12 @@ Plain :class:`Enum` classes always evaluate as :data:`True`. """"""""""""""""""""""""""""" If you give your enum subclass extra methods, like the `Planet`_ -class below, those methods will show up in a :func:`dir` of the member, -but not of the class:: +class below, those methods will show up in a :func:`dir` of the member and the +class. Attributes defined in an :func:`__init__` method will only show up in a +:func:`dir` of the member:: >>> dir(Planet) - ['EARTH', 'JUPITER', 'MARS', 'MERCURY', 'NEPTUNE', 'SATURN', 'URANUS', 'VENUS', '__class__', '__doc__', '__members__', '__module__'] + ['EARTH', 'JUPITER', 'MARS', 'MERCURY', 'NEPTUNE', 'SATURN', 'URANUS', 'VENUS', '__class__', '__doc__', '__init__', '__members__', '__module__', 'surface_gravity'] >>> dir(Planet.EARTH) ['__class__', '__doc__', '__module__', 'mass', 'name', 'radius', 'surface_gravity', 'value'] diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst index 850b491680c68..572048a255bf0 100644 --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -162,7 +162,8 @@ Data Types .. method:: EnumType.__dir__(cls) Returns ``['__class__', '__doc__', '__members__', '__module__']`` and the - names of the members in *cls*:: + names of the members in ``cls``. User-defined methods and methods from + mixin classes will also be included:: >>> dir(Color) ['BLUE', 'GREEN', 'RED', '__class__', '__doc__', '__members__', '__module__'] @@ -260,7 +261,7 @@ Data Types .. method:: Enum.__dir__(self) Returns ``['__class__', '__doc__', '__module__', 'name', 'value']`` and - any public methods defined on *self.__class__*:: + any public methods defined on ``self.__class__`` or a mixin class:: >>> from datetime import date >>> class Weekday(Enum): diff --git a/Lib/enum.py b/Lib/enum.py index 461d276eed862..8efc38c3d78db 100644 --- a/Lib/enum.py +++ b/Lib/enum.py @@ -635,10 +635,60 @@ def __delattr__(cls, attr): super().__delattr__(attr) def __dir__(self): - return ( - ['__class__', '__doc__', '__members__', '__module__'] - + self._member_names_ - ) + # Start off with the desired result for dir(Enum) + cls_dir = {'__class__', '__doc__', '__members__', '__module__'} + add_to_dir = cls_dir.add + mro = self.__mro__ + this_module = globals().values() + is_from_this_module = lambda cls: any(cls is thing for thing in this_module) + first_enum_base = next(cls for cls in mro if is_from_this_module(cls)) + enum_dict = Enum.__dict__ + sentinel = object() + # special-case __new__ + ignored = {'__new__', *filter(_is_sunder, enum_dict)} + add_to_ignored = ignored.add + + # We want these added to __dir__ + # if and only if they have been user-overridden + enum_dunders = set(filter(_is_dunder, enum_dict)) + + # special-case __new__ + if self.__new__ is not first_enum_base.__new__: + add_to_dir('__new__') + + for cls in mro: + # Ignore any classes defined in this module + if cls is object or is_from_this_module(cls): + continue + + cls_lookup = cls.__dict__ + + # If not an instance of EnumType, + # ensure all attributes excluded from that class's `dir()` are ignored here. + if not isinstance(cls, EnumType): + cls_lookup = set(cls_lookup).intersection(dir(cls)) + + for attr_name in cls_lookup: + # Already seen it? Carry on + if attr_name in cls_dir or attr_name in ignored: + continue + # Sunders defined in Enum.__dict__ are already in `ignored`, + # But sunders defined in a subclass won't be (we want all sunders excluded). + elif _is_sunder(attr_name): + add_to_ignored(attr_name) + # Not an "enum dunder"? Add it to dir() output. + elif attr_name not in enum_dunders: + add_to_dir(attr_name) + # Is an "enum dunder", and is defined by a class from enum.py? Ignore it. + elif getattr(self, attr_name) is getattr(first_enum_base, attr_name, sentinel): + add_to_ignored(attr_name) + # Is an "enum dunder", and is either user-defined or defined by a mixin class? + # Add it to dir() output. + else: + add_to_dir(attr_name) + + # sort the output before returning it, so that the result is deterministic. + return sorted(cls_dir) def __getattr__(cls, name): """ @@ -985,13 +1035,10 @@ def __dir__(self): """ Returns all members and all public methods """ - added_behavior = [ - m - for cls in self.__class__.mro() - for m in cls.__dict__ - if m[0] != '_' and m not in self._member_map_ - ] + [m for m in self.__dict__ if m[0] != '_'] - return (['__class__', '__doc__', '__module__'] + added_behavior) + cls = type(self) + to_exclude = {'__members__', '__init__', '__new__', *cls._member_names_} + filtered_self_dict = (name for name in self.__dict__ if not name.startswith('_')) + return sorted({'name', 'value', *dir(cls), *filtered_self_dict} - to_exclude) def __format__(self, format_spec): """ diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py index 7d220871a35cc..eecb9fd4835c4 100644 --- a/Lib/test/test_enum.py +++ b/Lib/test/test_enum.py @@ -203,59 +203,340 @@ class Holiday(date, Enum): IDES_OF_MARCH = 2013, 3, 15 self.Holiday = Holiday - def test_dir_on_class(self): - Season = self.Season - self.assertEqual( - set(dir(Season)), - set(['__class__', '__doc__', '__members__', '__module__', - 'SPRING', 'SUMMER', 'AUTUMN', 'WINTER']), - ) + class DateEnum(date, Enum): pass + self.DateEnum = DateEnum - def test_dir_on_item(self): - Season = self.Season - self.assertEqual( - set(dir(Season.WINTER)), - set(['__class__', '__doc__', '__module__', 'name', 'value']), - ) + class FloatEnum(float, Enum): pass + self.FloatEnum = FloatEnum - def test_dir_with_added_behavior(self): - class Test(Enum): + class Wowser(Enum): this = 'that' these = 'those' def wowser(self): + """Wowser docstring""" return ("Wowser! I'm %s!" % self.name) - self.assertEqual( - set(dir(Test)), - set(['__class__', '__doc__', '__members__', '__module__', 'this', 'these']), - ) - self.assertEqual( - set(dir(Test.this)), - set(['__class__', '__doc__', '__module__', 'name', 'value', 'wowser']), - ) + @classmethod + def classmethod_wowser(cls): pass + @staticmethod + def staticmethod_wowser(): pass + self.Wowser = Wowser + + class IntWowser(IntEnum): + this = 1 + these = 2 + def wowser(self): + """Wowser docstring""" + return ("Wowser! I'm %s!" % self.name) + @classmethod + def classmethod_wowser(cls): pass + @staticmethod + def staticmethod_wowser(): pass + self.IntWowser = IntWowser + + class FloatWowser(float, Enum): + this = 3.14 + these = 4.2 + def wowser(self): + """Wowser docstring""" + return ("Wowser! I'm %s!" % self.name) + @classmethod + def classmethod_wowser(cls): pass + @staticmethod + def staticmethod_wowser(): pass + self.FloatWowser = FloatWowser + + class WowserNoMembers(Enum): + def wowser(self): pass + @classmethod + def classmethod_wowser(cls): pass + @staticmethod + def staticmethod_wowser(): pass + class SubclassOfWowserNoMembers(WowserNoMembers): pass + self.WowserNoMembers = WowserNoMembers + self.SubclassOfWowserNoMembers = SubclassOfWowserNoMembers + + class IntWowserNoMembers(IntEnum): + def wowser(self): pass + @classmethod + def classmethod_wowser(cls): pass + @staticmethod + def staticmethod_wowser(): pass + self.IntWowserNoMembers = IntWowserNoMembers + + class FloatWowserNoMembers(float, Enum): + def wowser(self): pass + @classmethod + def classmethod_wowser(cls): pass + @staticmethod + def staticmethod_wowser(): pass + self.FloatWowserNoMembers = FloatWowserNoMembers + + class EnumWithInit(Enum): + def __init__(self, greeting, farewell): + self.greeting = greeting + self.farewell = farewell + ENGLISH = 'hello', 'goodbye' + GERMAN = 'Guten Morgen', 'Auf Wiedersehen' + def some_method(self): pass + self.EnumWithInit = EnumWithInit - def test_dir_on_sub_with_behavior_on_super(self): # see issue22506 - class SuperEnum(Enum): + class SuperEnum1(Enum): def invisible(self): return "did you see me?" - class SubEnum(SuperEnum): + class SubEnum1(SuperEnum1): sample = 5 - self.assertEqual( - set(dir(SubEnum.sample)), - set(['__class__', '__doc__', '__module__', 'name', 'value', 'invisible']), - ) + self.SubEnum1 = SubEnum1 - def test_dir_on_sub_with_behavior_including_instance_dict_on_super(self): - # see issue40084 - class SuperEnum(IntEnum): + class SuperEnum2(IntEnum): def __new__(cls, value, description=""): obj = int.__new__(cls, value) obj._value_ = value obj.description = description return obj - class SubEnum(SuperEnum): + class SubEnum2(SuperEnum2): sample = 5 - self.assertTrue({'description'} <= set(dir(SubEnum.sample))) + self.SubEnum2 = SubEnum2 + + def test_dir_basics_for_all_enums(self): + enums_for_tests = ( + # Generic enums in enum.py + Enum, + IntEnum, + StrEnum, + # Generic enums defined outside of enum.py + self.DateEnum, + self.FloatEnum, + # Concrete enums derived from enum.py generics + self.Grades, + self.Season, + # Concrete enums derived from generics defined outside of enum.py + self.Konstants, + self.Holiday, + # Standard enum with added behaviour & members + self.Wowser, + # Mixin-enum-from-enum.py with added behaviour & members + self.IntWowser, + # Mixin-enum-from-oustide-enum.py with added behaviour & members + self.FloatWowser, + # Equivalents of the three immediately above, but with no members + self.WowserNoMembers, + self.IntWowserNoMembers, + self.FloatWowserNoMembers, + # Enum with members and an __init__ method + self.EnumWithInit, + # Special cases to test + self.SubEnum1, + self.SubEnum2 + ) + + for cls in enums_for_tests: + with self.subTest(cls=cls): + cls_dir = dir(cls) + # test that dir is deterministic + self.assertEqual(cls_dir, dir(cls)) + # test that dir is sorted + self.assertEqual(list(cls_dir), sorted(cls_dir)) + # test that there are no dupes in dir + self.assertEqual(len(cls_dir), len(set(cls_dir))) + # test that there are no sunders in dir + self.assertFalse(any(enum._is_sunder(attr) for attr in cls_dir)) + self.assertNotIn('__new__', cls_dir) + + for attr in ('__class__', '__doc__', '__members__', '__module__'): + with self.subTest(attr=attr): + self.assertIn(attr, cls_dir) + + def test_dir_for_enum_with_members(self): + enums_for_test = ( + # Enum with members + self.Season, + # IntEnum with members + self.Grades, + # Two custom-mixin enums with members + self.Konstants, + self.Holiday, + # several enums-with-added-behaviour and members + self.Wowser, + self.IntWowser, + self.FloatWowser, + # An enum with an __init__ method and members + self.EnumWithInit, + # Special cases to test + self.SubEnum1, + self.SubEnum2 + ) + + for cls in enums_for_test: + cls_dir = dir(cls) + member_names = cls._member_names_ + with self.subTest(cls=cls): + self.assertTrue(all(member_name in cls_dir for member_name in member_names)) + for member in cls: + member_dir = dir(member) + # test that dir is deterministic + self.assertEqual(member_dir, dir(member)) + # test that dir is sorted + self.assertEqual(list(member_dir), sorted(member_dir)) + # test that there are no dupes in dir + self.assertEqual(len(member_dir), len(set(member_dir))) + + for attr_name in cls_dir: + with self.subTest(attr_name=attr_name): + if attr_name in {'__members__', '__init__', '__new__', *member_names}: + self.assertNotIn(attr_name, member_dir) + else: + self.assertIn(attr_name, member_dir) + + self.assertFalse(any(enum._is_sunder(attr) for attr in member_dir)) + + def test_dir_for_enums_with_added_behaviour(self): + enums_for_test = ( + self.Wowser, + self.IntWowser, + self.FloatWowser, + self.WowserNoMembers, + self.SubclassOfWowserNoMembers, + self.IntWowserNoMembers, + self.FloatWowserNoMembers + ) + + for cls in enums_for_test: + with self.subTest(cls=cls): + self.assertIn('wowser', dir(cls)) + self.assertIn('classmethod_wowser', dir(cls)) + self.assertIn('staticmethod_wowser', dir(cls)) + self.assertTrue(all( + all(attr in dir(member) for attr in ('wowser', 'classmethod_wowser', 'staticmethod_wowser')) + for member in cls + )) + + self.assertEqual(dir(self.WowserNoMembers), dir(self.SubclassOfWowserNoMembers)) + # Check classmethods are present + self.assertIn('from_bytes', dir(self.IntWowser)) + self.assertIn('from_bytes', dir(self.IntWowserNoMembers)) + + def test_help_output_on_enum_members(self): + added_behaviour_enums = ( + self.Wowser, + self.IntWowser, + self.FloatWowser + ) + + for cls in added_behaviour_enums: + with self.subTest(cls=cls): + rendered_doc = pydoc.render_doc(cls.this) + self.assertIn('Wowser docstring', rendered_doc) + if cls in {self.IntWowser, self.FloatWowser}: + self.assertIn('float(self)', rendered_doc) + + def test_dir_for_enum_with_init(self): + EnumWithInit = self.EnumWithInit + + cls_dir = dir(EnumWithInit) + self.assertIn('__init__', cls_dir) + self.assertIn('some_method', cls_dir) + self.assertNotIn('greeting', cls_dir) + self.assertNotIn('farewell', cls_dir) + + member_dir = dir(EnumWithInit.ENGLISH) + self.assertNotIn('__init__', member_dir) + self.assertIn('some_method', member_dir) + self.assertIn('greeting', member_dir) + self.assertIn('farewell', member_dir) + + def test_mixin_dirs(self): + from datetime import date + + enums_for_test = ( + # generic mixins from enum.py + (IntEnum, int), + (StrEnum, str), + # generic mixins from outside enum.py + (self.FloatEnum, float), + (self.DateEnum, date), + # concrete mixin from enum.py + (self.Grades, int), + # concrete mixin from outside enum.py + (self.Holiday, date), + # concrete mixin from enum.py with added behaviour + (self.IntWowser, int), + # concrete mixin from outside enum.py with added behaviour + (self.FloatWowser, float) + ) + + enum_dict = Enum.__dict__ + enum_dir = dir(Enum) + enum_module_names = enum.__all__ + is_from_enum_module = lambda cls: cls.__name__ in enum_module_names + is_enum_dunder = lambda attr: enum._is_dunder(attr) and attr in enum_dict + + def attr_is_inherited_from_object(cls, attr_name): + for base in cls.__mro__: + if attr_name in base.__dict__: + return base is object + return False + + # General tests + for enum_cls, mixin_cls in enums_for_test: + with self.subTest(enum_cls=enum_cls): + cls_dir = dir(enum_cls) + cls_dict = enum_cls.__dict__ + + mixin_attrs = [ + x for x in dir(mixin_cls) + if not attr_is_inherited_from_object(cls=mixin_cls, attr_name=x) + ] + + first_enum_base = next( + base for base in enum_cls.__mro__ + if is_from_enum_module(base) + ) + + for attr in mixin_attrs: + with self.subTest(attr=attr): + if enum._is_sunder(attr): + # Unlikely, but no harm in testing + self.assertNotIn(attr, cls_dir) + elif attr in {'__class__', '__doc__', '__members__', '__module__'}: + self.assertIn(attr, cls_dir) + elif is_enum_dunder(attr): + if is_from_enum_module(enum_cls): + self.assertNotIn(attr, cls_dir) + elif getattr(enum_cls, attr) is getattr(first_enum_base, attr): + self.assertNotIn(attr, cls_dir) + else: + self.assertIn(attr, cls_dir) + else: + self.assertIn(attr, cls_dir) + + # Some specific examples + int_enum_dir = dir(IntEnum) + self.assertIn('imag', int_enum_dir) + self.assertIn('__rfloordiv__', int_enum_dir) + self.assertNotIn('__format__', int_enum_dir) + self.assertNotIn('__hash__', int_enum_dir) + self.assertNotIn('__init_subclass__', int_enum_dir) + self.assertNotIn('__subclasshook__', int_enum_dir) + + class OverridesFormatOutsideEnumModule(Enum): + def __format__(self, *args, **kwargs): + return super().__format__(*args, **kwargs) + SOME_MEMBER = 1 + + self.assertIn('__format__', dir(OverridesFormatOutsideEnumModule)) + self.assertIn('__format__', dir(OverridesFormatOutsideEnumModule.SOME_MEMBER)) + + def test_dir_on_sub_with_behavior_on_super(self): + # see issue22506 + self.assertEqual( + set(dir(self.SubEnum1.sample)), + set(['__class__', '__doc__', '__module__', 'name', 'value', 'invisible']), + ) + + def test_dir_on_sub_with_behavior_including_instance_dict_on_super(self): + # see issue40084 + self.assertTrue({'description'} <= set(dir(self.SubEnum2.sample))) def test_enum_in_enum_out(self): Season = self.Season @@ -4156,7 +4437,8 @@ def test_convert(self): self.assertEqual(test_type.CONVERT_TEST_NAME_E, 5) # Ensure that test_type only picked up names matching the filter. self.assertEqual([name for name in dir(test_type) - if name[0:2] not in ('CO', '__')], + if name[0:2] not in ('CO', '__') + and name not in dir(IntEnum)], [], msg='Names other than CONVERT_TEST_* found.') @unittest.skipUnless(python_version == (3, 8), @@ -4207,7 +4489,8 @@ def test_convert(self): self.assertEqual(test_type.CONVERT_STR_TEST_2, 'goodbye') # Ensure that test_type only picked up names matching the filter. self.assertEqual([name for name in dir(test_type) - if name[0:2] not in ('CO', '__')], + if name[0:2] not in ('CO', '__') + and name not in dir(StrEnum)], [], msg='Names other than CONVERT_STR_* found.') def test_convert_repr_and_str(self): diff --git a/Misc/NEWS.d/next/Library/2021-10-29-16-28-06.bpo-45535.n8NiOE.rst b/Misc/NEWS.d/next/Library/2021-10-29-16-28-06.bpo-45535.n8NiOE.rst new file mode 100644 index 0000000000000..bda1b407a0ee0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-10-29-16-28-06.bpo-45535.n8NiOE.rst @@ -0,0 +1 @@ +Improve output of ``dir()`` with Enums. From webhook-mailer at python.org Thu Dec 2 12:43:06 2021 From: webhook-mailer at python.org (tiran) Date: Thu, 02 Dec 2021 17:43:06 -0000 Subject: [Python-checkins] bpo-40280: Update what's new (GH-29893) Message-ID: https://github.com/python/cpython/commit/a31173c5ceb1708df687f942d714bdecae7cb759 commit: a31173c5ceb1708df687f942d714bdecae7cb759 branch: main author: Christian Heimes committer: tiran date: 2021-12-02T18:42:56+01:00 summary: bpo-40280: Update what's new (GH-29893) files: M Doc/whatsnew/3.11.rst diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 345b2df43f403..1ec629d8229cb 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -585,6 +585,11 @@ Build Changes ``libdb`` 3.x and 4.x are no longer supported. (Contributed by Christian Heimes in :issue:`45747`.) +* CPython now has experimental support for cross compiling to WebAssembly + platform ``wasm32-emscripten``. The effort is inspired by previous work + like Pyodide. + (Contributed by Christian Heimes and Ethan Smith in :issue:`40280`.) + C API Changes ============= From webhook-mailer at python.org Thu Dec 2 15:24:37 2021 From: webhook-mailer at python.org (zware) Date: Thu, 02 Dec 2021 20:24:37 -0000 Subject: [Python-checkins] bpo-45916: Use HTTPS link for The Perils of Floating Point (GH-29896) Message-ID: https://github.com/python/cpython/commit/9f2f7e42269db74a89fc8cd74d82a875787f01d7 commit: 9f2f7e42269db74a89fc8cd74d82a875787f01d7 branch: main author: Zachary Ware committer: zware date: 2021-12-02T14:24:25-06:00 summary: bpo-45916: Use HTTPS link for The Perils of Floating Point (GH-29896) files: M Doc/tutorial/floatingpoint.rst diff --git a/Doc/tutorial/floatingpoint.rst b/Doc/tutorial/floatingpoint.rst index b98de6e56a003..7212b40be8377 100644 --- a/Doc/tutorial/floatingpoint.rst +++ b/Doc/tutorial/floatingpoint.rst @@ -133,7 +133,7 @@ with inexact values become comparable to one another:: Binary floating-point arithmetic holds many surprises like this. The problem with "0.1" is explained in precise detail below, in the "Representation Error" -section. See `The Perils of Floating Point `_ +section. See `The Perils of Floating Point `_ for a more complete account of other common surprises. As that says near the end, "there are no easy answers." Still, don't be unduly From webhook-mailer at python.org Thu Dec 2 15:45:21 2021 From: webhook-mailer at python.org (miss-islington) Date: Thu, 02 Dec 2021 20:45:21 -0000 Subject: [Python-checkins] bpo-45916: Use HTTPS link for The Perils of Floating Point (GH-29896) Message-ID: https://github.com/python/cpython/commit/f6648e229edf07a1e4897244d7d34989dd9ea647 commit: f6648e229edf07a1e4897244d7d34989dd9ea647 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-02T12:45:09-08:00 summary: bpo-45916: Use HTTPS link for The Perils of Floating Point (GH-29896) (cherry picked from commit 9f2f7e42269db74a89fc8cd74d82a875787f01d7) Co-authored-by: Zachary Ware files: M Doc/tutorial/floatingpoint.rst diff --git a/Doc/tutorial/floatingpoint.rst b/Doc/tutorial/floatingpoint.rst index b98de6e56a003..7212b40be8377 100644 --- a/Doc/tutorial/floatingpoint.rst +++ b/Doc/tutorial/floatingpoint.rst @@ -133,7 +133,7 @@ with inexact values become comparable to one another:: Binary floating-point arithmetic holds many surprises like this. The problem with "0.1" is explained in precise detail below, in the "Representation Error" -section. See `The Perils of Floating Point `_ +section. See `The Perils of Floating Point `_ for a more complete account of other common surprises. As that says near the end, "there are no easy answers." Still, don't be unduly From webhook-mailer at python.org Thu Dec 2 19:08:51 2021 From: webhook-mailer at python.org (zooba) Date: Fri, 03 Dec 2021 00:08:51 -0000 Subject: [Python-checkins] bpo-45582: Port getpath[p].c to Python (GH-29041) Message-ID: https://github.com/python/cpython/commit/99fcf1505218464c489d419d4500f126b6d6dc28 commit: 99fcf1505218464c489d419d4500f126b6d6dc28 branch: main author: Steve Dower committer: zooba date: 2021-12-03T00:08:42Z summary: bpo-45582: Port getpath[p].c to Python (GH-29041) The getpath.py file is frozen at build time and executed as code over a namespace. It is never imported, nor is it meant to be importable or reusable. However, it should be easier to read, modify, and patch than the previous code. This commit attempts to preserve every previously tested quirk, but these may be changed in the future to better align platforms. files: A Lib/test/test_getpath.py A Misc/NEWS.d/next/Core and Builtins/2021-10-23-00-39-31.bpo-45582.YONPuo.rst A Modules/getpath.py A Modules/getpath_noop.c D PC/getpathp.c M .gitignore M Doc/c-api/init_config.rst M Include/cpython/fileutils.h M Include/cpython/initconfig.h M Include/internal/pycore_fileutils.h M Include/internal/pycore_initconfig.h M Include/internal/pycore_pathconfig.h M Lib/ntpath.py M Lib/posixpath.py M Lib/site.py M Lib/sysconfig.py M Lib/test/_test_embed_set_config.py M Lib/test/test_embed.py M Lib/test/test_ntpath.py M Lib/test/test_site.py M Lib/test/test_sysconfig.py M Lib/test/test_venv.py M Makefile.pre.in M Modules/_testinternalcapi.c M Modules/clinic/posixmodule.c.h M Modules/getpath.c M Modules/main.c M Modules/posixmodule.c M PC/config_minimal.c M PC/pyconfig.h M PCbuild/_freeze_module.vcxproj M PCbuild/_freeze_module.vcxproj.filters M PCbuild/python.vcxproj M PCbuild/pythoncore.vcxproj M PCbuild/pythoncore.vcxproj.filters M Python/dynload_win.c M Python/fileutils.c M Python/initconfig.c M Python/pathconfig.c M Python/pylifecycle.c diff --git a/.gitignore b/.gitignore index 0363244bdaf63..7e80446d4d4a6 100644 --- a/.gitignore +++ b/.gitignore @@ -74,6 +74,7 @@ Mac/pythonw Misc/python.pc Misc/python-embed.pc Misc/python-config.sh +Modules/getpath.h Modules/Setup.config Modules/Setup.local Modules/Setup.stdlib diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst index 3642a8bf7fbc7..7c8fb7b1dee5d 100644 --- a/Doc/c-api/init_config.rst +++ b/Doc/c-api/init_config.rst @@ -479,6 +479,9 @@ PyConfig Fields which are already initialized are left unchanged. + Fields for :ref:`path configuration ` are no longer + calculated or modified when calling this function, as of Python 3.11. + The :c:func:`PyConfig_Read` function only parses :c:member:`PyConfig.argv` arguments once: :c:member:`PyConfig.parse_argv` is set to ``2`` after arguments are parsed. Since Python arguments are @@ -493,6 +496,12 @@ PyConfig parsed, and arguments are only parsed if :c:member:`PyConfig.parse_argv` equals ``1``. + .. versionchanged:: 3.11 + :c:func:`PyConfig_Read` no longer calculates all paths, and so fields + listed under :ref:`Python Path Configuration ` may + no longer be updated until :c:func:`Py_InitializeFromConfig` is + called. + .. c:function:: void PyConfig_Clear(PyConfig *config) Release configuration memory. @@ -848,12 +857,19 @@ PyConfig Default: value of the ``PLATLIBDIR`` macro which is set by the :option:`configure --with-platlibdir option <--with-platlibdir>` - (default: ``"lib"``). + (default: ``"lib"``, or ``"DLLs"`` on Windows). Part of the :ref:`Python Path Configuration ` input. .. versionadded:: 3.9 + .. versionchanged:: 3.11 + This macro is now used on Windows to locate the standard + library extension modules, typically under ``DLLs``. However, + for compatibility, note that this value is ignored for any + non-standard layouts, including in-tree builds and virtual + environments. + .. c:member:: wchar_t* pythonpath_env Module search paths (:data:`sys.path`) as a string separated by ``DELIM`` @@ -870,9 +886,9 @@ PyConfig Module search paths: :data:`sys.path`. - If :c:member:`~PyConfig.module_search_paths_set` is equal to 0, the - function calculating the :ref:`Python Path Configuration ` - overrides the :c:member:`~PyConfig.module_search_paths` and sets + If :c:member:`~PyConfig.module_search_paths_set` is equal to 0, + :c:func:`Py_InitializeFromConfig` will replace + :c:member:`~PyConfig.module_search_paths` and sets :c:member:`~PyConfig.module_search_paths_set` to ``1``. Default: empty list (``module_search_paths``) and ``0`` @@ -944,16 +960,16 @@ PyConfig .. c:member:: int pathconfig_warnings - On Unix, if non-zero, calculating the :ref:`Python Path Configuration - ` can log warnings into ``stderr``. If equals to 0, - suppress these warnings. - - It has no effect on Windows. + If non-zero, calculation of path configuration is allowed to log + warnings into ``stderr``. If equals to 0, suppress these warnings. Default: ``1`` in Python mode, ``0`` in isolated mode. Part of the :ref:`Python Path Configuration ` input. + .. versionchanged:: 3.11 + Now also applies on Windows. + .. c:member:: wchar_t* prefix The site-specific directory prefix where the platform independent Python @@ -1305,10 +1321,9 @@ variables, command line arguments (:c:member:`PyConfig.argv` is not parsed) and user site directory. The C standard streams (ex: ``stdout``) and the LC_CTYPE locale are left unchanged. Signal handlers are not installed. -Configuration files are still used with this configuration. Set the -:ref:`Python Path Configuration ` ("output fields") to ignore these -configuration files and avoid the function computing the default path -configuration. +Configuration files are still used with this configuration to determine +paths that are unspecified. Ensure :c:member:`PyConfig.home` is specified +to avoid computing the default path configuration. .. _init-python-config: diff --git a/Include/cpython/fileutils.h b/Include/cpython/fileutils.h index ccf37e9468d61..7ab2290184a2f 100644 --- a/Include/cpython/fileutils.h +++ b/Include/cpython/fileutils.h @@ -135,12 +135,6 @@ PyAPI_FUNC(wchar_t*) _Py_wrealpath( size_t resolved_path_len); #endif -#ifndef MS_WINDOWS -PyAPI_FUNC(int) _Py_isabs(const wchar_t *path); -#endif - -PyAPI_FUNC(int) _Py_abspath(const wchar_t *path, wchar_t **abspath_p); - PyAPI_FUNC(wchar_t*) _Py_wgetcwd( wchar_t *buf, /* Number of characters of 'buf' buffer diff --git a/Include/cpython/initconfig.h b/Include/cpython/initconfig.h index 2be4c25ec0b09..2ba1224d9b0b0 100644 --- a/Include/cpython/initconfig.h +++ b/Include/cpython/initconfig.h @@ -213,6 +213,9 @@ typedef struct PyConfig { // If non-zero, disallow threads, subprocesses, and fork. // Default: 0. int _isolated_interpreter; + + // If non-zero, we believe we're running from a source tree. + int _is_python_build; } PyConfig; PyAPI_FUNC(void) PyConfig_InitPythonConfig(PyConfig *config); diff --git a/Include/internal/pycore_fileutils.h b/Include/internal/pycore_fileutils.h index d1caf9c237234..38df73b745bcb 100644 --- a/Include/internal/pycore_fileutils.h +++ b/Include/internal/pycore_fileutils.h @@ -74,14 +74,15 @@ extern int _Py_EncodeNonUnicodeWchar_InPlace( Py_ssize_t size); #endif +extern int _Py_isabs(const wchar_t *path); +extern int _Py_abspath(const wchar_t *path, wchar_t **abspath_p); extern wchar_t * _Py_join_relfile(const wchar_t *dirname, const wchar_t *relfile); extern int _Py_add_relfile(wchar_t *dirname, const wchar_t *relfile, size_t bufsize); extern size_t _Py_find_basename(const wchar_t *filename); -PyAPI_FUNC(int) _Py_normalize_path(const wchar_t *path, - wchar_t *buf, const size_t buf_len); +PyAPI_FUNC(wchar_t *) _Py_normpath(wchar_t *path, Py_ssize_t size); // Macros to protect CRT calls against instant termination when passed an diff --git a/Include/internal/pycore_initconfig.h b/Include/internal/pycore_initconfig.h index 9014fcd41d868..be545f495dc0f 100644 --- a/Include/internal/pycore_initconfig.h +++ b/Include/internal/pycore_initconfig.h @@ -166,6 +166,10 @@ extern PyStatus _PyConfig_SetPyArgv( PyAPI_FUNC(PyObject*) _PyConfig_AsDict(const PyConfig *config); PyAPI_FUNC(int) _PyConfig_FromDict(PyConfig *config, PyObject *dict); +extern void _Py_DumpPathConfig(PyThreadState *tstate); + +PyAPI_FUNC(PyObject*) _Py_Get_Getpath_CodeObject(); + /* --- Function used for testing ---------------------------------- */ diff --git a/Include/internal/pycore_pathconfig.h b/Include/internal/pycore_pathconfig.h index a258aab239766..b8deaa0c3eb06 100644 --- a/Include/internal/pycore_pathconfig.h +++ b/Include/internal/pycore_pathconfig.h @@ -8,65 +8,15 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -typedef struct _PyPathConfig { - /* Full path to the Python program */ - wchar_t *program_full_path; - wchar_t *prefix; - wchar_t *exec_prefix; - wchar_t *stdlib_dir; - /* Set by Py_SetPath(), or computed by _PyConfig_InitPathConfig() */ - wchar_t *module_search_path; - /* Python program name */ - wchar_t *program_name; - /* Set by Py_SetPythonHome() or PYTHONHOME environment variable */ - wchar_t *home; -#ifdef MS_WINDOWS - /* isolated and site_import are used to set Py_IsolatedFlag and - Py_NoSiteFlag flags on Windows in read_pth_file(). These fields - are ignored when their value are equal to -1 (unset). */ - int isolated; - int site_import; - /* Set when a venv is detected */ - wchar_t *base_executable; -#endif -} _PyPathConfig; - -#ifdef MS_WINDOWS -# define _PyPathConfig_INIT \ - {.module_search_path = NULL, \ - .isolated = -1, \ - .site_import = -1} -#else -# define _PyPathConfig_INIT \ - {.module_search_path = NULL} -#endif -/* Note: _PyPathConfig_INIT sets other fields to 0/NULL */ - -PyAPI_DATA(_PyPathConfig) _Py_path_config; -#ifdef MS_WINDOWS -PyAPI_DATA(wchar_t*) _Py_dll_path; -#endif - -extern void _PyPathConfig_ClearGlobal(void); +PyAPI_FUNC(void) _PyPathConfig_ClearGlobal(void); +extern PyStatus _PyPathConfig_ReadGlobal(PyConfig *config); +extern PyStatus _PyPathConfig_UpdateGlobal(const PyConfig *config); +extern const wchar_t * _PyPathConfig_GetGlobalModuleSearchPath(void); -extern PyStatus _PyPathConfig_Calculate( - _PyPathConfig *pathconfig, - const PyConfig *config); extern int _PyPathConfig_ComputeSysPath0( const PyWideStringList *argv, PyObject **path0); -extern PyStatus _Py_FindEnvConfigValue( - FILE *env_file, - const wchar_t *key, - wchar_t **value_p); - -#ifdef MS_WINDOWS -extern wchar_t* _Py_GetDLLPath(void); -#endif -extern PyStatus _PyConfig_WritePathConfig(const PyConfig *config); -extern void _Py_DumpPathConfig(PyThreadState *tstate); -extern PyObject* _PyPathConfig_AsDict(void); #ifdef __cplusplus } diff --git a/Lib/ntpath.py b/Lib/ntpath.py index 527c7ae1938fb..58483a0c0a98b 100644 --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -70,7 +70,7 @@ def isabs(s): if s.replace('/', '\\').startswith('\\\\?\\'): return True s = splitdrive(s)[1] - return len(s) > 0 and s[0] in _get_bothseps(s) + return len(s) > 0 and s[0] and s[0] in _get_bothseps(s) # Join two (or more) paths. @@ -268,11 +268,13 @@ def ismount(path): root, rest = splitdrive(path) if root and root[0] in seps: return (not rest) or (rest in seps) - if rest in seps: + if rest and rest in seps: return True if _getvolumepathname: - return path.rstrip(seps) == _getvolumepathname(path).rstrip(seps) + x = path.rstrip(seps) + y =_getvolumepathname(path).rstrip(seps) + return x.casefold() == y.casefold() else: return False @@ -459,56 +461,68 @@ def expandvars(path): # Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A\B. # Previously, this function also truncated pathnames to 8+3 format, # but as this module is called "ntpath", that's obviously wrong! +try: + from nt import _path_normpath -def normpath(path): - """Normalize path, eliminating double slashes, etc.""" - path = os.fspath(path) - if isinstance(path, bytes): - sep = b'\\' - altsep = b'/' - curdir = b'.' - pardir = b'..' - special_prefixes = (b'\\\\.\\', b'\\\\?\\') - else: - sep = '\\' - altsep = '/' - curdir = '.' - pardir = '..' - special_prefixes = ('\\\\.\\', '\\\\?\\') - if path.startswith(special_prefixes): - # in the case of paths with these prefixes: - # \\.\ -> device names - # \\?\ -> literal paths - # do not do any normalization, but return the path - # unchanged apart from the call to os.fspath() - return path - path = path.replace(altsep, sep) - prefix, path = splitdrive(path) - - # collapse initial backslashes - if path.startswith(sep): - prefix += sep - path = path.lstrip(sep) - - comps = path.split(sep) - i = 0 - while i < len(comps): - if not comps[i] or comps[i] == curdir: - del comps[i] - elif comps[i] == pardir: - if i > 0 and comps[i-1] != pardir: - del comps[i-1:i+1] - i -= 1 - elif i == 0 and prefix.endswith(sep): +except ImportError: + def normpath(path): + """Normalize path, eliminating double slashes, etc.""" + path = os.fspath(path) + if isinstance(path, bytes): + sep = b'\\' + altsep = b'/' + curdir = b'.' + pardir = b'..' + special_prefixes = (b'\\\\.\\', b'\\\\?\\') + else: + sep = '\\' + altsep = '/' + curdir = '.' + pardir = '..' + special_prefixes = ('\\\\.\\', '\\\\?\\') + if path.startswith(special_prefixes): + # in the case of paths with these prefixes: + # \\.\ -> device names + # \\?\ -> literal paths + # do not do any normalization, but return the path + # unchanged apart from the call to os.fspath() + return path + path = path.replace(altsep, sep) + prefix, path = splitdrive(path) + + # collapse initial backslashes + if path.startswith(sep): + prefix += sep + path = path.lstrip(sep) + + comps = path.split(sep) + i = 0 + while i < len(comps): + if not comps[i] or comps[i] == curdir: del comps[i] + elif comps[i] == pardir: + if i > 0 and comps[i-1] != pardir: + del comps[i-1:i+1] + i -= 1 + elif i == 0 and prefix.endswith(sep): + del comps[i] + else: + i += 1 else: i += 1 - else: - i += 1 - # If the path is now empty, substitute '.' - if not prefix and not comps: - comps.append(curdir) - return prefix + sep.join(comps) + # If the path is now empty, substitute '.' + if not prefix and not comps: + comps.append(curdir) + return prefix + sep.join(comps) + +else: + def normpath(path): + """Normalize path, eliminating double slashes, etc.""" + path = os.fspath(path) + if isinstance(path, bytes): + return os.fsencode(_path_normpath(os.fsdecode(path))) or b"." + return _path_normpath(path) or "." + def _abspath_fallback(path): """Return the absolute version of a path as a fallback function in case diff --git a/Lib/posixpath.py b/Lib/posixpath.py index 195374613a779..a46c667db5633 100644 --- a/Lib/posixpath.py +++ b/Lib/posixpath.py @@ -334,43 +334,55 @@ def expandvars(path): # It should be understood that this may change the meaning of the path # if it contains symbolic links! -def normpath(path): - """Normalize path, eliminating double slashes, etc.""" - path = os.fspath(path) - if isinstance(path, bytes): - sep = b'/' - empty = b'' - dot = b'.' - dotdot = b'..' - else: - sep = '/' - empty = '' - dot = '.' - dotdot = '..' - if path == empty: - return dot - initial_slashes = path.startswith(sep) - # POSIX allows one or two initial slashes, but treats three or more - # as single slash. - # (see http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13) - if (initial_slashes and - path.startswith(sep*2) and not path.startswith(sep*3)): - initial_slashes = 2 - comps = path.split(sep) - new_comps = [] - for comp in comps: - if comp in (empty, dot): - continue - if (comp != dotdot or (not initial_slashes and not new_comps) or - (new_comps and new_comps[-1] == dotdot)): - new_comps.append(comp) - elif new_comps: - new_comps.pop() - comps = new_comps - path = sep.join(comps) - if initial_slashes: - path = sep*initial_slashes + path - return path or dot +try: + from posix import _path_normpath + +except ImportError: + def normpath(path): + """Normalize path, eliminating double slashes, etc.""" + path = os.fspath(path) + if isinstance(path, bytes): + sep = b'/' + empty = b'' + dot = b'.' + dotdot = b'..' + else: + sep = '/' + empty = '' + dot = '.' + dotdot = '..' + if path == empty: + return dot + initial_slashes = path.startswith(sep) + # POSIX allows one or two initial slashes, but treats three or more + # as single slash. + # (see http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13) + if (initial_slashes and + path.startswith(sep*2) and not path.startswith(sep*3)): + initial_slashes = 2 + comps = path.split(sep) + new_comps = [] + for comp in comps: + if comp in (empty, dot): + continue + if (comp != dotdot or (not initial_slashes and not new_comps) or + (new_comps and new_comps[-1] == dotdot)): + new_comps.append(comp) + elif new_comps: + new_comps.pop() + comps = new_comps + path = sep.join(comps) + if initial_slashes: + path = sep*initial_slashes + path + return path or dot + +else: + def normpath(path): + """Normalize path, eliminating double slashes, etc.""" + path = os.fspath(path) + if isinstance(path, bytes): + return os.fsencode(_path_normpath(os.fsdecode(path))) or b"." + return _path_normpath(path) or "." def abspath(path): diff --git a/Lib/site.py b/Lib/site.py index e129f3b4851f3..b11cd48e69e9a 100644 --- a/Lib/site.py +++ b/Lib/site.py @@ -361,11 +361,11 @@ def getsitepackages(prefixes=None): continue seen.add(prefix) - libdirs = [sys.platlibdir] - if sys.platlibdir != "lib": - libdirs.append("lib") - if os.sep == '/': + libdirs = [sys.platlibdir] + if sys.platlibdir != "lib": + libdirs.append("lib") + for libdir in libdirs: path = os.path.join(prefix, libdir, "python%d.%d" % sys.version_info[:2], @@ -373,10 +373,7 @@ def getsitepackages(prefixes=None): sitepackages.append(path) else: sitepackages.append(prefix) - - for libdir in libdirs: - path = os.path.join(prefix, libdir, "site-packages") - sitepackages.append(path) + sitepackages.append(os.path.join(prefix, "Lib", "site-packages")) return sitepackages def addsitepackages(known_paths, prefixes=None): diff --git a/Lib/sysconfig.py b/Lib/sysconfig.py index daf9f000060a3..da918b7ba1904 100644 --- a/Lib/sysconfig.py +++ b/Lib/sysconfig.py @@ -216,6 +216,11 @@ def _expand_vars(scheme, vars): if vars is None: vars = {} _extend_dict(vars, get_config_vars()) + if os.name == 'nt': + # On Windows we want to substitute 'lib' for schemes rather + # than the native value (without modifying vars, in case it + # was passed in) + vars = vars | {'platlibdir': 'lib'} for key, value in _INSTALL_SCHEMES[scheme].items(): if os.name in ('posix', 'nt'): diff --git a/Lib/test/_test_embed_set_config.py b/Lib/test/_test_embed_set_config.py index d05907ecfe744..e7b7106e17851 100644 --- a/Lib/test/_test_embed_set_config.py +++ b/Lib/test/_test_embed_set_config.py @@ -20,6 +20,7 @@ def setUp(self): self.sys_copy = dict(sys.__dict__) def tearDown(self): + _testinternalcapi.reset_path_config() _testinternalcapi.set_config(self.old_config) sys.__dict__.clear() sys.__dict__.update(self.sys_copy) diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index 4781c7f2a9d12..3620a7619601d 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -13,6 +13,7 @@ import shutil import subprocess import sys +import sysconfig import tempfile import textwrap @@ -445,6 +446,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): '_init_main': 1, '_isolated_interpreter': 0, 'use_frozen_modules': 1, + '_is_python_build': IGNORE_CONFIG, } if MS_WINDOWS: CONFIG_COMPAT.update({ @@ -508,32 +510,6 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): ('Py_LegacyWindowsStdioFlag', 'legacy_windows_stdio'), )) - # path config - if MS_WINDOWS: - PATH_CONFIG = { - 'isolated': -1, - 'site_import': -1, - 'python3_dll': GET_DEFAULT_CONFIG, - } - else: - PATH_CONFIG = {} - # other keys are copied by COPY_PATH_CONFIG - - COPY_PATH_CONFIG = [ - # Copy core config to global config for expected values - 'prefix', - 'exec_prefix', - 'program_name', - 'home', - 'stdlib_dir', - # program_full_path and module_search_path are copied indirectly from - # the core configuration in check_path_config(). - ] - if MS_WINDOWS: - COPY_PATH_CONFIG.extend(( - 'base_executable', - )) - EXPECTED_CONFIG = None @classmethod @@ -599,8 +575,7 @@ def _get_expected_config(self): return configs def get_expected_config(self, expected_preconfig, expected, - expected_pathconfig, env, api, - modify_path_cb=None): + env, api, modify_path_cb=None): configs = self._get_expected_config() pre_config = configs['pre_config'] @@ -608,11 +583,6 @@ def get_expected_config(self, expected_preconfig, expected, if value is self.GET_DEFAULT_CONFIG: expected_preconfig[key] = pre_config[key] - path_config = configs['path_config'] - for key, value in expected_pathconfig.items(): - if value is self.GET_DEFAULT_CONFIG: - expected_pathconfig[key] = path_config[key] - if not expected_preconfig['configure_locale'] or api == API_COMPAT: # there is no easy way to get the locale encoding before # setlocale(LC_CTYPE, "") is called: don't test encodings @@ -705,18 +675,8 @@ def check_global_config(self, configs): self.assertEqual(configs['global_config'], expected) - def check_path_config(self, configs, expected): - config = configs['config'] - - for key in self.COPY_PATH_CONFIG: - expected[key] = config[key] - expected['module_search_path'] = os.path.pathsep.join(config['module_search_paths']) - expected['program_full_path'] = config['executable'] - - self.assertEqual(configs['path_config'], expected) - def check_all_configs(self, testname, expected_config=None, - expected_preconfig=None, expected_pathconfig=None, + expected_preconfig=None, modify_path_cb=None, stderr=None, *, api, preconfig_api=None, env=None, ignore_stderr=False, cwd=None): @@ -740,10 +700,6 @@ def check_all_configs(self, testname, expected_config=None, if expected_config is None: expected_config = {} - if expected_pathconfig is None: - expected_pathconfig = {} - expected_pathconfig = dict(self.PATH_CONFIG, **expected_pathconfig) - if api == API_PYTHON: default_config = self.CONFIG_PYTHON elif api == API_ISOLATED: @@ -754,7 +710,6 @@ def check_all_configs(self, testname, expected_config=None, self.get_expected_config(expected_preconfig, expected_config, - expected_pathconfig, env, api, modify_path_cb) @@ -772,7 +727,6 @@ def check_all_configs(self, testname, expected_config=None, self.check_pre_config(configs, expected_preconfig) self.check_config(configs, expected_config) self.check_global_config(configs) - self.check_path_config(configs, expected_pathconfig) return configs def test_init_default_config(self): @@ -1039,10 +993,13 @@ def test_init_dont_configure_locale(self): self.check_all_configs("test_init_dont_configure_locale", {}, preconfig, api=API_PYTHON) + @unittest.skip('as of 3.11 this test no longer works because ' + 'path calculations do not occur on read') def test_init_read_set(self): config = { 'program_name': './init_read_set', 'executable': 'my_executable', + 'base_executable': 'my_executable', } def modify_path(path): path.insert(1, "test_path_insert1") @@ -1156,7 +1113,6 @@ def test_init_setpath(self): # The current getpath.c doesn't determine the stdlib dir # in this case. 'stdlib_dir': '', - 'use_frozen_modules': -1, } self.default_program_name(config) env = {'TESTPATH': os.path.pathsep.join(paths)} @@ -1180,7 +1136,7 @@ def test_init_setpath_config(self): # The current getpath.c doesn't determine the stdlib dir # in this case. 'stdlib_dir': '', - 'use_frozen_modules': -1, + 'use_frozen_modules': 1, # overridden by PyConfig 'program_name': 'conf_program_name', 'base_executable': 'conf_executable', @@ -1210,13 +1166,16 @@ def module_search_paths(self, prefix=None, exec_prefix=None): ] @contextlib.contextmanager - def tmpdir_with_python(self): + def tmpdir_with_python(self, subdir=None): # Temporary directory with a copy of the Python program with tempfile.TemporaryDirectory() as tmpdir: # bpo-38234: On macOS and FreeBSD, the temporary directory # can be symbolic link. For example, /tmp can be a symbolic link # to /var/tmp. Call realpath() to resolve all symbolic links. tmpdir = os.path.realpath(tmpdir) + if subdir: + tmpdir = os.path.normpath(os.path.join(tmpdir, subdir)) + os.makedirs(tmpdir) if MS_WINDOWS: # Copy pythonXY.dll (or pythonXY_d.dll) @@ -1260,11 +1219,14 @@ def test_init_setpythonhome(self): prefix = exec_prefix = home if MS_WINDOWS: - stdlib = os.path.join(home, sys.platlibdir) + stdlib = os.path.join(home, "Lib") + # Because we are specifying 'home', module search paths + # are fairly static + expected_paths = [paths[0], stdlib, os.path.join(home, 'DLLs')] else: version = f'{sys.version_info.major}.{sys.version_info.minor}' stdlib = os.path.join(home, sys.platlibdir, f'python{version}') - expected_paths = self.module_search_paths(prefix=home, exec_prefix=home) + expected_paths = self.module_search_paths(prefix=home, exec_prefix=home) config = { 'home': home, @@ -1291,7 +1253,7 @@ def copy_paths_by_env(self, config): env = {'PYTHONPATH': paths_str} return env - @unittest.skipIf(MS_WINDOWS, 'Windows does not use pybuilddir.txt') + @unittest.skipIf(MS_WINDOWS, 'See test_init_pybuilddir_win32') def test_init_pybuilddir(self): # Test path configuration with pybuilddir.txt configuration file @@ -1300,6 +1262,8 @@ def test_init_pybuilddir(self): # directory (tmpdir) subdir = 'libdir' libdir = os.path.join(tmpdir, subdir) + # The stdlib dir is dirname(executable) + VPATH + 'Lib' + stdlibdir = os.path.join(tmpdir, 'Lib') os.mkdir(libdir) filename = os.path.join(tmpdir, 'pybuilddir.txt') @@ -1307,21 +1271,58 @@ def test_init_pybuilddir(self): fp.write(subdir) module_search_paths = self.module_search_paths() + module_search_paths[-2] = stdlibdir module_search_paths[-1] = libdir executable = self.test_exe config = { + 'base_exec_prefix': sysconfig.get_config_var("exec_prefix"), + 'base_prefix': sysconfig.get_config_var("prefix"), 'base_executable': executable, 'executable': executable, 'module_search_paths': module_search_paths, - 'stdlib_dir': STDLIB_INSTALL, - 'use_frozen_modules': 1 if STDLIB_INSTALL else -1, + 'stdlib_dir': stdlibdir, } env = self.copy_paths_by_env(config) self.check_all_configs("test_init_compat_config", config, api=API_COMPAT, env=env, ignore_stderr=True, cwd=tmpdir) + @unittest.skipUnless(MS_WINDOWS, 'See test_init_pybuilddir') + def test_init_pybuilddir_win32(self): + # Test path configuration with pybuilddir.txt configuration file + + with self.tmpdir_with_python(r'PCbuild\arch') as tmpdir: + # The prefix is dirname(executable) + VPATH + prefix = os.path.normpath(os.path.join(tmpdir, r'..\..')) + # The stdlib dir is dirname(executable) + VPATH + 'Lib' + stdlibdir = os.path.normpath(os.path.join(tmpdir, r'..\..\Lib')) + + filename = os.path.join(tmpdir, 'pybuilddir.txt') + with open(filename, "w", encoding="utf8") as fp: + fp.write(tmpdir) + + module_search_paths = self.module_search_paths() + module_search_paths[-3] = os.path.join(tmpdir, os.path.basename(module_search_paths[-3])) + module_search_paths[-2] = stdlibdir + module_search_paths[-1] = tmpdir + + executable = self.test_exe + config = { + 'base_exec_prefix': prefix, + 'base_prefix': prefix, + 'base_executable': executable, + 'executable': executable, + 'prefix': prefix, + 'exec_prefix': prefix, + 'module_search_paths': module_search_paths, + 'stdlib_dir': stdlibdir, + } + env = self.copy_paths_by_env(config) + self.check_all_configs("test_init_compat_config", config, + api=API_COMPAT, env=env, + ignore_stderr=False, cwd=tmpdir) + def test_init_pyvenv_cfg(self): # Test path configuration with pyvenv.cfg configuration file @@ -1336,12 +1337,12 @@ def test_init_pyvenv_cfg(self): 'lib-dynload') os.makedirs(lib_dynload) else: - lib_dynload = os.path.join(pyvenv_home, 'lib') - os.makedirs(lib_dynload) - # getpathp.c uses Lib\os.py as the LANDMARK + lib_folder = os.path.join(pyvenv_home, 'Lib') + os.makedirs(lib_folder) + # getpath.py uses Lib\os.py as the LANDMARK shutil.copyfile( os.path.join(support.STDLIB_DIR, 'os.py'), - os.path.join(lib_dynload, 'os.py'), + os.path.join(lib_folder, 'os.py'), ) filename = os.path.join(tmpdir, 'pyvenv.cfg') @@ -1355,43 +1356,38 @@ def test_init_pyvenv_cfg(self): else: for index, path in enumerate(paths): if index == 0: + # Because we copy the DLLs into tmpdir as well, the zip file + # entry in sys.path will be there. For a regular venv, it will + # usually be in the home directory. paths[index] = os.path.join(tmpdir, os.path.basename(path)) else: paths[index] = os.path.join(pyvenv_home, os.path.basename(path)) paths[-1] = pyvenv_home executable = self.test_exe + base_executable = os.path.join(pyvenv_home, os.path.basename(executable)) exec_prefix = pyvenv_home config = { + 'base_prefix': sysconfig.get_config_var("prefix"), 'base_exec_prefix': exec_prefix, 'exec_prefix': exec_prefix, - 'base_executable': executable, + 'base_executable': base_executable, 'executable': executable, 'module_search_paths': paths, } - path_config = {} if MS_WINDOWS: config['base_prefix'] = pyvenv_home config['prefix'] = pyvenv_home - config['stdlib_dir'] = os.path.join(pyvenv_home, 'lib') + config['stdlib_dir'] = os.path.join(pyvenv_home, 'Lib') config['use_frozen_modules'] = 1 - - ver = sys.version_info - dll = f'python{ver.major}' - if debug_build(executable): - dll += '_d' - dll += '.DLL' - dll = os.path.join(os.path.dirname(executable), dll) - path_config['python3_dll'] = dll else: - # The current getpath.c doesn't determine the stdlib dir - # in this case. - config['stdlib_dir'] = STDLIB_INSTALL - config['use_frozen_modules'] = 1 if STDLIB_INSTALL else -1 + # cannot reliably assume stdlib_dir here because it + # depends too much on our build. But it ought to be found + config['stdlib_dir'] = self.IGNORE_CONFIG + config['use_frozen_modules'] = 1 env = self.copy_paths_by_env(config) self.check_all_configs("test_init_compat_config", config, - expected_pathconfig=path_config, api=API_COMPAT, env=env, ignore_stderr=True, cwd=tmpdir) @@ -1502,10 +1498,14 @@ class SetConfigTests(unittest.TestCase): def test_set_config(self): # bpo-42260: Test _PyInterpreterState_SetConfig() import_helper.import_module('_testcapi') - cmd = [sys.executable, '-I', '-m', 'test._test_embed_set_config'] + cmd = [sys.executable, '-X', 'utf8', '-I', '-m', 'test._test_embed_set_config'] proc = subprocess.run(cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) + stderr=subprocess.PIPE, + encoding='utf-8', errors='backslashreplace') + if proc.returncode and support.verbose: + print(proc.stdout) + print(proc.stderr) self.assertEqual(proc.returncode, 0, (proc.returncode, proc.stdout, proc.stderr)) diff --git a/Lib/test/test_getpath.py b/Lib/test/test_getpath.py new file mode 100644 index 0000000000000..c18689c0590d4 --- /dev/null +++ b/Lib/test/test_getpath.py @@ -0,0 +1,879 @@ +import copy +import ntpath +import pathlib +import posixpath +import sys +import unittest + +from test.support import verbose + +try: + # If we are in a source tree, use the original source file for tests + SOURCE = (pathlib.Path(__file__).absolute().parent.parent.parent / "Modules/getpath.py").read_bytes() +except FileNotFoundError: + # Try from _testcapimodule instead + from _testinternalcapi import get_getpath_codeobject + SOURCE = get_getpath_codeobject() + + +class MockGetPathTests(unittest.TestCase): + def __init__(self, *a, **kw): + super().__init__(*a, **kw) + self.maxDiff = None + + def test_normal_win32(self): + "Test a 'standard' install layout on Windows." + ns = MockNTNamespace( + argv0=r"C:\Python\python.exe", + real_executable=r"C:\Python\python.exe", + ) + ns.add_known_xfile(r"C:\Python\python.exe") + ns.add_known_file(r"C:\Python\Lib\os.py") + ns.add_known_dir(r"C:\Python\DLLs") + expected = dict( + executable=r"C:\Python\python.exe", + base_executable=r"C:\Python\python.exe", + prefix=r"C:\Python", + exec_prefix=r"C:\Python", + module_search_paths_set=1, + module_search_paths=[ + r"C:\Python\python98.zip", + r"C:\Python\Lib", + r"C:\Python\DLLs", + ], + ) + actual = getpath(ns, expected) + self.assertEqual(expected, actual) + + def test_buildtree_win32(self): + "Test an in-build-tree layout on Windows." + ns = MockNTNamespace( + argv0=r"C:\CPython\PCbuild\amd64\python.exe", + real_executable=r"C:\CPython\PCbuild\amd64\python.exe", + ) + ns.add_known_xfile(r"C:\CPython\PCbuild\amd64\python.exe") + ns.add_known_file(r"C:\CPython\Lib\os.py") + ns.add_known_file(r"C:\CPython\PCbuild\amd64\pybuilddir.txt", [""]) + expected = dict( + executable=r"C:\CPython\PCbuild\amd64\python.exe", + base_executable=r"C:\CPython\PCbuild\amd64\python.exe", + prefix=r"C:\CPython", + exec_prefix=r"C:\CPython", + build_prefix=r"C:\CPython", + _is_python_build=1, + module_search_paths_set=1, + module_search_paths=[ + r"C:\CPython\PCbuild\amd64\python98.zip", + r"C:\CPython\Lib", + r"C:\CPython\PCbuild\amd64", + ], + ) + actual = getpath(ns, expected) + self.assertEqual(expected, actual) + + def test_venv_win32(self): + """Test a venv layout on Windows. + + This layout is discovered by the presence of %__PYVENV_LAUNCHER__%, + specifying the original launcher executable. site.py is responsible + for updating prefix and exec_prefix. + """ + ns = MockNTNamespace( + argv0=r"C:\Python\python.exe", + ENV___PYVENV_LAUNCHER__=r"C:\venv\Scripts\python.exe", + real_executable=r"C:\Python\python.exe", + ) + ns.add_known_xfile(r"C:\Python\python.exe") + ns.add_known_xfile(r"C:\venv\Scripts\python.exe") + ns.add_known_file(r"C:\Python\Lib\os.py") + ns.add_known_dir(r"C:\Python\DLLs") + ns.add_known_file(r"C:\venv\pyvenv.cfg", [ + r"home = C:\Python" + ]) + expected = dict( + executable=r"C:\venv\Scripts\python.exe", + prefix=r"C:\Python", + exec_prefix=r"C:\Python", + base_executable=r"C:\Python\python.exe", + base_prefix=r"C:\Python", + base_exec_prefix=r"C:\Python", + module_search_paths_set=1, + module_search_paths=[ + r"C:\Python\python98.zip", + r"C:\Python\Lib", + r"C:\Python", + ], + ) + actual = getpath(ns, expected) + self.assertEqual(expected, actual) + + def test_registry_win32(self): + """Test registry lookup on Windows. + + On Windows there are registry entries that are intended for other + applications to register search paths. + """ + hkey = rf"HKLM\Software\Python\PythonCore\9.8-XY\PythonPath" + winreg = MockWinreg({ + hkey: None, + f"{hkey}\\Path1": "path1-dir", + f"{hkey}\\Path1\\Subdir": "not-subdirs", + }) + ns = MockNTNamespace( + argv0=r"C:\Python\python.exe", + real_executable=r"C:\Python\python.exe", + winreg=winreg, + ) + ns.add_known_xfile(r"C:\Python\python.exe") + ns.add_known_file(r"C:\Python\Lib\os.py") + ns.add_known_dir(r"C:\Python\DLLs") + expected = dict( + module_search_paths_set=1, + module_search_paths=[ + r"C:\Python\python98.zip", + "path1-dir", + # should not contain not-subdirs + r"C:\Python\Lib", + r"C:\Python\DLLs", + ], + ) + actual = getpath(ns, expected) + self.assertEqual(expected, actual) + + ns["config"]["use_environment"] = 0 + ns["config"]["module_search_paths_set"] = 0 + ns["config"]["module_search_paths"] = None + expected = dict( + module_search_paths_set=1, + module_search_paths=[ + r"C:\Python\python98.zip", + r"C:\Python\Lib", + r"C:\Python\DLLs", + ], + ) + actual = getpath(ns, expected) + self.assertEqual(expected, actual) + + def test_symlink_normal_win32(self): + "Test a 'standard' install layout via symlink on Windows." + ns = MockNTNamespace( + argv0=r"C:\LinkedFrom\python.exe", + real_executable=r"C:\Python\python.exe", + ) + ns.add_known_xfile(r"C:\LinkedFrom\python.exe") + ns.add_known_xfile(r"C:\Python\python.exe") + ns.add_known_link(r"C:\LinkedFrom\python.exe", r"C:\Python\python.exe") + ns.add_known_file(r"C:\Python\Lib\os.py") + ns.add_known_dir(r"C:\Python\DLLs") + expected = dict( + executable=r"C:\LinkedFrom\python.exe", + base_executable=r"C:\LinkedFrom\python.exe", + prefix=r"C:\Python", + exec_prefix=r"C:\Python", + module_search_paths_set=1, + module_search_paths=[ + r"C:\Python\python98.zip", + r"C:\Python\Lib", + r"C:\Python\DLLs", + ], + ) + actual = getpath(ns, expected) + self.assertEqual(expected, actual) + + def test_symlink_buildtree_win32(self): + "Test an in-build-tree layout via symlink on Windows." + ns = MockNTNamespace( + argv0=r"C:\LinkedFrom\python.exe", + real_executable=r"C:\CPython\PCbuild\amd64\python.exe", + ) + ns.add_known_xfile(r"C:\LinkedFrom\python.exe") + ns.add_known_xfile(r"C:\CPython\PCbuild\amd64\python.exe") + ns.add_known_link(r"C:\LinkedFrom\python.exe", r"C:\CPython\PCbuild\amd64\python.exe") + ns.add_known_file(r"C:\CPython\Lib\os.py") + ns.add_known_file(r"C:\CPython\PCbuild\amd64\pybuilddir.txt", [""]) + expected = dict( + executable=r"C:\LinkedFrom\python.exe", + base_executable=r"C:\LinkedFrom\python.exe", + prefix=r"C:\CPython", + exec_prefix=r"C:\CPython", + build_prefix=r"C:\CPython", + _is_python_build=1, + module_search_paths_set=1, + module_search_paths=[ + r"C:\CPython\PCbuild\amd64\python98.zip", + r"C:\CPython\Lib", + r"C:\CPython\PCbuild\amd64", + ], + ) + actual = getpath(ns, expected) + self.assertEqual(expected, actual) + + def test_normal_posix(self): + "Test a 'standard' install layout on *nix" + ns = MockPosixNamespace( + PREFIX="/usr", + argv0="python", + ENV_PATH="/usr/bin", + ) + ns.add_known_xfile("/usr/bin/python") + ns.add_known_file("/usr/lib/python9.8/os.py") + ns.add_known_dir("/usr/lib/python9.8/lib-dynload") + expected = dict( + executable="/usr/bin/python", + base_executable="/usr/bin/python", + prefix="/usr", + exec_prefix="/usr", + module_search_paths_set=1, + module_search_paths=[ + "/usr/lib/python98.zip", + "/usr/lib/python9.8", + "/usr/lib/python9.8/lib-dynload", + ], + ) + actual = getpath(ns, expected) + self.assertEqual(expected, actual) + + def test_buildpath_posix(self): + """Test an in-build-tree layout on POSIX. + + This layout is discovered from the presence of pybuilddir.txt, which + contains the relative path from the executable's directory to the + platstdlib path. + """ + ns = MockPosixNamespace( + argv0=r"/home/cpython/python", + PREFIX="/usr/local", + ) + ns.add_known_xfile("/home/cpython/python") + ns.add_known_xfile("/usr/local/bin/python") + ns.add_known_file("/home/cpython/pybuilddir.txt", ["build/lib.linux-x86_64-9.8"]) + ns.add_known_file("/home/cpython/Lib/os.py") + ns.add_known_dir("/home/cpython/lib-dynload") + expected = dict( + executable="/home/cpython/python", + prefix="/usr/local", + exec_prefix="/usr/local", + base_executable="/home/cpython/python", + build_prefix="/home/cpython", + _is_python_build=1, + module_search_paths_set=1, + module_search_paths=[ + "/usr/local/lib/python98.zip", + "/home/cpython/Lib", + "/home/cpython/build/lib.linux-x86_64-9.8", + ], + ) + actual = getpath(ns, expected) + self.assertEqual(expected, actual) + + def test_venv_posix(self): + "Test a venv layout on *nix." + ns = MockPosixNamespace( + argv0="python", + PREFIX="/usr", + ENV_PATH="/venv/bin:/usr/bin", + ) + ns.add_known_xfile("/usr/bin/python") + ns.add_known_xfile("/venv/bin/python") + ns.add_known_file("/usr/lib/python9.8/os.py") + ns.add_known_dir("/usr/lib/python9.8/lib-dynload") + ns.add_known_file("/venv/pyvenv.cfg", [ + r"home = /usr/bin" + ]) + expected = dict( + executable="/venv/bin/python", + prefix="/usr", + exec_prefix="/usr", + base_executable="/usr/bin/python", + base_prefix="/usr", + base_exec_prefix="/usr", + module_search_paths_set=1, + module_search_paths=[ + "/usr/lib/python98.zip", + "/usr/lib/python9.8", + "/usr/lib/python9.8/lib-dynload", + ], + ) + actual = getpath(ns, expected) + self.assertEqual(expected, actual) + + def test_symlink_normal_posix(self): + "Test a 'standard' install layout via symlink on *nix" + ns = MockPosixNamespace( + PREFIX="/usr", + argv0="/linkfrom/python", + ) + ns.add_known_xfile("/linkfrom/python") + ns.add_known_xfile("/usr/bin/python") + ns.add_known_link("/linkfrom/python", "/usr/bin/python") + ns.add_known_file("/usr/lib/python9.8/os.py") + ns.add_known_dir("/usr/lib/python9.8/lib-dynload") + expected = dict( + executable="/linkfrom/python", + base_executable="/linkfrom/python", + prefix="/usr", + exec_prefix="/usr", + module_search_paths_set=1, + module_search_paths=[ + "/usr/lib/python98.zip", + "/usr/lib/python9.8", + "/usr/lib/python9.8/lib-dynload", + ], + ) + actual = getpath(ns, expected) + self.assertEqual(expected, actual) + + def test_symlink_buildpath_posix(self): + """Test an in-build-tree layout on POSIX. + + This layout is discovered from the presence of pybuilddir.txt, which + contains the relative path from the executable's directory to the + platstdlib path. + """ + ns = MockPosixNamespace( + argv0=r"/linkfrom/python", + PREFIX="/usr/local", + ) + ns.add_known_xfile("/linkfrom/python") + ns.add_known_xfile("/home/cpython/python") + ns.add_known_link("/linkfrom/python", "/home/cpython/python") + ns.add_known_xfile("/usr/local/bin/python") + ns.add_known_file("/home/cpython/pybuilddir.txt", ["build/lib.linux-x86_64-9.8"]) + ns.add_known_file("/home/cpython/Lib/os.py") + ns.add_known_dir("/home/cpython/lib-dynload") + expected = dict( + executable="/linkfrom/python", + prefix="/usr/local", + exec_prefix="/usr/local", + base_executable="/linkfrom/python", + build_prefix="/home/cpython", + _is_python_build=1, + module_search_paths_set=1, + module_search_paths=[ + "/usr/local/lib/python98.zip", + "/home/cpython/Lib", + "/home/cpython/build/lib.linux-x86_64-9.8", + ], + ) + actual = getpath(ns, expected) + self.assertEqual(expected, actual) + + def test_custom_platlibdir_posix(self): + "Test an install with custom platlibdir on *nix" + ns = MockPosixNamespace( + PREFIX="/usr", + argv0="/linkfrom/python", + PLATLIBDIR="lib64", + ) + ns.add_known_xfile("/usr/bin/python") + ns.add_known_file("/usr/lib64/python9.8/os.py") + ns.add_known_dir("/usr/lib64/python9.8/lib-dynload") + expected = dict( + executable="/linkfrom/python", + base_executable="/linkfrom/python", + prefix="/usr", + exec_prefix="/usr", + module_search_paths_set=1, + module_search_paths=[ + "/usr/lib64/python98.zip", + "/usr/lib64/python9.8", + "/usr/lib64/python9.8/lib-dynload", + ], + ) + actual = getpath(ns, expected) + self.assertEqual(expected, actual) + + def test_venv_macos(self): + """Test a venv layout on macOS. + + This layout is discovered when 'executable' and 'real_executable' match, + but $__PYVENV_LAUNCHER__ has been set to the original process. + """ + ns = MockPosixNamespace( + os_name="darwin", + argv0="/usr/bin/python", + PREFIX="/usr", + ENV___PYVENV_LAUNCHER__="/framework/Python9.8/python", + real_executable="/usr/bin/python", + ) + ns.add_known_xfile("/usr/bin/python") + ns.add_known_xfile("/framework/Python9.8/python") + ns.add_known_file("/usr/lib/python9.8/os.py") + ns.add_known_dir("/usr/lib/python9.8/lib-dynload") + ns.add_known_file("/framework/Python9.8/pyvenv.cfg", [ + "home = /usr/bin" + ]) + expected = dict( + executable="/framework/Python9.8/python", + prefix="/usr", + exec_prefix="/usr", + base_executable="/usr/bin/python", + base_prefix="/usr", + base_exec_prefix="/usr", + module_search_paths_set=1, + module_search_paths=[ + "/usr/lib/python98.zip", + "/usr/lib/python9.8", + "/usr/lib/python9.8/lib-dynload", + ], + ) + actual = getpath(ns, expected) + self.assertEqual(expected, actual) + + def test_symlink_normal_macos(self): + "Test a 'standard' install layout via symlink on macOS" + ns = MockPosixNamespace( + os_name="darwin", + PREFIX="/usr", + argv0="python", + ENV_PATH="/linkfrom:/usr/bin", + # real_executable on macOS matches the invocation path + real_executable="/linkfrom/python", + ) + ns.add_known_xfile("/linkfrom/python") + ns.add_known_xfile("/usr/bin/python") + ns.add_known_link("/linkfrom/python", "/usr/bin/python") + ns.add_known_file("/usr/lib/python9.8/os.py") + ns.add_known_dir("/usr/lib/python9.8/lib-dynload") + expected = dict( + executable="/linkfrom/python", + base_executable="/linkfrom/python", + prefix="/usr", + exec_prefix="/usr", + module_search_paths_set=1, + module_search_paths=[ + "/usr/lib/python98.zip", + "/usr/lib/python9.8", + "/usr/lib/python9.8/lib-dynload", + ], + ) + actual = getpath(ns, expected) + self.assertEqual(expected, actual) + + def test_symlink_buildpath_macos(self): + """Test an in-build-tree layout via symlink on macOS. + + This layout is discovered from the presence of pybuilddir.txt, which + contains the relative path from the executable's directory to the + platstdlib path. + """ + ns = MockPosixNamespace( + os_name="darwin", + argv0=r"python", + ENV_PATH="/linkfrom:/usr/bin", + PREFIX="/usr/local", + # real_executable on macOS matches the invocation path + real_executable="/linkfrom/python", + ) + ns.add_known_xfile("/linkfrom/python") + ns.add_known_xfile("/home/cpython/python") + ns.add_known_link("/linkfrom/python", "/home/cpython/python") + ns.add_known_xfile("/usr/local/bin/python") + ns.add_known_file("/home/cpython/pybuilddir.txt", ["build/lib.macos-9.8"]) + ns.add_known_file("/home/cpython/Lib/os.py") + ns.add_known_dir("/home/cpython/lib-dynload") + expected = dict( + executable="/linkfrom/python", + prefix="/usr/local", + exec_prefix="/usr/local", + base_executable="/linkfrom/python", + build_prefix="/home/cpython", + _is_python_build=1, + module_search_paths_set=1, + module_search_paths=[ + "/usr/local/lib/python98.zip", + "/home/cpython/Lib", + "/home/cpython/build/lib.macos-9.8", + ], + ) + actual = getpath(ns, expected) + self.assertEqual(expected, actual) + + +# ****************************************************************************** + +DEFAULT_NAMESPACE = dict( + PREFIX="", + EXEC_PREFIX="", + PYTHONPATH="", + VPATH="", + PLATLIBDIR="", + PYDEBUGEXT="", + VERSION_MAJOR=9, # fixed version number for ease + VERSION_MINOR=8, # of testing + PYWINVER=None, + EXE_SUFFIX=None, + + ENV_PATH="", + ENV_PYTHONHOME="", + ENV_PYTHONEXECUTABLE="", + ENV___PYVENV_LAUNCHER__="", + argv0="", + py_setpath="", + real_executable="", + executable_dir="", + library="", + winreg=None, + build_prefix=None, + venv_prefix=None, +) + +DEFAULT_CONFIG = dict( + home=None, + platlibdir=None, + pythonpath=None, + program_name=None, + prefix=None, + exec_prefix=None, + base_prefix=None, + base_exec_prefix=None, + executable=None, + base_executable="", + stdlib_dir=None, + platstdlib_dir=None, + module_search_paths=None, + module_search_paths_set=0, + pythonpath_env=None, + argv=None, + orig_argv=None, + + isolated=0, + use_environment=1, + use_site=1, +) + +class MockNTNamespace(dict): + def __init__(self, *a, argv0=None, config=None, **kw): + self.update(DEFAULT_NAMESPACE) + self["config"] = DEFAULT_CONFIG.copy() + self["os_name"] = "nt" + self["PLATLIBDIR"] = "DLLs" + self["PYWINVER"] = "9.8-XY" + self["VPATH"] = r"..\.." + super().__init__(*a, **kw) + if argv0: + self["config"]["orig_argv"] = [argv0] + if config: + self["config"].update(config) + self._files = {} + self._links = {} + self._dirs = set() + self._warnings = [] + + def add_known_file(self, path, lines=None): + self._files[path.casefold()] = list(lines or ()) + self.add_known_dir(path.rpartition("\\")[0]) + + def add_known_xfile(self, path): + self.add_known_file(path) + + def add_known_link(self, path, target): + self._links[path.casefold()] = target + + def add_known_dir(self, path): + p = path.rstrip("\\").casefold() + while p: + self._dirs.add(p) + p = p.rpartition("\\")[0] + + def __missing__(self, key): + try: + return getattr(self, key) + except AttributeError: + raise KeyError(key) from None + + def abspath(self, path): + if self.isabs(path): + return path + return self.joinpath("C:\\Absolute", path) + + def basename(self, path): + return path.rpartition("\\")[2] + + def dirname(self, path): + name = path.rstrip("\\").rpartition("\\")[0] + if name[1:] == ":": + return name + "\\" + return name + + def hassuffix(self, path, suffix): + return path.casefold().endswith(suffix.casefold()) + + def isabs(self, path): + return path[1:3] == ":\\" + + def isdir(self, path): + if verbose: + print("Check if", path, "is a dir") + return path.casefold() in self._dirs + + def isfile(self, path): + if verbose: + print("Check if", path, "is a file") + return path.casefold() in self._files + + def ismodule(self, path): + if verbose: + print("Check if", path, "is a module") + path = path.casefold() + return path in self._files and path.rpartition(".")[2] == "py".casefold() + + def isxfile(self, path): + if verbose: + print("Check if", path, "is a executable") + path = path.casefold() + return path in self._files and path.rpartition(".")[2] == "exe".casefold() + + def joinpath(self, *path): + return ntpath.normpath(ntpath.join(*path)) + + def readlines(self, path): + try: + return self._files[path.casefold()] + except KeyError: + raise FileNotFoundError(path) from None + + def realpath(self, path, _trail=None): + if verbose: + print("Read link from", path) + try: + link = self._links[path.casefold()] + except KeyError: + return path + if _trail is None: + _trail = set() + elif link.casefold() in _trail: + raise OSError("circular link") + _trail.add(link.casefold()) + return self.realpath(link, _trail) + + def warn(self, message): + self._warnings.append(message) + if verbose: + print(message) + + +class MockWinreg: + HKEY_LOCAL_MACHINE = "HKLM" + HKEY_CURRENT_USER = "HKCU" + + def __init__(self, keys): + self.keys = {k.casefold(): v for k, v in keys.items()} + self.open = {} + + def __repr__(self): + return "" + + def __eq__(self, other): + return isinstance(other, type(self)) + + def open_keys(self): + return list(self.open) + + def OpenKeyEx(self, hkey, subkey): + if verbose: + print(f"OpenKeyEx({hkey}, {subkey})") + key = f"{hkey}\\{subkey}".casefold() + if key in self.keys: + self.open[key] = self.open.get(key, 0) + 1 + return key + raise FileNotFoundError() + + def CloseKey(self, hkey): + if verbose: + print(f"CloseKey({hkey})") + hkey = hkey.casefold() + if hkey not in self.open: + raise RuntimeError("key is not open") + self.open[hkey] -= 1 + if not self.open[hkey]: + del self.open[hkey] + + def EnumKey(self, hkey, i): + if verbose: + print(f"EnumKey({hkey}, {i})") + hkey = hkey.casefold() + if hkey not in self.open: + raise RuntimeError("key is not open") + prefix = f'{hkey}\\' + subkeys = [k[len(prefix):] for k in sorted(self.keys) if k.startswith(prefix)] + subkeys[:] = [k for k in subkeys if '\\' not in k] + for j, n in enumerate(subkeys): + if j == i: + return n.removeprefix(prefix) + raise OSError("end of enumeration") + + def QueryValue(self, hkey): + if verbose: + print(f"QueryValue({hkey})") + hkey = hkey.casefold() + if hkey not in self.open: + raise RuntimeError("key is not open") + try: + return self.keys[hkey] + except KeyError: + raise OSError() + + +class MockPosixNamespace(dict): + def __init__(self, *a, argv0=None, config=None, **kw): + self.update(DEFAULT_NAMESPACE) + self["config"] = DEFAULT_CONFIG.copy() + self["os_name"] = "posix" + self["PLATLIBDIR"] = "lib" + super().__init__(*a, **kw) + if argv0: + self["config"]["orig_argv"] = [argv0] + if config: + self["config"].update(config) + self._files = {} + self._xfiles = set() + self._links = {} + self._dirs = set() + self._warnings = [] + + def add_known_file(self, path, lines=None): + self._files[path] = list(lines or ()) + self.add_known_dir(path.rpartition("/")[0]) + + def add_known_xfile(self, path): + self.add_known_file(path) + self._xfiles.add(path) + + def add_known_link(self, path, target): + self._links[path] = target + + def add_known_dir(self, path): + p = path.rstrip("/") + while p: + self._dirs.add(p) + p = p.rpartition("/")[0] + + def __missing__(self, key): + try: + return getattr(self, key) + except AttributeError: + raise KeyError(key) from None + + def abspath(self, path): + if self.isabs(path): + return path + return self.joinpath("/Absolute", path) + + def basename(self, path): + return path.rpartition("/")[2] + + def dirname(self, path): + return path.rstrip("/").rpartition("/")[0] + + def hassuffix(self, path, suffix): + return path.endswith(suffix) + + def isabs(self, path): + return path[0:1] == "/" + + def isdir(self, path): + if verbose: + print("Check if", path, "is a dir") + return path in self._dirs + + def isfile(self, path): + if verbose: + print("Check if", path, "is a file") + return path in self._files + + def ismodule(self, path): + if verbose: + print("Check if", path, "is a module") + return path in self._files and path.rpartition(".")[2] == "py" + + def isxfile(self, path): + if verbose: + print("Check if", path, "is an xfile") + return path in self._xfiles + + def joinpath(self, *path): + return posixpath.normpath(posixpath.join(*path)) + + def readlines(self, path): + try: + return self._files[path] + except KeyError: + raise FileNotFoundError(path) from None + + def realpath(self, path, _trail=None): + if verbose: + print("Read link from", path) + try: + link = self._links[path] + except KeyError: + return path + if _trail is None: + _trail = set() + elif link in _trail: + raise OSError("circular link") + _trail.add(link) + return self.realpath(link, _trail) + + def warn(self, message): + self._warnings.append(message) + if verbose: + print(message) + + +def diff_dict(before, after, prefix="global"): + diff = [] + for k in sorted(before): + if k[:2] == "__": + continue + if k == "config": + diff_dict(before[k], after[k], prefix="config") + continue + if k in after and after[k] != before[k]: + diff.append((k, before[k], after[k])) + if not diff: + return + max_k = max(len(k) for k, _, _ in diff) + indent = " " * (len(prefix) + 1 + max_k) + if verbose: + for k, b, a in diff: + if b: + print("{}.{} -{!r}\n{} +{!r}".format(prefix, k.ljust(max_k), b, indent, a)) + else: + print("{}.{} +{!r}".format(prefix, k.ljust(max_k), a)) + + +def dump_dict(before, after, prefix="global"): + if not verbose or not after: + return + max_k = max(len(k) for k in after) + for k, v in sorted(after.items(), key=lambda i: i[0]): + if k[:2] == "__": + continue + if k == "config": + dump_dict(before[k], after[k], prefix="config") + continue + try: + if v != before[k]: + print("{}.{} {!r} (was {!r})".format(prefix, k.ljust(max_k), v, before[k])) + continue + except KeyError: + pass + print("{}.{} {!r}".format(prefix, k.ljust(max_k), v)) + + +def getpath(ns, keys): + before = copy.deepcopy(ns) + failed = True + try: + exec(SOURCE, ns) + failed = False + finally: + if failed: + dump_dict(before, ns) + else: + diff_dict(before, ns) + return { + k: ns['config'].get(k, ns.get(k, ...)) + for k in keys + } diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py index 661c59d617163..a8d87e53db9e9 100644 --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -741,8 +741,9 @@ def test_ismount(self): # (or any other volume root). The drive-relative # locations below cannot then refer to mount points # - drive, path = ntpath.splitdrive(sys.executable) - with os_helper.change_cwd(ntpath.dirname(sys.executable)): + test_cwd = os.getenv("SystemRoot") + drive, path = ntpath.splitdrive(test_cwd) + with os_helper.change_cwd(test_cwd): self.assertFalse(ntpath.ismount(drive.lower())) self.assertFalse(ntpath.ismount(drive.upper())) diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py index 5f06a0d4b0372..76d35daed0b80 100644 --- a/Lib/test/test_site.py +++ b/Lib/test/test_site.py @@ -11,6 +11,7 @@ from test.support import socket_helper from test.support import captured_stderr from test.support.os_helper import TESTFN, EnvironmentVarGuard, change_cwd +import ast import builtins import encodings import glob @@ -300,7 +301,8 @@ def test_getsitepackages(self): self.assertEqual(len(dirs), 2) self.assertEqual(dirs[0], 'xoxo') wanted = os.path.join('xoxo', 'lib', 'site-packages') - self.assertEqual(dirs[1], wanted) + self.assertEqual(os.path.normcase(dirs[1]), + os.path.normcase(wanted)) @unittest.skipUnless(HAS_USER_SITE, 'need user site') def test_no_home_directory(self): @@ -497,13 +499,14 @@ class StartupImportTests(unittest.TestCase): def test_startup_imports(self): # Get sys.path in isolated mode (python3 -I) - popen = subprocess.Popen([sys.executable, '-I', '-c', - 'import sys; print(repr(sys.path))'], + popen = subprocess.Popen([sys.executable, '-X', 'utf8', '-I', + '-c', 'import sys; print(repr(sys.path))'], stdout=subprocess.PIPE, - encoding='utf-8') + encoding='utf-8', + errors='surrogateescape') stdout = popen.communicate()[0] self.assertEqual(popen.returncode, 0, repr(stdout)) - isolated_paths = eval(stdout) + isolated_paths = ast.literal_eval(stdout) # bpo-27807: Even with -I, the site module executes all .pth files # found in sys.path (see site.addpackage()). Skip the test if at least @@ -515,14 +518,15 @@ def test_startup_imports(self): # This tests checks which modules are loaded by Python when it # initially starts upon startup. - popen = subprocess.Popen([sys.executable, '-I', '-v', '-c', - 'import sys; print(set(sys.modules))'], + popen = subprocess.Popen([sys.executable, '-X', 'utf8', '-I', '-v', + '-c', 'import sys; print(set(sys.modules))'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, - encoding='utf-8') + encoding='utf-8', + errors='surrogateescape') stdout, stderr = popen.communicate() self.assertEqual(popen.returncode, 0, (stdout, stderr)) - modules = eval(stdout) + modules = ast.literal_eval(stdout) self.assertIn('site', modules) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index 9408657c91886..506266d08185d 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -102,6 +102,10 @@ def test_get_paths(self): def test_get_path(self): config_vars = get_config_vars() + if os.name == 'nt': + # On Windows, we replace the native platlibdir name with the + # default so that POSIX schemes resolve correctly + config_vars = config_vars | {'platlibdir': 'lib'} for scheme in _INSTALL_SCHEMES: for name in _INSTALL_SCHEMES[scheme]: expected = _INSTALL_SCHEMES[scheme][name].format(**config_vars) diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py index 94d626598bac3..de714de2a2049 100644 --- a/Lib/test/test_venv.py +++ b/Lib/test/test_venv.py @@ -15,7 +15,7 @@ import sys import tempfile from test.support import (captured_stdout, captured_stderr, requires_zlib, - skip_if_broken_multiprocessing_synchronize) + skip_if_broken_multiprocessing_synchronize, verbose) from test.support.os_helper import (can_symlink, EnvironmentVarGuard, rmtree) import unittest import venv @@ -40,6 +40,8 @@ def check_output(cmd, encoding=None): encoding=encoding) out, err = p.communicate() if p.returncode: + if verbose and err: + print(err.decode('utf-8', 'backslashreplace')) raise subprocess.CalledProcessError( p.returncode, cmd, out, err) return out, err @@ -194,7 +196,7 @@ def test_prefixes(self): ('base_exec_prefix', sys.base_exec_prefix)): cmd[2] = 'import sys; print(sys.%s)' % prefix out, err = check_output(cmd) - self.assertEqual(out.strip(), expected.encode()) + self.assertEqual(out.strip(), expected.encode(), prefix) if sys.platform == 'win32': ENV_SUBDIRS = ( diff --git a/Makefile.pre.in b/Makefile.pre.in index d5be6edf784e2..3dc131b6c9651 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -308,7 +308,6 @@ COVERAGE_REPORT_OPTIONS=--no-branch-coverage --title "CPython lcov report" # Modules MODULE_OBJS= \ Modules/config.o \ - Modules/getpath.o \ Modules/main.o \ Modules/gcmodule.o @@ -505,6 +504,7 @@ LIBRARY_OBJS_OMIT_FROZEN= \ LIBRARY_OBJS= \ $(LIBRARY_OBJS_OMIT_FROZEN) \ $(DEEPFREEZE_OBJS) \ + Modules/getpath.o \ Python/frozen.o ########################################################################## @@ -1061,8 +1061,11 @@ FROZEN_FILES_OUT = \ Programs/_freeze_module.o: Programs/_freeze_module.c Makefile -Programs/_freeze_module: Programs/_freeze_module.o $(LIBRARY_OBJS_OMIT_FROZEN) - $(LINKCC) $(PY_CORE_LDFLAGS) -o $@ Programs/_freeze_module.o $(LIBRARY_OBJS_OMIT_FROZEN) $(LIBS) $(MODLIBS) $(SYSLIBS) +Modules/getpath_noop.o: $(srcdir)/Modules/getpath_noop.c Makefile + $(CC) -c $(PY_CORE_CFLAGS) -o $@ $(srcdir)/Modules/getpath_noop.c + +Programs/_freeze_module: Programs/_freeze_module.o $(LIBRARY_OBJS_OMIT_FROZEN) Modules/getpath_noop.o + $(LINKCC) $(PY_CORE_LDFLAGS) -o $@ Programs/_freeze_module.o $(LIBRARY_OBJS_OMIT_FROZEN) Modules/getpath_noop.o $(LIBS) $(MODLIBS) $(SYSLIBS) # BEGIN: freezing modules @@ -1130,6 +1133,10 @@ Python/frozen_modules/frozen_only.h: $(FREEZE_MODULE) Tools/freeze/flag.py Tools/scripts/freeze_modules.py: $(FREEZE_MODULE) +# We manually freeze getpath.py rather than through freeze_modules +Modules/getpath.h: Programs/_freeze_module Modules/getpath.py + Programs/_freeze_module getpath $(srcdir)/Modules/getpath.py $(srcdir)/Modules/getpath.h + .PHONY: regen-frozen regen-frozen: Tools/scripts/freeze_modules.py $(FROZEN_FILES_IN) $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/freeze_modules.py @@ -1170,12 +1177,13 @@ Modules/getbuildinfo.o: $(PARSER_OBJS) \ -DGITBRANCH="\"`LC_ALL=C $(GITBRANCH)`\"" \ -o $@ $(srcdir)/Modules/getbuildinfo.c -Modules/getpath.o: $(srcdir)/Modules/getpath.c Makefile +Modules/getpath.o: $(srcdir)/Modules/getpath.c Modules/getpath.h Makefile $(CC) -c $(PY_CORE_CFLAGS) -DPYTHONPATH='"$(PYTHONPATH)"' \ -DPREFIX='"$(prefix)"' \ -DEXEC_PREFIX='"$(exec_prefix)"' \ -DVERSION='"$(VERSION)"' \ -DVPATH='"$(VPATH)"' \ + -DPLATLIBDIR='"$(PLATLIBDIR)"' \ -o $@ $(srcdir)/Modules/getpath.c Programs/python.o: $(srcdir)/Programs/python.c @@ -1210,11 +1218,6 @@ Python/sysmodule.o: $(srcdir)/Python/sysmodule.c Makefile $(srcdir)/Include/pydt $(MULTIARCH_CPPFLAGS) \ -o $@ $(srcdir)/Python/sysmodule.c -Python/initconfig.o: $(srcdir)/Python/initconfig.c - $(CC) -c $(PY_CORE_CFLAGS) \ - -DPLATLIBDIR='"$(PLATLIBDIR)"' \ - -o $@ $(srcdir)/Python/initconfig.c - $(IO_OBJS): $(IO_H) .PHONY: regen-pegen-metaparser diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-23-00-39-31.bpo-45582.YONPuo.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-23-00-39-31.bpo-45582.YONPuo.rst new file mode 100644 index 0000000000000..45fa75e870d78 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-10-23-00-39-31.bpo-45582.YONPuo.rst @@ -0,0 +1,3 @@ +Path calculation (known as ``getpath``) has been reimplemented as a frozen +Python module. This should have no visible impact, but may affect +calculation of all paths referenced in :mod:`sys` and :mod:`sysconfig`. diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index c230ba28d6111..19babb06f5635 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -14,10 +14,11 @@ #include "Python.h" #include "pycore_atomic_funcs.h" // _Py_atomic_int_get() #include "pycore_bitutils.h" // _Py_bswap32() -#include "pycore_fileutils.h" // _Py_normalize_path +#include "pycore_fileutils.h" // _Py_normpath #include "pycore_gc.h" // PyGC_Head #include "pycore_hashtable.h" // _Py_hashtable_new() #include "pycore_initconfig.h" // _Py_GetConfigsAsDict() +#include "pycore_pathconfig.h" // _PyPathConfig_ClearGlobal() #include "pycore_interp.h" // _PyInterpreterState_GetConfigCopy() #include "pycore_pyerrors.h" // _Py_UTF8_Edit_Cost() #include "pycore_pystate.h" // _PyThreadState_GET() @@ -273,6 +274,14 @@ test_set_config(PyObject *Py_UNUSED(self), PyObject *dict) } +static PyObject * +test_reset_path_config(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(arg)) +{ + _PyPathConfig_ClearGlobal(); + Py_RETURN_NONE; +} + + static PyObject* test_atomic_funcs(PyObject *self, PyObject *Py_UNUSED(args)) { @@ -378,15 +387,15 @@ normalize_path(PyObject *self, PyObject *filename) return NULL; } - wchar_t buf[MAXPATHLEN + 1]; - int res = _Py_normalize_path(encoded, buf, Py_ARRAY_LENGTH(buf)); + PyObject *result = PyUnicode_FromWideChar(_Py_normpath(encoded, size), -1); PyMem_Free(encoded); - if (res != 0) { - PyErr_SetString(PyExc_ValueError, "string too long"); - return NULL; - } - return PyUnicode_FromWideChar(buf, -1); + return result; +} + +static PyObject * +get_getpath_codeobject(PyObject *self, PyObject *Py_UNUSED(args)) { + return _Py_Get_Getpath_CodeObject(); } @@ -399,9 +408,11 @@ static PyMethodDef TestMethods[] = { {"test_hashtable", test_hashtable, METH_NOARGS}, {"get_config", test_get_config, METH_NOARGS}, {"set_config", test_set_config, METH_O}, + {"reset_path_config", test_reset_path_config, METH_NOARGS}, {"test_atomic_funcs", test_atomic_funcs, METH_NOARGS}, {"test_edit_cost", test_edit_cost, METH_NOARGS}, {"normalize_path", normalize_path, METH_O, NULL}, + {"get_getpath_codeobject", get_getpath_codeobject, METH_NOARGS, NULL}, {NULL, NULL} /* sentinel */ }; diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index 7921c222b9009..86da08711fd44 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -1317,6 +1317,38 @@ os__path_splitroot(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py #endif /* defined(MS_WINDOWS) */ +PyDoc_STRVAR(os__path_normpath__doc__, +"_path_normpath($module, /, path)\n" +"--\n" +"\n" +"Basic path normalization."); + +#define OS__PATH_NORMPATH_METHODDEF \ + {"_path_normpath", (PyCFunction)(void(*)(void))os__path_normpath, METH_FASTCALL|METH_KEYWORDS, os__path_normpath__doc__}, + +static PyObject * +os__path_normpath_impl(PyObject *module, PyObject *path); + +static PyObject * +os__path_normpath(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"path", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "_path_normpath", 0}; + PyObject *argsbuf[1]; + PyObject *path; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + path = args[0]; + return_value = os__path_normpath_impl(module, path); + +exit: + return return_value; +} + PyDoc_STRVAR(os_mkdir__doc__, "mkdir($module, /, path, mode=511, *, dir_fd=None)\n" "--\n" @@ -9263,4 +9295,4 @@ os_waitstatus_to_exitcode(PyObject *module, PyObject *const *args, Py_ssize_t na #ifndef OS_WAITSTATUS_TO_EXITCODE_METHODDEF #define OS_WAITSTATUS_TO_EXITCODE_METHODDEF #endif /* !defined(OS_WAITSTATUS_TO_EXITCODE_METHODDEF) */ -/*[clinic end generated code: output=65a85d7d3f2c487e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=05505f171cdcff72 input=a9049054013a1b77]*/ diff --git a/Modules/getpath.c b/Modules/getpath.c index 4dbd502ddcf04..32d5db9d2c4dc 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -1,1617 +1,935 @@ /* Return the initial module search path. */ #include "Python.h" -#include "pycore_fileutils.h" +#include "marshal.h" // PyMarshal_ReadObjectFromString +#include "osdefs.h" // DELIM #include "pycore_initconfig.h" +#include "pycore_fileutils.h" #include "pycore_pathconfig.h" -#include "osdefs.h" // DELIM +#include "pycore_pymem.h" // _PyMem_SetDefaultAllocator() +#include -#include // getenv() -#include -#include +#ifdef MS_WINDOWS +# include // GetFullPathNameW(), MAX_PATH +# include +#endif #ifdef __APPLE__ # include #endif -/* Search in some common locations for the associated Python libraries. - * - * Two directories must be found, the platform independent directory - * (prefix), containing the common .py and .pyc files, and the platform - * dependent directory (exec_prefix), containing the shared library - * modules. Note that prefix and exec_prefix can be the same directory, - * but for some installations, they are different. - * - * Py_GetPath() carries out separate searches for prefix and exec_prefix. - * Each search tries a number of different locations until a ``landmark'' - * file or directory is found. If no prefix or exec_prefix is found, a - * warning message is issued and the preprocessor defined PREFIX and - * EXEC_PREFIX are used (even though they will not work); python carries on - * as best as is possible, but most imports will fail. - * - * Before any searches are done, the location of the executable is - * determined. If argv[0] has one or more slashes in it, it is used - * unchanged. Otherwise, it must have been invoked from the shell's path, - * so we search $PATH for the named executable and use that. If the - * executable was not found on $PATH (or there was no $PATH environment - * variable), the original argv[0] string is used. - * - * Next, the executable location is examined to see if it is a symbolic - * link. If so, the link is chased (correctly interpreting a relative - * pathname if one is found) and the directory of the link target is used. - * - * Finally, argv0_path is set to the directory containing the executable - * (i.e. the last component is stripped). - * - * With argv0_path in hand, we perform a number of steps. The same steps - * are performed for prefix and for exec_prefix, but with a different - * landmark. - * - * Step 1. Are we running python out of the build directory? This is - * checked by looking for a different kind of landmark relative to - * argv0_path. For prefix, the landmark's path is derived from the VPATH - * preprocessor variable (taking into account that its value is almost, but - * not quite, what we need). For exec_prefix, the landmark is - * pybuilddir.txt. If the landmark is found, we're done. - * - * For the remaining steps, the prefix landmark will always be - * lib/python$VERSION/os.py and the exec_prefix will always be - * lib/python$VERSION/lib-dynload, where $VERSION is Python's version - * number as supplied by the Makefile. Note that this means that no more - * build directory checking is performed; if the first step did not find - * the landmarks, the assumption is that python is running from an - * installed setup. - * - * Step 2. See if the $PYTHONHOME environment variable points to the - * installed location of the Python libraries. If $PYTHONHOME is set, then - * it points to prefix and exec_prefix. $PYTHONHOME can be a single - * directory, which is used for both, or the prefix and exec_prefix - * directories separated by a colon. - * - * Step 3. Try to find prefix and exec_prefix relative to argv0_path, - * backtracking up the path until it is exhausted. This is the most common - * step to succeed. Note that if prefix and exec_prefix are different, - * exec_prefix is more likely to be found; however if exec_prefix is a - * subdirectory of prefix, both will be found. - * - * Step 4. Search the directories pointed to by the preprocessor variables - * PREFIX and EXEC_PREFIX. These are supplied by the Makefile but can be - * passed in as options to the configure script. - * - * That's it! - * - * Well, almost. Once we have determined prefix and exec_prefix, the - * preprocessor variable PYTHONPATH is used to construct a path. Each - * relative path on PYTHONPATH is prefixed with prefix. Then the directory - * containing the shared library modules is appended. The environment - * variable $PYTHONPATH is inserted in front of it all. Finally, the - * prefix and exec_prefix globals are tweaked so they reflect the values - * expected by other code, by stripping the "lib/python$VERSION/..." stuff - * off. If either points to the build directory, the globals are reset to - * the corresponding preprocessor variables (so sys.prefix will reflect the - * installation location, even though sys.path points into the build - * directory). This seems to make more sense given that currently the only - * known use of sys.prefix and sys.exec_prefix is for the ILU installation - * process to find the installed Python tree. - * - * An embedding application can use Py_SetPath() to override all of - * these automatic path computations. - * - * NOTE: Windows MSVC builds use PC/getpathp.c instead! - */ - -#ifdef __cplusplus -extern "C" { -#endif - +/* Reference the precompiled getpath.py */ +#include "getpath.h" #if (!defined(PREFIX) || !defined(EXEC_PREFIX) \ - || !defined(VERSION) || !defined(VPATH)) -#error "PREFIX, EXEC_PREFIX, VERSION and VPATH macros must be defined" + || !defined(VERSION) || !defined(VPATH) \ + || !defined(PLATLIBDIR)) +#error "PREFIX, EXEC_PREFIX, VERSION, VPATH and PLATLIBDIR macros must be defined" #endif -#ifndef LANDMARK -#define LANDMARK L"os.py" +#if !defined(PYTHONPATH) +#define PYTHONPATH NULL #endif -#define BUILD_LANDMARK L"Modules/Setup.local" - -#define PATHLEN_ERR() _PyStatus_ERR("path configuration: path too long") - -typedef struct { - wchar_t *path_env; /* PATH environment variable */ - - wchar_t *pythonpath_macro; /* PYTHONPATH macro */ - wchar_t *prefix_macro; /* PREFIX macro */ - wchar_t *exec_prefix_macro; /* EXEC_PREFIX macro */ - wchar_t *vpath_macro; /* VPATH macro */ - - wchar_t *lib_python; /* / "pythonX.Y" */ - - int prefix_found; /* found platform independent libraries? */ - int exec_prefix_found; /* found the platform dependent libraries? */ - - int warnings; - const wchar_t *pythonpath_env; - const wchar_t *platlibdir; - - wchar_t *argv0_path; - wchar_t *zip_path; - wchar_t *prefix; - wchar_t *exec_prefix; -} PyCalculatePath; - -static const wchar_t delimiter[2] = {DELIM, '\0'}; -static const wchar_t separator[2] = {SEP, '\0'}; - - -static void -reduce(wchar_t *dir) -{ - size_t i = wcslen(dir); - while (i > 0 && dir[i] != SEP) { - --i; - } - dir[i] = '\0'; -} - +#if !defined(PYDEBUGEXT) +#define PYDEBUGEXT NULL +#endif -/* Is file, not directory */ -static int -isfile(const wchar_t *filename) -{ - struct stat buf; - if (_Py_wstat(filename, &buf) != 0) { - return 0; - } - if (!S_ISREG(buf.st_mode)) { - return 0; - } - return 1; -} +#if !defined(PYWINVER) +#ifdef MS_DLL_ID +#define PYWINVER MS_DLL_ID +#else +#define PYWINVER NULL +#endif +#endif +#if !defined(EXE_SUFFIX) +#if defined(MS_WINDOWS) || defined(__CYGWIN__) || defined(__MINGW32__) +#define EXE_SUFFIX L".exe" +#else +#define EXE_SUFFIX NULL +#endif +#endif -/* Is executable file */ -static int -isxfile(const wchar_t *filename) -{ - struct stat buf; - if (_Py_wstat(filename, &buf) != 0) { - return 0; - } - if (!S_ISREG(buf.st_mode)) { - return 0; - } - if ((buf.st_mode & 0111) == 0) { - return 0; - } - return 1; -} +/* HELPER FUNCTIONS for getpath.py */ -/* Is directory */ -static int -isdir(const wchar_t *filename) +static PyObject * +getpath_abspath(PyObject *Py_UNUSED(self), PyObject *args) { - struct stat buf; - if (_Py_wstat(filename, &buf) != 0) { - return 0; + PyObject *r = NULL; + PyObject *pathobj; + const wchar_t *path; + if (!PyArg_ParseTuple(args, "U", &pathobj)) { + return NULL; } - if (!S_ISDIR(buf.st_mode)) { - return 0; + Py_ssize_t len; + path = PyUnicode_AsWideCharString(pathobj, &len); + if (path) { + wchar_t *abs; + if (_Py_abspath(path, &abs) == 0 && abs) { + r = PyUnicode_FromWideChar(_Py_normpath(abs, -1), -1); + PyMem_RawFree((void *)abs); + } else { + PyErr_SetString(PyExc_OSError, "failed to make path absolute"); + } + PyMem_Free((void *)path); } - return 1; + return r; } -/* Add a path component, by appending stuff to buffer. - buflen: 'buffer' length in characters including trailing NUL. - - If path2 is empty: - - - if path doesn't end with SEP and is not empty, add SEP to path - - otherwise, do nothing. */ -static PyStatus -joinpath(wchar_t *path, const wchar_t *path2, size_t path_len) +static PyObject * +getpath_basename(PyObject *Py_UNUSED(self), PyObject *args) { - if (_Py_isabs(path2)) { - if (wcslen(path2) >= path_len) { - return PATHLEN_ERR(); - } - wcscpy(path, path2); - } - else { - if (_Py_add_relfile(path, path2, path_len) < 0) { - return PATHLEN_ERR(); - } - return _PyStatus_OK(); + const char *path; + if (!PyArg_ParseTuple(args, "s", &path)) { + return NULL; } - return _PyStatus_OK(); + const char *name = strrchr(path, SEP); + return PyUnicode_FromString(name ? name + 1 : path); } -static wchar_t* -substring(const wchar_t *str, size_t len) +static PyObject * +getpath_dirname(PyObject *Py_UNUSED(self), PyObject *args) { - wchar_t *substr = PyMem_RawMalloc((len + 1) * sizeof(wchar_t)); - if (substr == NULL) { + const char *path; + if (!PyArg_ParseTuple(args, "s", &path)) { return NULL; } - - if (len) { - memcpy(substr, str, len * sizeof(wchar_t)); + const char *name = strrchr(path, SEP); + if (!name) { + return PyUnicode_FromStringAndSize(NULL, 0); } - substr[len] = L'\0'; - return substr; + return PyUnicode_FromStringAndSize(path, (name - path)); } -static wchar_t* -joinpath2(const wchar_t *path, const wchar_t *path2) +static PyObject * +getpath_isabs(PyObject *Py_UNUSED(self), PyObject *args) { - if (_Py_isabs(path2)) { - return _PyMem_RawWcsdup(path2); + PyObject *r = NULL; + PyObject *pathobj; + const wchar_t *path; + if (!PyArg_ParseTuple(args, "U", &pathobj)) { + return NULL; } - return _Py_join_relfile(path, path2); -} - - -static inline int -safe_wcscpy(wchar_t *dst, const wchar_t *src, size_t n) -{ - size_t srclen = wcslen(src); - if (n <= srclen) { - dst[0] = L'\0'; - return -1; + path = PyUnicode_AsWideCharString(pathobj, NULL); + if (path) { + r = _Py_isabs(path) ? Py_True : Py_False; + PyMem_Free((void *)path); } - memcpy(dst, src, (srclen + 1) * sizeof(wchar_t)); - return 0; + Py_XINCREF(r); + return r; } -/* copy_absolute requires that path be allocated at least - 'abs_path_len' characters (including trailing NUL). */ -static PyStatus -copy_absolute(wchar_t *abs_path, const wchar_t *path, size_t abs_path_len) +static PyObject * +getpath_hassuffix(PyObject *Py_UNUSED(self), PyObject *args) { - if (_Py_isabs(path)) { - if (safe_wcscpy(abs_path, path, abs_path_len) < 0) { - return PATHLEN_ERR(); - } + PyObject *r = NULL; + PyObject *pathobj; + PyObject *suffixobj; + const wchar_t *path; + const wchar_t *suffix; + if (!PyArg_ParseTuple(args, "UU", &pathobj, &suffixobj)) { + return NULL; } - else { - if (!_Py_wgetcwd(abs_path, abs_path_len)) { - /* unable to get the current directory */ - if (safe_wcscpy(abs_path, path, abs_path_len) < 0) { - return PATHLEN_ERR(); + Py_ssize_t len, suffixLen; + path = PyUnicode_AsWideCharString(pathobj, &len); + if (path) { + suffix = PyUnicode_AsWideCharString(suffixobj, &suffixLen); + if (suffix) { + if (suffixLen < len || +#ifdef MS_WINDOWS + wcsicmp(&path[len - suffixLen], suffix) != 0 +#else + wcscmp(&path[len - suffixLen], suffix) != 0 +#endif + ) { + r = Py_False; + } else { + r = Py_True; } - return _PyStatus_OK(); - } - if (path[0] == '.' && path[1] == SEP) { - path += 2; - } - PyStatus status = joinpath(abs_path, path, abs_path_len); - if (_PyStatus_EXCEPTION(status)) { - return status; + Py_INCREF(r); + PyMem_Free((void *)suffix); } + PyMem_Free((void *)path); } - return _PyStatus_OK(); -} - - -/* path_len: path length in characters including trailing NUL */ -static PyStatus -absolutize(wchar_t **path_p) -{ - assert(!_Py_isabs(*path_p)); - - wchar_t abs_path[MAXPATHLEN+1]; - wchar_t *path = *path_p; - - PyStatus status = copy_absolute(abs_path, path, Py_ARRAY_LENGTH(abs_path)); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - - PyMem_RawFree(*path_p); - *path_p = _PyMem_RawWcsdup(abs_path); - if (*path_p == NULL) { - return _PyStatus_NO_MEMORY(); - } - return _PyStatus_OK(); + return r; } -/* Is module -- check for .pyc too */ -static PyStatus -ismodule(const wchar_t *path, int *result) +static PyObject * +getpath_isdir(PyObject *Py_UNUSED(self), PyObject *args) { - wchar_t *filename = joinpath2(path, LANDMARK); - if (filename == NULL) { - return _PyStatus_NO_MEMORY(); - } - - if (isfile(filename)) { - PyMem_RawFree(filename); - *result = 1; - return _PyStatus_OK(); - } - - /* Check for the compiled version of prefix. */ - size_t len = wcslen(filename); - wchar_t *pyc = PyMem_RawMalloc((len + 2) * sizeof(wchar_t)); - if (pyc == NULL) { - PyMem_RawFree(filename); - return _PyStatus_NO_MEMORY(); + PyObject *r = NULL; + PyObject *pathobj; + const wchar_t *path; + if (!PyArg_ParseTuple(args, "U", &pathobj)) { + return NULL; } - - memcpy(pyc, filename, len * sizeof(wchar_t)); - pyc[len] = L'c'; - pyc[len + 1] = L'\0'; - *result = isfile(pyc); - - PyMem_RawFree(filename); - PyMem_RawFree(pyc); - - return _PyStatus_OK(); -} - - -#if defined(__CYGWIN__) || defined(__MINGW32__) -#ifndef EXE_SUFFIX -#define EXE_SUFFIX L".exe" + path = PyUnicode_AsWideCharString(pathobj, NULL); + if (path) { +#ifdef MS_WINDOWS + r = (GetFileAttributesW(path) & FILE_ATTRIBUTE_DIRECTORY) ? Py_True : Py_False; +#else + struct stat st; + r = (_Py_wstat(path, &st) == 0) && S_ISDIR(st.st_mode) ? Py_True : Py_False; #endif - -/* pathlen: 'path' length in characters including trailing NUL */ -static PyStatus -add_exe_suffix(wchar_t **progpath_p) -{ - wchar_t *progpath = *progpath_p; - - /* Check for already have an executable suffix */ - size_t n = wcslen(progpath); - size_t s = wcslen(EXE_SUFFIX); - if (wcsncasecmp(EXE_SUFFIX, progpath + n - s, s) == 0) { - return _PyStatus_OK(); - } - - wchar_t *progpath2 = PyMem_RawMalloc((n + s + 1) * sizeof(wchar_t)); - if (progpath2 == NULL) { - return _PyStatus_NO_MEMORY(); - } - - memcpy(progpath2, progpath, n * sizeof(wchar_t)); - memcpy(progpath2 + n, EXE_SUFFIX, s * sizeof(wchar_t)); - progpath2[n+s] = L'\0'; - - if (isxfile(progpath2)) { - PyMem_RawFree(*progpath_p); - *progpath_p = progpath2; - } - else { - PyMem_RawFree(progpath2); + PyMem_Free((void *)path); } - return _PyStatus_OK(); + Py_XINCREF(r); + return r; } -#endif -/* search_for_prefix requires that argv0_path be no more than MAXPATHLEN - bytes long. -*/ -static PyStatus -search_for_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig, - wchar_t *prefix, size_t prefix_len, int *found) +static PyObject * +getpath_isfile(PyObject *Py_UNUSED(self), PyObject *args) { - PyStatus status; - - /* If PYTHONHOME is set, we believe it unconditionally */ - if (pathconfig->home) { - /* Path: / */ - if (safe_wcscpy(prefix, pathconfig->home, prefix_len) < 0) { - return PATHLEN_ERR(); - } - wchar_t *delim = wcschr(prefix, DELIM); - if (delim) { - *delim = L'\0'; - } - status = joinpath(prefix, calculate->lib_python, prefix_len); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - *found = 1; - return _PyStatus_OK(); - } - - /* Check to see if argv0_path is in the build directory - - Path: / */ - wchar_t *path = joinpath2(calculate->argv0_path, BUILD_LANDMARK); - if (path == NULL) { - return _PyStatus_NO_MEMORY(); - } - - int is_build_dir = isfile(path); - PyMem_RawFree(path); - - if (is_build_dir) { - /* argv0_path is the build directory (BUILD_LANDMARK exists), - now also check LANDMARK using ismodule(). */ - - /* Path: / / Lib */ - /* or if VPATH is empty: / Lib */ - if (safe_wcscpy(prefix, calculate->argv0_path, prefix_len) < 0) { - return PATHLEN_ERR(); - } - - status = joinpath(prefix, calculate->vpath_macro, prefix_len); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - - status = joinpath(prefix, L"Lib", prefix_len); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - - int module; - status = ismodule(prefix, &module); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - if (module) { - /* BUILD_LANDMARK and LANDMARK found */ - *found = -1; - return _PyStatus_OK(); - } - } - - /* Search from argv0_path, until root is found */ - status = copy_absolute(prefix, calculate->argv0_path, prefix_len); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - - do { - /* Path: / / LANDMARK */ - size_t n = wcslen(prefix); - status = joinpath(prefix, calculate->lib_python, prefix_len); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - - int module; - status = ismodule(prefix, &module); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - if (module) { - *found = 1; - return _PyStatus_OK(); - } - prefix[n] = L'\0'; - reduce(prefix); - } while (prefix[0]); - - /* Look at configure's PREFIX. - Path: / / LANDMARK */ - if (safe_wcscpy(prefix, calculate->prefix_macro, prefix_len) < 0) { - return PATHLEN_ERR(); - } - status = joinpath(prefix, calculate->lib_python, prefix_len); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - - int module; - status = ismodule(prefix, &module); - if (_PyStatus_EXCEPTION(status)) { - return status; + PyObject *r = NULL; + PyObject *pathobj; + const wchar_t *path; + if (!PyArg_ParseTuple(args, "U", &pathobj)) { + return NULL; } - if (module) { - *found = 1; - return _PyStatus_OK(); + path = PyUnicode_AsWideCharString(pathobj, NULL); + if (path) { +#ifdef MS_WINDOWS + r = !(GetFileAttributesW(path) & FILE_ATTRIBUTE_DIRECTORY) ? Py_True : Py_False; +#else + struct stat st; + r = (_Py_wstat(path, &st) == 0) && S_ISREG(st.st_mode) ? Py_True : Py_False; +#endif + PyMem_Free((void *)path); } - - /* Fail */ - *found = 0; - return _PyStatus_OK(); + Py_XINCREF(r); + return r; } -static PyStatus -calculate_set_stdlib_dir(PyCalculatePath *calculate, _PyPathConfig *pathconfig) +static PyObject * +getpath_isxfile(PyObject *Py_UNUSED(self), PyObject *args) { - // Note that, unlike calculate_set_prefix(), here we allow a negative - // prefix_found. That means the source tree Lib dir gets used. - if (!calculate->prefix_found) { - return _PyStatus_OK(); - } - PyStatus status; - wchar_t *prefix = calculate->prefix; - if (!_Py_isabs(prefix)) { - prefix = _PyMem_RawWcsdup(prefix); - if (prefix == NULL) { - return _PyStatus_NO_MEMORY(); - } - status = absolutize(&prefix); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - } - wchar_t buf[MAXPATHLEN + 1]; - int res = _Py_normalize_path(prefix, buf, Py_ARRAY_LENGTH(buf)); - if (prefix != calculate->prefix) { - PyMem_RawFree(prefix); - } - if (res < 0) { - return PATHLEN_ERR(); + PyObject *r = NULL; + PyObject *pathobj; + const wchar_t *path; + Py_ssize_t cchPath; + if (!PyArg_ParseTuple(args, "U", &pathobj)) { + return NULL; } - pathconfig->stdlib_dir = _PyMem_RawWcsdup(buf); - if (pathconfig->stdlib_dir == NULL) { - return _PyStatus_NO_MEMORY(); + path = PyUnicode_AsWideCharString(pathobj, &cchPath); + if (path) { +#ifdef MS_WINDOWS + const wchar_t *ext; + r = (GetFileAttributesW(path) & FILE_ATTRIBUTE_DIRECTORY) && + SUCCEEDED(PathCchFindExtension(path, cchPath, &ext)) && + (CompareStringOrdinal(ext, -1, L".exe", -1, 1 /* ignore case */) == CSTR_EQUAL) + ? Py_True : Py_False; +#else + struct stat st; + r = (_Py_wstat(path, &st) == 0) && + S_ISREG(st.st_mode) && + (st.st_mode & 0111) + ? Py_True : Py_False; +#endif + PyMem_Free((void *)path); } - return _PyStatus_OK(); + Py_XINCREF(r); + return r; } -static PyStatus -calculate_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig) +static PyObject * +getpath_joinpath(PyObject *Py_UNUSED(self), PyObject *args) { - wchar_t prefix[MAXPATHLEN+1]; - memset(prefix, 0, sizeof(prefix)); - size_t prefix_len = Py_ARRAY_LENGTH(prefix); - - PyStatus status; - status = search_for_prefix(calculate, pathconfig, - prefix, prefix_len, - &calculate->prefix_found); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - - if (!calculate->prefix_found) { - if (calculate->warnings) { - fprintf(stderr, - "Could not find platform independent libraries \n"); - } - - calculate->prefix = joinpath2(calculate->prefix_macro, - calculate->lib_python); - } - else { - calculate->prefix = _PyMem_RawWcsdup(prefix); - } - - if (calculate->prefix == NULL) { - return _PyStatus_NO_MEMORY(); + if (!PyTuple_Check(args)) { + PyErr_SetString(PyExc_TypeError, "requires tuple of arguments"); + return NULL; } - return _PyStatus_OK(); -} - - -static PyStatus -calculate_set_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig) -{ - /* Reduce prefix and exec_prefix to their essence, - * e.g. /usr/local/lib/python1.5 is reduced to /usr/local. - * If we're loading relative to the build directory, - * return the compiled-in defaults instead. - */ - if (calculate->prefix_found > 0) { - wchar_t *prefix = _PyMem_RawWcsdup(calculate->prefix); - if (prefix == NULL) { - return _PyStatus_NO_MEMORY(); - } - - reduce(prefix); - reduce(prefix); - if (prefix[0]) { - pathconfig->prefix = prefix; - } - else { - PyMem_RawFree(prefix); - - /* The prefix is the root directory, but reduce() chopped - off the "/". */ - pathconfig->prefix = _PyMem_RawWcsdup(separator); - if (pathconfig->prefix == NULL) { - return _PyStatus_NO_MEMORY(); + Py_ssize_t n = PyTuple_GET_SIZE(args); + if (n == 0) { + return PyUnicode_FromString(NULL); + } + /* Convert all parts to wchar and accumulate max final length */ + wchar_t **parts = (wchar_t **)PyMem_Malloc(n * sizeof(wchar_t *)); + memset(parts, 0, n * sizeof(wchar_t *)); + Py_ssize_t cchFinal = 0; + Py_ssize_t first = 0; + + for (Py_ssize_t i = 0; i < n; ++i) { + PyObject *s = PyTuple_GET_ITEM(args, i); + Py_ssize_t cch; + if (s == Py_None) { + cch = 0; + } else if (PyUnicode_Check(s)) { + parts[i] = PyUnicode_AsWideCharString(s, &cch); + if (!parts[i]) { + cchFinal = -1; + break; } + if (_Py_isabs(parts[i])) { + first = i; + } + } else { + PyErr_SetString(PyExc_TypeError, "all arguments to joinpath() must be str or None"); + cchFinal = -1; + break; } + cchFinal += cch + 1; } - else { - pathconfig->prefix = _PyMem_RawWcsdup(calculate->prefix_macro); - if (pathconfig->prefix == NULL) { - return _PyStatus_NO_MEMORY(); - } - } - return _PyStatus_OK(); -} - - -static PyStatus -calculate_pybuilddir(const wchar_t *argv0_path, - wchar_t *exec_prefix, size_t exec_prefix_len, - int *found) -{ - PyStatus status; - - /* Check to see if argv[0] is in the build directory. "pybuilddir.txt" - is written by setup.py and contains the relative path to the location - of shared library modules. - - Filename: / "pybuilddir.txt" */ - wchar_t *filename = joinpath2(argv0_path, L"pybuilddir.txt"); - if (filename == NULL) { - return _PyStatus_NO_MEMORY(); - } - - FILE *fp = _Py_wfopen(filename, L"rb"); - PyMem_RawFree(filename); - if (fp == NULL) { - errno = 0; - return _PyStatus_OK(); - } - - char buf[MAXPATHLEN + 1]; - size_t n = fread(buf, 1, Py_ARRAY_LENGTH(buf) - 1, fp); - buf[n] = '\0'; - fclose(fp); - - size_t dec_len; - wchar_t *pybuilddir = _Py_DecodeUTF8_surrogateescape(buf, n, &dec_len); - if (!pybuilddir) { - return DECODE_LOCALE_ERR("pybuilddir.txt", dec_len); - } - - /* Path: / */ - if (safe_wcscpy(exec_prefix, argv0_path, exec_prefix_len) < 0) { - PyMem_RawFree(pybuilddir); - return PATHLEN_ERR(); - } - status = joinpath(exec_prefix, pybuilddir, exec_prefix_len); - PyMem_RawFree(pybuilddir); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - - *found = -1; - return _PyStatus_OK(); -} - -/* search_for_exec_prefix requires that argv0_path be no more than - MAXPATHLEN bytes long. -*/ -static PyStatus -search_for_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig, - wchar_t *exec_prefix, size_t exec_prefix_len, - int *found) -{ - PyStatus status; - - /* If PYTHONHOME is set, we believe it unconditionally */ - if (pathconfig->home) { - /* Path: / / "lib-dynload" */ - wchar_t *delim = wcschr(pathconfig->home, DELIM); - if (delim) { - if (safe_wcscpy(exec_prefix, delim+1, exec_prefix_len) < 0) { - return PATHLEN_ERR(); - } + wchar_t *final = cchFinal > 0 ? (wchar_t *)PyMem_Malloc(cchFinal * sizeof(wchar_t)) : NULL; + if (!final) { + for (Py_ssize_t i = 0; i < n; ++i) { + PyMem_Free(parts[i]); } - else { - if (safe_wcscpy(exec_prefix, pathconfig->home, exec_prefix_len) < 0) { - return PATHLEN_ERR(); - } - } - status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len); - if (_PyStatus_EXCEPTION(status)) { - return status; + PyMem_Free(parts); + if (cchFinal) { + PyErr_NoMemory(); + return NULL; } - status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - *found = 1; - return _PyStatus_OK(); - } - - /* Check for pybuilddir.txt */ - assert(*found == 0); - status = calculate_pybuilddir(calculate->argv0_path, - exec_prefix, exec_prefix_len, found); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - if (*found) { - return _PyStatus_OK(); + return PyUnicode_FromStringAndSize(NULL, 0); } - /* Search from argv0_path, until root is found */ - status = copy_absolute(exec_prefix, calculate->argv0_path, exec_prefix_len); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - - do { - /* Path: / / "lib-dynload" */ - size_t n = wcslen(exec_prefix); - status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len); - if (_PyStatus_EXCEPTION(status)) { - return status; + final[0] = '\0'; + /* Now join all the paths. The final result should be shorter than the buffer */ + for (Py_ssize_t i = 0; i < n; ++i) { + if (!parts[i]) { + continue; } - if (isdir(exec_prefix)) { - *found = 1; - return _PyStatus_OK(); + if (i >= first && final) { + if (!final[0]) { + /* final is definitely long enough to fit any individual part */ + wcscpy(final, parts[i]); + } else if (_Py_add_relfile(final, parts[i], cchFinal) < 0) { + /* if we fail, keep iterating to free memory, but stop adding parts */ + PyMem_Free(final); + final = NULL; + } } - exec_prefix[n] = L'\0'; - reduce(exec_prefix); - } while (exec_prefix[0]); - - /* Look at configure's EXEC_PREFIX. - - Path: / / "lib-dynload" */ - if (safe_wcscpy(exec_prefix, calculate->exec_prefix_macro, exec_prefix_len) < 0) { - return PATHLEN_ERR(); + PyMem_Free(parts[i]); } - status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - if (isdir(exec_prefix)) { - *found = 1; - return _PyStatus_OK(); + PyMem_Free(parts); + if (!final) { + PyErr_SetString(PyExc_SystemError, "failed to join paths"); + return NULL; } - - /* Fail */ - *found = 0; - return _PyStatus_OK(); + PyObject *r = PyUnicode_FromWideChar(_Py_normpath(final, -1), -1); + PyMem_Free(final); + return r; } -static PyStatus -calculate_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig) +static PyObject * +getpath_readlines(PyObject *Py_UNUSED(self), PyObject *args) { - PyStatus status; - wchar_t exec_prefix[MAXPATHLEN+1]; - memset(exec_prefix, 0, sizeof(exec_prefix)); - size_t exec_prefix_len = Py_ARRAY_LENGTH(exec_prefix); - - status = search_for_exec_prefix(calculate, pathconfig, - exec_prefix, exec_prefix_len, - &calculate->exec_prefix_found); - if (_PyStatus_EXCEPTION(status)) { - return status; + PyObject *r = NULL; + PyObject *pathobj; + const wchar_t *path; + if (!PyArg_ParseTuple(args, "U", &pathobj)) { + return NULL; } - - if (!calculate->exec_prefix_found) { - if (calculate->warnings) { - fprintf(stderr, - "Could not find platform dependent libraries \n"); - } - - /* / "lib-dynload" */ - wchar_t *lib_dynload = joinpath2(calculate->platlibdir, - L"lib-dynload"); - if (lib_dynload == NULL) { - return _PyStatus_NO_MEMORY(); - } - - calculate->exec_prefix = joinpath2(calculate->exec_prefix_macro, - lib_dynload); - PyMem_RawFree(lib_dynload); - - if (calculate->exec_prefix == NULL) { - return _PyStatus_NO_MEMORY(); - } + path = PyUnicode_AsWideCharString(pathobj, NULL); + if (!path) { + return NULL; } - else { - /* If we found EXEC_PREFIX do *not* reduce it! (Yet.) */ - calculate->exec_prefix = _PyMem_RawWcsdup(exec_prefix); - if (calculate->exec_prefix == NULL) { - return _PyStatus_NO_MEMORY(); - } + FILE *fp = _Py_wfopen(path, L"rb"); + PyMem_Free((void *)path); + if (!fp) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; } - return _PyStatus_OK(); -} - - -static PyStatus -calculate_set_exec_prefix(PyCalculatePath *calculate, - _PyPathConfig *pathconfig) -{ - if (calculate->exec_prefix_found > 0) { - wchar_t *exec_prefix = _PyMem_RawWcsdup(calculate->exec_prefix); - if (exec_prefix == NULL) { - return _PyStatus_NO_MEMORY(); - } - reduce(exec_prefix); - reduce(exec_prefix); - reduce(exec_prefix); - - if (exec_prefix[0]) { - pathconfig->exec_prefix = exec_prefix; - } - else { - /* empty string: use SEP instead */ - PyMem_RawFree(exec_prefix); - - /* The exec_prefix is the root directory, but reduce() chopped - off the "/". */ - pathconfig->exec_prefix = _PyMem_RawWcsdup(separator); - if (pathconfig->exec_prefix == NULL) { - return _PyStatus_NO_MEMORY(); - } - } + r = PyList_New(0); + if (!r) { + fclose(fp); + return NULL; } - else { - pathconfig->exec_prefix = _PyMem_RawWcsdup(calculate->exec_prefix_macro); - if (pathconfig->exec_prefix == NULL) { - return _PyStatus_NO_MEMORY(); - } + const size_t MAX_FILE = 32 * 1024; + char *buffer = (char *)PyMem_Malloc(MAX_FILE); + if (!buffer) { + Py_DECREF(r); + fclose(fp); + return NULL; } - return _PyStatus_OK(); -} - - -/* Similar to shutil.which(). - If found, write the path into *abs_path_p. */ -static PyStatus -calculate_which(const wchar_t *path_env, wchar_t *program_name, - wchar_t **abs_path_p) -{ - while (1) { - wchar_t *delim = wcschr(path_env, DELIM); - wchar_t *abs_path; - - if (delim) { - wchar_t *path = substring(path_env, delim - path_env); - if (path == NULL) { - return _PyStatus_NO_MEMORY(); - } - abs_path = joinpath2(path, program_name); - PyMem_RawFree(path); - } - else { - abs_path = joinpath2(path_env, program_name); - } - - if (abs_path == NULL) { - return _PyStatus_NO_MEMORY(); - } - - if (isxfile(abs_path)) { - *abs_path_p = abs_path; - return _PyStatus_OK(); - } - PyMem_RawFree(abs_path); - if (!delim) { - break; - } - path_env = delim + 1; + size_t cb = fread(buffer, 1, MAX_FILE, fp); + fclose(fp); + if (!cb) { + return r; } - - /* not found */ - return _PyStatus_OK(); -} - - -#ifdef __APPLE__ -static PyStatus -calculate_program_macos(wchar_t **abs_path_p) -{ - char execpath[MAXPATHLEN + 1]; - uint32_t nsexeclength = Py_ARRAY_LENGTH(execpath) - 1; - - /* On Mac OS X, if a script uses an interpreter of the form - "#!/opt/python2.3/bin/python", the kernel only passes "python" - as argv[0], which falls through to the $PATH search below. - If /opt/python2.3/bin isn't in your path, or is near the end, - this algorithm may incorrectly find /usr/bin/python. To work - around this, we can use _NSGetExecutablePath to get a better - hint of what the intended interpreter was, although this - will fail if a relative path was used. but in that case, - absolutize() should help us out below - */ - if (_NSGetExecutablePath(execpath, &nsexeclength) != 0 - || (wchar_t)execpath[0] != SEP) - { - /* _NSGetExecutablePath() failed or the path is relative */ - return _PyStatus_OK(); + if (cb >= MAX_FILE) { + Py_DECREF(r); + PyErr_SetString(PyExc_MemoryError, + "cannot read file larger than 32KB during initialization"); + return NULL; } + buffer[cb] = '\0'; size_t len; - *abs_path_p = Py_DecodeLocale(execpath, &len); - if (*abs_path_p == NULL) { - return DECODE_LOCALE_ERR("executable path", len); - } - return _PyStatus_OK(); -} -#endif /* __APPLE__ */ - - -static PyStatus -calculate_program_impl(PyCalculatePath *calculate, _PyPathConfig *pathconfig) -{ - assert(pathconfig->program_full_path == NULL); - - PyStatus status; - - /* If there is no slash in the argv0 path, then we have to - * assume python is on the user's $PATH, since there's no - * other way to find a directory to start the search from. If - * $PATH isn't exported, you lose. - */ - if (wcschr(pathconfig->program_name, SEP)) { - pathconfig->program_full_path = _PyMem_RawWcsdup(pathconfig->program_name); - if (pathconfig->program_full_path == NULL) { - return _PyStatus_NO_MEMORY(); - } - return _PyStatus_OK(); - } - -#ifdef __APPLE__ - wchar_t *abs_path = NULL; - status = calculate_program_macos(&abs_path); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - if (abs_path) { - pathconfig->program_full_path = abs_path; - return _PyStatus_OK(); + wchar_t *wbuffer = _Py_DecodeUTF8_surrogateescape(buffer, cb, &len); + PyMem_Free((void *)buffer); + if (!wbuffer) { + Py_DECREF(r); + PyErr_NoMemory(); + return NULL; } -#endif /* __APPLE__ */ - if (calculate->path_env) { - wchar_t *abs_path = NULL; - status = calculate_which(calculate->path_env, pathconfig->program_name, - &abs_path); - if (_PyStatus_EXCEPTION(status)) { - return status; + wchar_t *p1 = wbuffer; + wchar_t *p2 = p1; + while ((p2 = wcschr(p1, L'\n')) != NULL) { + size_t cb = p2 - p1; + while (cb && (p1[cb] == L'\n' || p1[cb] == L'\r')) { + --cb; } - if (abs_path) { - pathconfig->program_full_path = abs_path; - return _PyStatus_OK(); + PyObject *u = PyUnicode_FromWideChar(p1, cb + 1); + if (!u || PyList_Append(r, u) < 0) { + Py_XDECREF(u); + Py_CLEAR(r); + break; } + Py_DECREF(u); + p1 = p2 + 1; } - - /* In the last resort, use an empty string */ - pathconfig->program_full_path = _PyMem_RawWcsdup(L""); - if (pathconfig->program_full_path == NULL) { - return _PyStatus_NO_MEMORY(); + if (r && p1 && *p1) { + PyObject *u = PyUnicode_FromWideChar(p1, -1); + if (!u || PyList_Append(r, u) < 0) { + Py_CLEAR(r); + } + Py_XDECREF(u); } - return _PyStatus_OK(); + PyMem_RawFree(wbuffer); + return r; } -/* Calculate pathconfig->program_full_path */ -static PyStatus -calculate_program(PyCalculatePath *calculate, _PyPathConfig *pathconfig) +static PyObject * +getpath_realpath(PyObject *Py_UNUSED(self) , PyObject *args) { - PyStatus status; - - status = calculate_program_impl(calculate, pathconfig); - if (_PyStatus_EXCEPTION(status)) { - return status; + PyObject *pathobj; + if (!PyArg_ParseTuple(args, "U", &pathobj)) { + return NULL; } - - if (pathconfig->program_full_path[0] != '\0') { - /* program_full_path is not empty */ - - /* Make sure that program_full_path is an absolute path */ - if (!_Py_isabs(pathconfig->program_full_path)) { - status = absolutize(&pathconfig->program_full_path); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - } - -#if defined(__CYGWIN__) || defined(__MINGW32__) - /* For these platforms it is necessary to ensure that the .exe suffix - * is appended to the filename, otherwise there is potential for - * sys.executable to return the name of a directory under the same - * path (bpo-28441). - */ - status = add_exe_suffix(&pathconfig->program_full_path); - if (_PyStatus_EXCEPTION(status)) { - return status; - } -#endif +#if defined(HAVE_READLINK) + /* This readlink calculation only resolves a symlinked file, and + does not resolve any path segments. This is consistent with + prior releases, however, the realpath implementation below is + potentially correct in more cases. */ + PyObject *r = NULL; + int nlink = 0; + wchar_t *path = PyUnicode_AsWideCharString(pathobj, NULL); + if (!path) { + goto done; } - return _PyStatus_OK(); -} - - -#if HAVE_READLINK -static PyStatus -resolve_symlinks(wchar_t **path_p) -{ - wchar_t new_path[MAXPATHLEN + 1]; - const size_t new_path_len = Py_ARRAY_LENGTH(new_path); - unsigned int nlink = 0; - - while (1) { - int linklen = _Py_wreadlink(*path_p, new_path, new_path_len); + wchar_t *path2 = _PyMem_RawWcsdup(path); + PyMem_Free((void *)path); + path = path2; + while (path) { + wchar_t resolved[MAXPATHLEN + 1]; + int linklen = _Py_wreadlink(path, resolved, Py_ARRAY_LENGTH(resolved)); if (linklen == -1) { - /* not a symbolic link: we are done */ + r = PyUnicode_FromWideChar(path, -1); break; } - - if (_Py_isabs(new_path)) { - PyMem_RawFree(*path_p); - *path_p = _PyMem_RawWcsdup(new_path); - if (*path_p == NULL) { - return _PyStatus_NO_MEMORY(); + if (_Py_isabs(resolved)) { + PyMem_RawFree((void *)path); + path = _PyMem_RawWcsdup(resolved); + } else { + wchar_t *s = wcsrchr(path, SEP); + if (s) { + *s = L'\0'; } + path2 = _Py_normpath(_Py_join_relfile(path, resolved), -1); + PyMem_RawFree((void *)path); + path = path2; } - else { - /* new_path is relative to path */ - reduce(*path_p); - - wchar_t *abs_path = joinpath2(*path_p, new_path); - if (abs_path == NULL) { - return _PyStatus_NO_MEMORY(); - } - - PyMem_RawFree(*path_p); - *path_p = abs_path; - } - nlink++; /* 40 is the Linux kernel 4.2 limit */ if (nlink >= 40) { - return _PyStatus_ERR("maximum number of symbolic links reached"); + PyErr_SetString(PyExc_OSError, "maximum number of symbolic links reached"); + break; } } - return _PyStatus_OK(); -} -#endif /* HAVE_READLINK */ - - -#ifdef WITH_NEXT_FRAMEWORK -static PyStatus -calculate_argv0_path_framework(PyCalculatePath *calculate, _PyPathConfig *pathconfig) -{ - NSModule pythonModule; - - /* On Mac OS X we have a special case if we're running from a framework. - This is because the python home should be set relative to the library, - which is in the framework, not relative to the executable, which may - be outside of the framework. Except when we're in the build - directory... */ - pythonModule = NSModuleForSymbol(NSLookupAndBindSymbol("_Py_Initialize")); - - /* Use dylib functions to find out where the framework was loaded from */ - const char* modPath = NSLibraryNameForModule(pythonModule); - if (modPath == NULL) { - return _PyStatus_OK(); - } - - /* We're in a framework. - See if we might be in the build directory. The framework in the - build directory is incomplete, it only has the .dylib and a few - needed symlinks, it doesn't have the Lib directories and such. - If we're running with the framework from the build directory we must - be running the interpreter in the build directory, so we use the - build-directory-specific logic to find Lib and such. */ - size_t len; - wchar_t* wbuf = Py_DecodeLocale(modPath, &len); - if (wbuf == NULL) { - return DECODE_LOCALE_ERR("framework location", len); + if (!path) { + PyErr_NoMemory(); } - - /* Path: reduce(modPath) / lib_python / LANDMARK */ - PyStatus status; - - wchar_t *parent = _PyMem_RawWcsdup(wbuf); - if (parent == NULL) { - status = _PyStatus_NO_MEMORY(); +done: + PyMem_RawFree((void *)path); + return r; + +#elif defined(HAVE_REALPATH) + PyObject *r = NULL; + struct stat st; + const char *narrow = NULL; + wchar_t *path = PyUnicode_AsWideCharString(pathobj, NULL); + if (!path) { goto done; } - - reduce(parent); - wchar_t *lib_python = joinpath2(parent, calculate->lib_python); - PyMem_RawFree(parent); - - if (lib_python == NULL) { - status = _PyStatus_NO_MEMORY(); + narrow = Py_EncodeLocale(path, NULL); + if (!narrow) { + PyErr_NoMemory(); goto done; } - - int module; - status = ismodule(lib_python, &module); - PyMem_RawFree(lib_python); - - if (_PyStatus_EXCEPTION(status)) { + if (lstat(narrow, &st)) { + PyErr_SetFromErrno(PyExc_OSError); goto done; } - if (!module) { - /* We are in the build directory so use the name of the - executable - we know that the absolute path is passed */ - PyMem_RawFree(calculate->argv0_path); - calculate->argv0_path = _PyMem_RawWcsdup(pathconfig->program_full_path); - if (calculate->argv0_path == NULL) { - status = _PyStatus_NO_MEMORY(); - goto done; - } - - status = _PyStatus_OK(); + if (!S_ISLNK(st.st_mode)) { + Py_INCREF(pathobj); + r = pathobj; goto done; } - - /* Use the location of the library as argv0_path */ - PyMem_RawFree(calculate->argv0_path); - calculate->argv0_path = wbuf; - return _PyStatus_OK(); - + wchar_t resolved[MAXPATHLEN+1]; + if (_Py_wrealpath(path, resolved, MAXPATHLEN) == NULL) { + PyErr_SetFromErrno(PyExc_OSError); + } else { + r = PyUnicode_FromWideChar(resolved, -1); + } done: - PyMem_RawFree(wbuf); - return status; -} + PyMem_Free((void *)path); + PyMem_Free((void *)narrow); + return r; #endif + Py_INCREF(pathobj); + return pathobj; +} -static PyStatus -calculate_argv0_path(PyCalculatePath *calculate, - _PyPathConfig *pathconfig) -{ - PyStatus status; - - calculate->argv0_path = _PyMem_RawWcsdup(pathconfig->program_full_path); - if (calculate->argv0_path == NULL) { - return _PyStatus_NO_MEMORY(); - } - -#ifdef WITH_NEXT_FRAMEWORK - status = calculate_argv0_path_framework(calculate, pathconfig); - if (_PyStatus_EXCEPTION(status)) { - return status; - } -#endif - - status = resolve_symlinks(&calculate->argv0_path); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - reduce(calculate->argv0_path); +static PyMethodDef getpath_methods[] = { + {"abspath", getpath_abspath, METH_VARARGS, NULL}, + {"basename", getpath_basename, METH_VARARGS, NULL}, + {"dirname", getpath_dirname, METH_VARARGS, NULL}, + {"hassuffix", getpath_hassuffix, METH_VARARGS, NULL}, + {"isabs", getpath_isabs, METH_VARARGS, NULL}, + {"isdir", getpath_isdir, METH_VARARGS, NULL}, + {"isfile", getpath_isfile, METH_VARARGS, NULL}, + {"isxfile", getpath_isxfile, METH_VARARGS, NULL}, + {"joinpath", getpath_joinpath, METH_VARARGS, NULL}, + {"readlines", getpath_readlines, METH_VARARGS, NULL}, + {"realpath", getpath_realpath, METH_VARARGS, NULL}, + {NULL, NULL, 0, NULL} +}; - return _PyStatus_OK(); -} +/* Two implementations of warn() to use depending on whether warnings + are enabled or not. */ -static PyStatus -calculate_open_pyenv(PyCalculatePath *calculate, FILE **env_file_p) +static PyObject * +getpath_warn(PyObject *Py_UNUSED(self), PyObject *args) { - *env_file_p = NULL; - - const wchar_t *env_cfg = L"pyvenv.cfg"; - - /* Filename: / "pyvenv.cfg" */ - wchar_t *filename = joinpath2(calculate->argv0_path, env_cfg); - if (filename == NULL) { - return _PyStatus_NO_MEMORY(); + PyObject *msgobj; + if (!PyArg_ParseTuple(args, "U", &msgobj)) { + return NULL; } + fprintf(stderr, "%s\n", PyUnicode_AsUTF8(msgobj)); + Py_RETURN_NONE; +} - *env_file_p = _Py_wfopen(filename, L"r"); - PyMem_RawFree(filename); - if (*env_file_p != NULL) { - return _PyStatus_OK(); +static PyObject * +getpath_nowarn(PyObject *Py_UNUSED(self), PyObject *args) +{ + Py_RETURN_NONE; +} - } - /* fopen() failed: reset errno */ - errno = 0; +static PyMethodDef getpath_warn_method = {"warn", getpath_warn, METH_VARARGS, NULL}; +static PyMethodDef getpath_nowarn_method = {"warn", getpath_nowarn, METH_VARARGS, NULL}; - /* Path: / "pyvenv.cfg" */ - wchar_t *parent = _PyMem_RawWcsdup(calculate->argv0_path); - if (parent == NULL) { - return _PyStatus_NO_MEMORY(); +/* Add the helper functions to the dict */ +static int +funcs_to_dict(PyObject *dict, int warnings) +{ + for (PyMethodDef *m = getpath_methods; m->ml_name; ++m) { + PyObject *f = PyCFunction_NewEx(m, NULL, NULL); + if (!f) { + return 0; + } + if (PyDict_SetItemString(dict, m->ml_name, f) < 0) { + Py_DECREF(f); + return 0; + } + Py_DECREF(f); } - reduce(parent); - - filename = joinpath2(parent, env_cfg); - PyMem_RawFree(parent); - if (filename == NULL) { - return _PyStatus_NO_MEMORY(); + PyMethodDef *m2 = warnings ? &getpath_warn_method : &getpath_nowarn_method; + PyObject *f = PyCFunction_NewEx(m2, NULL, NULL); + if (!f) { + return 0; } - - *env_file_p = _Py_wfopen(filename, L"r"); - PyMem_RawFree(filename); - - if (*env_file_p == NULL) { - /* fopen() failed: reset errno */ - errno = 0; + if (PyDict_SetItemString(dict, m2->ml_name, f) < 0) { + Py_DECREF(f); + return 0; } - return _PyStatus_OK(); + Py_DECREF(f); + return 1; } -/* Search for an "pyvenv.cfg" environment configuration file, first in the - executable's directory and then in the parent directory. - If found, open it for use when searching for prefixes. - - Write the 'home' variable of pyvenv.cfg into calculate->argv0_path. */ -static PyStatus -calculate_read_pyenv(PyCalculatePath *calculate) +/* Add a wide-character string constant to the dict */ +static int +wchar_to_dict(PyObject *dict, const char *key, const wchar_t *s) { - PyStatus status; - FILE *env_file = NULL; - - status = calculate_open_pyenv(calculate, &env_file); - if (_PyStatus_EXCEPTION(status)) { - assert(env_file == NULL); - return status; - } - if (env_file == NULL) { - /* pyvenv.cfg not found */ - return _PyStatus_OK(); - } - - /* Look for a 'home' variable and set argv0_path to it, if found */ - wchar_t *home = NULL; - status = _Py_FindEnvConfigValue(env_file, L"home", &home); - if (_PyStatus_EXCEPTION(status)) { - fclose(env_file); - return status; - } - - if (home) { - PyMem_RawFree(calculate->argv0_path); - calculate->argv0_path = home; + PyObject *u; + int r; + if (s && s[0]) { + u = PyUnicode_FromWideChar(s, -1); + if (!u) { + return 0; + } + } else { + u = Py_None; + Py_INCREF(u); } - fclose(env_file); - return _PyStatus_OK(); + r = PyDict_SetItemString(dict, key, u) == 0; + Py_DECREF(u); + return r; } -static PyStatus -calculate_zip_path(PyCalculatePath *calculate) +/* Add a narrow string constant to the dict, using default locale decoding */ +static int +decode_to_dict(PyObject *dict, const char *key, const char *s) { - PyStatus res; - - /* Path: / "pythonXY.zip" */ - wchar_t *path = joinpath2(calculate->platlibdir, - L"python" Py_STRINGIFY(PY_MAJOR_VERSION) Py_STRINGIFY(PY_MINOR_VERSION) - L".zip"); - if (path == NULL) { - return _PyStatus_NO_MEMORY(); + PyObject *u = NULL; + int r; + if (s && s[0]) { + size_t len; + const wchar_t *w = Py_DecodeLocale(s, &len); + if (w) { + u = PyUnicode_FromWideChar(w, len); + PyMem_RawFree((void *)w); + } + if (!u) { + return 0; + } + } else { + u = Py_None; + Py_INCREF(u); } + r = PyDict_SetItemString(dict, key, u) == 0; + Py_DECREF(u); + return r; +} - if (calculate->prefix_found > 0) { - /* Use the reduced prefix returned by Py_GetPrefix() - - Path: / / "pythonXY.zip" */ - wchar_t *parent = _PyMem_RawWcsdup(calculate->prefix); - if (parent == NULL) { - res = _PyStatus_NO_MEMORY(); - goto done; +/* Add an environment variable to the dict, optionally clearing it afterwards */ +static int +env_to_dict(PyObject *dict, const char *key, int and_clear) +{ + PyObject *u = NULL; + int r = 0; + assert(strncmp(key, "ENV_", 4) == 0); + assert(strlen(key) < 64); +#ifdef MS_WINDOWS + wchar_t wkey[64]; + // Quick convert to wchar_t, since we know key is ASCII + wchar_t *wp = wkey; + for (const char *p = &key[4]; *p; ++p) { + assert(*p < 128); + *wp++ = *p; + } + *wp = L'\0'; + const wchar_t *v = _wgetenv(wkey); + if (v) { + u = PyUnicode_FromWideChar(v, -1); + if (!u) { + PyErr_Clear(); + } + } +#else + const char *v = getenv(&key[4]); + if (v) { + size_t len; + const wchar_t *w = Py_DecodeLocale(v, &len); + if (w) { + u = PyUnicode_FromWideChar(w, len); + if (!u) { + PyErr_Clear(); + } + PyMem_RawFree((void *)w); } - reduce(parent); - reduce(parent); - calculate->zip_path = joinpath2(parent, path); - PyMem_RawFree(parent); } - else { - calculate->zip_path = joinpath2(calculate->prefix_macro, path); - } - - if (calculate->zip_path == NULL) { - res = _PyStatus_NO_MEMORY(); - goto done; +#endif + if (u) { + r = PyDict_SetItemString(dict, key, u) == 0; + Py_DECREF(u); + } else { + r = PyDict_SetItemString(dict, key, Py_None) == 0; + } + if (r && and_clear) { +#ifdef MS_WINDOWS + _wputenv_s(wkey, L""); +#else + unsetenv(&key[4]); +#endif } - - res = _PyStatus_OK(); - -done: - PyMem_RawFree(path); - return res; + return r; } -static PyStatus -calculate_module_search_path(PyCalculatePath *calculate, - _PyPathConfig *pathconfig) +/* Add an integer constant to the dict */ +static int +int_to_dict(PyObject *dict, const char *key, int v) { - /* Calculate size of return buffer */ - size_t bufsz = 0; - if (calculate->pythonpath_env != NULL) { - bufsz += wcslen(calculate->pythonpath_env) + 1; + PyObject *o; + int r; + o = PyLong_FromLong(v); + if (!o) { + return 0; } + r = PyDict_SetItemString(dict, key, o) == 0; + Py_DECREF(o); + return r; +} - wchar_t *defpath = calculate->pythonpath_macro; - size_t prefixsz = wcslen(calculate->prefix) + 1; - while (1) { - wchar_t *delim = wcschr(defpath, DELIM); - - if (!_Py_isabs(defpath)) { - /* Paths are relative to prefix */ - bufsz += prefixsz; - } - if (delim) { - bufsz += delim - defpath + 1; - } - else { - bufsz += wcslen(defpath) + 1; - break; +#ifdef MS_WINDOWS +static int +winmodule_to_dict(PyObject *dict, const char *key, HMODULE mod) +{ + wchar_t *buffer = NULL; + for (DWORD cch = 256; buffer == NULL && cch < (1024 * 1024); cch *= 2) { + buffer = (wchar_t*)PyMem_RawMalloc(cch * sizeof(wchar_t)); + if (buffer) { + if (GetModuleFileNameW(mod, buffer, cch) == cch) { + PyMem_RawFree(buffer); + buffer = NULL; + } } - defpath = delim + 1; - } - - bufsz += wcslen(calculate->zip_path) + 1; - bufsz += wcslen(calculate->exec_prefix) + 1; - - /* Allocate the buffer */ - wchar_t *buf = PyMem_RawMalloc(bufsz * sizeof(wchar_t)); - if (buf == NULL) { - return _PyStatus_NO_MEMORY(); } - buf[0] = '\0'; - - /* Run-time value of $PYTHONPATH goes first */ - if (calculate->pythonpath_env) { - wcscpy(buf, calculate->pythonpath_env); - wcscat(buf, delimiter); - } - - /* Next is the default zip path */ - wcscat(buf, calculate->zip_path); - wcscat(buf, delimiter); - - /* Next goes merge of compile-time $PYTHONPATH with - * dynamically located prefix. - */ - defpath = calculate->pythonpath_macro; - while (1) { - wchar_t *delim = wcschr(defpath, DELIM); + int r = wchar_to_dict(dict, key, buffer); + PyMem_RawFree(buffer); + return r; +} +#endif - if (!_Py_isabs(defpath)) { - wcscat(buf, calculate->prefix); - if (prefixsz >= 2 && calculate->prefix[prefixsz - 2] != SEP && - defpath[0] != (delim ? DELIM : L'\0')) - { - /* not empty */ - wcscat(buf, separator); - } - } - if (delim) { - size_t len = delim - defpath + 1; - size_t end = wcslen(buf) + len; - wcsncat(buf, defpath, len); - buf[end] = '\0'; +/* Add the current executable's path to the dict */ +static int +progname_to_dict(PyObject *dict, const char *key) +{ +#ifdef MS_WINDOWS + return winmodule_to_dict(dict, key, NULL); +#elif defined(__APPLE__) + char *path; + uint32_t pathLen = 256; + while (pathLen) { + path = PyMem_RawMalloc((pathLen + 1) * sizeof(char)); + if (!path) { + return 0; + } + if (_NSGetExecutablePath(path, &pathLen) != 0) { + PyMem_RawFree(path); + continue; } - else { - wcscat(buf, defpath); - break; + // Only keep if the path is absolute + if (path[0] == SEP) { + int r = decode_to_dict(dict, key, path); + PyMem_RawFree(path); + return r; } - defpath = delim + 1; + // Fall back and store None + PyMem_RawFree(path); + break; } - wcscat(buf, delimiter); - - /* Finally, on goes the directory for dynamic-load modules */ - wcscat(buf, calculate->exec_prefix); - - pathconfig->module_search_path = buf; - return _PyStatus_OK(); +#endif + return PyDict_SetItemString(dict, key, Py_None) == 0; } -static PyStatus -calculate_init(PyCalculatePath *calculate, const PyConfig *config) +/* Add the runtime library's path to the dict */ +static int +library_to_dict(PyObject *dict, const char *key) { - size_t len; - - calculate->warnings = config->pathconfig_warnings; - calculate->pythonpath_env = config->pythonpath_env; - calculate->platlibdir = config->platlibdir; - - const char *path = getenv("PATH"); - if (path) { - calculate->path_env = Py_DecodeLocale(path, &len); - if (!calculate->path_env) { - return DECODE_LOCALE_ERR("PATH environment variable", len); - } +#ifdef MS_WINDOWS + extern HMODULE PyWin_DLLhModule; + if (PyWin_DLLhModule) { + return winmodule_to_dict(dict, key, PyWin_DLLhModule); } +#elif defined(WITH_NEXT_FRAMEWORK) + static const char modPath[MAXPATHLEN + 1]; + static int modPathInitialized = -1; + if (modPathInitialized < 0) { + NSModule pythonModule; + modPathInitialized = 0; - /* Decode macros */ - calculate->pythonpath_macro = Py_DecodeLocale(PYTHONPATH, &len); - if (!calculate->pythonpath_macro) { - return DECODE_LOCALE_ERR("PYTHONPATH macro", len); - } - calculate->prefix_macro = Py_DecodeLocale(PREFIX, &len); - if (!calculate->prefix_macro) { - return DECODE_LOCALE_ERR("PREFIX macro", len); - } - calculate->exec_prefix_macro = Py_DecodeLocale(EXEC_PREFIX, &len); - if (!calculate->exec_prefix_macro) { - return DECODE_LOCALE_ERR("EXEC_PREFIX macro", len); - } - calculate->vpath_macro = Py_DecodeLocale(VPATH, &len); - if (!calculate->vpath_macro) { - return DECODE_LOCALE_ERR("VPATH macro", len); - } + /* On Mac OS X we have a special case if we're running from a framework. + This is because the python home should be set relative to the library, + which is in the framework, not relative to the executable, which may + be outside of the framework. Except when we're in the build + directory... */ + pythonModule = NSModuleForSymbol(NSLookupAndBindSymbol("_Py_Initialize")); - // / "pythonX.Y" - wchar_t *pyversion = Py_DecodeLocale("python" VERSION, &len); - if (!pyversion) { - return DECODE_LOCALE_ERR("VERSION macro", len); + /* Use dylib functions to find out where the framework was loaded from */ + const char *path = NSLibraryNameForModule(pythonModule); + if (path) { + strncpy(modPath, path, MAXPATHLEN); + } } - calculate->lib_python = joinpath2(config->platlibdir, pyversion); - PyMem_RawFree(pyversion); - if (calculate->lib_python == NULL) { - return _PyStatus_NO_MEMORY(); + if (modPathInitialized > 0) { + return decode_to_dict(dict, key, modPath); } - - return _PyStatus_OK(); +#endif + return PyDict_SetItemString(dict, key, Py_None) == 0; } -static void -calculate_free(PyCalculatePath *calculate) +PyObject * +_Py_Get_Getpath_CodeObject() { - PyMem_RawFree(calculate->pythonpath_macro); - PyMem_RawFree(calculate->prefix_macro); - PyMem_RawFree(calculate->exec_prefix_macro); - PyMem_RawFree(calculate->vpath_macro); - PyMem_RawFree(calculate->lib_python); - PyMem_RawFree(calculate->path_env); - PyMem_RawFree(calculate->zip_path); - PyMem_RawFree(calculate->argv0_path); - PyMem_RawFree(calculate->prefix); - PyMem_RawFree(calculate->exec_prefix); + return PyMarshal_ReadObjectFromString( + (const char*)_Py_M__getpath, sizeof(_Py_M__getpath)); } -static PyStatus -calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig) -{ - PyStatus status; - - if (pathconfig->program_full_path == NULL) { - status = calculate_program(calculate, pathconfig); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - } +/* Perform the actual path calculation. - status = calculate_argv0_path(calculate, pathconfig); - if (_PyStatus_EXCEPTION(status)) { - return status; - } + When compute_path_config is 0, this only reads any initialised path + config values into the PyConfig struct. For example, Py_SetHome() or + Py_SetPath(). The only error should be due to failed memory allocation. - /* If a pyvenv.cfg configure file is found, - argv0_path is overridden with its 'home' variable. */ - status = calculate_read_pyenv(calculate); - if (_PyStatus_EXCEPTION(status)) { - return status; - } + When compute_path_config is 1, full path calculation is performed. + The GIL must be held, and there may be filesystem access, side + effects, and potential unraisable errors that are reported directly + to stderr. - status = calculate_prefix(calculate, pathconfig); - if (_PyStatus_EXCEPTION(status)) { - return status; - } + Calling this function multiple times on the same PyConfig is only + safe because already-configured values are not recalculated. To + actually recalculate paths, you need a clean PyConfig. +*/ +PyStatus +_PyConfig_InitPathConfig(PyConfig *config, int compute_path_config) +{ + PyStatus status = _PyPathConfig_ReadGlobal(config); - status = calculate_zip_path(calculate); - if (_PyStatus_EXCEPTION(status)) { + if (_PyStatus_EXCEPTION(status) || !compute_path_config) { return status; } - status = calculate_exec_prefix(calculate, pathconfig); - if (_PyStatus_EXCEPTION(status)) { - return status; + if (!_PyThreadState_UncheckedGet()) { + return PyStatus_Error("cannot calculate path configuration without GIL"); } - if ((!calculate->prefix_found || !calculate->exec_prefix_found) - && calculate->warnings) - { - fprintf(stderr, - "Consider setting $PYTHONHOME to [:]\n"); + PyObject *configDict = _PyConfig_AsDict(config); + if (!configDict) { + PyErr_Clear(); + return PyStatus_NoMemory(); } - if (pathconfig->module_search_path == NULL) { - status = calculate_module_search_path(calculate, pathconfig); - if (_PyStatus_EXCEPTION(status)) { - return status; - } + PyObject *dict = PyDict_New(); + if (!dict) { + PyErr_Clear(); + Py_DECREF(configDict); + return PyStatus_NoMemory(); } - if (pathconfig->stdlib_dir == NULL) { - /* This must be done *before* calculate_set_prefix() is called. */ - status = calculate_set_stdlib_dir(calculate, pathconfig); - if (_PyStatus_EXCEPTION(status)) { - return status; - } + if (PyDict_SetItemString(dict, "config", configDict) < 0) { + PyErr_Clear(); + Py_DECREF(configDict); + Py_DECREF(dict); + return PyStatus_NoMemory(); } + /* reference now held by dict */ + Py_DECREF(configDict); - if (pathconfig->prefix == NULL) { - status = calculate_set_prefix(calculate, pathconfig); - if (_PyStatus_EXCEPTION(status)) { - return status; - } + PyObject *co = _Py_Get_Getpath_CodeObject(); + if (!co || !PyCode_Check(co)) { + PyErr_Clear(); + Py_XDECREF(co); + Py_DECREF(dict); + return PyStatus_Error("error reading frozen getpath.py"); } - if (pathconfig->exec_prefix == NULL) { - status = calculate_set_exec_prefix(calculate, pathconfig); - if (_PyStatus_EXCEPTION(status)) { - return status; +#ifdef MS_WINDOWS + PyObject *winreg = PyImport_ImportModule("winreg"); + if (!winreg || PyDict_SetItemString(dict, "winreg", winreg) < 0) { + PyErr_Clear(); + Py_XDECREF(winreg); + if (PyDict_SetItemString(dict, "winreg", Py_None) < 0) { + PyErr_Clear(); + Py_DECREF(co); + Py_DECREF(dict); + return PyStatus_Error("error importing winreg module"); } + } else { + Py_DECREF(winreg); } - return _PyStatus_OK(); -} - - -/* Calculate the Python path configuration. - - Inputs: - - - PATH environment variable - - Macros: PYTHONPATH, PREFIX, EXEC_PREFIX, VERSION (ex: "3.9"). - PREFIX and EXEC_PREFIX are generated by the configure script. - PYTHONPATH macro is the default search path. - - pybuilddir.txt file - - pyvenv.cfg configuration file - - PyConfig fields ('config' function argument): - - - pathconfig_warnings - - pythonpath_env (PYTHONPATH environment variable) - - - _PyPathConfig fields ('pathconfig' function argument): - - - program_name: see config_init_program_name() - - home: Py_SetPythonHome() or PYTHONHOME environment variable - - - current working directory: see copy_absolute() - - Outputs, 'pathconfig' fields: - - - program_full_path - - module_search_path - - prefix - - exec_prefix - - If a field is already set (non NULL), it is left unchanged. */ -PyStatus -_PyPathConfig_Calculate(_PyPathConfig *pathconfig, const PyConfig *config) -{ - PyStatus status; - PyCalculatePath calculate; - memset(&calculate, 0, sizeof(calculate)); +#endif - status = calculate_init(&calculate, config); - if (_PyStatus_EXCEPTION(status)) { - goto done; - } + if ( +#ifdef MS_WINDOWS + !decode_to_dict(dict, "os_name", "nt") || +#elif defined(__APPLE__) + !decode_to_dict(dict, "os_name", "darwin") || +#else + !decode_to_dict(dict, "os_name", "posix") || +#endif + !decode_to_dict(dict, "PREFIX", PREFIX) || + !decode_to_dict(dict, "EXEC_PREFIX", EXEC_PREFIX) || + !decode_to_dict(dict, "PYTHONPATH", PYTHONPATH) || + !decode_to_dict(dict, "VPATH", VPATH) || + !decode_to_dict(dict, "PLATLIBDIR", PLATLIBDIR) || + !decode_to_dict(dict, "PYDEBUGEXT", PYDEBUGEXT) || + !int_to_dict(dict, "VERSION_MAJOR", PY_MAJOR_VERSION) || + !int_to_dict(dict, "VERSION_MINOR", PY_MINOR_VERSION) || + !decode_to_dict(dict, "PYWINVER", PYWINVER) || + !wchar_to_dict(dict, "EXE_SUFFIX", EXE_SUFFIX) || + !env_to_dict(dict, "ENV_PATH", 0) || + !env_to_dict(dict, "ENV_PYTHONHOME", 0) || + !env_to_dict(dict, "ENV_PYTHONEXECUTABLE", 0) || + !env_to_dict(dict, "ENV___PYVENV_LAUNCHER__", 1) || + !progname_to_dict(dict, "real_executable") || + !library_to_dict(dict, "library") || + !wchar_to_dict(dict, "executable_dir", NULL) || + !wchar_to_dict(dict, "py_setpath", _PyPathConfig_GetGlobalModuleSearchPath()) || + !funcs_to_dict(dict, config->pathconfig_warnings) || +#ifndef MS_WINDOWS + PyDict_SetItemString(dict, "winreg", Py_None) < 0 || +#endif + PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins()) < 0 + ) { + Py_DECREF(co); + Py_DECREF(dict); + _PyErr_WriteUnraisableMsg("error evaluating initial values", NULL); + return PyStatus_Error("error evaluating initial values"); + } + + PyObject *r = PyEval_EvalCode(co, dict, dict); + Py_DECREF(co); + + if (!r) { + Py_DECREF(dict); + _PyErr_WriteUnraisableMsg("error evaluating path", NULL); + return PyStatus_Error("error evaluating path"); + } + Py_DECREF(r); + +#if 0 + PyObject *it = PyObject_GetIter(configDict); + for (PyObject *k = PyIter_Next(it); k; k = PyIter_Next(it)) { + if (!strcmp("__builtins__", PyUnicode_AsUTF8(k))) { + Py_DECREF(k); + continue; + } + fprintf(stderr, "%s = ", PyUnicode_AsUTF8(k)); + PyObject *o = PyDict_GetItem(configDict, k); + o = PyObject_Repr(o); + fprintf(stderr, "%s\n", PyUnicode_AsUTF8(o)); + Py_DECREF(o); + Py_DECREF(k); + } + Py_DECREF(it); +#endif - status = calculate_path(&calculate, pathconfig); - if (_PyStatus_EXCEPTION(status)) { - goto done; + if (_PyConfig_FromDict(config, configDict) < 0) { + _PyErr_WriteUnraisableMsg("reading getpath results", NULL); + Py_DECREF(dict); + return PyStatus_Error("error getting getpath results"); } - /* program_full_path must an either an empty string or an absolute path */ - assert(wcslen(pathconfig->program_full_path) == 0 - || _Py_isabs(pathconfig->program_full_path)); - - status = _PyStatus_OK(); + Py_DECREF(dict); -done: - calculate_free(&calculate); - return status; -} - -#ifdef __cplusplus + return _PyStatus_OK(); } -#endif diff --git a/Modules/getpath.py b/Modules/getpath.py new file mode 100644 index 0000000000000..2eadfba1dfda2 --- /dev/null +++ b/Modules/getpath.py @@ -0,0 +1,727 @@ +# ****************************************************************************** +# getpath.py +# ****************************************************************************** + +# This script is designed to be precompiled to bytecode, frozen into the +# main binary, and then directly evaluated. It is not an importable module, +# and does not import any other modules (besides winreg on Windows). +# Rather, the values listed below must be specified in the globals dict +# used when evaluating the bytecode. + +# See _PyConfig_InitPathConfig in Modules/getpath.c for the execution. + +# ****************************************************************************** +# REQUIRED GLOBALS +# ****************************************************************************** + +# ** Helper functions ** +# abspath(path) -- make relative paths absolute against CWD +# basename(path) -- the filename of path +# dirname(path) -- the directory name of path +# hassuffix(path, suffix) -- returns True if path has suffix +# isabs(path) -- path is absolute or not +# isdir(path) -- path exists and is a directory +# isfile(path) -- path exists and is a file +# isxfile(path) -- path exists and is an executable file +# joinpath(*paths) -- combine the paths +# readlines(path) -- a list of each line of text in the UTF-8 encoded file +# realpath(path) -- resolves symlinks in path +# warn(message) -- print a warning (if enabled) + +# ** Values known at compile time ** +# os_name -- [in] one of 'nt', 'posix', 'darwin' +# PREFIX -- [in] sysconfig.get_config_var(...) +# EXEC_PREFIX -- [in] sysconfig.get_config_var(...) +# PYTHONPATH -- [in] sysconfig.get_config_var(...) +# VPATH -- [in] sysconfig.get_config_var(...) +# PLATLIBDIR -- [in] sysconfig.get_config_var(...) +# PYDEBUGEXT -- [in, opt] '_d' on Windows for debug builds +# EXE_SUFFIX -- [in, opt] '.exe' on Windows/Cygwin/similar +# VERSION_MAJOR -- [in] sys.version_info.major +# VERSION_MINOR -- [in] sys.version_info.minor +# PYWINVER -- [in] the Windows platform-specific version (e.g. 3.8-32) + +# ** Values read from the environment ** +# There is no need to check the use_environment flag before reading +# these, as the flag will be tested in this script. +# Also note that ENV_PYTHONPATH is read from config['pythonpath_env'] +# to allow for embedders who choose to specify it via that struct. +# ENV_PATH -- [in] getenv(...) +# ENV_PYTHONHOME -- [in] getenv(...) +# ENV_PYTHONEXECUTABLE -- [in] getenv(...) +# ENV___PYVENV_LAUNCHER__ -- [in] getenv(...) + +# ** Values calculated at runtime ** +# config -- [in/out] dict of the PyConfig structure +# real_executable -- [in, optional] resolved path to main process +# On Windows and macOS, read directly from the running process +# Otherwise, leave None and it will be calculated from executable +# executable_dir -- [in, optional] real directory containing binary +# If None, will be calculated from real_executable or executable +# py_setpath -- [in] argument provided to Py_SetPath +# If None, 'prefix' and 'exec_prefix' may be updated in config +# library -- [in, optional] path of dylib/DLL/so +# Only used for locating ._pth files +# winreg -- [in, optional] the winreg module (only on Windows) + +# ****************************************************************************** +# HIGH-LEVEL ALGORITHM +# ****************************************************************************** + +# IMPORTANT: The code is the actual specification at time of writing. +# This prose description is based on the original comment from the old +# getpath.c to help capture the intent, but should not be considered +# a specification. + +# Search in some common locations for the associated Python libraries. + +# Two directories must be found, the platform independent directory +# (prefix), containing the common .py and .pyc files, and the platform +# dependent directory (exec_prefix), containing the shared library +# modules. Note that prefix and exec_prefix can be the same directory, +# but for some installations, they are different. + +# This script carries out separate searches for prefix and exec_prefix. +# Each search tries a number of different locations until a ``landmark'' +# file or directory is found. If no prefix or exec_prefix is found, a +# warning message is issued and the preprocessor defined PREFIX and +# EXEC_PREFIX are used (even though they will not work); python carries on +# as best as is possible, but most imports will fail. + +# Before any searches are done, the location of the executable is +# determined. If Py_SetPath() was called, or if we are running on +# Windows, the 'real_executable' path is used (if known). Otherwise, +# we use the config-specified program name or default to argv[0]. +# If this has one or more slashes in it, it is made absolute against +# the current working directory. If it only contains a name, it must +# have been invoked from the shell's path, so we search $PATH for the +# named executable and use that. If the executable was not found on +# $PATH (or there was no $PATH environment variable), the original +# argv[0] string is used. + +# At this point, provided Py_SetPath was not used, the +# __PYVENV_LAUNCHER__ variable may override the executable (on macOS, +# the PYTHON_EXECUTABLE variable may also override). This allows +# certain launchers that run Python as a subprocess to properly +# specify the executable path. They are not intended for users. + +# Next, the executable location is examined to see if it is a symbolic +# link. If so, the link is realpath-ed and the directory of the link +# target is used for the remaining searches. The same steps are +# performed for prefix and for exec_prefix, but with different landmarks. + +# Step 1. Are we running in a virtual environment? Unless 'home' has +# been specified another way, check for a pyvenv.cfg and use its 'home' +# property to override the executable dir used later for prefix searches. +# We do not activate the venv here - that is performed later by site.py. + +# Step 2. Is there a ._pth file? A ._pth file lives adjacent to the +# runtime library (if any) or the actual executable (not the symlink), +# and contains precisely the intended contents of sys.path as relative +# paths (to its own location). Its presence also enables isolated mode +# and suppresses other environment variable usage. Unless already +# specified by Py_SetHome(), the directory containing the ._pth file is +# set as 'home'. + +# Step 3. Are we running python out of the build directory? This is +# checked by looking for the BUILDDIR_TXT file, which contains the +# relative path to the platlib dir. The executable_dir value is +# derived from joining the VPATH preprocessor variable to the +# directory containing pybuilddir.txt. If it is not found, the +# BUILD_LANDMARK file is found, which is part of the source tree. +# prefix is then found by searching up for a file that should only +# exist in the source tree, and the stdlib dir is set to prefix/Lib. + +# Step 4. If 'home' is set, either by Py_SetHome(), ENV_PYTHONHOME, +# a pyvenv.cfg file, ._pth file, or by detecting a build directory, it +# is assumed to point to prefix and exec_prefix. $PYTHONHOME can be a +# single directory, which is used for both, or the prefix and exec_prefix +# directories separated by DELIM (colon on POSIX; semicolon on Windows). + +# Step 5. Try to find prefix and exec_prefix relative to executable_dir, +# backtracking up the path until it is exhausted. This is the most common +# step to succeed. Note that if prefix and exec_prefix are different, +# exec_prefix is more likely to be found; however if exec_prefix is a +# subdirectory of prefix, both will be found. + +# Step 6. Search the directories pointed to by the preprocessor variables +# PREFIX and EXEC_PREFIX. These are supplied by the Makefile but can be +# passed in as options to the configure script. + +# That's it! + +# Well, almost. Once we have determined prefix and exec_prefix, the +# preprocessor variable PYTHONPATH is used to construct a path. Each +# relative path on PYTHONPATH is prefixed with prefix. Then the directory +# containing the shared library modules is appended. The environment +# variable $PYTHONPATH is inserted in front of it all. On POSIX, if we are +# in a build directory, both prefix and exec_prefix are reset to the +# corresponding preprocessor variables (so sys.prefix will reflect the +# installation location, even though sys.path points into the build +# directory). This seems to make more sense given that currently the only +# known use of sys.prefix and sys.exec_prefix is for the ILU installation +# process to find the installed Python tree. + +# An embedding application can use Py_SetPath() to override all of +# these automatic path computations. + + +# ****************************************************************************** +# PLATFORM CONSTANTS +# ****************************************************************************** + +platlibdir = config.get('platlibdir') or PLATLIBDIR + +if os_name == 'posix' or os_name == 'darwin': + BUILDDIR_TXT = 'pybuilddir.txt' + BUILD_LANDMARK = 'Modules/Setup.local' + DEFAULT_PROGRAM_NAME = f'python{VERSION_MAJOR}' + STDLIB_SUBDIR = f'{platlibdir}/python{VERSION_MAJOR}.{VERSION_MINOR}' + STDLIB_LANDMARKS = [f'{STDLIB_SUBDIR}/os.py', f'{STDLIB_SUBDIR}/os.pyc'] + PLATSTDLIB_LANDMARK = f'{platlibdir}/python{VERSION_MAJOR}.{VERSION_MINOR}/lib-dynload' + BUILDSTDLIB_LANDMARKS = ['Lib/os.py'] + VENV_LANDMARK = 'pyvenv.cfg' + ZIP_LANDMARK = f'{platlibdir}/python{VERSION_MAJOR}{VERSION_MINOR}.zip' + DELIM = ':' + SEP = '/' + +elif os_name == 'nt': + BUILDDIR_TXT = 'pybuilddir.txt' + BUILD_LANDMARK = r'..\..\Modules\Setup.local' + DEFAULT_PROGRAM_NAME = f'python' + STDLIB_SUBDIR = 'Lib' + STDLIB_LANDMARKS = [f'{STDLIB_SUBDIR}\\os.py', f'{STDLIB_SUBDIR}\\os.pyc'] + PLATSTDLIB_LANDMARK = f'{platlibdir}' + BUILDSTDLIB_LANDMARKS = ['Lib\\os.py'] + VENV_LANDMARK = 'pyvenv.cfg' + ZIP_LANDMARK = f'python{VERSION_MAJOR}{VERSION_MINOR}{PYDEBUGEXT or ""}.zip' + WINREG_KEY = f'SOFTWARE\\Python\\PythonCore\\{PYWINVER}\\PythonPath' + DELIM = ';' + SEP = '\\' + + +# ****************************************************************************** +# HELPER FUNCTIONS (note that we prefer C functions for performance) +# ****************************************************************************** + +def search_up(prefix, *landmarks, test=isfile): + while prefix: + if any(test(joinpath(prefix, f)) for f in landmarks): + return prefix + prefix = dirname(prefix) + + +# ****************************************************************************** +# READ VARIABLES FROM config +# ****************************************************************************** + +program_name = config.get('program_name') +home = config.get('home') +executable = config.get('executable') +base_executable = config.get('base_executable') +prefix = config.get('prefix') +exec_prefix = config.get('exec_prefix') +base_prefix = config.get('base_prefix') +base_exec_prefix = config.get('base_exec_prefix') +ENV_PYTHONPATH = config['pythonpath_env'] +use_environment = config.get('use_environment', 1) + +pythonpath = config.get('module_search_paths') + +real_executable_dir = None +stdlib_dir = None +platstdlib_dir = None + +# ****************************************************************************** +# CALCULATE program_name +# ****************************************************************************** + +program_name_was_set = bool(program_name) + +if not program_name: + try: + program_name = config.get('orig_argv', [])[0] + except IndexError: + pass + +if not program_name: + program_name = DEFAULT_PROGRAM_NAME + +if EXE_SUFFIX and not hassuffix(program_name, EXE_SUFFIX) and isxfile(program_name + EXE_SUFFIX): + program_name = program_name + EXE_SUFFIX + + +# ****************************************************************************** +# CALCULATE executable +# ****************************************************************************** + +if py_setpath: + # When Py_SetPath has been called, executable defaults to + # the real executable path. + if not executable: + executable = real_executable + +if not executable and SEP in program_name: + # Resolve partial path program_name against current directory + executable = abspath(program_name) + +if not executable: + # All platforms default to real_executable if known at this + # stage. POSIX does not set this value. + executable = real_executable +elif os_name == 'darwin': + # QUIRK: On macOS we may know the real executable path, but + # if our caller has lied to us about it (e.g. most of + # test_embed), we need to use their path in order to detect + # whether we are in a build tree. This is true even if the + # executable path was provided in the config. + real_executable = executable + +if not executable and program_name: + # Resolve names against PATH. + # NOTE: The use_environment value is ignored for this lookup. + # To properly isolate, launch Python with a full path. + for p in ENV_PATH.split(DELIM): + p = joinpath(p, program_name) + if isxfile(p): + executable = p + break + +if not executable: + executable = '' + # When we cannot calculate the executable, subsequent searches + # look in the current working directory. Here, we emulate that + # (the former getpath.c would do it apparently by accident). + executable_dir = abspath('.') + # Also need to set this fallback in case we are running from a + # build directory with an invalid argv0 (i.e. test_sys.test_executable) + real_executable_dir = executable_dir + +if ENV_PYTHONEXECUTABLE or ENV___PYVENV_LAUNCHER__: + # If set, these variables imply that we should be using them as + # sys.executable and when searching for venvs. However, we should + # use the argv0 path for prefix calculation + base_executable = executable + if not real_executable: + real_executable = executable + executable = ENV_PYTHONEXECUTABLE or ENV___PYVENV_LAUNCHER__ + executable_dir = dirname(executable) + + +# ****************************************************************************** +# CALCULATE (default) home +# ****************************************************************************** + +# Used later to distinguish between Py_SetPythonHome and other +# ways that it may have been set +home_was_set = False + +if home: + home_was_set = True +elif use_environment and ENV_PYTHONHOME and not py_setpath: + home = ENV_PYTHONHOME + + +# ****************************************************************************** +# READ pyvenv.cfg +# ****************************************************************************** + +venv_prefix = None + +# Calling Py_SetPythonHome(), Py_SetPath() or +# setting $PYTHONHOME will override venv detection. +if not home and not py_setpath: + try: + # prefix2 is just to avoid calculating dirname again later, + # as the path in venv_prefix is the more common case. + venv_prefix2 = executable_dir or dirname(executable) + venv_prefix = dirname(venv_prefix2) + try: + # Read pyvenv.cfg from one level above executable + pyvenvcfg = readlines(joinpath(venv_prefix, VENV_LANDMARK)) + except FileNotFoundError: + # Try the same directory as executable + pyvenvcfg = readlines(joinpath(venv_prefix2, VENV_LANDMARK)) + venv_prefix = venv_prefix2 + except FileNotFoundError: + venv_prefix = None + pyvenvcfg = [] + + for line in pyvenvcfg: + key, had_equ, value = line.partition('=') + if had_equ and key.strip().lower() == 'home': + executable_dir = real_executable_dir = value.strip() + base_executable = joinpath(executable_dir, basename(executable)) + break + else: + venv_prefix = None + + +# ****************************************************************************** +# CALCULATE base_executable, real_executable AND executable_dir +# ****************************************************************************** + +if not base_executable: + base_executable = executable or real_executable or '' + +if not real_executable: + real_executable = base_executable + +try: + real_executable = realpath(real_executable) +except OSError as ex: + # Only warn if the file actually exists and was unresolvable + # Otherwise users who specify a fake executable may get spurious warnings. + if isfile(real_executable): + warn(f'Failed to find real location of {base_executable}') + +if not executable_dir and os_name == 'darwin' and library: + # QUIRK: macOS checks adjacent to its library early + library_dir = dirname(library) + if any(isfile(joinpath(library_dir, p)) for p in STDLIB_LANDMARKS): + # Exceptions here should abort the whole process (to match + # previous behavior) + executable_dir = realpath(library_dir) + real_executable_dir = executable_dir + +# If we do not have the executable's directory, we can calculate it. +# This is the directory used to find prefix/exec_prefix if necessary. +if not executable_dir: + executable_dir = real_executable_dir = dirname(real_executable) + +# If we do not have the real executable's directory, we calculate it. +# This is the directory used to detect build layouts. +if not real_executable_dir: + real_executable_dir = dirname(real_executable) + +# ****************************************************************************** +# DETECT _pth FILE +# ****************************************************************************** + +# The contents of an optional ._pth file are used to totally override +# sys.path calcualation. Its presence also implies isolated mode and +# no-site (unless explicitly requested) +pth = None +pth_dir = None + +# Calling Py_SetPythonHome() or Py_SetPath() will override ._pth search, +# but environment variables and command-line options cannot. +if not py_setpath and not home_was_set: + # Check adjacent to the main DLL/dylib/so + if library: + try: + pth = readlines(library.rpartition('.')[0] + '._pth') + pth_dir = dirname(library) + except FileNotFoundError: + pass + + # Check adjacent to the original executable, even if we + # redirected to actually launch Python. This may allow a + # venv to override the base_executable's ._pth file, but + # it cannot override the library's one. + if not pth_dir: + try: + pth = readlines(executable.rpartition('.')[0] + '._pth') + pth_dir = dirname(executable) + except FileNotFoundError: + pass + + # If we found a ._pth file, disable environment and home + # detection now. Later, we will do the rest. + if pth_dir: + use_environment = 0 + home = pth_dir + pythonpath = [] + + +# ****************************************************************************** +# CHECK FOR BUILD DIRECTORY +# ****************************************************************************** + +build_prefix = None + +if not home_was_set and real_executable_dir and not py_setpath: + # Detect a build marker and use it to infer prefix, exec_prefix, + # stdlib_dir and the platstdlib_dir directories. + try: + platstdlib_dir = joinpath( + real_executable_dir, + readlines(joinpath(real_executable_dir, BUILDDIR_TXT))[0], + ) + build_prefix = joinpath(real_executable_dir, VPATH) + except FileNotFoundError: + if isfile(joinpath(real_executable_dir, BUILD_LANDMARK)): + build_prefix = joinpath(real_executable_dir, VPATH) + if os_name == 'nt': + # QUIRK: Windows builds need platstdlib_dir to be the executable + # dir. Normally the builddir marker handles this, but in this + # case we need to correct manually. + platstdlib_dir = real_executable_dir + + if build_prefix: + if os_name == 'nt': + # QUIRK: No searching for more landmarks on Windows + build_stdlib_prefix = build_prefix + else: + build_stdlib_prefix = search_up(build_prefix, *BUILDSTDLIB_LANDMARKS) + # Always use the build prefix for stdlib + if build_stdlib_prefix: + stdlib_dir = joinpath(build_stdlib_prefix, 'Lib') + else: + stdlib_dir = joinpath(build_prefix, 'Lib') + # Only use the build prefix for prefix if it hasn't already been set + if not prefix: + prefix = build_stdlib_prefix + # Do not warn, because 'prefix' never equals 'build_prefix' on POSIX + #elif not venv_prefix and prefix != build_prefix: + # warn('Detected development environment but prefix is already set') + if not exec_prefix: + exec_prefix = build_prefix + # Do not warn, because 'exec_prefix' never equals 'build_prefix' on POSIX + #elif not venv_prefix and exec_prefix != build_prefix: + # warn('Detected development environment but exec_prefix is already set') + config['_is_python_build'] = 1 + + +# ****************************************************************************** +# CALCULATE prefix AND exec_prefix +# ****************************************************************************** + +if py_setpath: + # As documented, calling Py_SetPath will force both prefix + # and exec_prefix to the empty string. + prefix = exec_prefix = '' + +else: + # Read prefix and exec_prefix from explicitly set home + if home: + # When multiple paths are listed with ':' or ';' delimiters, + # split into prefix:exec_prefix + prefix, had_delim, exec_prefix = home.partition(DELIM) + if not had_delim: + exec_prefix = prefix + + + # First try to detect prefix by looking alongside our runtime library, if known + if library and not prefix: + library_dir = dirname(library) + if ZIP_LANDMARK: + if os_name == 'nt': + # QUIRK: Windows does not search up for ZIP file + if isfile(joinpath(library_dir, ZIP_LANDMARK)): + prefix = library_dir + else: + prefix = search_up(library_dir, ZIP_LANDMARK) + if STDLIB_SUBDIR and STDLIB_LANDMARKS and not prefix: + if any(isfile(joinpath(library_dir, f)) for f in STDLIB_LANDMARKS): + prefix = library_dir + stdlib_dir = joinpath(prefix, STDLIB_SUBDIR) + + + # Detect prefix by looking for zip file + if ZIP_LANDMARK and executable_dir and not prefix: + if os_name == 'nt': + # QUIRK: Windows does not search up for ZIP file + if isfile(joinpath(executable_dir, ZIP_LANDMARK)): + prefix = executable_dir + else: + prefix = search_up(executable_dir, ZIP_LANDMARK) + if prefix: + stdlib_dir = joinpath(prefix, STDLIB_SUBDIR) + if not isdir(stdlib_dir): + stdlib_dir = None + + + # 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: + stdlib_dir = joinpath(prefix, STDLIB_SUBDIR) + + if PREFIX and not prefix: + prefix = PREFIX + if not any(isfile(joinpath(prefix, f)) for f in STDLIB_LANDMARKS): + warn('Could not find platform independent libraries ') + + if not prefix: + prefix = abspath('') + warn('Could not find platform independent libraries ') + + + # Detect exec_prefix by searching from executable for the platstdlib_dir + if PLATSTDLIB_LANDMARK and not exec_prefix: + if executable_dir: + exec_prefix = search_up(executable_dir, PLATSTDLIB_LANDMARK, test=isdir) + if not exec_prefix: + if EXEC_PREFIX: + exec_prefix = EXEC_PREFIX + if not isdir(joinpath(exec_prefix, PLATSTDLIB_LANDMARK)): + warn('Could not find platform dependent libraries ') + else: + warn('Could not find platform dependent libraries ') + + # Fallback: assume exec_prefix == prefix + if not exec_prefix: + exec_prefix = prefix + + + if not prefix or not exec_prefix: + 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: +# base_prefix = prefix +# base_exec_prefix = exec_prefix +# prefix = exec_prefix = venv_prefix + + +# ****************************************************************************** +# UPDATE pythonpath (sys.path) +# ****************************************************************************** + +if py_setpath: + # If Py_SetPath was called then it overrides any existing search path + config['module_search_paths'] = py_setpath.split(DELIM) + config['module_search_paths_set'] = 1 + +elif not pythonpath: + # If pythonpath was already set, we leave it alone. + # This won't matter in normal use, but if an embedded host is trying to + # recalculate paths while running then we do not want to change it. + pythonpath = [] + + # First add entries from the process environment + if use_environment and ENV_PYTHONPATH: + for p in ENV_PYTHONPATH.split(DELIM): + pythonpath.append(abspath(p)) + + # Then add the default zip file + if os_name == 'nt': + # QUIRK: Windows uses the library directory rather than the prefix + if library: + library_dir = dirname(library) + else: + library_dir = executable_dir + pythonpath.append(joinpath(library_dir, ZIP_LANDMARK)) + elif build_prefix or venv_prefix: + # QUIRK: POSIX uses the default prefix when in the build directory + # or a venv + pythonpath.append(joinpath(PREFIX, ZIP_LANDMARK)) + else: + pythonpath.append(joinpath(prefix, ZIP_LANDMARK)) + + if os_name == 'nt' and use_environment and winreg: + # QUIRK: Windows also lists paths in the registry. Paths are stored + # as the default value of each subkey of + # {HKCU,HKLM}\Software\Python\PythonCore\{winver}\PythonPath + # where winver is sys.winver (typically '3.x' or '3.x-32') + for hk in (winreg.HKEY_CURRENT_USER, winreg.HKEY_LOCAL_MACHINE): + try: + key = winreg.OpenKeyEx(hk, WINREG_KEY) + try: + i = 0 + while True: + try: + keyname = winreg.EnumKey(key, i) + subkey = winreg.OpenKeyEx(key, keyname) + if not subkey: + continue + try: + v = winreg.QueryValue(subkey) + finally: + winreg.CloseKey(subkey) + if isinstance(v, str): + pythonpath.append(v) + i += 1 + except OSError: + break + finally: + winreg.CloseKey(key) + except OSError: + pass + + # Then add any entries compiled into the PYTHONPATH macro. + if PYTHONPATH: + for p in PYTHONPATH.split(DELIM): + pythonpath.append(joinpath(prefix, p)) + + # Then add stdlib_dir and platstdlib_dir + if stdlib_dir: + pythonpath.append(stdlib_dir) + if platstdlib_dir: + if os_name == 'nt' and venv_prefix: + # QUIRK: Windows appends executable_dir instead of platstdlib_dir + # when in a venv + pythonpath.append(executable_dir) + else: + pythonpath.append(platstdlib_dir) + + config['module_search_paths'] = pythonpath + config['module_search_paths_set'] = 1 + + +# ****************************************************************************** +# POSIX prefix/exec_prefix QUIRKS +# ****************************************************************************** + +# QUIRK: Non-Windows replaces prefix/exec_prefix with defaults when running +# in build directory. This happens after pythonpath calculation. +if os_name != 'nt' and build_prefix: + prefix = config.get('prefix') or PREFIX + exec_prefix = config.get('exec_prefix') or EXEC_PREFIX or prefix + + +# ****************************************************************************** +# SET pythonpath FROM _PTH FILE +# ****************************************************************************** + +if pth: + config['isolated'] = 1 + config['use_environment'] = 0 + config['site_import'] = 0 + pythonpath = [] + for line in pth: + line = line.partition('#')[0].strip() + if not line: + pass + elif line == 'import site': + config['site_import'] = 1 + elif line.startswith('import '): + warn("unsupported 'import' line in ._pth file") + else: + pythonpath.append(joinpath(pth_dir, line)) + config['module_search_paths'] = pythonpath + config['module_search_paths_set'] = 1 + +# ****************************************************************************** +# UPDATE config FROM CALCULATED VALUES +# ****************************************************************************** + +config['program_name'] = program_name +config['home'] = home +config['executable'] = executable +config['base_executable'] = base_executable +config['prefix'] = prefix +config['exec_prefix'] = exec_prefix +config['base_prefix'] = base_prefix or prefix +config['base_exec_prefix'] = base_exec_prefix or exec_prefix + +config['platlibdir'] = platlibdir +config['stdlib_dir'] = stdlib_dir +config['platstdlib_dir'] = platstdlib_dir diff --git a/Modules/getpath_noop.c b/Modules/getpath_noop.c new file mode 100644 index 0000000000000..c10e41d07f27c --- /dev/null +++ b/Modules/getpath_noop.c @@ -0,0 +1,10 @@ +/* Implements the getpath API for compiling with no functionality */ + +#include "Python.h" +#include "pycore_pathconfig.h" + +PyStatus +_PyConfig_InitPathConfig(PyConfig *config, int compute_path_config) +{ + return PyStatus_Error("path configuration is unsupported"); +} diff --git a/Modules/main.c b/Modules/main.c index c537e6b678515..b9bcea393abe3 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -534,11 +534,16 @@ pymain_repl(PyConfig *config, int *exitcode) static void pymain_run_python(int *exitcode) { + PyObject *main_importer_path = NULL; PyInterpreterState *interp = _PyInterpreterState_GET(); /* pymain_run_stdin() modify the config */ PyConfig *config = (PyConfig*)_PyInterpreterState_GetConfig(interp); - PyObject *main_importer_path = NULL; + /* ensure path config is written into global variables */ + if (_PyStatus_EXCEPTION(_PyPathConfig_UpdateGlobal(config))) { + goto error; + } + if (config->run_filename != NULL) { /* If filename is a package (ex: directory or ZIP file) which contains __main__.py, main_importer_path is set to filename and will be diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index a89cff7295163..b1c2914fb0f1f 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -4444,6 +4444,33 @@ os__path_splitroot_impl(PyObject *module, path_t *path) #endif /* MS_WINDOWS */ +/*[clinic input] +os._path_normpath + + path: object + +Basic path normalization. +[clinic start generated code]*/ + +static PyObject * +os__path_normpath_impl(PyObject *module, PyObject *path) +/*[clinic end generated code: output=b94d696d828019da input=5e90c39e12549dc0]*/ +{ + if (!PyUnicode_Check(path)) { + PyErr_Format(PyExc_TypeError, "expected 'str', not '%.200s'", + Py_TYPE(path)->tp_name); + return NULL; + } + Py_ssize_t len; + wchar_t *buffer = PyUnicode_AsWideCharString(path, &len); + if (!buffer) { + return NULL; + } + PyObject *result = PyUnicode_FromWideChar(_Py_normpath(buffer, len), -1); + PyMem_Free(buffer); + return result; +} + /*[clinic input] os.mkdir @@ -14826,6 +14853,7 @@ static PyMethodDef posix_methods[] = { OS__GETFINALPATHNAME_METHODDEF OS__GETVOLUMEPATHNAME_METHODDEF OS__PATH_SPLITROOT_METHODDEF + OS__PATH_NORMPATH_METHODDEF OS_GETLOADAVG_METHODDEF OS_URANDOM_METHODDEF OS_SETRESUID_METHODDEF diff --git a/PC/config_minimal.c b/PC/config_minimal.c index adb1c44a7242e..928a4efd32e13 100644 --- a/PC/config_minimal.c +++ b/PC/config_minimal.c @@ -5,6 +5,10 @@ #include "Python.h" +/* Define extern variables omitted from minimal builds */ +void *PyWin_DLLhModule = NULL; + + extern PyObject* PyInit_faulthandler(void); extern PyObject* PyInit__tracemalloc(void); extern PyObject* PyInit_gc(void); diff --git a/PC/getpathp.c b/PC/getpathp.c deleted file mode 100644 index a27348024d252..0000000000000 --- a/PC/getpathp.c +++ /dev/null @@ -1,1174 +0,0 @@ - -/* Return the initial module search path. */ -/* Used by DOS, Windows 3.1, Windows 95/98, Windows NT. */ - -/* ---------------------------------------------------------------- - PATH RULES FOR WINDOWS: - This describes how sys.path is formed on Windows. It describes the - functionality, not the implementation (ie, the order in which these - are actually fetched is different). The presence of a python._pth or - pythonXY._pth file alongside the program overrides these rules - see - below. - - * Python always adds an empty entry at the start, which corresponds - to the current directory. - - * If the PYTHONPATH env. var. exists, its entries are added next. - - * We look in the registry for "application paths" - that is, sub-keys - under the main PythonPath registry key. These are added next (the - order of sub-key processing is undefined). - HKEY_CURRENT_USER is searched and added first. - HKEY_LOCAL_MACHINE is searched and added next. - (Note that all known installers only use HKLM, so HKCU is typically - empty) - - * We attempt to locate the "Python Home" - if the PYTHONHOME env var - is set, we believe it. Otherwise, we use the path of our host .EXE's - to try and locate one of our "landmarks" and deduce our home. - - If we DO have a Python Home: The relevant sub-directories (Lib, - DLLs, etc) are based on the Python Home - - If we DO NOT have a Python Home, the core Python Path is - loaded from the registry. (This is the main PythonPath key, - and both HKLM and HKCU are combined to form the path) - - * Iff - we can not locate the Python Home, have not had a PYTHONPATH - specified, and can't locate any Registry entries (ie, we have _nothing_ - we can assume is a good path), a default path with relative entries is - used (eg. .\Lib;.\DLLs, etc) - - - If a '._pth' file exists adjacent to the executable with the same base name - (e.g. python._pth adjacent to python.exe) or adjacent to the shared library - (e.g. python36._pth adjacent to python36.dll), it is used in preference to - the above process. The shared library file takes precedence over the - executable. The path file must contain a list of paths to add to sys.path, - one per line. Each path is relative to the directory containing the file. - Blank lines and comments beginning with '#' are permitted. - - In the presence of this ._pth file, no other paths are added to the search - path, the registry finder is not enabled, site.py is not imported and - isolated mode is enabled. The site package can be enabled by including a - line reading "import site"; no other imports are recognized. Any invalid - entry (other than directories that do not exist) will result in immediate - termination of the program. - - - The end result of all this is: - * When running python.exe, or any other .exe in the main Python directory - (either an installed version, or directly from the PCbuild directory), - the core path is deduced, and the core paths in the registry are - ignored. Other "application paths" in the registry are always read. - - * When Python is hosted in another exe (different directory, embedded via - COM, etc), the Python Home will not be deduced, so the core path from - the registry is used. Other "application paths" in the registry are - always read. - - * If Python can't find its home and there is no registry (eg, frozen - exe, some very strange installation setup) you get a path with - some default, but relative, paths. - - * An embedding application can use Py_SetPath() to override all of - these automatic path computations. - - * An install of Python can fully specify the contents of sys.path using - either a 'EXENAME._pth' or 'DLLNAME._pth' file, optionally including - "import site" to enable the site module. - - ---------------------------------------------------------------- */ - - -#include "Python.h" -#include "pycore_fileutils.h" // _Py_add_relfile() -#include "pycore_initconfig.h" // PyStatus -#include "pycore_pathconfig.h" // _PyPathConfig -#include "osdefs.h" // SEP, ALTSEP -#include - -#ifndef MS_WINDOWS -#error getpathp.c should only be built on Windows -#endif - -#include -#include - -#ifdef HAVE_SYS_TYPES_H -#include -#endif /* HAVE_SYS_TYPES_H */ - -#ifdef HAVE_SYS_STAT_H -#include -#endif /* HAVE_SYS_STAT_H */ - -#include - -/* Search in some common locations for the associated Python libraries. - * - * Py_GetPath() tries to return a sensible Python module search path. - * - * The approach is an adaptation for Windows of the strategy used in - * ../Modules/getpath.c; it uses the Windows Registry as one of its - * information sources. - * - * Py_SetPath() can be used to override this mechanism. Call Py_SetPath - * with a semicolon separated path prior to calling Py_Initialize. - */ - -#define STDLIB_SUBDIR L"lib" - -#define INIT_ERR_BUFFER_OVERFLOW() _PyStatus_ERR("buffer overflow") - - -typedef struct { - const wchar_t *path_env; /* PATH environment variable */ - const wchar_t *home; /* PYTHONHOME environment variable */ - - /* Registry key "Software\Python\PythonCore\X.Y\PythonPath" - where X.Y is the Python version (major.minor) */ - wchar_t *machine_path; /* from HKEY_LOCAL_MACHINE */ - wchar_t *user_path; /* from HKEY_CURRENT_USER */ - - const wchar_t *pythonpath_env; -} PyCalculatePath; - - -/* determine if "ch" is a separator character */ -static int -is_sep(wchar_t ch) -{ -#ifdef ALTSEP - return ch == SEP || ch == ALTSEP; -#else - return ch == SEP; -#endif -} - - -/* assumes 'dir' null terminated in bounds. Never writes - beyond existing terminator. */ -static void -reduce(wchar_t *dir) -{ - size_t i = wcsnlen_s(dir, MAXPATHLEN+1); - if (i >= MAXPATHLEN+1) { - Py_FatalError("buffer overflow in getpathp.c's reduce()"); - } - - while (i > 0 && !is_sep(dir[i])) - --i; - dir[i] = '\0'; -} - - -static int -change_ext(wchar_t *dest, const wchar_t *src, const wchar_t *ext) -{ - if (src && src != dest) { - size_t src_len = wcsnlen_s(src, MAXPATHLEN+1); - size_t i = src_len; - if (i >= MAXPATHLEN+1) { - Py_FatalError("buffer overflow in getpathp.c's reduce()"); - } - - while (i > 0 && src[i] != '.' && !is_sep(src[i])) - --i; - - if (i == 0) { - dest[0] = '\0'; - return -1; - } - - if (is_sep(src[i])) { - i = src_len; - } - - if (wcsncpy_s(dest, MAXPATHLEN+1, src, i)) { - dest[0] = '\0'; - return -1; - } - } else { - wchar_t *s = wcsrchr(dest, L'.'); - if (s) { - s[0] = '\0'; - } - } - - if (wcscat_s(dest, MAXPATHLEN+1, ext)) { - dest[0] = '\0'; - return -1; - } - - return 0; -} - - -static int -exists(const wchar_t *filename) -{ - return GetFileAttributesW(filename) != 0xFFFFFFFF; -} - - -/* Is module -- check for .pyc too. - Assumes 'filename' MAXPATHLEN+1 bytes long - - may extend 'filename' by one character. */ -static int -ismodule(wchar_t *filename) -{ - size_t n; - - if (exists(filename)) { - return 1; - } - - /* Check for the compiled version of prefix. */ - n = wcsnlen_s(filename, MAXPATHLEN+1); - if (n < MAXPATHLEN) { - int exist = 0; - filename[n] = L'c'; - filename[n + 1] = L'\0'; - exist = exists(filename); - // Drop the 'c' we just added. - filename[n] = L'\0'; - return exist; - } - return 0; -} - - -/* Add a path component, by appending stuff to buffer. - buffer must have at least MAXPATHLEN + 1 bytes allocated, and contain a - NUL-terminated string with no more than MAXPATHLEN characters (not counting - the trailing NUL). It's a fatal error if it contains a string longer than - that (callers must be careful!). If these requirements are met, it's - guaranteed that buffer will still be a NUL-terminated string with no more - than MAXPATHLEN characters at exit. If stuff is too long, only as much of - stuff as fits will be appended. -*/ - -static void -join(wchar_t *buffer, const wchar_t *stuff) -{ - if (_Py_add_relfile(buffer, stuff, MAXPATHLEN+1) < 0) { - Py_FatalError("buffer overflow in getpathp.c's join()"); - } -} - -/* Call PathCchCanonicalizeEx(path): remove navigation elements such as "." - and ".." to produce a direct, well-formed path. */ -static PyStatus -canonicalize(wchar_t *buffer, const wchar_t *path) -{ - if (buffer == NULL) { - return _PyStatus_NO_MEMORY(); - } - - const wchar_t *pathTail; - if (FAILED(PathCchSkipRoot(path, &pathTail)) || path == pathTail) { - wchar_t buff[MAXPATHLEN + 1]; - if (!GetCurrentDirectoryW(MAXPATHLEN, buff)) { - return _PyStatus_ERR("unable to find current working directory"); - } - if (FAILED(PathCchCombineEx(buff, MAXPATHLEN + 1, buff, path, PATHCCH_ALLOW_LONG_PATHS))) { - return INIT_ERR_BUFFER_OVERFLOW(); - } - if (FAILED(PathCchCanonicalizeEx(buffer, MAXPATHLEN + 1, buff, PATHCCH_ALLOW_LONG_PATHS))) { - return INIT_ERR_BUFFER_OVERFLOW(); - } - return _PyStatus_OK(); - } - - if (FAILED(PathCchCanonicalizeEx(buffer, MAXPATHLEN + 1, path, PATHCCH_ALLOW_LONG_PATHS))) { - return INIT_ERR_BUFFER_OVERFLOW(); - } - return _PyStatus_OK(); -} - -static int -is_stdlibdir(wchar_t *stdlibdir) -{ - wchar_t *filename = stdlibdir; -#ifndef LANDMARK -# define LANDMARK L"os.py" -#endif - /* join() ensures 'landmark' can not overflow prefix if too long. */ - join(filename, LANDMARK); - return ismodule(filename); -} - -/* assumes argv0_path is MAXPATHLEN+1 bytes long, already \0 term'd. - assumption provided by only caller, calculate_path() */ -static int -search_for_prefix(wchar_t *prefix, const wchar_t *argv0_path) -{ - /* Search from argv0_path, until LANDMARK is found. - We guarantee 'prefix' is null terminated in bounds. */ - wcscpy_s(prefix, MAXPATHLEN+1, argv0_path); - if (!prefix[0]) { - return 0; - } - wchar_t stdlibdir[MAXPATHLEN+1]; - wcscpy_s(stdlibdir, Py_ARRAY_LENGTH(stdlibdir), prefix); - /* We initialize with the longest possible path, in case it doesn't fit. - This also gives us an initial SEP at stdlibdir[wcslen(prefix)]. */ - join(stdlibdir, STDLIB_SUBDIR); - do { - assert(stdlibdir[wcslen(prefix)] == SEP); - /* Due to reduce() and our initial value, this result - is guaranteed to fit. */ - wcscpy(&stdlibdir[wcslen(prefix) + 1], STDLIB_SUBDIR); - if (is_stdlibdir(stdlibdir)) { - return 1; - } - reduce(prefix); - } while (prefix[0]); - return 0; -} - - -static int -get_dllpath(wchar_t *dllpath) -{ -#ifdef Py_ENABLE_SHARED - extern HANDLE PyWin_DLLhModule; - if (PyWin_DLLhModule && GetModuleFileNameW(PyWin_DLLhModule, dllpath, MAXPATHLEN)) { - return 0; - } -#endif - return -1; -} - - -#ifdef Py_ENABLE_SHARED - -/* a string loaded from the DLL at startup.*/ -extern const char *PyWin_DLLVersionString; - -/* Load a PYTHONPATH value from the registry. - Load from either HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER. - - Works in both Unicode and 8bit environments. Only uses the - Ex family of functions so it also works with Windows CE. - - Returns NULL, or a pointer that should be freed. - - XXX - this code is pretty strange, as it used to also - work on Win16, where the buffer sizes were not available - in advance. It could be simplied now Win16/Win32s is dead! -*/ -static wchar_t * -getpythonregpath(HKEY keyBase, int skipcore) -{ - HKEY newKey = 0; - DWORD dataSize = 0; - DWORD numKeys = 0; - LONG rc; - wchar_t *retval = NULL; - WCHAR *dataBuf = NULL; - static const WCHAR keyPrefix[] = L"Software\\Python\\PythonCore\\"; - static const WCHAR keySuffix[] = L"\\PythonPath"; - size_t versionLen, keyBufLen; - DWORD index; - WCHAR *keyBuf = NULL; - WCHAR *keyBufPtr; - WCHAR **ppPaths = NULL; - - /* Tried to use sysget("winver") but here is too early :-( */ - versionLen = strlen(PyWin_DLLVersionString); - /* Space for all the chars, plus one \0 */ - keyBufLen = sizeof(keyPrefix) + - sizeof(WCHAR)*(versionLen-1) + - sizeof(keySuffix); - keyBuf = keyBufPtr = PyMem_RawMalloc(keyBufLen); - if (keyBuf==NULL) { - goto done; - } - - memcpy_s(keyBufPtr, keyBufLen, keyPrefix, sizeof(keyPrefix)-sizeof(WCHAR)); - keyBufPtr += Py_ARRAY_LENGTH(keyPrefix) - 1; - mbstowcs(keyBufPtr, PyWin_DLLVersionString, versionLen); - keyBufPtr += versionLen; - /* NULL comes with this one! */ - memcpy(keyBufPtr, keySuffix, sizeof(keySuffix)); - /* Open the root Python key */ - rc=RegOpenKeyExW(keyBase, - keyBuf, /* subkey */ - 0, /* reserved */ - KEY_READ, - &newKey); - if (rc!=ERROR_SUCCESS) { - goto done; - } - /* Find out how big our core buffer is, and how many subkeys we have */ - rc = RegQueryInfoKeyW(newKey, NULL, NULL, NULL, &numKeys, NULL, NULL, - NULL, NULL, &dataSize, NULL, NULL); - if (rc!=ERROR_SUCCESS) { - goto done; - } - if (skipcore) { - dataSize = 0; /* Only count core ones if we want them! */ - } - /* Allocate a temp array of char buffers, so we only need to loop - reading the registry once - */ - ppPaths = PyMem_RawCalloc(numKeys, sizeof(WCHAR *)); - if (ppPaths==NULL) { - goto done; - } - /* Loop over all subkeys, allocating a temp sub-buffer. */ - for(index=0;index 0) { - *(szCur++) = L';'; - dataSize--; - } - if (ppPaths[index]) { - Py_ssize_t len = wcslen(ppPaths[index]); - wcsncpy(szCur, ppPaths[index], len); - szCur += len; - assert(dataSize > (DWORD)len); - dataSize -= (DWORD)len; - } - } - if (skipcore) { - *szCur = '\0'; - } - else { - /* If we have no values, we don't need a ';' */ - if (numKeys) { - *(szCur++) = L';'; - dataSize--; - } - /* Now append the core path entries - - this will include the NULL - */ - rc = RegQueryValueExW(newKey, NULL, 0, NULL, - (LPBYTE)szCur, &dataSize); - if (rc != ERROR_SUCCESS) { - PyMem_RawFree(dataBuf); - goto done; - } - } - /* And set the result - caller must free */ - retval = dataBuf; - } -done: - /* Loop freeing my temp buffers */ - if (ppPaths) { - for(index=0; indexbase_executable == NULL) { - pathconfig->base_executable = PyMem_RawMalloc( - sizeof(wchar_t) * (MAXPATHLEN + 1)); - if (pathconfig->base_executable == NULL) { - return _PyStatus_NO_MEMORY(); - } - - status = canonicalize(pathconfig->base_executable, - program_full_path); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - } - - wcscpy_s(program_full_path, MAXPATHLEN+1, pyvenv_launcher); - /* bpo-35873: Clear the environment variable to avoid it being - * inherited by child processes. */ - _wputenv_s(L"__PYVENV_LAUNCHER__", L""); - } - - if (pathconfig->program_full_path == NULL) { - pathconfig->program_full_path = PyMem_RawMalloc( - sizeof(wchar_t) * (MAXPATHLEN + 1)); - if (pathconfig->program_full_path == NULL) { - return _PyStatus_NO_MEMORY(); - } - - status = canonicalize(pathconfig->program_full_path, - program_full_path); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - } - return _PyStatus_OK(); -} - - -static PyStatus -read_pth_file(_PyPathConfig *pathconfig, wchar_t *prefix, const wchar_t *path, - int *found) -{ - PyStatus status; - wchar_t *buf = NULL; - wchar_t *wline = NULL; - FILE *sp_file; - - sp_file = _Py_wfopen(path, L"r"); - if (sp_file == NULL) { - return _PyStatus_OK(); - } - - wcscpy_s(prefix, MAXPATHLEN+1, path); - reduce(prefix); - pathconfig->isolated = 1; - pathconfig->site_import = 0; - - size_t bufsiz = MAXPATHLEN; - size_t prefixlen = wcslen(prefix); - - buf = (wchar_t*)PyMem_RawMalloc(bufsiz * sizeof(wchar_t)); - if (buf == NULL) { - status = _PyStatus_NO_MEMORY(); - goto done; - } - buf[0] = '\0'; - - while (!feof(sp_file)) { - char line[MAXPATHLEN + 1]; - char *p = fgets(line, Py_ARRAY_LENGTH(line), sp_file); - if (!p) { - break; - } - if (*p == '\0' || *p == '\r' || *p == '\n' || *p == '#') { - continue; - } - while (*++p) { - if (*p == '\r' || *p == '\n') { - *p = '\0'; - break; - } - } - - if (strcmp(line, "import site") == 0) { - pathconfig->site_import = 1; - continue; - } - else if (strncmp(line, "import ", 7) == 0) { - status = _PyStatus_ERR("only 'import site' is supported " - "in ._pth file"); - goto done; - } - - DWORD wn = MultiByteToWideChar(CP_UTF8, 0, line, -1, NULL, 0); - wchar_t *wline = (wchar_t*)PyMem_RawMalloc((wn + 1) * sizeof(wchar_t)); - if (wline == NULL) { - status = _PyStatus_NO_MEMORY(); - goto done; - } - wn = MultiByteToWideChar(CP_UTF8, 0, line, -1, wline, wn + 1); - wline[wn] = '\0'; - - size_t usedsiz = wcslen(buf); - while (usedsiz + wn + prefixlen + 4 > bufsiz) { - bufsiz += MAXPATHLEN; - wchar_t *tmp = (wchar_t*)PyMem_RawRealloc(buf, (bufsiz + 1) * - sizeof(wchar_t)); - if (tmp == NULL) { - status = _PyStatus_NO_MEMORY(); - goto done; - } - buf = tmp; - } - - if (usedsiz) { - wcscat_s(buf, bufsiz, L";"); - usedsiz += 1; - } - - errno_t result; - _Py_BEGIN_SUPPRESS_IPH - result = wcscat_s(buf, bufsiz, prefix); - _Py_END_SUPPRESS_IPH - - if (result == EINVAL) { - status = _PyStatus_ERR("invalid argument during ._pth processing"); - goto done; - } else if (result == ERANGE) { - status = _PyStatus_ERR("buffer overflow during ._pth processing"); - goto done; - } - - wchar_t *b = &buf[usedsiz]; - join(b, wline); - - PyMem_RawFree(wline); - wline = NULL; - } - - if (pathconfig->module_search_path == NULL) { - pathconfig->module_search_path = _PyMem_RawWcsdup(buf); - if (pathconfig->module_search_path == NULL) { - status = _PyStatus_NO_MEMORY(); - goto done; - } - } - - *found = 1; - status = _PyStatus_OK(); - goto done; - -done: - PyMem_RawFree(buf); - PyMem_RawFree(wline); - fclose(sp_file); - return status; -} - - -static int -get_pth_filename(PyCalculatePath *calculate, wchar_t *filename, - const _PyPathConfig *pathconfig) -{ - if (!get_dllpath(filename) && - !change_ext(filename, filename, L"._pth") && - exists(filename)) - { - return 1; - } - if (pathconfig->program_full_path[0] && - !change_ext(filename, pathconfig->program_full_path, L"._pth") && - exists(filename)) - { - return 1; - } - return 0; -} - - -static PyStatus -calculate_pth_file(PyCalculatePath *calculate, _PyPathConfig *pathconfig, - wchar_t *prefix, int *found) -{ - wchar_t filename[MAXPATHLEN+1]; - - if (!get_pth_filename(calculate, filename, pathconfig)) { - return _PyStatus_OK(); - } - - return read_pth_file(pathconfig, prefix, filename, found); -} - - -/* Search for an environment configuration file, first in the - executable's directory and then in the parent directory. - If found, open it for use when searching for prefixes. -*/ -static PyStatus -calculate_pyvenv_file(PyCalculatePath *calculate, - wchar_t *argv0_path, size_t argv0_path_len) -{ - wchar_t filename[MAXPATHLEN+1]; - const wchar_t *env_cfg = L"pyvenv.cfg"; - - /* Filename: / "pyvenv.cfg" */ - wcscpy_s(filename, MAXPATHLEN+1, argv0_path); - join(filename, env_cfg); - - FILE *env_file = _Py_wfopen(filename, L"r"); - if (env_file == NULL) { - errno = 0; - - /* Filename: / "pyvenv.cfg" */ - reduce(filename); - reduce(filename); - join(filename, env_cfg); - - env_file = _Py_wfopen(filename, L"r"); - if (env_file == NULL) { - errno = 0; - return _PyStatus_OK(); - } - } - - /* Look for a 'home' variable and set argv0_path to it, if found */ - wchar_t *home = NULL; - PyStatus status = _Py_FindEnvConfigValue(env_file, L"home", &home); - if (_PyStatus_EXCEPTION(status)) { - fclose(env_file); - return status; - } - if (home) { - wcscpy_s(argv0_path, argv0_path_len, home); - PyMem_RawFree(home); - } - fclose(env_file); - return _PyStatus_OK(); -} - - -static void -calculate_home_prefix(PyCalculatePath *calculate, - const wchar_t *argv0_path, - const wchar_t *zip_path, - wchar_t *prefix) -{ - if (calculate->home == NULL || *calculate->home == '\0') { - if (zip_path[0] && exists(zip_path)) { - wcscpy_s(prefix, MAXPATHLEN+1, zip_path); - reduce(prefix); - calculate->home = prefix; - } - else if (search_for_prefix(prefix, argv0_path)) { - calculate->home = prefix; - } - else { - calculate->home = NULL; - } - } - else { - wcscpy_s(prefix, MAXPATHLEN+1, calculate->home); - } -} - - -static PyStatus -calculate_module_search_path(PyCalculatePath *calculate, - _PyPathConfig *pathconfig, - const wchar_t *argv0_path, - wchar_t *prefix, - const wchar_t *zip_path) -{ - int skiphome = calculate->home==NULL ? 0 : 1; -#ifdef Py_ENABLE_SHARED - if (!Py_IgnoreEnvironmentFlag) { - calculate->machine_path = getpythonregpath(HKEY_LOCAL_MACHINE, - skiphome); - calculate->user_path = getpythonregpath(HKEY_CURRENT_USER, skiphome); - } -#endif - /* We only use the default relative PYTHONPATH if we haven't - anything better to use! */ - int skipdefault = (calculate->pythonpath_env != NULL || - calculate->home != NULL || - calculate->machine_path != NULL || - calculate->user_path != NULL); - - /* We need to construct a path from the following parts. - (1) the PYTHONPATH environment variable, if set; - (2) for Win32, the zip archive file path; - (3) for Win32, the machine_path and user_path, if set; - (4) the PYTHONPATH config macro, with the leading "." - of each component replaced with home, if set; - (5) the directory containing the executable (argv0_path). - The length calculation calculates #4 first. - Extra rules: - - If PYTHONHOME is set (in any way) item (3) is ignored. - - If registry values are used, (4) and (5) are ignored. - */ - - /* Calculate size of return buffer */ - size_t bufsz = 0; - if (calculate->home != NULL) { - const wchar_t *p; - bufsz = 1; - for (p = PYTHONPATH; *p; p++) { - if (*p == DELIM) { - bufsz++; /* number of DELIM plus one */ - } - } - bufsz *= wcslen(calculate->home); - } - bufsz += wcslen(PYTHONPATH) + 1; - bufsz += wcslen(argv0_path) + 1; - if (calculate->user_path) { - bufsz += wcslen(calculate->user_path) + 1; - } - if (calculate->machine_path) { - bufsz += wcslen(calculate->machine_path) + 1; - } - bufsz += wcslen(zip_path) + 1; - if (calculate->pythonpath_env != NULL) { - bufsz += wcslen(calculate->pythonpath_env) + 1; - } - - wchar_t *buf, *start_buf; - buf = PyMem_RawMalloc(bufsz * sizeof(wchar_t)); - if (buf == NULL) { - return _PyStatus_NO_MEMORY(); - } - start_buf = buf; - - if (calculate->pythonpath_env) { - if (wcscpy_s(buf, bufsz - (buf - start_buf), - calculate->pythonpath_env)) { - return INIT_ERR_BUFFER_OVERFLOW(); - } - buf = wcschr(buf, L'\0'); - *buf++ = DELIM; - } - if (zip_path[0]) { - if (wcscpy_s(buf, bufsz - (buf - start_buf), zip_path)) { - return INIT_ERR_BUFFER_OVERFLOW(); - } - buf = wcschr(buf, L'\0'); - *buf++ = DELIM; - } - if (calculate->user_path) { - if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->user_path)) { - return INIT_ERR_BUFFER_OVERFLOW(); - } - buf = wcschr(buf, L'\0'); - *buf++ = DELIM; - } - if (calculate->machine_path) { - if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->machine_path)) { - return INIT_ERR_BUFFER_OVERFLOW(); - } - buf = wcschr(buf, L'\0'); - *buf++ = DELIM; - } - if (calculate->home == NULL) { - if (!skipdefault) { - if (wcscpy_s(buf, bufsz - (buf - start_buf), PYTHONPATH)) { - return INIT_ERR_BUFFER_OVERFLOW(); - } - buf = wcschr(buf, L'\0'); - *buf++ = DELIM; - } - } else { - const wchar_t *p = PYTHONPATH; - const wchar_t *q; - size_t n; - for (;;) { - q = wcschr(p, DELIM); - if (q == NULL) { - n = wcslen(p); - } - else { - n = q-p; - } - if (p[0] == '.' && is_sep(p[1])) { - if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->home)) { - return INIT_ERR_BUFFER_OVERFLOW(); - } - buf = wcschr(buf, L'\0'); - p++; - n--; - } - wcsncpy(buf, p, n); - buf += n; - *buf++ = DELIM; - if (q == NULL) { - break; - } - p = q+1; - } - } - if (argv0_path) { - wcscpy(buf, argv0_path); - buf = wcschr(buf, L'\0'); - *buf++ = DELIM; - } - *(buf - 1) = L'\0'; - - /* Now to pull one last hack/trick. If sys.prefix is - empty, then try and find it somewhere on the paths - we calculated. We scan backwards, as our general policy - is that Python core directories are at the *end* of - sys.path. We assume that our "lib" directory is - on the path, and that our 'prefix' directory is - the parent of that. - */ - if (prefix[0] == L'\0') { - PyStatus status; - wchar_t lookBuf[MAXPATHLEN+1]; - const wchar_t *look = buf - 1; /* 'buf' is at the end of the buffer */ - while (1) { - Py_ssize_t nchars; - const wchar_t *lookEnd = look; - /* 'look' will end up one character before the - start of the path in question - even if this - is one character before the start of the buffer - */ - while (look >= start_buf && *look != DELIM) - look--; - nchars = lookEnd-look; - wcsncpy(lookBuf, look+1, nchars); - lookBuf[nchars] = L'\0'; - status = canonicalize(lookBuf, lookBuf); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - /* Up one level to the parent */ - reduce(lookBuf); - if (search_for_prefix(prefix, lookBuf)) { - break; - } - /* If we are out of paths to search - give up */ - if (look < start_buf) { - break; - } - look--; - } - } - - pathconfig->module_search_path = start_buf; - return _PyStatus_OK(); -} - - -static PyStatus -calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig) -{ - PyStatus status; - - status = get_program_full_path(pathconfig); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - - /* program_full_path guaranteed \0 terminated in MAXPATH+1 bytes. */ - wchar_t argv0_path[MAXPATHLEN+1]; - memset(argv0_path, 0, sizeof(argv0_path)); - - wcscpy_s(argv0_path, MAXPATHLEN+1, pathconfig->program_full_path); - reduce(argv0_path); - - wchar_t prefix[MAXPATHLEN+1]; - memset(prefix, 0, sizeof(prefix)); - - /* Search for a sys.path file */ - int pth_found = 0; - status = calculate_pth_file(calculate, pathconfig, prefix, &pth_found); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - if (pth_found) { - goto done; - } - - status = calculate_pyvenv_file(calculate, - argv0_path, Py_ARRAY_LENGTH(argv0_path)); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - - /* Calculate zip archive path from DLL or exe path */ - wchar_t zip_path[MAXPATHLEN+1]; - memset(zip_path, 0, sizeof(zip_path)); - - if (get_dllpath(zip_path) || change_ext(zip_path, zip_path, L".zip")) - { - if (change_ext(zip_path, pathconfig->program_full_path, L".zip")) { - zip_path[0] = L'\0'; - } - } - - calculate_home_prefix(calculate, argv0_path, zip_path, prefix); - - if (pathconfig->module_search_path == NULL) { - status = calculate_module_search_path(calculate, pathconfig, - argv0_path, prefix, zip_path); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - } - -done: - if (pathconfig->stdlib_dir == NULL) { - pathconfig->stdlib_dir = _Py_join_relfile(prefix, STDLIB_SUBDIR); - if (pathconfig->stdlib_dir == NULL) { - return _PyStatus_NO_MEMORY(); - } - } - if (pathconfig->prefix == NULL) { - pathconfig->prefix = _PyMem_RawWcsdup(prefix); - if (pathconfig->prefix == NULL) { - return _PyStatus_NO_MEMORY(); - } - } - if (pathconfig->exec_prefix == NULL) { - pathconfig->exec_prefix = _PyMem_RawWcsdup(prefix); - if (pathconfig->exec_prefix == NULL) { - return _PyStatus_NO_MEMORY(); - } - } - - return _PyStatus_OK(); -} - - -static PyStatus -calculate_init(PyCalculatePath *calculate, _PyPathConfig *pathconfig, - const PyConfig *config) -{ - calculate->home = pathconfig->home; - calculate->path_env = _wgetenv(L"PATH"); - - calculate->pythonpath_env = config->pythonpath_env; - - return _PyStatus_OK(); -} - - -static void -calculate_free(PyCalculatePath *calculate) -{ - PyMem_RawFree(calculate->machine_path); - PyMem_RawFree(calculate->user_path); -} - - -/* Calculate the Python path configuration. - - Inputs: - - - PyConfig.pythonpath_env: PYTHONPATH environment variable - - _PyPathConfig.home: Py_SetPythonHome() or PYTHONHOME environment variable - - PATH environment variable - - __PYVENV_LAUNCHER__ environment variable - - GetModuleFileNameW(NULL): fully qualified path of the executable file of - the current process - - ._pth configuration file - - pyvenv.cfg configuration file - - Registry key "Software\Python\PythonCore\X.Y\PythonPath" - of HKEY_CURRENT_USER and HKEY_LOCAL_MACHINE where X.Y is the Python - version. - - Outputs, 'pathconfig' fields: - - - base_executable - - program_full_path - - module_search_path - - prefix - - exec_prefix - - isolated - - site_import - - If a field is already set (non NULL), it is left unchanged. */ -PyStatus -_PyPathConfig_Calculate(_PyPathConfig *pathconfig, const PyConfig *config) -{ - PyStatus status; - PyCalculatePath calculate; - memset(&calculate, 0, sizeof(calculate)); - - status = calculate_init(&calculate, pathconfig, config); - if (_PyStatus_EXCEPTION(status)) { - goto done; - } - - status = calculate_path(&calculate, pathconfig); - -done: - calculate_free(&calculate); - return status; -} - - -/* Load python3.dll before loading any extension module that might refer - to it. That way, we can be sure that always the python3.dll corresponding - to this python DLL is loaded, not a python3.dll that might be on the path - by chance. - Return whether the DLL was found. -*/ -static int python3_checked = 0; -static HANDLE hPython3; -int -_Py_CheckPython3(void) -{ - wchar_t py3path[MAXPATHLEN+1]; - if (python3_checked) { - return hPython3 != NULL; - } - python3_checked = 1; - - /* If there is a python3.dll next to the python3y.dll, - use that DLL */ - if (!get_dllpath(py3path)) { - reduce(py3path); - join(py3path, PY3_DLLNAME); - hPython3 = LoadLibraryExW(py3path, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); - if (hPython3 != NULL) { - return 1; - } - } - - /* If we can locate python3.dll in our application dir, - use that DLL */ - hPython3 = LoadLibraryExW(PY3_DLLNAME, NULL, LOAD_LIBRARY_SEARCH_APPLICATION_DIR); - if (hPython3 != NULL) { - return 1; - } - - /* For back-compat, also search {sys.prefix}\DLLs, though - that has not been a normal install layout for a while */ - wcscpy(py3path, Py_GetPrefix()); - if (py3path[0]) { - join(py3path, L"DLLs\\" PY3_DLLNAME); - hPython3 = LoadLibraryExW(py3path, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); - } - return hPython3 != NULL; -} diff --git a/PC/pyconfig.h b/PC/pyconfig.h index 5d8d9f3618454..e0d875adf2e4a 100644 --- a/PC/pyconfig.h +++ b/PC/pyconfig.h @@ -66,9 +66,6 @@ WIN32 is still required for the locale module. #define MS_WIN32 /* only support win32 and greater. */ #define MS_WINDOWS -#ifndef PYTHONPATH -# define PYTHONPATH L".\\DLLs;.\\lib" -#endif #define NT_THREADS #define WITH_THREAD #ifndef NETSCAPE_PI @@ -671,6 +668,4 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ /* Define if libssl has X509_VERIFY_PARAM_set1_host and related function */ #define HAVE_X509_VERIFY_PARAM_SET1_HOST 1 -#define PLATLIBDIR "lib" - #endif /* !Py_CONFIG_H */ diff --git a/PCbuild/_freeze_module.vcxproj b/PCbuild/_freeze_module.vcxproj index 54fef9ca629b1..7b2df4b8afcc2 100644 --- a/PCbuild/_freeze_module.vcxproj +++ b/PCbuild/_freeze_module.vcxproj @@ -104,6 +104,7 @@ + @@ -168,7 +169,6 @@ - @@ -374,9 +374,29 @@ + + + + getpath + $(IntDir)getpath.g.h + $(PySourcePath)Modules\getpath.h + + + + + + + + + + + diff --git a/PCbuild/_freeze_module.vcxproj.filters b/PCbuild/_freeze_module.vcxproj.filters index 5894909e0fbe1..1c8f1b0dcf449 100644 --- a/PCbuild/_freeze_module.vcxproj.filters +++ b/PCbuild/_freeze_module.vcxproj.filters @@ -13,6 +13,395 @@ Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Python Files + @@ -78,4 +467,4 @@ - + \ No newline at end of file diff --git a/PCbuild/python.vcxproj b/PCbuild/python.vcxproj index b58945a4d19b6..0b4329dd07636 100644 --- a/PCbuild/python.vcxproj +++ b/PCbuild/python.vcxproj @@ -147,4 +147,11 @@ $(_PGOPath) + + + <_Content>$(OutDir) + <_ExistingContent Condition="Exists('$(OutDir)pybuilddir.txt')">$([System.IO.File]::ReadAllText('$(OutDir)pybuilddir.txt')) + + + diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 9d96f4bd5361b..b446e0995565e 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -109,6 +109,19 @@ version.lib;ws2_32.lib;pathcch.lib;bcrypt.lib;%(AdditionalDependencies) + + + + PREFIX=NULL; + EXEC_PREFIX=NULL; + VERSION=NULL; + VPATH="..\\.."; + PYDEBUGEXT="$(PyDebugExt)"; + PLATLIBDIR="DLLs"; + %(PreprocessorDefinitions) + + + @@ -349,6 +362,7 @@ + @@ -442,7 +456,6 @@ - @@ -570,7 +583,7 @@ - + GITVERSION="$(GitVersion)";GITTAG="$(GitTag)";GITBRANCH="$(GitBranch)";%(PreprocessorDefinitions) @@ -590,4 +603,8 @@ + + + + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index b19f0279ec311..c1667e3fb74fd 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -648,6 +648,9 @@ Modules\zlib + + Include\internal + @@ -971,9 +974,6 @@ PC - - PC - PC @@ -1229,10 +1229,25 @@ Objects + + Python + + + Modules + + + Python + + + Python + + + Modules + Resource Files - + \ No newline at end of file diff --git a/Python/dynload_win.c b/Python/dynload_win.c index 5702ab2cd71ba..854b1e64c15fa 100644 --- a/Python/dynload_win.c +++ b/Python/dynload_win.c @@ -2,6 +2,9 @@ /* Support for dynamic loading of extension modules */ #include "Python.h" +#include "pycore_fileutils.h" // _Py_add_relfile() +#include "pycore_pathconfig.h" // _PyPathConfig_ComputeSysPath0() +#include "pycore_pystate.h" // _PyInterpreterState_GET() #ifdef HAVE_DIRECT_H #include @@ -160,6 +163,60 @@ static char *GetPythonImport (HINSTANCE hModule) return NULL; } +/* Load python3.dll before loading any extension module that might refer + to it. That way, we can be sure that always the python3.dll corresponding + to this python DLL is loaded, not a python3.dll that might be on the path + by chance. + Return whether the DLL was found. +*/ +extern HMODULE PyWin_DLLhModule; +static int +_Py_CheckPython3(void) +{ + static int python3_checked = 0; + static HANDLE hPython3; + #define MAXPATHLEN 512 + wchar_t py3path[MAXPATHLEN+1]; + if (python3_checked) { + return hPython3 != NULL; + } + python3_checked = 1; + + /* If there is a python3.dll next to the python3y.dll, + use that DLL */ + if (PyWin_DLLhModule && GetModuleFileNameW(PyWin_DLLhModule, py3path, MAXPATHLEN)) { + wchar_t *p = wcsrchr(py3path, L'\\'); + if (p) { + wcscpy(p + 1, PY3_DLLNAME); + hPython3 = LoadLibraryExW(py3path, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); + if (hPython3 != NULL) { + return 1; + } + } + } + + /* If we can locate python3.dll in our application dir, + use that DLL */ + hPython3 = LoadLibraryExW(PY3_DLLNAME, NULL, LOAD_LIBRARY_SEARCH_APPLICATION_DIR); + if (hPython3 != NULL) { + return 1; + } + + /* For back-compat, also search {sys.prefix}\DLLs, though + that has not been a normal install layout for a while */ + PyInterpreterState *interp = _PyInterpreterState_GET(); + PyConfig *config = (PyConfig*)_PyInterpreterState_GetConfig(interp); + assert(config->prefix); + if (config->prefix) { + wcscpy_s(py3path, MAXPATHLEN, config->prefix); + if (py3path[0] && _Py_add_relfile(py3path, L"DLLs\\" PY3_DLLNAME, MAXPATHLEN) >= 0) { + hPython3 = LoadLibraryExW(py3path, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); + } + } + return hPython3 != NULL; + #undef MAXPATHLEN +} + dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix, const char *shortname, PyObject *pathname, FILE *fp) diff --git a/Python/fileutils.c b/Python/fileutils.c index ac0046cdac37c..cae6b75b6ae9b 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -2000,13 +2000,28 @@ _Py_wrealpath(const wchar_t *path, #endif -#ifndef MS_WINDOWS int _Py_isabs(const wchar_t *path) { +#ifdef MS_WINDOWS + const wchar_t *tail; + HRESULT hr = PathCchSkipRoot(path, &tail); + if (FAILED(hr) || path == tail) { + return 0; + } + if (tail == &path[1] && (path[0] == SEP || path[0] == ALTSEP)) { + // Exclude paths with leading SEP + return 0; + } + if (tail == &path[2] && path[1] == L':') { + // Exclude drive-relative paths (e.g. C:filename.ext) + return 0; + } + return 1; +#else return (path[0] == SEP); -} #endif +} /* Get an absolute path. @@ -2017,6 +2032,22 @@ _Py_isabs(const wchar_t *path) int _Py_abspath(const wchar_t *path, wchar_t **abspath_p) { + if (path[0] == '\0' || !wcscmp(path, L".")) { + wchar_t cwd[MAXPATHLEN + 1]; + cwd[Py_ARRAY_LENGTH(cwd) - 1] = 0; + if (!_Py_wgetcwd(cwd, Py_ARRAY_LENGTH(cwd) - 1)) { + /* unable to get the current directory */ + return -1; + } + *abspath_p = _PyMem_RawWcsdup(cwd); + return 0; + } + + if (_Py_isabs(path)) { + *abspath_p = _PyMem_RawWcsdup(path); + return 0; + } + #ifdef MS_WINDOWS wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf; DWORD result; @@ -2028,7 +2059,7 @@ _Py_abspath(const wchar_t *path, wchar_t **abspath_p) return -1; } - if (result > Py_ARRAY_LENGTH(woutbuf)) { + if (result >= Py_ARRAY_LENGTH(woutbuf)) { if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) { woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t)); } @@ -2055,11 +2086,6 @@ _Py_abspath(const wchar_t *path, wchar_t **abspath_p) *abspath_p = _PyMem_RawWcsdup(woutbufp); return 0; #else - if (_Py_isabs(path)) { - *abspath_p = _PyMem_RawWcsdup(path); - return 0; - } - wchar_t cwd[MAXPATHLEN + 1]; cwd[Py_ARRAY_LENGTH(cwd) - 1] = 0; if (!_Py_wgetcwd(cwd, Py_ARRAY_LENGTH(cwd) - 1)) { @@ -2102,7 +2128,8 @@ join_relfile(wchar_t *buffer, size_t bufsize, const wchar_t *dirname, const wchar_t *relfile) { #ifdef MS_WINDOWS - if (FAILED(PathCchCombineEx(buffer, bufsize, dirname, relfile, 0))) { + if (FAILED(PathCchCombineEx(buffer, bufsize, dirname, relfile, + PATHCCH_ALLOW_LONG_PATHS | PATHCCH_FORCE_ENABLE_LONG_NAME_PROCESS))) { return -1; } #else @@ -2180,99 +2207,125 @@ _Py_find_basename(const wchar_t *filename) return 0; } - -/* Remove navigation elements such as "." and "..". - - This is mostly a C implementation of posixpath.normpath(). - Return 0 on success. Return -1 if "orig" is too big for the buffer. */ -int -_Py_normalize_path(const wchar_t *path, wchar_t *buf, const size_t buf_len) +/* In-place path normalisation. Returns the start of the normalized + path, which will be within the original buffer. Guaranteed to not + make the path longer, and will not fail. 'size' is the length of + the path, if known. If -1, the first null character will be assumed + to be the end of the path. */ +wchar_t * +_Py_normpath(wchar_t *path, Py_ssize_t size) { - assert(path && *path != L'\0'); - assert(*path == SEP); // an absolute path - if (wcslen(path) + 1 >= buf_len) { - return -1; + if (!path[0] || size == 0) { + return path; } + wchar_t lastC = L'\0'; + wchar_t *p1 = path; + wchar_t *pEnd = size >= 0 ? &path[size] : NULL; + wchar_t *p2 = path; + wchar_t *minP2 = path; - int dots = -1; - int check_leading = 1; - const wchar_t *buf_start = buf; - wchar_t *buf_next = buf; - // The resulting filename will never be longer than path. - for (const wchar_t *remainder = path; *remainder != L'\0'; remainder++) { - wchar_t c = *remainder; - buf_next[0] = c; - buf_next++; - if (c == SEP) { - assert(dots <= 2); - if (dots == 2) { - // Turn "/x/y/../z" into "/x/z". - buf_next -= 4; // "/../" - assert(*buf_next == SEP); - // We cap it off at the root, so "/../spam" becomes "/spam". - if (buf_next == buf_start) { - buf_next++; - } - else { - // Move to the previous SEP in the buffer. - while (*(buf_next - 1) != SEP) { - assert(buf_next != buf_start); - buf_next--; - } - } - } - else if (dots == 1) { - // Turn "/./" into "/". - buf_next -= 2; // "./" - assert(*(buf_next - 1) == SEP); - } - else if (dots == 0) { - // Turn "//" into "/". - buf_next--; - assert(*(buf_next - 1) == SEP); - if (check_leading) { - if (buf_next - 1 == buf && *(remainder + 1) != SEP) { - // Leave a leading "//" alone, unless "///...". - buf_next++; - buf_start++; - } - check_leading = 0; - } - } - dots = 0; +#define IS_END(x) (pEnd ? (x) == pEnd : !*(x)) +#ifdef ALTSEP +#define IS_SEP(x) (*(x) == SEP || *(x) == ALTSEP) +#else +#define IS_SEP(x) (*(x) == SEP) +#endif +#define SEP_OR_END(x) (IS_SEP(x) || IS_END(x)) + + // Skip leading '.\' + if (p1[0] == L'.' && IS_SEP(&p1[1])) { + path = &path[2]; + while (IS_SEP(path) && !IS_END(path)) { + path++; } - else { - check_leading = 0; - if (dots >= 0) { - if (c == L'.' && dots < 2) { - dots++; - } - else { - dots = -1; - } + p1 = p2 = minP2 = path; + lastC = SEP; + } +#ifdef MS_WINDOWS + // Skip past drive segment and update minP2 + else if (p1[0] && p1[1] == L':') { + *p2++ = *p1++; + *p2++ = *p1++; + minP2 = p2; + lastC = L':'; + } + // Skip past all \\-prefixed paths, including \\?\, \\.\, + // and network paths, including the first segment. + else if (IS_SEP(&p1[0]) && IS_SEP(&p1[1])) { + int sepCount = 2; + *p2++ = SEP; + *p2++ = SEP; + p1 += 2; + for (; !IS_END(p1) && sepCount; ++p1) { + if (IS_SEP(p1)) { + --sepCount; + *p2++ = lastC = SEP; + } else { + *p2++ = lastC = *p1; } } + minP2 = p2; } - if (dots >= 0) { - // Strip any trailing dots and trailing slash. - buf_next -= dots + 1; // "/" or "/." or "/.." - assert(*buf_next == SEP); - if (buf_next == buf_start) { - // Leave the leading slash for root. - buf_next++; +#else + // Skip past two leading SEPs + else if (IS_SEP(&p1[0]) && IS_SEP(&p1[1]) && !IS_SEP(&p1[2])) { + *p2++ = *p1++; + *p2++ = *p1++; + minP2 = p2; + lastC = SEP; + } +#endif /* MS_WINDOWS */ + + /* if pEnd is specified, check that. Else, check for null terminator */ + for (; !IS_END(p1); ++p1) { + wchar_t c = *p1; +#ifdef ALTSEP + if (c == ALTSEP) { + c = SEP; } - else { - if (dots == 2) { - // Move to the previous SEP in the buffer. - do { - assert(buf_next != buf_start); - buf_next--; - } while (*(buf_next) != SEP); +#endif + if (lastC == SEP) { + if (c == L'.') { + int sep_at_1 = SEP_OR_END(&p1[1]); + int sep_at_2 = !sep_at_1 && SEP_OR_END(&p1[2]); + if (sep_at_2 && p1[1] == L'.') { + wchar_t *p3 = p2; + while (p3 != minP2 && *--p3 == SEP) { } + while (p3 != minP2 && *(p3 - 1) != SEP) { --p3; } + if (p3[0] == L'.' && p3[1] == L'.' && IS_SEP(&p3[2])) { + // Previous segment is also ../, so append instead + *p2++ = L'.'; + *p2++ = L'.'; + lastC = L'.'; + } else if (p3[0] == SEP) { + // Absolute path, so absorb segment + p2 = p3 + 1; + } else { + p2 = p3; + } + p1 += 1; + } else if (sep_at_1) { + } else { + *p2++ = lastC = c; + } + } else if (c == SEP) { + } else { + *p2++ = lastC = c; } + } else { + *p2++ = lastC = c; + } + } + *p2 = L'\0'; + if (p2 != minP2) { + while (--p2 != minP2 && *p2 == SEP) { + *p2 = L'\0'; } } - *buf_next = L'\0'; - return 0; +#undef SEP_OR_END +#undef IS_SEP +#undef IS_END + return path; } diff --git a/Python/initconfig.c b/Python/initconfig.c index 53b624fdd72ec..47ebc64c8470a 100644 --- a/Python/initconfig.c +++ b/Python/initconfig.c @@ -22,11 +22,6 @@ # endif #endif -#ifndef PLATLIBDIR -# error "PLATLIBDIR macro must be defined" -#endif - - /* --- Command line options --------------------------------------- */ /* Short usage message (with %s for argv0) */ @@ -632,7 +627,6 @@ config_check_consistency(const PyConfig *config) assert(config->parse_argv >= 0); assert(config->configure_c_stdio >= 0); assert(config->buffered_stdio >= 0); - assert(config->program_name != NULL); assert(_PyWideStringList_CheckConsistency(&config->orig_argv)); assert(_PyWideStringList_CheckConsistency(&config->argv)); /* sys.argv must be non-empty: empty argv is replaced with [''] */ @@ -641,7 +635,6 @@ config_check_consistency(const PyConfig *config) assert(_PyWideStringList_CheckConsistency(&config->warnoptions)); assert(_PyWideStringList_CheckConsistency(&config->module_search_paths)); assert(config->module_search_paths_set >= 0); - assert(config->platlibdir != NULL); assert(config->filesystem_encoding != NULL); assert(config->filesystem_errors != NULL); assert(config->stdio_encoding != NULL); @@ -740,6 +733,7 @@ _PyConfig_InitCompatConfig(PyConfig *config) config->legacy_windows_stdio = -1; #endif config->use_frozen_modules = -1; + config->_is_python_build = 0; config->code_debug_ranges = 1; } @@ -962,6 +956,7 @@ _PyConfig_Copy(PyConfig *config, const PyConfig *config2) COPY_ATTR(_isolated_interpreter); COPY_ATTR(use_frozen_modules); COPY_WSTRLIST(orig_argv); + COPY_ATTR(_is_python_build); #undef COPY_ATTR #undef COPY_WSTR_ATTR @@ -1066,6 +1061,7 @@ _PyConfig_AsDict(const PyConfig *config) SET_ITEM_INT(_isolated_interpreter); SET_ITEM_WSTRLIST(orig_argv); SET_ITEM_INT(use_frozen_modules); + SET_ITEM_INT(_is_python_build); return dict; @@ -1350,6 +1346,7 @@ _PyConfig_FromDict(PyConfig *config, PyObject *dict) GET_UINT(_init_main); GET_UINT(_isolated_interpreter); GET_UINT(use_frozen_modules); + GET_UINT(_is_python_build); #undef CHECK_VALUE #undef GET_UINT @@ -1489,117 +1486,6 @@ config_set_global_vars(const PyConfig *config) } -/* Get the program name: use PYTHONEXECUTABLE and __PYVENV_LAUNCHER__ - environment variables on macOS if available. */ -static PyStatus -config_init_program_name(PyConfig *config) -{ - PyStatus status; - - /* If Py_SetProgramName() was called, use its value */ - const wchar_t *program_name = _Py_path_config.program_name; - if (program_name != NULL) { - config->program_name = _PyMem_RawWcsdup(program_name); - if (config->program_name == NULL) { - return _PyStatus_NO_MEMORY(); - } - return _PyStatus_OK(); - } - -#ifdef __APPLE__ - /* On MacOS X, when the Python interpreter is embedded in an - application bundle, it gets executed by a bootstrapping script - that does os.execve() with an argv[0] that's different from the - actual Python executable. This is needed to keep the Finder happy, - or rather, to work around Apple's overly strict requirements of - the process name. However, we still need a usable sys.executable, - so the actual executable path is passed in an environment variable. - See Lib/plat-mac/bundlebuilder.py for details about the bootstrap - script. */ - const char *p = config_get_env(config, "PYTHONEXECUTABLE"); - if (p != NULL) { - status = CONFIG_SET_BYTES_STR(config, &config->program_name, p, - "PYTHONEXECUTABLE environment variable"); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - return _PyStatus_OK(); - } -#ifdef WITH_NEXT_FRAMEWORK - else { - const char* pyvenv_launcher = getenv("__PYVENV_LAUNCHER__"); - if (pyvenv_launcher && *pyvenv_launcher) { - /* Used by Mac/Tools/pythonw.c to forward - * the argv0 of the stub executable - */ - status = CONFIG_SET_BYTES_STR(config, - &config->program_name, - pyvenv_launcher, - "__PYVENV_LAUNCHER__ environment variable"); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - - /* - * This environment variable is used to communicate between - * the stub launcher and the real interpreter and isn't needed - * beyond this point. - * - * Clean up to avoid problems when launching other programs - * later on. - */ - (void)unsetenv("__PYVENV_LAUNCHER__"); - - return _PyStatus_OK(); - } - } -#endif /* WITH_NEXT_FRAMEWORK */ -#endif /* __APPLE__ */ - - /* Use argv[0] if available and non-empty */ - const PyWideStringList *argv = &config->argv; - if (argv->length >= 1 && argv->items[0][0] != L'\0') { - config->program_name = _PyMem_RawWcsdup(argv->items[0]); - if (config->program_name == NULL) { - return _PyStatus_NO_MEMORY(); - } - return _PyStatus_OK(); - } - - /* Last fall back: hardcoded name */ -#ifdef MS_WINDOWS - const wchar_t *default_program_name = L"python"; -#else - const wchar_t *default_program_name = L"python3"; -#endif - status = PyConfig_SetString(config, &config->program_name, - default_program_name); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - return _PyStatus_OK(); -} - -static PyStatus -config_init_executable(PyConfig *config) -{ - assert(config->executable == NULL); - - /* If Py_SetProgramFullPath() was called, use its value */ - const wchar_t *program_full_path = _Py_path_config.program_full_path; - if (program_full_path != NULL) { - PyStatus status = PyConfig_SetString(config, - &config->executable, - program_full_path); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - return _PyStatus_OK(); - } - return _PyStatus_OK(); -} - - static const wchar_t* config_get_xoption(const PyConfig *config, wchar_t *name) { @@ -1618,25 +1504,6 @@ config_get_xoption_value(const PyConfig *config, wchar_t *name) } -static PyStatus -config_init_home(PyConfig *config) -{ - assert(config->home == NULL); - - /* If Py_SetPythonHome() was called, use its value */ - wchar_t *home = _Py_path_config.home; - if (home) { - PyStatus status = PyConfig_SetString(config, &config->home, home); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - return _PyStatus_OK(); - } - - return CONFIG_GET_ENV_DUP(config, &config->home, - L"PYTHONHOME", "PYTHONHOME"); -} - static PyStatus config_init_hash_seed(PyConfig *config) { @@ -2092,44 +1959,6 @@ config_init_fs_encoding(PyConfig *config, const PyPreConfig *preconfig) } -/* Determine if the current build is a "development" build (e.g. running - out of the source tree) or not. - - A return value of -1 indicates that we do not know. - */ -static int -is_dev_env(PyConfig *config) -{ - // This should only ever get called early in runtime initialization, - // before the global path config is written. Otherwise we would - // use Py_GetProgramFullPath() and _Py_GetStdlibDir(). - assert(config != NULL); - - const wchar_t *executable = config->executable; - const wchar_t *stdlib = config->stdlib_dir; - if (executable == NULL || *executable == L'\0' || - stdlib == NULL || *stdlib == L'\0') { - // _PyPathConfig_Calculate() hasn't run yet. - return -1; - } - size_t len = _Py_find_basename(executable); - if (wcscmp(executable + len, L"python") != 0 && - wcscmp(executable + len, L"python.exe") != 0) { - return 0; - } - /* If dirname() is the same for both then it is a dev build. */ - if (len != _Py_find_basename(stdlib)) { - return 0; - } - // We do not bother normalizing the two filenames first since - // for config_init_import() is does the right thing as-is. - if (wcsncmp(stdlib, executable, len) != 0) { - return 0; - } - return 1; -} - - static PyStatus config_init_import(PyConfig *config, int compute_path_config) { @@ -2144,10 +1973,7 @@ config_init_import(PyConfig *config, int compute_path_config) if (config->use_frozen_modules < 0) { const wchar_t *value = config_get_xoption_value(config, L"frozen_modules"); if (value == NULL) { - int isdev = is_dev_env(config); - if (isdev >= 0) { - config->use_frozen_modules = !isdev; - } + config->use_frozen_modules = !config->_is_python_build; } else if (wcscmp(value, L"on") == 0) { config->use_frozen_modules = 1; @@ -2246,28 +2072,6 @@ config_read(PyConfig *config, int compute_path_config) return status; } - if (config->home == NULL) { - status = config_init_home(config); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - } - - if (config->executable == NULL) { - status = config_init_executable(config); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - } - - if(config->platlibdir == NULL) { - status = CONFIG_SET_BYTES_STR(config, &config->platlibdir, PLATLIBDIR, - "PLATLIBDIR macro"); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - } - if (config->_install_importlib) { status = config_init_import(config, compute_path_config); if (_PyStatus_EXCEPTION(status)) { @@ -2890,13 +2694,6 @@ config_read_cmdline(PyConfig *config) config->parse_argv = 1; } - if (config->program_name == NULL) { - status = config_init_program_name(config); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - } - if (config->parse_argv == 1) { Py_ssize_t opt_index; status = config_parse_cmdline(config, &cmdline_warnoptions, &opt_index); @@ -3076,7 +2873,7 @@ _PyConfig_Read(PyConfig *config, int compute_path_config) PyStatus PyConfig_Read(PyConfig *config) { - return _PyConfig_Read(config, 1); + return _PyConfig_Read(config, 0); } @@ -3124,16 +2921,6 @@ _Py_GetConfigsAsDict(void) } Py_CLEAR(dict); - /* path config */ - dict = _PyPathConfig_AsDict(); - if (dict == NULL) { - goto error; - } - if (PyDict_SetItemString(result, "path_config", dict) < 0) { - goto error; - } - Py_CLEAR(dict); - return result; error: @@ -3199,6 +2986,7 @@ _Py_DumpPathConfig(PyThreadState *tstate) PySys_WriteStderr(" environment = %i\n", config->use_environment); PySys_WriteStderr(" user site = %i\n", config->user_site_directory); PySys_WriteStderr(" import site = %i\n", config->site_import); + PySys_WriteStderr(" is in build tree = %i\n", config->_is_python_build); DUMP_CONFIG("stdlib dir", stdlib_dir); #undef DUMP_CONFIG diff --git a/Python/pathconfig.c b/Python/pathconfig.c index ad22222e000fc..4271928571fa1 100644 --- a/Python/pathconfig.c +++ b/Python/pathconfig.c @@ -1,6 +1,7 @@ /* Path configuration like module_search_path (sys.path) */ #include "Python.h" +#include "marshal.h" // PyMarshal_ReadObjectFromString #include "osdefs.h" // DELIM #include "pycore_initconfig.h" #include "pycore_fileutils.h" @@ -9,6 +10,8 @@ #include #ifdef MS_WINDOWS # include // GetFullPathNameW(), MAX_PATH +# include +# include #endif #ifdef __cplusplus @@ -16,462 +19,170 @@ extern "C" { #endif +/* External interface */ + +/* Stored values set by C API functions */ +typedef struct _PyPathConfig { + /* Full path to the Python program */ + wchar_t *program_full_path; + wchar_t *prefix; + wchar_t *exec_prefix; + wchar_t *stdlib_dir; + /* Set by Py_SetPath */ + wchar_t *module_search_path; + /* Set by _PyPathConfig_UpdateGlobal */ + wchar_t *calculated_module_search_path; + /* Python program name */ + wchar_t *program_name; + /* Set by Py_SetPythonHome() or PYTHONHOME environment variable */ + wchar_t *home; +} _PyPathConfig; + +# define _PyPathConfig_INIT \ + {.module_search_path = NULL} + + _PyPathConfig _Py_path_config = _PyPathConfig_INIT; -static int -copy_wstr(wchar_t **dst, const wchar_t *src) +const wchar_t * +_PyPathConfig_GetGlobalModuleSearchPath(void) { - assert(*dst == NULL); - if (src != NULL) { - *dst = _PyMem_RawWcsdup(src); - if (*dst == NULL) { - return -1; - } - } - else { - *dst = NULL; - } - return 0; + return _Py_path_config.module_search_path; } -static void -pathconfig_clear(_PyPathConfig *config) +void +_PyPathConfig_ClearGlobal(void) { - /* _PyMem_SetDefaultAllocator() is needed to get a known memory allocator, - since Py_SetPath(), Py_SetPythonHome() and Py_SetProgramName() can be - called before Py_Initialize() which can changes the memory allocator. */ PyMemAllocatorEx old_alloc; _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); #define CLEAR(ATTR) \ do { \ - PyMem_RawFree(ATTR); \ - ATTR = NULL; \ + PyMem_RawFree(_Py_path_config.ATTR); \ + _Py_path_config.ATTR = NULL; \ } while (0) - CLEAR(config->program_full_path); - CLEAR(config->prefix); - CLEAR(config->exec_prefix); - CLEAR(config->stdlib_dir); - CLEAR(config->module_search_path); - CLEAR(config->program_name); - CLEAR(config->home); -#ifdef MS_WINDOWS - CLEAR(config->base_executable); -#endif + CLEAR(program_full_path); + CLEAR(prefix); + CLEAR(exec_prefix); + CLEAR(stdlib_dir); + CLEAR(module_search_path); + CLEAR(calculated_module_search_path); + CLEAR(program_name); + CLEAR(home); #undef CLEAR PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); } - -static PyStatus -pathconfig_copy(_PyPathConfig *config, const _PyPathConfig *config2) +PyStatus +_PyPathConfig_ReadGlobal(PyConfig *config) { - pathconfig_clear(config); + PyStatus status = _PyStatus_OK(); -#define COPY_ATTR(ATTR) \ +#define COPY(ATTR) \ do { \ - if (copy_wstr(&config->ATTR, config2->ATTR) < 0) { \ - return _PyStatus_NO_MEMORY(); \ + if (_Py_path_config.ATTR && !config->ATTR) { \ + status = PyConfig_SetString(config, &config->ATTR, _Py_path_config.ATTR); \ + if (_PyStatus_EXCEPTION(status)) goto done; \ } \ } while (0) - COPY_ATTR(program_full_path); - COPY_ATTR(prefix); - COPY_ATTR(exec_prefix); - COPY_ATTR(module_search_path); - COPY_ATTR(stdlib_dir); - COPY_ATTR(program_name); - COPY_ATTR(home); -#ifdef MS_WINDOWS - config->isolated = config2->isolated; - config->site_import = config2->site_import; - COPY_ATTR(base_executable); -#endif - -#undef COPY_ATTR - - return _PyStatus_OK(); -} - - -void -_PyPathConfig_ClearGlobal(void) -{ - PyMemAllocatorEx old_alloc; - _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - - pathconfig_clear(&_Py_path_config); - - PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); -} - - -static wchar_t* -_PyWideStringList_Join(const PyWideStringList *list, wchar_t sep) -{ - size_t len = 1; /* NUL terminator */ - for (Py_ssize_t i=0; i < list->length; i++) { - if (i != 0) { - len++; - } - len += wcslen(list->items[i]); - } - - wchar_t *text = PyMem_RawMalloc(len * sizeof(wchar_t)); - if (text == NULL) { - return NULL; - } - wchar_t *str = text; - for (Py_ssize_t i=0; i < list->length; i++) { - wchar_t *path = list->items[i]; - if (i != 0) { - *str++ = sep; - } - len = wcslen(path); - memcpy(str, path, len * sizeof(wchar_t)); - str += len; - } - *str = L'\0'; - - return text; -} - - -static PyStatus -pathconfig_set_from_config(_PyPathConfig *pathconfig, const PyConfig *config) -{ - PyStatus status; - PyMemAllocatorEx old_alloc; - _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - - if (config->module_search_paths_set) { - PyMem_RawFree(pathconfig->module_search_path); - pathconfig->module_search_path = _PyWideStringList_Join(&config->module_search_paths, DELIM); - if (pathconfig->module_search_path == NULL) { - goto no_memory; - } - } - -#define COPY_CONFIG(PATH_ATTR, CONFIG_ATTR) \ - if (config->CONFIG_ATTR) { \ - PyMem_RawFree(pathconfig->PATH_ATTR); \ - pathconfig->PATH_ATTR = NULL; \ - if (copy_wstr(&pathconfig->PATH_ATTR, config->CONFIG_ATTR) < 0) { \ - goto no_memory; \ - } \ - } - - COPY_CONFIG(program_full_path, executable); - COPY_CONFIG(prefix, prefix); - COPY_CONFIG(exec_prefix, exec_prefix); - COPY_CONFIG(stdlib_dir, stdlib_dir); - COPY_CONFIG(program_name, program_name); - COPY_CONFIG(home, home); -#ifdef MS_WINDOWS - COPY_CONFIG(base_executable, base_executable); -#endif - -#undef COPY_CONFIG - - status = _PyStatus_OK(); - goto done; +#define COPY2(ATTR, SRCATTR) \ + do { \ + if (_Py_path_config.SRCATTR && !config->ATTR) { \ + status = PyConfig_SetString(config, &config->ATTR, _Py_path_config.SRCATTR); \ + if (_PyStatus_EXCEPTION(status)) goto done; \ + } \ + } while (0) -no_memory: - status = _PyStatus_NO_MEMORY(); + COPY(prefix); + COPY(exec_prefix); + COPY(stdlib_dir); + COPY(program_name); + COPY(home); + COPY2(executable, program_full_path); + // module_search_path must be initialised - not read +#undef COPY +#undef COPY2 done: - PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); return status; } -PyObject * -_PyPathConfig_AsDict(void) -{ - PyObject *dict = PyDict_New(); - if (dict == NULL) { - return NULL; - } - -#define SET_ITEM(KEY, EXPR) \ - do { \ - PyObject *obj = (EXPR); \ - if (obj == NULL) { \ - goto fail; \ - } \ - int res = PyDict_SetItemString(dict, KEY, obj); \ - Py_DECREF(obj); \ - if (res < 0) { \ - goto fail; \ - } \ - } while (0) -#define SET_ITEM_STR(KEY) \ - SET_ITEM(#KEY, \ - (_Py_path_config.KEY \ - ? PyUnicode_FromWideChar(_Py_path_config.KEY, -1) \ - : (Py_INCREF(Py_None), Py_None))) -#define SET_ITEM_INT(KEY) \ - SET_ITEM(#KEY, PyLong_FromLong(_Py_path_config.KEY)) - - SET_ITEM_STR(program_full_path); - SET_ITEM_STR(prefix); - SET_ITEM_STR(exec_prefix); - SET_ITEM_STR(module_search_path); - SET_ITEM_STR(stdlib_dir); - SET_ITEM_STR(program_name); - SET_ITEM_STR(home); -#ifdef MS_WINDOWS - SET_ITEM_INT(isolated); - SET_ITEM_INT(site_import); - SET_ITEM_STR(base_executable); - - { - wchar_t py3path[MAX_PATH]; - HMODULE hPython3 = GetModuleHandleW(PY3_DLLNAME); - PyObject *obj; - if (hPython3 - && GetModuleFileNameW(hPython3, py3path, Py_ARRAY_LENGTH(py3path))) - { - obj = PyUnicode_FromWideChar(py3path, -1); - if (obj == NULL) { - goto fail; - } - } - else { - obj = Py_None; - Py_INCREF(obj); - } - if (PyDict_SetItemString(dict, "python3_dll", obj) < 0) { - Py_DECREF(obj); - goto fail; - } - Py_DECREF(obj); - } -#endif - -#undef SET_ITEM -#undef SET_ITEM_STR -#undef SET_ITEM_INT - - return dict; - -fail: - Py_DECREF(dict); - return NULL; -} - - PyStatus -_PyConfig_WritePathConfig(const PyConfig *config) +_PyPathConfig_UpdateGlobal(const PyConfig *config) { - return pathconfig_set_from_config(&_Py_path_config, config); -} - - -static PyStatus -config_init_module_search_paths(PyConfig *config, _PyPathConfig *pathconfig) -{ - assert(!config->module_search_paths_set); - - _PyWideStringList_Clear(&config->module_search_paths); - - const wchar_t *sys_path = pathconfig->module_search_path; - const wchar_t delim = DELIM; - while (1) { - const wchar_t *p = wcschr(sys_path, delim); - if (p == NULL) { - p = sys_path + wcslen(sys_path); /* End of string */ - } - - size_t path_len = (p - sys_path); - wchar_t *path = PyMem_RawMalloc((path_len + 1) * sizeof(wchar_t)); - if (path == NULL) { - return _PyStatus_NO_MEMORY(); - } - memcpy(path, sys_path, path_len * sizeof(wchar_t)); - path[path_len] = L'\0'; - - PyStatus status = PyWideStringList_Append(&config->module_search_paths, path); - PyMem_RawFree(path); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - - if (*p == '\0') { - break; - } - sys_path = p + 1; - } - config->module_search_paths_set = 1; - return _PyStatus_OK(); -} - - -/* Calculate the path configuration: - - - exec_prefix - - module_search_path - - stdlib_dir - - prefix - - program_full_path - - On Windows, more fields are calculated: - - - base_executable - - isolated - - site_import - - On other platforms, isolated and site_import are left unchanged, and - _PyConfig_InitPathConfig() copies executable to base_executable (if it's not - set). - - Priority, highest to lowest: - - - PyConfig - - _Py_path_config: set by Py_SetPath(), Py_SetPythonHome() - and Py_SetProgramName() - - _PyPathConfig_Calculate() -*/ -static PyStatus -pathconfig_init(_PyPathConfig *pathconfig, const PyConfig *config, - int compute_path_config) -{ - PyStatus status; - PyMemAllocatorEx old_alloc; _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - status = pathconfig_copy(pathconfig, &_Py_path_config); - if (_PyStatus_EXCEPTION(status)) { - goto done; - } - - status = pathconfig_set_from_config(pathconfig, config); - if (_PyStatus_EXCEPTION(status)) { - goto done; - } - - if (compute_path_config) { - status = _PyPathConfig_Calculate(pathconfig, config); - } - -done: - PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - return status; -} - - -static PyStatus -config_init_pathconfig(PyConfig *config, int compute_path_config) -{ - _PyPathConfig pathconfig = _PyPathConfig_INIT; - PyStatus status; - - status = pathconfig_init(&pathconfig, config, compute_path_config); - if (_PyStatus_EXCEPTION(status)) { - goto done; - } - - if (!config->module_search_paths_set - && pathconfig.module_search_path != NULL) - { - status = config_init_module_search_paths(config, &pathconfig); - if (_PyStatus_EXCEPTION(status)) { - goto done; - } - } - -#define COPY_ATTR(PATH_ATTR, CONFIG_ATTR) \ - if (config->CONFIG_ATTR == NULL && pathconfig.PATH_ATTR != NULL) { \ - if (copy_wstr(&config->CONFIG_ATTR, pathconfig.PATH_ATTR) < 0) { \ - goto no_memory; \ - } \ - } - -#ifdef MS_WINDOWS - if (config->executable != NULL && config->base_executable == NULL) { - /* If executable is set explicitly in the configuration, - ignore calculated base_executable: _PyConfig_InitPathConfig() - will copy executable to base_executable */ - } - else { - COPY_ATTR(base_executable, base_executable); - } -#endif - - COPY_ATTR(program_full_path, executable); - COPY_ATTR(prefix, prefix); - COPY_ATTR(exec_prefix, exec_prefix); - COPY_ATTR(stdlib_dir, stdlib_dir); - -#undef COPY_ATTR - -#ifdef MS_WINDOWS - /* If a ._pth file is found: isolated and site_import are overridden */ - if (pathconfig.isolated != -1) { - config->isolated = pathconfig.isolated; - } - if (pathconfig.site_import != -1) { - config->site_import = pathconfig.site_import; - } -#endif - - status = _PyStatus_OK(); - goto done; - -no_memory: - status = _PyStatus_NO_MEMORY(); +#define COPY(ATTR) \ + do { \ + if (config->ATTR) { \ + PyMem_RawFree(_Py_path_config.ATTR); \ + _Py_path_config.ATTR = _PyMem_RawWcsdup(config->ATTR); \ + if (!_Py_path_config.ATTR) goto error; \ + } \ + } while (0) -done: - pathconfig_clear(&pathconfig); - return status; -} +#define COPY2(ATTR, SRCATTR) \ + do { \ + if (config->SRCATTR) { \ + PyMem_RawFree(_Py_path_config.ATTR); \ + _Py_path_config.ATTR = _PyMem_RawWcsdup(config->SRCATTR); \ + if (!_Py_path_config.ATTR) goto error; \ + } \ + } while (0) + COPY(prefix); + COPY(exec_prefix); + COPY(stdlib_dir); + COPY(program_name); + COPY(home); + COPY2(program_full_path, executable); +#undef COPY +#undef COPY2 -PyStatus -_PyConfig_InitPathConfig(PyConfig *config, int compute_path_config) -{ - /* Do we need to calculate the path? */ - if (!config->module_search_paths_set - || config->executable == NULL - || config->prefix == NULL - || config->exec_prefix == NULL) - { - PyStatus status = config_init_pathconfig(config, compute_path_config); - if (_PyStatus_EXCEPTION(status)) { - return status; + PyMem_RawFree(_Py_path_config.module_search_path); + _Py_path_config.module_search_path = NULL; + PyMem_RawFree(_Py_path_config.calculated_module_search_path); + _Py_path_config.calculated_module_search_path = NULL; + + do { + size_t cch = 1; + for (Py_ssize_t i = 0; i < config->module_search_paths.length; ++i) { + cch += 1 + wcslen(config->module_search_paths.items[i]); } - } - if (config->base_prefix == NULL && config->prefix != NULL) { - if (copy_wstr(&config->base_prefix, config->prefix) < 0) { - return _PyStatus_NO_MEMORY(); + wchar_t *path = (wchar_t*)PyMem_RawMalloc(sizeof(wchar_t) * cch); + if (!path) { + goto error; } - } - - if (config->base_exec_prefix == NULL && config->exec_prefix != NULL) { - if (copy_wstr(&config->base_exec_prefix, - config->exec_prefix) < 0) { - return _PyStatus_NO_MEMORY(); + wchar_t *p = path; + for (Py_ssize_t i = 0; i < config->module_search_paths.length; ++i) { + wcscpy(p, config->module_search_paths.items[i]); + p = wcschr(p, L'\0'); + *p++ = DELIM; + *p = L'\0'; } - } - if (config->base_executable == NULL && config->executable != NULL) { - if (copy_wstr(&config->base_executable, - config->executable) < 0) { - return _PyStatus_NO_MEMORY(); - } - } + do { + *p = L'\0'; + } while (p != path && *--p == DELIM); + _Py_path_config.calculated_module_search_path = path; + } while (0); + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); return _PyStatus_OK(); -} +error: + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + return _PyStatus_NO_MEMORY(); +} -/* External interface */ static void _Py_NO_RETURN path_out_of_memory(const char *func) @@ -483,7 +194,7 @@ void Py_SetPath(const wchar_t *path) { if (path == NULL) { - pathconfig_clear(&_Py_path_config); + _PyPathConfig_ClearGlobal(); return; } @@ -494,6 +205,7 @@ Py_SetPath(const wchar_t *path) PyMem_RawFree(_Py_path_config.exec_prefix); PyMem_RawFree(_Py_path_config.stdlib_dir); PyMem_RawFree(_Py_path_config.module_search_path); + PyMem_RawFree(_Py_path_config.calculated_module_search_path); _Py_path_config.prefix = _PyMem_RawWcsdup(L""); _Py_path_config.exec_prefix = _PyMem_RawWcsdup(L""); @@ -505,6 +217,7 @@ Py_SetPath(const wchar_t *path) _Py_path_config.stdlib_dir = _PyMem_RawWcsdup(L""); } _Py_path_config.module_search_path = _PyMem_RawWcsdup(path); + _Py_path_config.calculated_module_search_path = NULL; PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); @@ -521,19 +234,19 @@ Py_SetPath(const wchar_t *path) void Py_SetPythonHome(const wchar_t *home) { - if (home == NULL) { - return; - } + int has_value = home && home[0]; PyMemAllocatorEx old_alloc; _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); PyMem_RawFree(_Py_path_config.home); - _Py_path_config.home = _PyMem_RawWcsdup(home); + if (has_value) { + _Py_path_config.home = _PyMem_RawWcsdup(home); + } PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - if (_Py_path_config.home == NULL) { + if (has_value && _Py_path_config.home == NULL) { path_out_of_memory(__func__); } } @@ -542,19 +255,19 @@ Py_SetPythonHome(const wchar_t *home) void Py_SetProgramName(const wchar_t *program_name) { - if (program_name == NULL || program_name[0] == L'\0') { - return; - } + int has_value = program_name && program_name[0]; PyMemAllocatorEx old_alloc; _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); PyMem_RawFree(_Py_path_config.program_name); - _Py_path_config.program_name = _PyMem_RawWcsdup(program_name); + if (has_value) { + _Py_path_config.program_name = _PyMem_RawWcsdup(program_name); + } PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - if (_Py_path_config.program_name == NULL) { + if (has_value && _Py_path_config.program_name == NULL) { path_out_of_memory(__func__); } } @@ -562,19 +275,19 @@ Py_SetProgramName(const wchar_t *program_name) void _Py_SetProgramFullPath(const wchar_t *program_full_path) { - if (program_full_path == NULL || program_full_path[0] == L'\0') { - return; - } + int has_value = program_full_path && program_full_path[0]; PyMemAllocatorEx old_alloc; _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); PyMem_RawFree(_Py_path_config.program_full_path); - _Py_path_config.program_full_path = _PyMem_RawWcsdup(program_full_path); + if (has_value) { + _Py_path_config.program_full_path = _PyMem_RawWcsdup(program_full_path); + } PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - if (_Py_path_config.program_full_path == NULL) { + if (has_value && _Py_path_config.program_full_path == NULL) { path_out_of_memory(__func__); } } @@ -583,7 +296,12 @@ _Py_SetProgramFullPath(const wchar_t *program_full_path) wchar_t * Py_GetPath(void) { - return _Py_path_config.module_search_path; + /* If the user has provided a path, return that */ + if (_Py_path_config.module_search_path) { + return _Py_path_config.module_search_path; + } + /* If we have already done calculations, return the calculated path */ + return _Py_path_config.calculated_module_search_path; } @@ -632,6 +350,8 @@ Py_GetProgramName(void) return _Py_path_config.program_name; } + + /* Compute module search path from argv[0] or the current working directory ("-m module" case) which will be prepended to sys.argv: sys.path[0]. @@ -772,73 +492,6 @@ _PyPathConfig_ComputeSysPath0(const PyWideStringList *argv, PyObject **path0_p) } -#ifdef MS_WINDOWS -#define WCSTOK wcstok_s -#else -#define WCSTOK wcstok -#endif - -/* Search for a prefix value in an environment file (pyvenv.cfg). - - - If found, copy it into *value_p: string which must be freed by - PyMem_RawFree(). - - If not found, *value_p is set to NULL. -*/ -PyStatus -_Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key, - wchar_t **value_p) -{ - *value_p = NULL; - - char buffer[MAXPATHLEN * 2 + 1]; /* allow extra for key, '=', etc. */ - buffer[Py_ARRAY_LENGTH(buffer)-1] = '\0'; - - while (!feof(env_file)) { - char * p = fgets(buffer, Py_ARRAY_LENGTH(buffer) - 1, env_file); - - if (p == NULL) { - break; - } - - size_t n = strlen(p); - if (p[n - 1] != '\n') { - /* line has overflowed - bail */ - break; - } - if (p[0] == '#') { - /* Comment - skip */ - continue; - } - - wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n, NULL); - if (tmpbuffer) { - wchar_t * state; - wchar_t * tok = WCSTOK(tmpbuffer, L" \t\r\n", &state); - if ((tok != NULL) && !wcscmp(tok, key)) { - tok = WCSTOK(NULL, L" \t", &state); - if ((tok != NULL) && !wcscmp(tok, L"=")) { - tok = WCSTOK(NULL, L"\r\n", &state); - if (tok != NULL) { - *value_p = _PyMem_RawWcsdup(tok); - PyMem_RawFree(tmpbuffer); - - if (*value_p == NULL) { - return _PyStatus_NO_MEMORY(); - } - - /* found */ - return _PyStatus_OK(); - } - } - } - PyMem_RawFree(tmpbuffer); - } - } - - /* not found */ - return _PyStatus_OK(); -} - #ifdef __cplusplus } #endif diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index c6b2a1eb96148..84b76ea3275a7 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -459,7 +459,7 @@ interpreter_update_config(PyThreadState *tstate, int only_update_path_config) } if (_Py_IsMainInterpreter(tstate->interp)) { - PyStatus status = _PyConfig_WritePathConfig(config); + PyStatus status = _PyPathConfig_UpdateGlobal(config); if (_PyStatus_EXCEPTION(status)) { _PyErr_SetFromPyStatus(status); return -1; @@ -488,7 +488,7 @@ _PyInterpreterState_SetConfig(const PyConfig *src_config) goto done; } - status = PyConfig_Read(&config); + status = _PyConfig_Read(&config, 1); if (_PyStatus_EXCEPTION(status)) { _PyErr_SetFromPyStatus(status); goto done; @@ -549,7 +549,7 @@ pyinit_core_reconfigure(_PyRuntimeState *runtime, config = _PyInterpreterState_GetConfig(interp); if (config->_install_importlib) { - status = _PyConfig_WritePathConfig(config); + status = _PyPathConfig_UpdateGlobal(config); if (_PyStatus_EXCEPTION(status)) { return status; } From webhook-mailer at python.org Fri Dec 3 06:29:17 2021 From: webhook-mailer at python.org (markshannon) Date: Fri, 03 Dec 2021 11:29:17 -0000 Subject: [Python-checkins] bpo-45885: Specialize COMPARE_OP (GH-29734) Message-ID: https://github.com/python/cpython/commit/03768c4d139df46212a091ed931aad03bec18b57 commit: 03768c4d139df46212a091ed931aad03bec18b57 branch: main author: Dennis Sweeney <36520290+sweeneyde at users.noreply.github.com> committer: markshannon date: 2021-12-03T11:29:12Z summary: bpo-45885: Specialize COMPARE_OP (GH-29734) * Add COMPARE_OP_ADAPTIVE adaptive instruction. * Add COMPARE_OP_FLOAT_JUMP, COMPARE_OP_INT_JUMP and COMPARE_OP_STR_JUMP specialized instructions. * Introduce and use _PyUnicode_Equal files: A Misc/NEWS.d/next/Core and Builtins/2021-11-23-21-01-56.bpo-45885.3IxeCX.rst M Include/cpython/unicodeobject.h M Include/internal/pycore_code.h M Include/opcode.h M Lib/opcode.py M Objects/unicodeobject.c M Python/ceval.c M Python/opcode_targets.h M Python/specialize.c diff --git a/Include/cpython/unicodeobject.h b/Include/cpython/unicodeobject.h index ab4aebf5e70b9..e02137c7cad7d 100644 --- a/Include/cpython/unicodeobject.h +++ b/Include/cpython/unicodeobject.h @@ -1016,6 +1016,9 @@ PyAPI_FUNC(PyObject*) _PyUnicode_FromId(_Py_Identifier*); and where the hash values are equal (i.e. a very probable match) */ PyAPI_FUNC(int) _PyUnicode_EQ(PyObject *, PyObject *); +/* Equality check. Returns -1 on failure. */ +PyAPI_FUNC(int) _PyUnicode_Equal(PyObject *, PyObject *); + PyAPI_FUNC(int) _PyUnicode_WideCharString_Converter(PyObject *, void *); PyAPI_FUNC(int) _PyUnicode_WideCharString_Opt_Converter(PyObject *, void *); diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index d4d1392d05bde..496d52f580f1f 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -42,6 +42,7 @@ typedef struct { uint16_t defaults_len; } _PyCallCache; + /* Add specialized versions of entries to this union. * * Do not break the invariant: sizeof(SpecializedCacheEntry) == 8 @@ -273,6 +274,7 @@ int _Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub, _Py_CODEUNIT int _Py_Specialize_CallFunction(PyObject *callable, _Py_CODEUNIT *instr, int nargs, SpecializedCacheEntry *cache, PyObject *builtins); void _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache); +void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache); #define PRINT_SPECIALIZATION_STATS 0 #define PRINT_SPECIALIZATION_STATS_DETAILED 0 diff --git a/Include/opcode.h b/Include/opcode.h index 2c1a212cbd634..f22f7e94f6190 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -121,43 +121,47 @@ extern "C" { #define BINARY_OP_MULTIPLY_FLOAT 18 #define BINARY_OP_SUBTRACT_INT 19 #define BINARY_OP_SUBTRACT_FLOAT 20 -#define BINARY_SUBSCR_ADAPTIVE 21 -#define BINARY_SUBSCR_GETITEM 22 -#define BINARY_SUBSCR_LIST_INT 23 -#define BINARY_SUBSCR_TUPLE_INT 24 -#define BINARY_SUBSCR_DICT 26 -#define STORE_SUBSCR_ADAPTIVE 27 -#define STORE_SUBSCR_LIST_INT 28 -#define STORE_SUBSCR_DICT 29 -#define CALL_FUNCTION_ADAPTIVE 34 -#define CALL_FUNCTION_BUILTIN_O 36 -#define CALL_FUNCTION_BUILTIN_FAST 38 -#define CALL_FUNCTION_LEN 39 -#define CALL_FUNCTION_ISINSTANCE 40 -#define CALL_FUNCTION_PY_SIMPLE 41 -#define JUMP_ABSOLUTE_QUICK 42 -#define LOAD_ATTR_ADAPTIVE 43 -#define LOAD_ATTR_INSTANCE_VALUE 44 -#define LOAD_ATTR_WITH_HINT 45 -#define LOAD_ATTR_SLOT 46 -#define LOAD_ATTR_MODULE 47 -#define LOAD_GLOBAL_ADAPTIVE 48 -#define LOAD_GLOBAL_MODULE 55 -#define LOAD_GLOBAL_BUILTIN 56 -#define LOAD_METHOD_ADAPTIVE 57 -#define LOAD_METHOD_CACHED 58 -#define LOAD_METHOD_CLASS 59 -#define LOAD_METHOD_MODULE 62 -#define LOAD_METHOD_NO_DICT 63 -#define STORE_ATTR_ADAPTIVE 64 -#define STORE_ATTR_INSTANCE_VALUE 65 -#define STORE_ATTR_SLOT 66 -#define STORE_ATTR_WITH_HINT 67 -#define LOAD_FAST__LOAD_FAST 75 -#define STORE_FAST__LOAD_FAST 76 -#define LOAD_FAST__LOAD_CONST 77 -#define LOAD_CONST__LOAD_FAST 78 -#define STORE_FAST__STORE_FAST 79 +#define COMPARE_OP_ADAPTIVE 21 +#define COMPARE_OP_FLOAT_JUMP 22 +#define COMPARE_OP_INT_JUMP 23 +#define COMPARE_OP_STR_JUMP 24 +#define BINARY_SUBSCR_ADAPTIVE 26 +#define BINARY_SUBSCR_GETITEM 27 +#define BINARY_SUBSCR_LIST_INT 28 +#define BINARY_SUBSCR_TUPLE_INT 29 +#define BINARY_SUBSCR_DICT 34 +#define STORE_SUBSCR_ADAPTIVE 36 +#define STORE_SUBSCR_LIST_INT 38 +#define STORE_SUBSCR_DICT 39 +#define CALL_FUNCTION_ADAPTIVE 40 +#define CALL_FUNCTION_BUILTIN_O 41 +#define CALL_FUNCTION_BUILTIN_FAST 42 +#define CALL_FUNCTION_LEN 43 +#define CALL_FUNCTION_ISINSTANCE 44 +#define CALL_FUNCTION_PY_SIMPLE 45 +#define JUMP_ABSOLUTE_QUICK 46 +#define LOAD_ATTR_ADAPTIVE 47 +#define LOAD_ATTR_INSTANCE_VALUE 48 +#define LOAD_ATTR_WITH_HINT 55 +#define LOAD_ATTR_SLOT 56 +#define LOAD_ATTR_MODULE 57 +#define LOAD_GLOBAL_ADAPTIVE 58 +#define LOAD_GLOBAL_MODULE 59 +#define LOAD_GLOBAL_BUILTIN 62 +#define LOAD_METHOD_ADAPTIVE 63 +#define LOAD_METHOD_CACHED 64 +#define LOAD_METHOD_CLASS 65 +#define LOAD_METHOD_MODULE 66 +#define LOAD_METHOD_NO_DICT 67 +#define STORE_ATTR_ADAPTIVE 75 +#define STORE_ATTR_INSTANCE_VALUE 76 +#define STORE_ATTR_SLOT 77 +#define STORE_ATTR_WITH_HINT 78 +#define LOAD_FAST__LOAD_FAST 79 +#define STORE_FAST__LOAD_FAST 80 +#define LOAD_FAST__LOAD_CONST 81 +#define LOAD_CONST__LOAD_FAST 87 +#define STORE_FAST__STORE_FAST 88 #define DO_TRACING 255 #ifdef NEED_OPCODE_JUMP_TABLES static uint32_t _PyOpcode_RelativeJump[8] = { diff --git a/Lib/opcode.py b/Lib/opcode.py index 60805e92ff3c4..e5889bca4c161 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -234,6 +234,10 @@ def jabs_op(name, op): "BINARY_OP_MULTIPLY_FLOAT", "BINARY_OP_SUBTRACT_INT", "BINARY_OP_SUBTRACT_FLOAT", + "COMPARE_OP_ADAPTIVE", + "COMPARE_OP_FLOAT_JUMP", + "COMPARE_OP_INT_JUMP", + "COMPARE_OP_STR_JUMP", "BINARY_SUBSCR_ADAPTIVE", "BINARY_SUBSCR_GETITEM", "BINARY_SUBSCR_LIST_INT", diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-23-21-01-56.bpo-45885.3IxeCX.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-23-21-01-56.bpo-45885.3IxeCX.rst new file mode 100644 index 0000000000000..316daf966f149 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-23-21-01-56.bpo-45885.3IxeCX.rst @@ -0,0 +1 @@ +Specialized the ``COMPARE_OP`` opcode using the PEP 659 machinery. \ No newline at end of file diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 61fc34d71da3c..532c48ad4d4aa 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -11168,6 +11168,20 @@ unicode_compare_eq(PyObject *str1, PyObject *str2) return (cmp == 0); } +int +_PyUnicode_Equal(PyObject *str1, PyObject *str2) +{ + assert(PyUnicode_CheckExact(str1)); + assert(PyUnicode_CheckExact(str2)); + if (str1 == str2) { + return 1; + } + if (PyUnicode_READY(str1) || PyUnicode_READY(str2)) { + return -1; + } + return unicode_compare_eq(str1, str2); +} + int PyUnicode_Compare(PyObject *left, PyObject *right) diff --git a/Python/ceval.c b/Python/ceval.c index 97c684479abdc..05897c561a16e 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3778,6 +3778,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr } TARGET(COMPARE_OP) { + PREDICTED(COMPARE_OP); + STAT_INC(COMPARE_OP, unquickened); assert(oparg <= Py_GE); PyObject *right = POP(); PyObject *left = TOP(); @@ -3792,6 +3794,125 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr DISPATCH(); } + TARGET(COMPARE_OP_ADAPTIVE) { + assert(cframe.use_tracing == 0); + SpecializedCacheEntry *cache = GET_CACHE(); + if (cache->adaptive.counter == 0) { + PyObject *right = TOP(); + PyObject *left = SECOND(); + next_instr--; + _Py_Specialize_CompareOp(left, right, next_instr, cache); + DISPATCH(); + } + else { + STAT_INC(COMPARE_OP, deferred); + cache->adaptive.counter--; + oparg = cache->adaptive.original_oparg; + STAT_DEC(COMPARE_OP, unquickened); + JUMP_TO_INSTRUCTION(COMPARE_OP); + } + } + + TARGET(COMPARE_OP_FLOAT_JUMP) { + assert(cframe.use_tracing == 0); + // Combined: COMPARE_OP (float ? float) + POP_JUMP_IF_(true/false) + SpecializedCacheEntry *caches = GET_CACHE(); + int when_to_jump_mask = caches[0].adaptive.index; + PyObject *right = TOP(); + PyObject *left = SECOND(); + DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_OP); + DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_OP); + double dleft = PyFloat_AS_DOUBLE(left); + double dright = PyFloat_AS_DOUBLE(right); + int sign = (dleft > dright) - (dleft < dright); + DEOPT_IF(isnan(dleft), COMPARE_OP); + DEOPT_IF(isnan(dright), COMPARE_OP); + STAT_INC(COMPARE_OP, hit); + NEXTOPARG(); + STACK_SHRINK(2); + Py_DECREF(left); + Py_DECREF(right); + assert(opcode == POP_JUMP_IF_TRUE || opcode == POP_JUMP_IF_FALSE); + int jump = (1 << (sign + 1)) & when_to_jump_mask; + if (!jump) { + next_instr++; + NOTRACE_DISPATCH(); + } + else { + JUMPTO(oparg); + CHECK_EVAL_BREAKER(); + NOTRACE_DISPATCH(); + } + } + + TARGET(COMPARE_OP_INT_JUMP) { + assert(cframe.use_tracing == 0); + // Combined: COMPARE_OP (int ? int) + POP_JUMP_IF_(true/false) + SpecializedCacheEntry *caches = GET_CACHE(); + int when_to_jump_mask = caches[0].adaptive.index; + PyObject *right = TOP(); + PyObject *left = SECOND(); + DEOPT_IF(!PyLong_CheckExact(left), COMPARE_OP); + DEOPT_IF(!PyLong_CheckExact(right), COMPARE_OP); + DEOPT_IF((size_t)(Py_SIZE(left) + 1) > 2, COMPARE_OP); + DEOPT_IF((size_t)(Py_SIZE(right) + 1) > 2, COMPARE_OP); + STAT_INC(COMPARE_OP, hit); + assert(Py_ABS(Py_SIZE(left)) <= 1 && Py_ABS(Py_SIZE(right)) <= 1); + Py_ssize_t ileft = Py_SIZE(left) * ((PyLongObject *)left)->ob_digit[0]; + Py_ssize_t iright = Py_SIZE(right) * ((PyLongObject *)right)->ob_digit[0]; + int sign = (ileft > iright) - (ileft < iright); + NEXTOPARG(); + STACK_SHRINK(2); + Py_DECREF(left); + Py_DECREF(right); + assert(opcode == POP_JUMP_IF_TRUE || opcode == POP_JUMP_IF_FALSE); + int jump = (1 << (sign + 1)) & when_to_jump_mask; + if (!jump) { + next_instr++; + NOTRACE_DISPATCH(); + } + else { + JUMPTO(oparg); + CHECK_EVAL_BREAKER(); + NOTRACE_DISPATCH(); + } + } + + TARGET(COMPARE_OP_STR_JUMP) { + assert(cframe.use_tracing == 0); + // Combined: COMPARE_OP (str == str or str != str) + POP_JUMP_IF_(true/false) + SpecializedCacheEntry *caches = GET_CACHE(); + int invert = caches[0].adaptive.index; + PyObject *right = TOP(); + PyObject *left = SECOND(); + DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_OP); + DEOPT_IF(!PyUnicode_CheckExact(right), COMPARE_OP); + STAT_INC(COMPARE_OP, hit); + int res = _PyUnicode_Equal(left, right); + if (res < 0) { + goto error; + } + assert(caches[0].adaptive.original_oparg == Py_EQ || + caches[0].adaptive.original_oparg == Py_NE); + NEXTOPARG(); + assert(opcode == POP_JUMP_IF_TRUE || opcode == POP_JUMP_IF_FALSE); + STACK_SHRINK(2); + Py_DECREF(left); + Py_DECREF(right); + assert(res == 0 || res == 1); + assert(invert == 0 || invert == 1); + int jump = res ^ invert; + if (!jump) { + next_instr++; + NOTRACE_DISPATCH(); + } + else { + JUMPTO(oparg); + CHECK_EVAL_BREAKER(); + NOTRACE_DISPATCH(); + } + } + TARGET(IS_OP) { PyObject *right = POP(); PyObject *left = TOP(); @@ -5083,6 +5204,7 @@ MISS_WITH_CACHE(LOAD_GLOBAL) MISS_WITH_CACHE(LOAD_METHOD) MISS_WITH_CACHE(CALL_FUNCTION) MISS_WITH_CACHE(BINARY_OP) +MISS_WITH_CACHE(COMPARE_OP) MISS_WITH_CACHE(BINARY_SUBSCR) MISS_WITH_OPARG_COUNTER(STORE_SUBSCR) diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index c9d430d26814c..872a688311992 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -20,23 +20,27 @@ static void *opcode_targets[256] = { &&TARGET_BINARY_OP_MULTIPLY_FLOAT, &&TARGET_BINARY_OP_SUBTRACT_INT, &&TARGET_BINARY_OP_SUBTRACT_FLOAT, + &&TARGET_COMPARE_OP_ADAPTIVE, + &&TARGET_COMPARE_OP_FLOAT_JUMP, + &&TARGET_COMPARE_OP_INT_JUMP, + &&TARGET_COMPARE_OP_STR_JUMP, + &&TARGET_BINARY_SUBSCR, &&TARGET_BINARY_SUBSCR_ADAPTIVE, &&TARGET_BINARY_SUBSCR_GETITEM, &&TARGET_BINARY_SUBSCR_LIST_INT, &&TARGET_BINARY_SUBSCR_TUPLE_INT, - &&TARGET_BINARY_SUBSCR, - &&TARGET_BINARY_SUBSCR_DICT, - &&TARGET_STORE_SUBSCR_ADAPTIVE, - &&TARGET_STORE_SUBSCR_LIST_INT, - &&TARGET_STORE_SUBSCR_DICT, &&TARGET_GET_LEN, &&TARGET_MATCH_MAPPING, &&TARGET_MATCH_SEQUENCE, &&TARGET_MATCH_KEYS, - &&TARGET_CALL_FUNCTION_ADAPTIVE, + &&TARGET_BINARY_SUBSCR_DICT, &&TARGET_PUSH_EXC_INFO, - &&TARGET_CALL_FUNCTION_BUILTIN_O, + &&TARGET_STORE_SUBSCR_ADAPTIVE, &&TARGET_POP_EXCEPT_AND_RERAISE, + &&TARGET_STORE_SUBSCR_LIST_INT, + &&TARGET_STORE_SUBSCR_DICT, + &&TARGET_CALL_FUNCTION_ADAPTIVE, + &&TARGET_CALL_FUNCTION_BUILTIN_O, &&TARGET_CALL_FUNCTION_BUILTIN_FAST, &&TARGET_CALL_FUNCTION_LEN, &&TARGET_CALL_FUNCTION_ISINSTANCE, @@ -44,29 +48,25 @@ static void *opcode_targets[256] = { &&TARGET_JUMP_ABSOLUTE_QUICK, &&TARGET_LOAD_ATTR_ADAPTIVE, &&TARGET_LOAD_ATTR_INSTANCE_VALUE, - &&TARGET_LOAD_ATTR_WITH_HINT, - &&TARGET_LOAD_ATTR_SLOT, - &&TARGET_LOAD_ATTR_MODULE, - &&TARGET_LOAD_GLOBAL_ADAPTIVE, &&TARGET_WITH_EXCEPT_START, &&TARGET_GET_AITER, &&TARGET_GET_ANEXT, &&TARGET_BEFORE_ASYNC_WITH, &&TARGET_BEFORE_WITH, &&TARGET_END_ASYNC_FOR, + &&TARGET_LOAD_ATTR_WITH_HINT, + &&TARGET_LOAD_ATTR_SLOT, + &&TARGET_LOAD_ATTR_MODULE, + &&TARGET_LOAD_GLOBAL_ADAPTIVE, &&TARGET_LOAD_GLOBAL_MODULE, + &&TARGET_STORE_SUBSCR, + &&TARGET_DELETE_SUBSCR, &&TARGET_LOAD_GLOBAL_BUILTIN, &&TARGET_LOAD_METHOD_ADAPTIVE, &&TARGET_LOAD_METHOD_CACHED, &&TARGET_LOAD_METHOD_CLASS, - &&TARGET_STORE_SUBSCR, - &&TARGET_DELETE_SUBSCR, &&TARGET_LOAD_METHOD_MODULE, &&TARGET_LOAD_METHOD_NO_DICT, - &&TARGET_STORE_ATTR_ADAPTIVE, - &&TARGET_STORE_ATTR_INSTANCE_VALUE, - &&TARGET_STORE_ATTR_SLOT, - &&TARGET_STORE_ATTR_WITH_HINT, &&TARGET_GET_ITER, &&TARGET_GET_YIELD_FROM_ITER, &&TARGET_PRINT_EXPR, @@ -74,20 +74,20 @@ static void *opcode_targets[256] = { &&TARGET_YIELD_FROM, &&TARGET_GET_AWAITABLE, &&TARGET_LOAD_ASSERTION_ERROR, + &&TARGET_STORE_ATTR_ADAPTIVE, + &&TARGET_STORE_ATTR_INSTANCE_VALUE, + &&TARGET_STORE_ATTR_SLOT, + &&TARGET_STORE_ATTR_WITH_HINT, &&TARGET_LOAD_FAST__LOAD_FAST, &&TARGET_STORE_FAST__LOAD_FAST, &&TARGET_LOAD_FAST__LOAD_CONST, - &&TARGET_LOAD_CONST__LOAD_FAST, - &&TARGET_STORE_FAST__STORE_FAST, - &&_unknown_opcode, - &&_unknown_opcode, &&TARGET_LIST_TO_TUPLE, &&TARGET_RETURN_VALUE, &&TARGET_IMPORT_STAR, &&TARGET_SETUP_ANNOTATIONS, &&TARGET_YIELD_VALUE, - &&_unknown_opcode, - &&_unknown_opcode, + &&TARGET_LOAD_CONST__LOAD_FAST, + &&TARGET_STORE_FAST__STORE_FAST, &&TARGET_POP_EXCEPT, &&TARGET_STORE_NAME, &&TARGET_DELETE_NAME, diff --git a/Python/specialize.c b/Python/specialize.c index f5f12139df79b..b384675560be7 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -129,6 +129,7 @@ _Py_GetSpecializationStats(void) { err += add_stat_dict(stats, STORE_ATTR, "store_attr"); err += add_stat_dict(stats, CALL_FUNCTION, "call_function"); err += add_stat_dict(stats, BINARY_OP, "binary_op"); + err += add_stat_dict(stats, COMPARE_OP, "compare_op"); if (err < 0) { Py_DECREF(stats); return NULL; @@ -187,6 +188,7 @@ _Py_PrintSpecializationStats(void) print_stats(out, &_specialization_stats[STORE_ATTR], "store_attr"); print_stats(out, &_specialization_stats[CALL_FUNCTION], "call_function"); print_stats(out, &_specialization_stats[BINARY_OP], "binary_op"); + print_stats(out, &_specialization_stats[COMPARE_OP], "compare_op"); if (out != stderr) { fclose(out); } @@ -239,6 +241,7 @@ static uint8_t adaptive_opcodes[256] = { [CALL_FUNCTION] = CALL_FUNCTION_ADAPTIVE, [STORE_ATTR] = STORE_ATTR_ADAPTIVE, [BINARY_OP] = BINARY_OP_ADAPTIVE, + [COMPARE_OP] = COMPARE_OP_ADAPTIVE, }; /* The number of cache entries required for a "family" of instructions. */ @@ -251,6 +254,7 @@ static uint8_t cache_requirements[256] = { [CALL_FUNCTION] = 2, /* _PyAdaptiveEntry and _PyObjectCache/_PyCallCache */ [STORE_ATTR] = 2, /* _PyAdaptiveEntry and _PyAttrCache */ [BINARY_OP] = 1, // _PyAdaptiveEntry + [COMPARE_OP] = 1, /* _PyAdaptiveEntry */ }; /* Return the oparg for the cache_offset and instruction index. @@ -487,6 +491,10 @@ initial_counter_value(void) { #define SPEC_FAIL_BAD_CALL_FLAGS 17 #define SPEC_FAIL_CLASS 18 +/* COMPARE_OP */ +#define SPEC_FAIL_STRING_COMPARE 13 +#define SPEC_FAIL_NOT_FOLLOWED_BY_COND_JUMP 14 +#define SPEC_FAIL_BIG_INT 15 static int specialize_module_load_attr( @@ -1536,3 +1544,74 @@ _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, STAT_INC(BINARY_OP, specialization_success); adaptive->counter = initial_counter_value(); } + +static int compare_masks[] = { + // 1-bit: jump if less than + // 2-bit: jump if equal + // 4-bit: jump if greater + [Py_LT] = 1 | 0 | 0, + [Py_LE] = 1 | 2 | 0, + [Py_EQ] = 0 | 2 | 0, + [Py_NE] = 1 | 0 | 4, + [Py_GT] = 0 | 0 | 4, + [Py_GE] = 0 | 2 | 4, +}; + +void +_Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, + _Py_CODEUNIT *instr, SpecializedCacheEntry *cache) +{ + _PyAdaptiveEntry *adaptive = &cache->adaptive; + int op = adaptive->original_oparg; + int next_opcode = _Py_OPCODE(instr[1]); + if (next_opcode != POP_JUMP_IF_FALSE && next_opcode != POP_JUMP_IF_TRUE) { + // Can't ever combine, so don't don't bother being adaptive. + SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_NOT_FOLLOWED_BY_COND_JUMP); + *instr = _Py_MAKECODEUNIT(COMPARE_OP, adaptive->original_oparg); + goto failure; + } + assert(op <= Py_GE); + int when_to_jump_mask = compare_masks[op]; + if (next_opcode == POP_JUMP_IF_FALSE) { + when_to_jump_mask = (1 | 2 | 4) & ~when_to_jump_mask; + } + if (Py_TYPE(lhs) != Py_TYPE(rhs)) { + SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_DIFFERENT_TYPES); + goto failure; + } + if (PyFloat_CheckExact(lhs)) { + *instr = _Py_MAKECODEUNIT(COMPARE_OP_FLOAT_JUMP, _Py_OPARG(*instr)); + adaptive->index = when_to_jump_mask; + goto success; + } + if (PyLong_CheckExact(lhs)) { + if (Py_ABS(Py_SIZE(lhs)) <= 1 && Py_ABS(Py_SIZE(rhs)) <= 1) { + *instr = _Py_MAKECODEUNIT(COMPARE_OP_INT_JUMP, _Py_OPARG(*instr)); + adaptive->index = when_to_jump_mask; + goto success; + } + else { + SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_BIG_INT); + goto failure; + } + } + if (PyUnicode_CheckExact(lhs)) { + if (op != Py_EQ && op != Py_NE) { + SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_STRING_COMPARE); + goto failure; + } + else { + *instr = _Py_MAKECODEUNIT(COMPARE_OP_STR_JUMP, _Py_OPARG(*instr)); + adaptive->index = (when_to_jump_mask & 2) == 0; + goto success; + } + } + SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_OTHER); +failure: + STAT_INC(COMPARE_OP, specialization_failure); + cache_backoff(adaptive); + return; +success: + STAT_INC(COMPARE_OP, specialization_success); + adaptive->counter = initial_counter_value(); +} From webhook-mailer at python.org Fri Dec 3 08:47:17 2021 From: webhook-mailer at python.org (tiran) Date: Fri, 03 Dec 2021 13:47:17 -0000 Subject: [Python-checkins] bpo-45582: Fix out-of-tree build issues with new getpath (GH-29902) Message-ID: https://github.com/python/cpython/commit/ccb73a0d50dd03bc8455fe210cb83e41a6dc91d8 commit: ccb73a0d50dd03bc8455fe210cb83e41a6dc91d8 branch: main author: Christian Heimes committer: tiran date: 2021-12-03T14:47:06+01:00 summary: bpo-45582: Fix out-of-tree build issues with new getpath (GH-29902) files: M .gitignore M Makefile.pre.in M Modules/getpath.c M PCbuild/_freeze_module.vcxproj diff --git a/.gitignore b/.gitignore index 7e80446d4d4a6..0363244bdaf63 100644 --- a/.gitignore +++ b/.gitignore @@ -74,7 +74,6 @@ Mac/pythonw Misc/python.pc Misc/python-embed.pc Misc/python-config.sh -Modules/getpath.h Modules/Setup.config Modules/Setup.local Modules/Setup.stdlib diff --git a/Makefile.pre.in b/Makefile.pre.in index 3dc131b6c9651..264011f226bbc 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1062,10 +1062,9 @@ FROZEN_FILES_OUT = \ Programs/_freeze_module.o: Programs/_freeze_module.c Makefile Modules/getpath_noop.o: $(srcdir)/Modules/getpath_noop.c Makefile - $(CC) -c $(PY_CORE_CFLAGS) -o $@ $(srcdir)/Modules/getpath_noop.c -Programs/_freeze_module: Programs/_freeze_module.o $(LIBRARY_OBJS_OMIT_FROZEN) Modules/getpath_noop.o - $(LINKCC) $(PY_CORE_LDFLAGS) -o $@ Programs/_freeze_module.o $(LIBRARY_OBJS_OMIT_FROZEN) Modules/getpath_noop.o $(LIBS) $(MODLIBS) $(SYSLIBS) +Programs/_freeze_module: Programs/_freeze_module.o Modules/getpath_noop.o $(LIBRARY_OBJS_OMIT_FROZEN) + $(LINKCC) $(PY_CORE_LDFLAGS) -o $@ Programs/_freeze_module.o Modules/getpath_noop.o $(LIBRARY_OBJS_OMIT_FROZEN) $(LIBS) $(MODLIBS) $(SYSLIBS) # BEGIN: freezing modules @@ -1131,11 +1130,11 @@ Python/frozen_modules/frozen_only.h: $(FREEZE_MODULE) Tools/freeze/flag.py # END: freezing modules -Tools/scripts/freeze_modules.py: $(FREEZE_MODULE) - # We manually freeze getpath.py rather than through freeze_modules -Modules/getpath.h: Programs/_freeze_module Modules/getpath.py - Programs/_freeze_module getpath $(srcdir)/Modules/getpath.py $(srcdir)/Modules/getpath.h +Python/frozen_modules/getpath.h: $(FREEZE_MODULE) Modules/getpath.py + $(FREEZE_MODULE) getpath $(srcdir)/Modules/getpath.py Python/frozen_modules/getpath.h + +Tools/scripts/freeze_modules.py: $(FREEZE_MODULE) .PHONY: regen-frozen regen-frozen: Tools/scripts/freeze_modules.py $(FROZEN_FILES_IN) @@ -1177,7 +1176,7 @@ Modules/getbuildinfo.o: $(PARSER_OBJS) \ -DGITBRANCH="\"`LC_ALL=C $(GITBRANCH)`\"" \ -o $@ $(srcdir)/Modules/getbuildinfo.c -Modules/getpath.o: $(srcdir)/Modules/getpath.c Modules/getpath.h Makefile +Modules/getpath.o: $(srcdir)/Modules/getpath.c Python/frozen_modules/getpath.h Makefile $(PYTHON_HEADERS) $(CC) -c $(PY_CORE_CFLAGS) -DPYTHONPATH='"$(PYTHONPATH)"' \ -DPREFIX='"$(prefix)"' \ -DEXEC_PREFIX='"$(exec_prefix)"' \ diff --git a/Modules/getpath.c b/Modules/getpath.c index 32d5db9d2c4dc..f66fc8abbd4ff 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -19,7 +19,7 @@ #endif /* Reference the precompiled getpath.py */ -#include "getpath.h" +#include "../Python/frozen_modules/getpath.h" #if (!defined(PREFIX) || !defined(EXEC_PREFIX) \ || !defined(VERSION) || !defined(VPATH) \ diff --git a/PCbuild/_freeze_module.vcxproj b/PCbuild/_freeze_module.vcxproj index 7b2df4b8afcc2..07a6bfdde7402 100644 --- a/PCbuild/_freeze_module.vcxproj +++ b/PCbuild/_freeze_module.vcxproj @@ -379,7 +379,7 @@ getpath $(IntDir)getpath.g.h - $(PySourcePath)Modules\getpath.h + $(PySourcePath)Python\frozen_modules\getpath.h From webhook-mailer at python.org Fri Dec 3 10:01:20 2021 From: webhook-mailer at python.org (tiran) Date: Fri, 03 Dec 2021 15:01:20 -0000 Subject: [Python-checkins] bpo-45950: Introduce Bootstrap Python again (#29859) Message-ID: https://github.com/python/cpython/commit/84ca1232b0f1e4be368e89550a9ceb46f64a0eff commit: 84ca1232b0f1e4be368e89550a9ceb46f64a0eff branch: main author: Christian Heimes committer: tiran date: 2021-12-03T16:01:11+01:00 summary: bpo-45950: Introduce Bootstrap Python again (#29859) The build system now uses a :program:`_bootstrap_python` interpreter for freezing and deepfreezing again. To speed up build process the build tools :program:`_bootstrap_python` and :program:`_freeze_module` are no longer build with LTO. Cross building depends on a build Python interpreter, which must have same version and bytecode as target host Python. files: A Misc/NEWS.d/next/Build/2021-12-01-17-28-39.bpo-45950.eEVLoz.rst A Programs/_bootstrap_python.c D Python/bootstrap_frozen.c M .gitignore M Makefile.pre.in M Tools/scripts/deepfreeze.py M Tools/scripts/freeze_modules.py M configure M configure.ac diff --git a/.gitignore b/.gitignore index 0363244bdaf63..cfd3163cd1818 100644 --- a/.gitignore +++ b/.gitignore @@ -60,6 +60,7 @@ Lib/distutils/command/*.pdb Lib/lib2to3/*.pickle Lib/test/data/* !Lib/test/data/README +/_bootstrap_python /Makefile /Makefile.pre Mac/Makefile diff --git a/Makefile.pre.in b/Makefile.pre.in index 264011f226bbc..8e6e553554de1 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -90,6 +90,9 @@ CONFIGURE_CFLAGS_NODIST=@CFLAGS_NODIST@ # Use it when a linker flag should _not_ be part of the distutils LDFLAGS # once Python is installed (bpo-35257) CONFIGURE_LDFLAGS_NODIST=@LDFLAGS_NODIST@ +# LDFLAGS_NOLTO is an extra flag to disable lto. It is used to speed up building +# of _bootstrap_python and _freeze_module tools, which don't need LTO. +CONFIGURE_LDFLAGS_NOLTO=@LDFLAGS_NOLTO@ CONFIGURE_CPPFLAGS= @CPPFLAGS@ CONFIGURE_LDFLAGS= @LDFLAGS@ # Avoid assigning CFLAGS, LDFLAGS, etc. so users can use them on the @@ -103,6 +106,7 @@ PY_CFLAGS_NODIST=$(CONFIGURE_CFLAGS_NODIST) $(CFLAGS_NODIST) -I$(srcdir)/Include PY_CPPFLAGS= $(BASECPPFLAGS) -I. -I$(srcdir)/Include $(CONFIGURE_CPPFLAGS) $(CPPFLAGS) PY_LDFLAGS= $(CONFIGURE_LDFLAGS) $(LDFLAGS) PY_LDFLAGS_NODIST=$(CONFIGURE_LDFLAGS_NODIST) $(LDFLAGS_NODIST) +PY_LDFLAGS_NOLTO=$(PY_LDFLAGS) $(CONFIGURE_LDFLAGS_NOLTO) $(LDFLAGS_NODIST) NO_AS_NEEDED= @NO_AS_NEEDED@ CCSHARED= @CCSHARED@ # LINKFORSHARED are the flags passed to the $(CC) command that links @@ -279,6 +283,9 @@ BUILDPYTHON= python$(BUILDEXE) PYTHON_FOR_REGEN?=@PYTHON_FOR_REGEN@ UPDATE_FILE=$(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/update_file.py PYTHON_FOR_BUILD=@PYTHON_FOR_BUILD@ +# Standard builds use _bootstrap_python for freezing, cross compiling +# uses build Python, which must have the same version and bytecode, +PYTHON_FOR_FREEZE?=@PYTHON_FOR_FREEZE@ _PYTHON_HOST_PLATFORM=@_PYTHON_HOST_PLATFORM@ BUILD_GNU_TYPE= @build@ HOST_GNU_TYPE= @host@ @@ -938,75 +945,88 @@ regen-test-frozenmain: $(BUILDPYTHON) Programs/_testembed: Programs/_testembed.o $(LIBRARY_DEPS) $(LINKCC) $(PY_CORE_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/_testembed.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) +############################################################################ +# "Bootstrap Python" used to run deepfreeze.py + +BOOTSTRAP_HEADERS = \ + Python/frozen_modules/importlib._bootstrap.h \ + Python/frozen_modules/importlib._bootstrap_external.h + +Programs/_bootstrap_python.o: Programs/_bootstrap_python.c $(BOOTSTRAP_HEADERS) $(PYTHON_HEADERS) + +_bootstrap_python: $(LIBRARY_OBJS_OMIT_FROZEN) Programs/_bootstrap_python.o Modules/getpath.o Modules/Setup.local + $(LINKCC) $(PY_LDFLAGS_NOLTO) -o $@ $(LIBRARY_OBJS_OMIT_FROZEN) \ + Programs/_bootstrap_python.o Modules/getpath.o $(LIBS) $(MODLIBS) $(SYSLIBS) + ############################################################################ # Deepfreeze targets .PHONY: regen-deepfreeze regen-deepfreeze: $(DEEPFREEZE_OBJS) -DEEPFREEZE_DEPS=$(srcdir)/Tools/scripts/deepfreeze.py +DEEPFREEZE_DEPS=$(srcdir)/Tools/scripts/deepfreeze.py _bootstrap_python # BEGIN: deepfreeze modules Python/deepfreeze/importlib._bootstrap.c: Python/frozen_modules/importlib._bootstrap.h $(DEEPFREEZE_DEPS) - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/importlib._bootstrap.h -m importlib._bootstrap -o Python/deepfreeze/importlib._bootstrap.c + $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/importlib._bootstrap.h -m importlib._bootstrap -o Python/deepfreeze/importlib._bootstrap.c Python/deepfreeze/importlib._bootstrap_external.c: Python/frozen_modules/importlib._bootstrap_external.h $(DEEPFREEZE_DEPS) - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/importlib._bootstrap_external.h -m importlib._bootstrap_external -o Python/deepfreeze/importlib._bootstrap_external.c + $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/importlib._bootstrap_external.h -m importlib._bootstrap_external -o Python/deepfreeze/importlib._bootstrap_external.c Python/deepfreeze/zipimport.c: Python/frozen_modules/zipimport.h $(DEEPFREEZE_DEPS) - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/zipimport.h -m zipimport -o Python/deepfreeze/zipimport.c + $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/zipimport.h -m zipimport -o Python/deepfreeze/zipimport.c Python/deepfreeze/abc.c: Python/frozen_modules/abc.h $(DEEPFREEZE_DEPS) - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/abc.h -m abc -o Python/deepfreeze/abc.c + $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/abc.h -m abc -o Python/deepfreeze/abc.c Python/deepfreeze/codecs.c: Python/frozen_modules/codecs.h $(DEEPFREEZE_DEPS) - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/codecs.h -m codecs -o Python/deepfreeze/codecs.c + $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/codecs.h -m codecs -o Python/deepfreeze/codecs.c Python/deepfreeze/io.c: Python/frozen_modules/io.h $(DEEPFREEZE_DEPS) - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/io.h -m io -o Python/deepfreeze/io.c + $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/io.h -m io -o Python/deepfreeze/io.c Python/deepfreeze/_collections_abc.c: Python/frozen_modules/_collections_abc.h $(DEEPFREEZE_DEPS) - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/_collections_abc.h -m _collections_abc -o Python/deepfreeze/_collections_abc.c + $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/_collections_abc.h -m _collections_abc -o Python/deepfreeze/_collections_abc.c Python/deepfreeze/_sitebuiltins.c: Python/frozen_modules/_sitebuiltins.h $(DEEPFREEZE_DEPS) - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/_sitebuiltins.h -m _sitebuiltins -o Python/deepfreeze/_sitebuiltins.c + $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/_sitebuiltins.h -m _sitebuiltins -o Python/deepfreeze/_sitebuiltins.c Python/deepfreeze/genericpath.c: Python/frozen_modules/genericpath.h $(DEEPFREEZE_DEPS) - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/genericpath.h -m genericpath -o Python/deepfreeze/genericpath.c + $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/genericpath.h -m genericpath -o Python/deepfreeze/genericpath.c Python/deepfreeze/ntpath.c: Python/frozen_modules/ntpath.h $(DEEPFREEZE_DEPS) - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/ntpath.h -m ntpath -o Python/deepfreeze/ntpath.c + $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/ntpath.h -m ntpath -o Python/deepfreeze/ntpath.c Python/deepfreeze/posixpath.c: Python/frozen_modules/posixpath.h $(DEEPFREEZE_DEPS) - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/posixpath.h -m posixpath -o Python/deepfreeze/posixpath.c + $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/posixpath.h -m posixpath -o Python/deepfreeze/posixpath.c Python/deepfreeze/os.c: Python/frozen_modules/os.h $(DEEPFREEZE_DEPS) - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/os.h -m os -o Python/deepfreeze/os.c + $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/os.h -m os -o Python/deepfreeze/os.c Python/deepfreeze/site.c: Python/frozen_modules/site.h $(DEEPFREEZE_DEPS) - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/site.h -m site -o Python/deepfreeze/site.c + $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/site.h -m site -o Python/deepfreeze/site.c Python/deepfreeze/stat.c: Python/frozen_modules/stat.h $(DEEPFREEZE_DEPS) - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/stat.h -m stat -o Python/deepfreeze/stat.c + $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/stat.h -m stat -o Python/deepfreeze/stat.c Python/deepfreeze/__hello__.c: Python/frozen_modules/__hello__.h $(DEEPFREEZE_DEPS) - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/__hello__.h -m __hello__ -o Python/deepfreeze/__hello__.c + $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/__hello__.h -m __hello__ -o Python/deepfreeze/__hello__.c Python/deepfreeze/__phello__.c: Python/frozen_modules/__phello__.h $(DEEPFREEZE_DEPS) - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/__phello__.h -m __phello__ -o Python/deepfreeze/__phello__.c + $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/__phello__.h -m __phello__ -o Python/deepfreeze/__phello__.c Python/deepfreeze/__phello__.ham.c: Python/frozen_modules/__phello__.ham.h $(DEEPFREEZE_DEPS) - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/__phello__.ham.h -m __phello__.ham -o Python/deepfreeze/__phello__.ham.c + $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/__phello__.ham.h -m __phello__.ham -o Python/deepfreeze/__phello__.ham.c Python/deepfreeze/__phello__.ham.eggs.c: Python/frozen_modules/__phello__.ham.eggs.h $(DEEPFREEZE_DEPS) - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/__phello__.ham.eggs.h -m __phello__.ham.eggs -o Python/deepfreeze/__phello__.ham.eggs.c + $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/__phello__.ham.eggs.h -m __phello__.ham.eggs -o Python/deepfreeze/__phello__.ham.eggs.c Python/deepfreeze/__phello__.spam.c: Python/frozen_modules/__phello__.spam.h $(DEEPFREEZE_DEPS) - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/__phello__.spam.h -m __phello__.spam -o Python/deepfreeze/__phello__.spam.c + $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/__phello__.spam.h -m __phello__.spam -o Python/deepfreeze/__phello__.spam.c Python/deepfreeze/frozen_only.c: Python/frozen_modules/frozen_only.h $(DEEPFREEZE_DEPS) - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/frozen_only.h -m frozen_only -o Python/deepfreeze/frozen_only.c + $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/frozen_only.h -m frozen_only -o Python/deepfreeze/frozen_only.c # END: deepfreeze modules @@ -2295,6 +2315,7 @@ clean-retain-profile: pycremoval find build -name '*.py[co]' -exec rm -f {} ';' || true -rm -f pybuilddir.txt -rm -f Lib/lib2to3/*Grammar*.pickle + -rm -f _bootstrap_python -rm -f Programs/_testembed Programs/_freeze_module -rm -f Python/deepfreeze/*.[co] -rm -f Python/frozen_modules/*.h diff --git a/Misc/NEWS.d/next/Build/2021-12-01-17-28-39.bpo-45950.eEVLoz.rst b/Misc/NEWS.d/next/Build/2021-12-01-17-28-39.bpo-45950.eEVLoz.rst new file mode 100644 index 0000000000000..91f7560fd91d6 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-12-01-17-28-39.bpo-45950.eEVLoz.rst @@ -0,0 +1,4 @@ +The build system now uses a :program:`_bootstrap_python` interpreter for +freezing and deepfreezing again. To speed up build process the build tools +:program:`_bootstrap_python` and :program:`_freeze_module` are no longer +build with LTO. diff --git a/Programs/_bootstrap_python.c b/Programs/_bootstrap_python.c new file mode 100644 index 0000000000000..f2103fd5aaae5 --- /dev/null +++ b/Programs/_bootstrap_python.c @@ -0,0 +1,105 @@ + +/* Frozen modules bootstrap + * + * Limited and restricted Python interpreter to run + * "Tools/scripts/deepfreeze.py" on systems with no or older Python + * interpreter. + */ + +#include "Python.h" +#include "pycore_import.h" + +/* Includes for frozen modules: */ +#include "Python/frozen_modules/importlib._bootstrap.h" +#include "Python/frozen_modules/importlib._bootstrap_external.h" +/* End includes */ + +/* Note that a negative size indicates a package. */ + +static const struct _frozen bootstrap_modules[] = { + {"_frozen_importlib", _Py_M__importlib__bootstrap, (int)sizeof(_Py_M__importlib__bootstrap)}, + {"_frozen_importlib_external", _Py_M__importlib__bootstrap_external, (int)sizeof(_Py_M__importlib__bootstrap_external)}, + {0, 0, 0} /* bootstrap sentinel */ +}; +static const struct _frozen stdlib_modules[] = { + {0, 0, 0} /* stdlib sentinel */ +}; +static const struct _frozen test_modules[] = { + {0, 0, 0} /* test sentinel */ +}; +const struct _frozen *_PyImport_FrozenBootstrap = bootstrap_modules; +const struct _frozen *_PyImport_FrozenStdlib = stdlib_modules; +const struct _frozen *_PyImport_FrozenTest = test_modules; + +static const struct _module_alias aliases[] = { + {"_frozen_importlib", "importlib._bootstrap"}, + {"_frozen_importlib_external", "importlib._bootstrap_external"}, + {0, 0} /* aliases sentinel */ +}; +const struct _module_alias *_PyImport_FrozenAliases = aliases; + +/* Embedding apps may change this pointer to point to their favorite + collection of frozen modules: */ + +const struct _frozen *PyImport_FrozenModules = NULL; + +int +#ifdef MS_WINDOWS +wmain(int argc, wchar_t **argv) +#else +main(int argc, char **argv) +#endif +{ + PyStatus status; + + PyConfig config; + PyConfig_InitIsolatedConfig(&config); + // don't warn, pybuilddir.txt does not exist yet + config.pathconfig_warnings = 0; + // parse arguments + config.parse_argv = 1; + // add current script dir to sys.path + config.isolated = 0; + +#ifdef MS_WINDOWS + status = PyConfig_SetArgv(&config, argc, argv); +#else + status = PyConfig_SetBytesArgv(&config, argc, argv); +#endif + if (PyStatus_Exception(status)) { + goto error; + } + + status = PyConfig_Read(&config); + if (config.run_filename == NULL) { + status = PyStatus_Error("Run filename expected"); + goto error; + } + +#define CLEAR(ATTR) \ + do { \ + PyMem_RawFree(ATTR); \ + ATTR = NULL; \ + } while (0) + + // isolate from system Python + CLEAR(config.base_prefix); + CLEAR(config.prefix); + CLEAR(config.base_exec_prefix); + CLEAR(config.exec_prefix); + + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { + goto error; + } + PyConfig_Clear(&config); + + return Py_RunMain(); + +error: + PyConfig_Clear(&config); + if (PyStatus_IsExit(status)) { + return status.exitcode; + } + Py_ExitStatusException(status); +} diff --git a/Python/bootstrap_frozen.c b/Python/bootstrap_frozen.c deleted file mode 100644 index 68ba147a72710..0000000000000 --- a/Python/bootstrap_frozen.c +++ /dev/null @@ -1,45 +0,0 @@ - -/* Frozen modules bootstrap */ - -/* This file is linked with "bootstrap Python" - which is used (only) to run Tools/scripts/deepfreeze.py. */ - -#include "Python.h" -#include "pycore_import.h" - -/* Includes for frozen modules: */ -#include "frozen_modules/importlib._bootstrap.h" -#include "frozen_modules/importlib._bootstrap_external.h" -#include "frozen_modules/zipimport.h" -/* End includes */ - -/* Note that a negative size indicates a package. */ - -static const struct _frozen bootstrap_modules[] = { - {"_frozen_importlib", _Py_M__importlib__bootstrap, (int)sizeof(_Py_M__importlib__bootstrap)}, - {"_frozen_importlib_external", _Py_M__importlib__bootstrap_external, (int)sizeof(_Py_M__importlib__bootstrap_external)}, - {"zipimport", _Py_M__zipimport, (int)sizeof(_Py_M__zipimport)}, - {0, 0, 0} /* bootstrap sentinel */ -}; -static const struct _frozen stdlib_modules[] = { - {0, 0, 0} /* stdlib sentinel */ -}; -static const struct _frozen test_modules[] = { - {0, 0, 0} /* test sentinel */ -}; -const struct _frozen *_PyImport_FrozenBootstrap = bootstrap_modules; -const struct _frozen *_PyImport_FrozenStdlib = stdlib_modules; -const struct _frozen *_PyImport_FrozenTest = test_modules; - -static const struct _module_alias aliases[] = { - {"_frozen_importlib", "importlib._bootstrap"}, - {"_frozen_importlib_external", "importlib._bootstrap_external"}, - {0, 0} /* aliases sentinel */ -}; -const struct _module_alias *_PyImport_FrozenAliases = aliases; - - -/* Embedding apps may change this pointer to point to their favorite - collection of frozen modules: */ - -const struct _frozen *PyImport_FrozenModules = NULL; diff --git a/Tools/scripts/deepfreeze.py b/Tools/scripts/deepfreeze.py index 46776c768e648..30ca7bb0b6090 100644 --- a/Tools/scripts/deepfreeze.py +++ b/Tools/scripts/deepfreeze.py @@ -1,3 +1,8 @@ +"""Deep freeze + +The script is executed by _bootstrap_python interpreter. Shared library +extension modules are not available. +""" import argparse import ast import builtins @@ -8,7 +13,6 @@ import sys import time import types -import unicodedata from typing import Dict, FrozenSet, Tuple, TextIO import umarshal diff --git a/Tools/scripts/freeze_modules.py b/Tools/scripts/freeze_modules.py index 7496b6c868407..363a2e66bef52 100644 --- a/Tools/scripts/freeze_modules.py +++ b/Tools/scripts/freeze_modules.py @@ -589,7 +589,7 @@ def regen_makefile(modules): ]) deepfreezerules.append(f'{cfile}: {frozen_header} $(DEEPFREEZE_DEPS)') deepfreezerules.append( - f"\t$(PYTHON_FOR_REGEN) " + f"\t$(PYTHON_FOR_FREEZE) " f"$(srcdir)/Tools/scripts/deepfreeze.py " f"{frozen_header} -m {src.frozenid} -o {cfile}") deepfreezerules.append('') diff --git a/configure b/configure index 0aceffb35065a..5d47d03542e40 100755 --- a/configure +++ b/configure @@ -845,6 +845,7 @@ SHLIB_SUFFIX LIBTOOL_CRUFT OTHER_LIBTOOL_OPT UNIVERSAL_ARCH_FLAGS +LDFLAGS_NOLTO LDFLAGS_NODIST CFLAGS_NODIST BASECFLAGS @@ -932,6 +933,7 @@ CONFIG_ARGS SOVERSION VERSION PYTHON_FOR_REGEN +PYTHON_FOR_FREEZE PYTHON_FOR_BUILD FREEZE_MODULE host_os @@ -3250,6 +3252,7 @@ fi as_fn_error $? "\"$with_build_python\" has incompatible version $build_python_ver (expected: $PACKAGE_VERSION)" "$LINENO" 5 fi ac_cv_prog_PYTHON_FOR_REGEN=$with_build_python + PYTHON_FOR_FREEZE="$with_build_python" PYTHON_FOR_BUILD='_PYTHON_PROJECT_BASE=$(abs_builddir) _PYTHON_HOST_PLATFORM=$(_PYTHON_HOST_PLATFORM) PYTHONPATH=$(shell test -f pybuilddir.txt && echo $(abs_builddir)/`cat pybuilddir.txt`:)$(srcdir)/Lib _PYTHON_SYSCONFIGDATA_NAME=_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH) '$with_build_python { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_build_python" >&5 $as_echo "$with_build_python" >&6; } @@ -3261,12 +3264,19 @@ else fi PYTHON_FOR_BUILD='./$(BUILDPYTHON) -E' + PYTHON_FOR_FREEZE="./_bootstrap_python" fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python interpreter freezing" >&5 +$as_echo_n "checking for Python interpreter freezing... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_FOR_FREEZE" >&5 +$as_echo "$PYTHON_FOR_FREEZE" >&6; } + + for ac_prog in python$PACKAGE_VERSION python3.10 python3.9 python3.8 python3.7 python3.6 python3 python do # Extract the first word of "$ac_prog", so it can be a program name with args. @@ -3314,7 +3324,7 @@ test -n "$PYTHON_FOR_REGEN" || PYTHON_FOR_REGEN="python3" { $as_echo "$as_me:${as_lineno-$LINENO}: checking Python for regen version" >&5 $as_echo_n "checking Python for regen version... " >&6; } -if command -v $PYTHON_FOR_REGEN >/dev/null 2>&1; then +if command -v "$PYTHON_FOR_REGEN" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $($PYTHON_FOR_REGEN -V 2>/dev/null)" >&5 $as_echo "$($PYTHON_FOR_REGEN -V 2>/dev/null)" >&6; } else @@ -7101,6 +7111,7 @@ fi if test "$Py_LTO" = 'true' ; then case $CC in *clang*) + LDFLAGS_NOLTO="-fno-lto" if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}llvm-ar", so it can be a program name with args. @@ -7254,6 +7265,7 @@ $as_echo "$as_me: llvm-ar found via xcrun: ${LLVM_AR}" >&6;} then as_fn_error $? "thin lto is not supported under gcc compiler." "$LINENO" 5 fi + LDFLAGS_NOLTO="-fno-lto" case $ac_sys_system in Darwin*) LTOFLAGS="-flto -Wl,-export_dynamic" @@ -7534,6 +7546,7 @@ fi + # The -arch flags for universal builds on macOS UNIVERSAL_ARCH_FLAGS= diff --git a/configure.ac b/configure.ac index 99fa94d102909..b35c92acb85db 100644 --- a/configure.ac +++ b/configure.ac @@ -143,8 +143,9 @@ AC_ARG_WITH( if test "$build_python_ver" != "$PACKAGE_VERSION"; then AC_MSG_ERROR(["$with_build_python" has incompatible version $build_python_ver (expected: $PACKAGE_VERSION)]) fi - dnl use build Python for regeneration, too + dnl Build Python interpreter is used for regeneration and freezing. ac_cv_prog_PYTHON_FOR_REGEN=$with_build_python + PYTHON_FOR_FREEZE="$with_build_python" PYTHON_FOR_BUILD='_PYTHON_PROJECT_BASE=$(abs_builddir) _PYTHON_HOST_PLATFORM=$(_PYTHON_HOST_PLATFORM) PYTHONPATH=$(shell test -f pybuilddir.txt && echo $(abs_builddir)/`cat pybuilddir.txt`:)$(srcdir)/Lib _PYTHON_SYSCONFIGDATA_NAME=_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH) '$with_build_python AC_MSG_RESULT([$with_build_python]) ], [ @@ -152,17 +153,22 @@ AC_ARG_WITH( [AC_MSG_ERROR([Cross compiling requires --with-build-python])] ) PYTHON_FOR_BUILD='./$(BUILDPYTHON) -E' + PYTHON_FOR_FREEZE="./_bootstrap_python" ] ) AC_SUBST([PYTHON_FOR_BUILD]) +AC_MSG_CHECKING([for Python interpreter freezing]) +AC_MSG_RESULT([$PYTHON_FOR_FREEZE]) +AC_SUBST([PYTHON_FOR_FREEZE]) + AC_CHECK_PROGS([PYTHON_FOR_REGEN], [python$PACKAGE_VERSION python3.10 python3.9 python3.8 python3.7 python3.6 python3 python], [python3]) AC_SUBST(PYTHON_FOR_REGEN) AC_MSG_CHECKING([Python for regen version]) -if command -v $PYTHON_FOR_REGEN >/dev/null 2>&1; then +if command -v "$PYTHON_FOR_REGEN" >/dev/null 2>&1; then AC_MSG_RESULT([$($PYTHON_FOR_REGEN -V 2>/dev/null)]) else AC_MSG_RESULT([missing]) @@ -1510,6 +1516,8 @@ esac if test "$Py_LTO" = 'true' ; then case $CC in *clang*) + dnl flag to disable lto during linking + LDFLAGS_NOLTO="-fno-lto" AC_SUBST(LLVM_AR) AC_PATH_TOOL(LLVM_AR, llvm-ar, '', ${llvm_path}) AC_SUBST(LLVM_AR_FOUND) @@ -1565,6 +1573,8 @@ if test "$Py_LTO" = 'true' ; then then AC_MSG_ERROR([thin lto is not supported under gcc compiler.]) fi + dnl flag to disable lto during linking + LDFLAGS_NOLTO="-fno-lto" case $ac_sys_system in Darwin*) LTOFLAGS="-flto -Wl,-export_dynamic" @@ -1746,6 +1756,7 @@ fi AC_SUBST(BASECFLAGS) AC_SUBST(CFLAGS_NODIST) AC_SUBST(LDFLAGS_NODIST) +AC_SUBST(LDFLAGS_NOLTO) # The -arch flags for universal builds on macOS UNIVERSAL_ARCH_FLAGS= From webhook-mailer at python.org Fri Dec 3 14:05:24 2021 From: webhook-mailer at python.org (iritkatriel) Date: Fri, 03 Dec 2021 19:05:24 -0000 Subject: [Python-checkins] bpo-45711: [asyncio] Normalize exceptions immediately after Fetch, before they are stored as StackItem, which should be normalized (GH-29890) Message-ID: https://github.com/python/cpython/commit/2ff758bd1a144ee712e96ae1db91f476c3b252bb commit: 2ff758bd1a144ee712e96ae1db91f476c3b252bb branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-12-03T19:05:14Z summary: bpo-45711: [asyncio] Normalize exceptions immediately after Fetch, before they are stored as StackItem, which should be normalized (GH-29890) files: A Misc/NEWS.d/next/Library/2021-12-02-17-22-06.bpo-45711.D6jsdv.rst M Modules/_asynciomodule.c diff --git a/Misc/NEWS.d/next/Library/2021-12-02-17-22-06.bpo-45711.D6jsdv.rst b/Misc/NEWS.d/next/Library/2021-12-02-17-22-06.bpo-45711.D6jsdv.rst new file mode 100644 index 0000000000000..b2b57730c3ba8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-02-17-22-06.bpo-45711.D6jsdv.rst @@ -0,0 +1 @@ +Make :mod:`asyncio` normalize exceptions as soon as they are captured with :c:func:`PyErr_Fetch`, and before they are stored as an exc_info triplet. This brings :mod:`asyncio` in line with the rest of the codebase, where an exc_info triplet is always normalized. \ No newline at end of file diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index df6644ba248ed..267faacde8a17 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -2702,6 +2702,11 @@ task_step_impl(TaskObj *task, PyObject *exc) if (PyErr_ExceptionMatches(asyncio_CancelledError)) { /* CancelledError */ PyErr_Fetch(&et, &ev, &tb); + assert(et); + PyErr_NormalizeException(&et, &ev, &tb); + if (tb != NULL) { + PyException_SetTraceback(ev, tb); + } FutureObj *fut = (FutureObj*)task; _PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state; @@ -2714,14 +2719,12 @@ task_step_impl(TaskObj *task, PyObject *exc) /* Some other exception; pop it and call Task.set_exception() */ PyErr_Fetch(&et, &ev, &tb); - assert(et); - if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) { - PyErr_NormalizeException(&et, &ev, &tb); - } + PyErr_NormalizeException(&et, &ev, &tb); if (tb != NULL) { PyException_SetTraceback(ev, tb); } + o = future_set_exception((FutureObj*)task, ev); if (!o) { /* An exception in Task.set_exception() */ @@ -2965,7 +2968,7 @@ task_step(TaskObj *task, PyObject *exc) PyObject *et, *ev, *tb; PyErr_Fetch(&et, &ev, &tb); leave_task(task->task_loop, (PyObject*)task); - _PyErr_ChainExceptions(et, ev, tb); + _PyErr_ChainExceptions(et, ev, tb); /* Normalizes (et, ev, tb) */ return NULL; } else { @@ -3014,8 +3017,10 @@ task_wakeup(TaskObj *task, PyObject *o) } PyErr_Fetch(&et, &ev, &tb); - if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) { - PyErr_NormalizeException(&et, &ev, &tb); + assert(et); + PyErr_NormalizeException(&et, &ev, &tb); + if (tb != NULL) { + PyException_SetTraceback(ev, tb); } result = task_step(task, ev); From webhook-mailer at python.org Fri Dec 3 14:47:49 2021 From: webhook-mailer at python.org (zooba) Date: Fri, 03 Dec 2021 19:47:49 -0000 Subject: [Python-checkins] bpo-45816: Support building with VS 2022 (v143 toolset) on Windows (GH-29577) Message-ID: https://github.com/python/cpython/commit/d9301703fb1086cafbd730c17e3d450a192485d6 commit: d9301703fb1086cafbd730c17e3d450a192485d6 branch: main author: Crowthebird <78076854+thatbirdguythatuknownot at users.noreply.github.com> committer: zooba date: 2021-12-03T19:47:38Z summary: bpo-45816: Support building with VS 2022 (v143 toolset) on Windows (GH-29577) files: A Misc/NEWS.d/next/Build/2021-11-16-14-44-06.bpo-45816.nbdmVK.rst M PCbuild/pyproject.props M PCbuild/python.props M PCbuild/pythoncore.vcxproj M Tools/msi/bundle/bootstrap/pythonba.vcxproj diff --git a/Misc/NEWS.d/next/Build/2021-11-16-14-44-06.bpo-45816.nbdmVK.rst b/Misc/NEWS.d/next/Build/2021-11-16-14-44-06.bpo-45816.nbdmVK.rst new file mode 100644 index 0000000000000..4a14c90bf0138 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-16-14-44-06.bpo-45816.nbdmVK.rst @@ -0,0 +1 @@ +Python now supports building with Visual Studio 2022 (MSVC v143, VS Version 17.0). Patch by Jeremiah Vivian. \ No newline at end of file diff --git a/PCbuild/pyproject.props b/PCbuild/pyproject.props index bbcabb5cdb405..0eaeb6b1229a2 100644 --- a/PCbuild/pyproject.props +++ b/PCbuild/pyproject.props @@ -73,7 +73,7 @@ PGInstrument PGUpdate advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;%(AdditionalDependencies) - /OPT:REF,NOICF %(AdditionalOptions) + /OPT:REF,NOICF /CGTHREADS:1 /PDBTHREADS:1 %(AdditionalOptions) true diff --git a/PCbuild/python.props b/PCbuild/python.props index c608fb9ee7187..7b85ad1c94f16 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -11,7 +11,7 @@ We set BasePlatformToolset for ICC's benefit, it's otherwise ignored. --> - v142 + v143 v142 v141 v140 diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index b446e0995565e..119650a1eec51 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -588,7 +588,7 @@ - + diff --git a/Tools/msi/bundle/bootstrap/pythonba.vcxproj b/Tools/msi/bundle/bootstrap/pythonba.vcxproj index ef71fe7da08d3..d90b5e3ff0009 100644 --- a/Tools/msi/bundle/bootstrap/pythonba.vcxproj +++ b/Tools/msi/bundle/bootstrap/pythonba.vcxproj @@ -73,4 +73,4 @@ - \ No newline at end of file + From webhook-mailer at python.org Fri Dec 3 17:01:24 2021 From: webhook-mailer at python.org (iritkatriel) Date: Fri, 03 Dec 2021 22:01:24 -0000 Subject: [Python-checkins] bpo-45607: Make it possible to enrich exception displays via setting their __note__ field (GH-29880) Message-ID: https://github.com/python/cpython/commit/5bb7ef2768be5979b306e4c7552862b1746c251d commit: 5bb7ef2768be5979b306e4c7552862b1746c251d branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-12-03T22:01:15Z summary: bpo-45607: Make it possible to enrich exception displays via setting their __note__ field (GH-29880) files: A Misc/NEWS.d/next/Core and Builtins/2021-12-01-15-38-04.bpo-45607.JhuF8b.rst M Doc/library/exceptions.rst M Doc/whatsnew/3.11.rst M Include/cpython/pyerrors.h M Lib/test/test_exceptions.py M Lib/test/test_sys.py M Lib/test/test_traceback.py M Lib/traceback.py M Objects/exceptions.c M Python/pythonrun.c diff --git a/Doc/library/exceptions.rst b/Doc/library/exceptions.rst index 8fa82a98a199d..12d7d8abb2650 100644 --- a/Doc/library/exceptions.rst +++ b/Doc/library/exceptions.rst @@ -127,6 +127,14 @@ The following exceptions are used mostly as base classes for other exceptions. tb = sys.exc_info()[2] raise OtherException(...).with_traceback(tb) + .. attribute:: __note__ + + A mutable field which is :const:`None` by default and can be set to a string. + If it is not :const:`None`, it is included in the traceback. This field can + be used to enrich exceptions after they have been caught. + + .. versionadded:: 3.11 + .. exception:: Exception diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 1ec629d8229cb..c498225591a74 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -146,6 +146,12 @@ The :option:`-X` ``no_debug_ranges`` option and the environment variable See :pep:`657` for more details. (Contributed by Pablo Galindo, Batuhan Taskaya and Ammar Askar in :issue:`43950`.) +Exceptions can be enriched with a string ``__note__`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``__note__`` field was added to :exc:`BaseException`. It is ``None`` +by default but can be set to a string which is added to the exception's +traceback. (Contributed by Irit Katriel in :issue:`45607`.) Other Language Changes ====================== diff --git a/Include/cpython/pyerrors.h b/Include/cpython/pyerrors.h index a07018abae0cf..5281fde1f1a54 100644 --- a/Include/cpython/pyerrors.h +++ b/Include/cpython/pyerrors.h @@ -6,7 +6,7 @@ /* PyException_HEAD defines the initial segment of every exception class. */ #define PyException_HEAD PyObject_HEAD PyObject *dict;\ - PyObject *args; PyObject *traceback;\ + PyObject *args; PyObject *note; PyObject *traceback;\ PyObject *context; PyObject *cause;\ char suppress_context; diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index c6660043c805f..e4b7b8f0a6406 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -516,6 +516,27 @@ def testAttributes(self): 'pickled "%r", attribute "%s' % (e, checkArgName)) + def test_note(self): + for e in [BaseException(1), Exception(2), ValueError(3)]: + with self.subTest(e=e): + self.assertIsNone(e.__note__) + e.__note__ = "My Note" + self.assertEqual(e.__note__, "My Note") + + with self.assertRaises(TypeError): + e.__note__ = 42 + self.assertEqual(e.__note__, "My Note") + + e.__note__ = "Your Note" + self.assertEqual(e.__note__, "Your Note") + + with self.assertRaises(TypeError): + del e.__note__ + self.assertEqual(e.__note__, "Your Note") + + e.__note__ = None + self.assertIsNone(e.__note__) + def testWithTraceback(self): try: raise IndexError(4) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index db8d0082085cb..2b1ba2457f50d 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1298,13 +1298,13 @@ def inner(): class C(object): pass check(C.__dict__, size('P')) # BaseException - check(BaseException(), size('5Pb')) + check(BaseException(), size('6Pb')) # UnicodeEncodeError - check(UnicodeEncodeError("", "", 0, 0, ""), size('5Pb 2P2nP')) + check(UnicodeEncodeError("", "", 0, 0, ""), size('6Pb 2P2nP')) # UnicodeDecodeError - check(UnicodeDecodeError("", b"", 0, 0, ""), size('5Pb 2P2nP')) + check(UnicodeDecodeError("", b"", 0, 0, ""), size('6Pb 2P2nP')) # UnicodeTranslateError - check(UnicodeTranslateError("", 0, 1, ""), size('5Pb 2P2nP')) + check(UnicodeTranslateError("", 0, 1, ""), size('6Pb 2P2nP')) # ellipses check(Ellipsis, size('')) # EncodingMap diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index cde35f5dacb2d..a458b21b09466 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -1224,6 +1224,22 @@ def test_syntax_error_various_offsets(self): exp = "\n".join(expected) self.assertEqual(exp, err) + def test_exception_with_note(self): + e = ValueError(42) + vanilla = self.get_report(e) + + e.__note__ = 'My Note' + self.assertEqual(self.get_report(e), vanilla + 'My Note\n') + + e.__note__ = '' + self.assertEqual(self.get_report(e), vanilla + '\n') + + e.__note__ = 'Your Note' + self.assertEqual(self.get_report(e), vanilla + 'Your Note\n') + + e.__note__ = None + self.assertEqual(self.get_report(e), vanilla) + def test_exception_qualname(self): class A: class B: @@ -1566,6 +1582,59 @@ def test_exception_group_depth_limit(self): report = self.get_report(exc) self.assertEqual(report, expected) + def test_exception_group_with_notes(self): + def exc(): + try: + excs = [] + for msg in ['bad value', 'terrible value']: + try: + raise ValueError(msg) + except ValueError as e: + e.__note__ = f'the {msg}' + excs.append(e) + raise ExceptionGroup("nested", excs) + except ExceptionGroup as e: + e.__note__ = ('>> Multi line note\n' + '>> Because I am such\n' + '>> an important exception.\n' + '>> empty lines work too\n' + '\n' + '(that was an empty line)') + raise + + expected = (f' + Exception Group Traceback (most recent call last):\n' + f' | File "{__file__}", line {self.callable_line}, in get_exception\n' + f' | exception_or_callable()\n' + f' | ^^^^^^^^^^^^^^^^^^^^^^^\n' + f' | File "{__file__}", line {exc.__code__.co_firstlineno + 9}, in exc\n' + f' | raise ExceptionGroup("nested", excs)\n' + f' | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' + f' | ExceptionGroup: nested\n' + f' | >> Multi line note\n' + f' | >> Because I am such\n' + f' | >> an important exception.\n' + f' | >> empty lines work too\n' + f' | \n' + f' | (that was an empty line)\n' + f' +-+---------------- 1 ----------------\n' + f' | Traceback (most recent call last):\n' + f' | File "{__file__}", line {exc.__code__.co_firstlineno + 5}, in exc\n' + f' | raise ValueError(msg)\n' + f' | ^^^^^^^^^^^^^^^^^^^^^\n' + f' | ValueError: bad value\n' + f' | the bad value\n' + f' +---------------- 2 ----------------\n' + f' | Traceback (most recent call last):\n' + f' | File "{__file__}", line {exc.__code__.co_firstlineno + 5}, in exc\n' + f' | raise ValueError(msg)\n' + f' | ^^^^^^^^^^^^^^^^^^^^^\n' + f' | ValueError: terrible value\n' + f' | the terrible value\n' + f' +------------------------------------\n') + + report = self.get_report(exc) + self.assertEqual(report, expected) + class PyExcReportingTests(BaseExceptionReportingTests, unittest.TestCase): # diff --git a/Lib/traceback.py b/Lib/traceback.py index 77f8590719eb8..b244750fd016e 100644 --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -685,6 +685,8 @@ def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None, # Capture now to permit freeing resources: only complication is in the # unofficial API _format_final_exc_line self._str = _some_str(exc_value) + self.__note__ = exc_value.__note__ if exc_value else None + if exc_type and issubclass(exc_type, SyntaxError): # Handle SyntaxError's specially self.filename = exc_value.filename @@ -816,6 +818,8 @@ def format_exception_only(self): yield _format_final_exc_line(stype, self._str) else: yield from self._format_syntax_error(stype) + if self.__note__ is not None: + yield from [l + '\n' for l in self.__note__.split('\n')] def _format_syntax_error(self, stype): """Format SyntaxError exceptions (internal helper).""" diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-01-15-38-04.bpo-45607.JhuF8b.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-01-15-38-04.bpo-45607.JhuF8b.rst new file mode 100644 index 0000000000000..3e38c3e6f95e8 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-01-15-38-04.bpo-45607.JhuF8b.rst @@ -0,0 +1,4 @@ +The ``__note__`` field was added to :exc:`BaseException`. It is ``None`` +by default but can be set to a string which is added to the exception's +traceback. + diff --git a/Objects/exceptions.c b/Objects/exceptions.c index a5459da89a073..c99f17a30f169 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -46,6 +46,7 @@ BaseException_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; /* the dict is created on the fly in PyObject_GenericSetAttr */ self->dict = NULL; + self->note = NULL; self->traceback = self->cause = self->context = NULL; self->suppress_context = 0; @@ -81,6 +82,7 @@ BaseException_clear(PyBaseExceptionObject *self) { Py_CLEAR(self->dict); Py_CLEAR(self->args); + Py_CLEAR(self->note); Py_CLEAR(self->traceback); Py_CLEAR(self->cause); Py_CLEAR(self->context); @@ -105,6 +107,7 @@ BaseException_traverse(PyBaseExceptionObject *self, visitproc visit, void *arg) { Py_VISIT(self->dict); Py_VISIT(self->args); + Py_VISIT(self->note); Py_VISIT(self->traceback); Py_VISIT(self->cause); Py_VISIT(self->context); @@ -216,6 +219,33 @@ BaseException_set_args(PyBaseExceptionObject *self, PyObject *val, void *Py_UNUS return 0; } +static PyObject * +BaseException_get_note(PyBaseExceptionObject *self, void *Py_UNUSED(ignored)) +{ + if (self->note == NULL) { + Py_RETURN_NONE; + } + return Py_NewRef(self->note); +} + +static int +BaseException_set_note(PyBaseExceptionObject *self, PyObject *note, + void *Py_UNUSED(ignored)) +{ + if (note == NULL) { + PyErr_SetString(PyExc_TypeError, "__note__ may not be deleted"); + return -1; + } + else if (note != Py_None && !PyUnicode_CheckExact(note)) { + PyErr_SetString(PyExc_TypeError, "__note__ must be a string or None"); + return -1; + } + + Py_INCREF(note); + Py_XSETREF(self->note, note); + return 0; +} + static PyObject * BaseException_get_tb(PyBaseExceptionObject *self, void *Py_UNUSED(ignored)) { @@ -306,6 +336,7 @@ BaseException_set_cause(PyObject *self, PyObject *arg, void *Py_UNUSED(ignored)) static PyGetSetDef BaseException_getset[] = { {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict}, {"args", (getter)BaseException_get_args, (setter)BaseException_set_args}, + {"__note__", (getter)BaseException_get_note, (setter)BaseException_set_note}, {"__traceback__", (getter)BaseException_get_tb, (setter)BaseException_set_tb}, {"__context__", BaseException_get_context, BaseException_set_context, PyDoc_STR("exception context")}, diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 2f68b214603e1..5a118b4821ec0 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1083,6 +1083,41 @@ print_exception(struct exception_print_context *ctx, PyObject *value) PyErr_Clear(); } err += PyFile_WriteString("\n", f); + + if (err == 0 && PyExceptionInstance_Check(value)) { + _Py_IDENTIFIER(__note__); + + PyObject *note = _PyObject_GetAttrId(value, &PyId___note__); + if (note == NULL) { + err = -1; + } + if (err == 0 && PyUnicode_Check(note)) { + _Py_static_string(PyId_newline, "\n"); + PyObject *lines = PyUnicode_Split( + note, _PyUnicode_FromId(&PyId_newline), -1); + if (lines == NULL) { + err = -1; + } + else { + Py_ssize_t n = PyList_GET_SIZE(lines); + for (Py_ssize_t i = 0; i < n; i++) { + if (err == 0) { + PyObject *line = PyList_GET_ITEM(lines, i); + assert(PyUnicode_Check(line)); + err = write_indented_margin(ctx, f); + if (err == 0) { + err = PyFile_WriteObject(line, f, Py_PRINT_RAW); + } + if (err == 0) { + err = PyFile_WriteString("\n", f); + } + } + } + } + Py_DECREF(lines); + } + Py_XDECREF(note); + } Py_XDECREF(tb); Py_DECREF(value); /* If an error happened here, don't show it. From webhook-mailer at python.org Fri Dec 3 17:04:21 2021 From: webhook-mailer at python.org (zooba) Date: Fri, 03 Dec 2021 22:04:21 -0000 Subject: [Python-checkins] bpo-45582: Add a NOT operator to the condition in getpath_isxfile (GH-29906) Message-ID: https://github.com/python/cpython/commit/7d7c91a8e8c0bb04105a21a17d1061ffc1c04d80 commit: 7d7c91a8e8c0bb04105a21a17d1061ffc1c04d80 branch: main author: neonene <53406459+neonene at users.noreply.github.com> committer: zooba date: 2021-12-03T22:04:11Z summary: bpo-45582: Add a NOT operator to the condition in getpath_isxfile (GH-29906) files: M Modules/getpath.c diff --git a/Modules/getpath.c b/Modules/getpath.c index f66fc8abbd4ff..c8c85a8540d39 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -173,7 +173,9 @@ getpath_isdir(PyObject *Py_UNUSED(self), PyObject *args) path = PyUnicode_AsWideCharString(pathobj, NULL); if (path) { #ifdef MS_WINDOWS - r = (GetFileAttributesW(path) & FILE_ATTRIBUTE_DIRECTORY) ? Py_True : Py_False; + DWORD attr = GetFileAttributesW(path); + r = (attr != INVALID_FILE_ATTRIBUTES) && + (attr & FILE_ATTRIBUTE_DIRECTORY) ? Py_True : Py_False; #else struct stat st; r = (_Py_wstat(path, &st) == 0) && S_ISDIR(st.st_mode) ? Py_True : Py_False; @@ -197,7 +199,9 @@ getpath_isfile(PyObject *Py_UNUSED(self), PyObject *args) path = PyUnicode_AsWideCharString(pathobj, NULL); if (path) { #ifdef MS_WINDOWS - r = !(GetFileAttributesW(path) & FILE_ATTRIBUTE_DIRECTORY) ? Py_True : Py_False; + DWORD attr = GetFileAttributesW(path); + r = (attr != INVALID_FILE_ATTRIBUTES) && + !(attr & FILE_ATTRIBUTE_DIRECTORY) ? Py_True : Py_False; #else struct stat st; r = (_Py_wstat(path, &st) == 0) && S_ISREG(st.st_mode) ? Py_True : Py_False; @@ -223,7 +227,9 @@ getpath_isxfile(PyObject *Py_UNUSED(self), PyObject *args) if (path) { #ifdef MS_WINDOWS const wchar_t *ext; - r = (GetFileAttributesW(path) & FILE_ATTRIBUTE_DIRECTORY) && + DWORD attr = GetFileAttributesW(path); + r = (attr != INVALID_FILE_ATTRIBUTES) && + !(attr & FILE_ATTRIBUTE_DIRECTORY) && SUCCEEDED(PathCchFindExtension(path, cchPath, &ext)) && (CompareStringOrdinal(ext, -1, L".exe", -1, 1 /* ignore case */) == CSTR_EQUAL) ? Py_True : Py_False; From webhook-mailer at python.org Fri Dec 3 18:22:05 2021 From: webhook-mailer at python.org (miss-islington) Date: Fri, 03 Dec 2021 23:22:05 -0000 Subject: [Python-checkins] bpo-45582 Fix prototype of _Py_Get_Getpath_CodeObject. (GH-29907) Message-ID: https://github.com/python/cpython/commit/0ae4e0c959bbc90ec18180ef3cc957759d346ced commit: 0ae4e0c959bbc90ec18180ef3cc957759d346ced branch: main author: Benjamin Peterson committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-03T15:21:58-08:00 summary: bpo-45582 Fix prototype of _Py_Get_Getpath_CodeObject. (GH-29907) Automerge-Triggered-By: GH:tiran files: M Include/internal/pycore_initconfig.h diff --git a/Include/internal/pycore_initconfig.h b/Include/internal/pycore_initconfig.h index be545f495dc0f..a2f4cd182e8e9 100644 --- a/Include/internal/pycore_initconfig.h +++ b/Include/internal/pycore_initconfig.h @@ -168,7 +168,7 @@ PyAPI_FUNC(int) _PyConfig_FromDict(PyConfig *config, PyObject *dict); extern void _Py_DumpPathConfig(PyThreadState *tstate); -PyAPI_FUNC(PyObject*) _Py_Get_Getpath_CodeObject(); +PyAPI_FUNC(PyObject*) _Py_Get_Getpath_CodeObject(void); /* --- Function used for testing ---------------------------------- */ From webhook-mailer at python.org Fri Dec 3 21:37:16 2021 From: webhook-mailer at python.org (rhettinger) Date: Sat, 04 Dec 2021 02:37:16 -0000 Subject: [Python-checkins] bpo-20751: Replace method example with attribute example, matching the descriptor howto (GH-29909) Message-ID: https://github.com/python/cpython/commit/135ecc3492cee259090fd4aaed9056c130cd2eba commit: 135ecc3492cee259090fd4aaed9056c130cd2eba branch: main author: Raymond Hettinger committer: rhettinger date: 2021-12-03T20:37:08-06:00 summary: bpo-20751: Replace method example with attribute example, matching the descriptor howto (GH-29909) files: M Doc/reference/datamodel.rst diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index b14b2cb1ef5e4..41092458102de 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1818,10 +1818,38 @@ Class Binding ``A.__dict__['x'].__get__(None, A)``. Super Binding - If ``a`` is an instance of :class:`super`, then the binding ``super(B, obj).m()`` - searches ``obj.__class__.__mro__`` for the base class ``A`` - immediately following ``B`` and then invokes the descriptor with the call: - ``A.__dict__['m'].__get__(obj, obj.__class__)``. + A dotted lookup such as ``super(A, a).x`` searches + ``obj.__class__.__mro__`` for a base class ``B`` following ``A`` and then + returns ``B.__dict__['x'].__get__(a, A)``. If not a descriptor, ``x`` is + returned unchanged. + +.. testcode:: + :hide: + + class Desc: + def __get__(*args): + return args + + class B: + + x = Desc() + + class A(B): + + x = 999 + + def m(self): + 'Demonstrate these two calls are equivalent' + result1 = super(A, a).x + result2 = B.__dict__['x'].__get__(a, A) + return result1 == result2 + +.. doctest:: + :hide: + + >>> a = A() + >>> a.m() + True For instance bindings, the precedence of descriptor invocation depends on which descriptor methods are defined. A descriptor can define any combination From webhook-mailer at python.org Sat Dec 4 00:28:39 2021 From: webhook-mailer at python.org (terryjreedy) Date: Sat, 04 Dec 2021 05:28:39 -0000 Subject: [Python-checkins] bpo-45916: Use HTTPS link for The Perils of Floating Point (GH-29896) Message-ID: https://github.com/python/cpython/commit/257eea55860c5f35acce49c062c5823c7a3a1317 commit: 257eea55860c5f35acce49c062c5823c7a3a1317 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: terryjreedy date: 2021-12-04T00:28:30-05:00 summary: bpo-45916: Use HTTPS link for The Perils of Floating Point (GH-29896) (cherry picked from commit 9f2f7e42269db74a89fc8cd74d82a875787f01d7) Co-authored-by: Zachary Ware files: M Doc/tutorial/floatingpoint.rst diff --git a/Doc/tutorial/floatingpoint.rst b/Doc/tutorial/floatingpoint.rst index b98de6e56a003..7212b40be8377 100644 --- a/Doc/tutorial/floatingpoint.rst +++ b/Doc/tutorial/floatingpoint.rst @@ -133,7 +133,7 @@ with inexact values become comparable to one another:: Binary floating-point arithmetic holds many surprises like this. The problem with "0.1" is explained in precise detail below, in the "Representation Error" -section. See `The Perils of Floating Point `_ +section. See `The Perils of Floating Point `_ for a more complete account of other common surprises. As that says near the end, "there are no easy answers." Still, don't be unduly From webhook-mailer at python.org Sat Dec 4 05:08:04 2021 From: webhook-mailer at python.org (tiran) Date: Sat, 04 Dec 2021 10:08:04 -0000 Subject: [Python-checkins] bpo-45695: Test out-of-tree builds on GHA (GH-29904) Message-ID: https://github.com/python/cpython/commit/cee07b162843694e8166ad8715162d4d5886b50f commit: cee07b162843694e8166ad8715162d4d5886b50f branch: main author: Christian Heimes committer: tiran date: 2021-12-04T11:07:59+01:00 summary: bpo-45695: Test out-of-tree builds on GHA (GH-29904) files: A Misc/NEWS.d/next/Tests/2021-12-03-14-19-16.bpo-45695.QKBn2E.rst M .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fe4b14828699c..fbf7bb6fe2128 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -179,13 +179,28 @@ jobs: echo "PATH=/usr/lib/ccache:$PATH" >> $GITHUB_ENV - name: Configure ccache action uses: hendrikmuhs/ccache-action at v1 - - name: Configure CPython - run: ./configure --with-pydebug --with-openssl=$OPENSSL_DIR - - name: Build CPython + - name: Setup directory envs for out-of-tree builds + run: | + echo "CPYTHON_RO_SRCDIR=$(realpath -m ${GITHUB_WORKSPACE}/../cpython-ro-srcdir)" >> $GITHUB_ENV + echo "CPYTHON_BUILDDIR=$(realpath -m ${GITHUB_WORKSPACE}/../cpython-builddir)" >> $GITHUB_ENV + - name: Create directories for read-only out-of-tree builds + run: mkdir -p $CPYTHON_RO_SRCDIR $CPYTHON_BUILDDIR + - name: Bind mount sources read-only + run: sudo mount --bind -o ro $GITHUB_WORKSPACE $CPYTHON_RO_SRCDIR + - name: Configure CPython out-of-tree + working-directory: ${{ env.CPYTHON_BUILDDIR }} + run: ../cpython-ro-srcdir/configure --with-pydebug --with-openssl=$OPENSSL_DIR + - name: Build CPython out-of-tree + working-directory: ${{ env.CPYTHON_BUILDDIR }} run: make -j4 - name: Display build info + working-directory: ${{ env.CPYTHON_BUILDDIR }} run: make pythoninfo + - name: Remount sources writable for tests + # some tests write to srcdir, lack of pyc files slows down testing + run: sudo mount $CPYTHON_RO_SRCDIR -oremount,rw - name: Tests + working-directory: ${{ env.CPYTHON_BUILDDIR }} run: xvfb-run make buildbottest TESTOPTS="-j4 -uall,-cpu" build_ubuntu_ssltests: diff --git a/Misc/NEWS.d/next/Tests/2021-12-03-14-19-16.bpo-45695.QKBn2E.rst b/Misc/NEWS.d/next/Tests/2021-12-03-14-19-16.bpo-45695.QKBn2E.rst new file mode 100644 index 0000000000000..14ecd923dbd55 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-12-03-14-19-16.bpo-45695.QKBn2E.rst @@ -0,0 +1 @@ +Out-of-tree builds with a read-only source directory are now tested by CI. From webhook-mailer at python.org Sat Dec 4 05:21:50 2021 From: webhook-mailer at python.org (tiran) Date: Sat, 04 Dec 2021 10:21:50 -0000 Subject: [Python-checkins] bpo-45847: Port _ctypes partly to PY_STDLIB_MOD (GH-29747) Message-ID: https://github.com/python/cpython/commit/4045392e0e3446362841b3336497cb6eeccfcd23 commit: 4045392e0e3446362841b3336497cb6eeccfcd23 branch: main author: Christian Heimes committer: tiran date: 2021-12-04T11:21:43+01:00 summary: bpo-45847: Port _ctypes partly to PY_STDLIB_MOD (GH-29747) Co-authored-by: Erlend Egeberg Aasland files: M Modules/Setup.stdlib.in M configure M configure.ac M pyconfig.h.in M setup.py diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 9dfe918d05a09..ff92db3cc3784 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -130,6 +130,10 @@ ############################################################################ # Modules with third party dependencies # + +# needs -lffi and -ldl + at MODULE__CTYPES_TRUE@_ctypes _ctypes/_ctypes.c _ctypes/callbacks.c _ctypes/callproc.c _ctypes/stgdict.c _ctypes/cfield.c + @MODULE__SQLITE3_TRUE at _sqlite3 _sqlite/connection.c _sqlite/cursor.c _sqlite/microprotocols.c _sqlite/module.c _sqlite/prepare_protocol.c _sqlite/row.c _sqlite/statement.c _sqlite/util.c # needs -lssl and -lcrypt diff --git a/configure b/configure index 5d47d03542e40..8582224dfd28f 100755 --- a/configure +++ b/configure @@ -664,6 +664,8 @@ MODULE__GDBM_FALSE MODULE__GDBM_TRUE MODULE__DECIMAL_FALSE MODULE__DECIMAL_TRUE +MODULE__CTYPES_FALSE +MODULE__CTYPES_TRUE MODULE__CRYPT_FALSE MODULE__CRYPT_TRUE MODULE__BLAKE2_FALSE @@ -828,6 +830,8 @@ LIBMPDEC_INTERNAL LIBMPDEC_LDFLAGS LIBMPDEC_CFLAGS LIBFFI_INCLUDEDIR +LIBFFI_LIBS +LIBFFI_CFLAGS LIBEXPAT_INTERNAL LIBEXPAT_LDFLAGS LIBEXPAT_CFLAGS @@ -1060,6 +1064,8 @@ CPP PROFILE_TASK LIBUUID_CFLAGS LIBUUID_LIBS +LIBFFI_CFLAGS +LIBFFI_LIBS LIBNSL_CFLAGS LIBNSL_LIBS LIBSQLITE3_CFLAGS @@ -1857,6 +1863,9 @@ Some influential environment variables: C compiler flags for LIBUUID, overriding pkg-config LIBUUID_LIBS linker flags for LIBUUID, overriding pkg-config + LIBFFI_CFLAGS + C compiler flags for LIBFFI, overriding pkg-config + LIBFFI_LIBS linker flags for LIBFFI, overriding pkg-config LIBNSL_CFLAGS C compiler flags for LIBNSL, overriding pkg-config LIBNSL_LIBS linker flags for LIBNSL, overriding pkg-config @@ -11375,6 +11384,335 @@ $as_echo "$as_me: WARNING: --with(out)-system-ffi is ignored on this platform" > with_system_ffi="yes" fi +have_libffi=missing +if test "x$with_system_ffi" = xyes; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBFFI" >&5 +$as_echo_n "checking for LIBFFI... " >&6; } + +if test -n "$LIBFFI_CFLAGS"; then + pkg_cv_LIBFFI_CFLAGS="$LIBFFI_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libffi\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libffi") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBFFI_CFLAGS=`$PKG_CONFIG --cflags "libffi" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LIBFFI_LIBS"; then + pkg_cv_LIBFFI_LIBS="$LIBFFI_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libffi\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libffi") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBFFI_LIBS=`$PKG_CONFIG --libs "libffi" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LIBFFI_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libffi" 2>&1` + else + LIBFFI_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libffi" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LIBFFI_PKG_ERRORS" >&5 + + + ac_fn_c_check_header_mongrel "$LINENO" "ffi.h" "ac_cv_header_ffi_h" "$ac_includes_default" +if test "x$ac_cv_header_ffi_h" = xyes; then : + + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ffi_call in -lffi" >&5 +$as_echo_n "checking for ffi_call in -lffi... " >&6; } +if ${ac_cv_lib_ffi_ffi_call+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lffi $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ffi_call (); +int +main () +{ +return ffi_call (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ffi_ffi_call=yes +else + ac_cv_lib_ffi_ffi_call=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ffi_ffi_call" >&5 +$as_echo "$ac_cv_lib_ffi_ffi_call" >&6; } +if test "x$ac_cv_lib_ffi_ffi_call" = xyes; then : + have_libffi=yes +else + have_libffi=no +fi + + +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS + + + +fi + + + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + ac_fn_c_check_header_mongrel "$LINENO" "ffi.h" "ac_cv_header_ffi_h" "$ac_includes_default" +if test "x$ac_cv_header_ffi_h" = xyes; then : + + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ffi_call in -lffi" >&5 +$as_echo_n "checking for ffi_call in -lffi... " >&6; } +if ${ac_cv_lib_ffi_ffi_call+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lffi $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ffi_call (); +int +main () +{ +return ffi_call (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ffi_ffi_call=yes +else + ac_cv_lib_ffi_ffi_call=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ffi_ffi_call" >&5 +$as_echo "$ac_cv_lib_ffi_ffi_call" >&6; } +if test "x$ac_cv_lib_ffi_ffi_call" = xyes; then : + have_libffi=yes +else + have_libffi=no +fi + + +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS + + + +fi + + + +else + LIBFFI_CFLAGS=$pkg_cv_LIBFFI_CFLAGS + LIBFFI_LIBS=$pkg_cv_LIBFFI_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_libffi=yes +fi + +else + + have_libffi=yes + LIBFFI_CFLAGS="-I\$(srcdir)/Modules/_ctypes/darwin -DUSING_MALLOC_CLOSURE_DOT_C=1 -DMACOSX" + LIBFFI_LIBS= + +fi + +case $LIBS in #( + *-ldl*) : + LIBFFI_LIBS="$LIBFFI_LIBS -ldl" + ;; #( + *) : + ;; +esac + +if test "$with_system_ffi" = yes -a "$have_libffi" = yes; then + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + CFLAGS="$LIBFFI_CFLAGS $CFLAGS" + LIBS="$LIBFFI_LIBS $LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ffi_prep_cif_var in ffi.h" >&5 +$as_echo_n "checking for ffi_prep_cif_var in ffi.h... " >&6; } +if ${ac_cv_ffi_prep_cif_var+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "ffi_prep_cif_var" >/dev/null 2>&1; then : + ac_cv_ffi_prep_cif_var=yes +else + ac_cv_ffi_prep_cif_var=no +fi +rm -f conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_ffi_prep_cif_var" >&5 +$as_echo "$ac_cv_ffi_prep_cif_var" >&6; } + if test "x$ac_cv_ffi_prep_cif_var" = xyes; then : + + +$as_echo "#define HAVE_FFI_PREP_CIF_VAR 1" >>confdefs.h + + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ffi_prep_closure_loc in ffi.h" >&5 +$as_echo_n "checking for ffi_prep_closure_loc in ffi.h... " >&6; } +if ${ac_cv_ffi_prep_closure_loc+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "ffi_prep_closure_loc" >/dev/null 2>&1; then : + ac_cv_ffi_prep_closure_loc=yes +else + ac_cv_ffi_prep_closure_loc=no +fi +rm -f conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_ffi_prep_closure_loc" >&5 +$as_echo "$ac_cv_ffi_prep_closure_loc" >&6; } + if test "x$ac_cv_ffi_prep_closure_loc" = xyes; then : + + +$as_echo "#define HAVE_FFI_PREP_CLOSURE_LOC 1" >>confdefs.h + + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ffi_closure_alloc in ffi.h" >&5 +$as_echo_n "checking for ffi_closure_alloc in ffi.h... " >&6; } +if ${ac_cv_ffi_closure_alloc+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "ffi_closure_alloc" >/dev/null 2>&1; then : + ac_cv_ffi_closure_alloc=yes +else + ac_cv_ffi_closure_alloc=no +fi +rm -f conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_ffi_closure_alloc" >&5 +$as_echo "$ac_cv_ffi_closure_alloc" >&6; } + if test "x$ac_cv_ffi_closure_alloc" = xyes; then : + + +$as_echo "#define HAVE_FFI_CLOSURE_ALLOC 1" >>confdefs.h + + +fi + +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS + + +fi + + if test "$with_system_ffi" = "yes" && test -n "$PKG_CONFIG"; then LIBFFI_INCLUDEDIR="`"$PKG_CONFIG" libffi --cflags-only-I 2>/dev/null | sed -e 's/^-I//;s/ *$//'`" else @@ -22726,6 +23064,42 @@ fi $as_echo "$py_cv_module__crypt" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _ctypes" >&5 +$as_echo_n "checking for stdlib extension module _ctypes... " >&6; } + case $py_stdlib_not_available in #( + *_ctypes*) : + py_cv_module__ctypes=n/a ;; #( + *) : + if true; then : + if test "$have_libffi" = yes; then : + py_cv_module__ctypes=yes +else + py_cv_module__ctypes=missing +fi +else + py_cv_module__ctypes=disabled +fi + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__CTYPES=$py_cv_module__ctypes$as_nl" + if test "x$py_cv_module__ctypes" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE__CTYPES_CFLAGS=$LIBFFI_CFLAGS$as_nl" + as_fn_append MODULE_BLOCK "MODULE__CTYPES_LDFLAGS=$LIBFFI_LIBS$as_nl" + +fi + if test "$py_cv_module__ctypes" = yes; then + MODULE__CTYPES_TRUE= + MODULE__CTYPES_FALSE='#' +else + MODULE__CTYPES_TRUE='#' + MODULE__CTYPES_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__ctypes" >&5 +$as_echo "$py_cv_module__ctypes" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _decimal" >&5 $as_echo_n "checking for stdlib extension module _decimal... " >&6; } case $py_stdlib_not_available in #( @@ -23336,7 +23710,7 @@ $as_echo_n "checking for stdlib extension module _ctypes_test... " >&6; } py_cv_module__ctypes_test=n/a ;; #( *) : if test "$TEST_MODULES" = yes; then : - if true; then : + if test "$have_libffi" = yes; then : py_cv_module__ctypes_test=yes else py_cv_module__ctypes_test=missing @@ -23350,7 +23724,7 @@ esac if test "x$py_cv_module__ctypes_test" = xyes; then : - as_fn_append MODULE_BLOCK "MODULE__CTYPES_TEST_LDFLAGS=-lm$as_nl" + as_fn_append MODULE_BLOCK "MODULE__CTYPES_TEST_LDFLAGS=$LIBM$as_nl" fi if test "$py_cv_module__ctypes_test" = yes; then @@ -23774,6 +24148,10 @@ if test -z "${MODULE__CRYPT_TRUE}" && test -z "${MODULE__CRYPT_FALSE}"; then as_fn_error $? "conditional \"MODULE__CRYPT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__CTYPES_TRUE}" && test -z "${MODULE__CTYPES_FALSE}"; then + as_fn_error $? "conditional \"MODULE__CTYPES\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE__DECIMAL_TRUE}" && test -z "${MODULE__DECIMAL_FALSE}"; then as_fn_error $? "conditional \"MODULE__DECIMAL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index b35c92acb85db..40dc6f425f26f 100644 --- a/configure.ac +++ b/configure.ac @@ -3175,6 +3175,60 @@ else with_system_ffi="yes" fi +dnl detect libffi +have_libffi=missing +AS_VAR_IF([with_system_ffi], [yes], [ + PKG_CHECK_MODULES([LIBFFI], [libffi], [have_libffi=yes], [ + AC_CHECK_HEADER([ffi.h], [ + WITH_SAVE_ENV([ + AC_CHECK_LIB([ffi], [ffi_call], [have_libffi=yes], [have_libffi=no]) + ]) + ]) + ]) +], [ + dnl private ffi copy + have_libffi=yes + LIBFFI_CFLAGS="-I\$(srcdir)/Modules/_ctypes/darwin -DUSING_MALLOC_CLOSURE_DOT_C=1 -DMACOSX" + LIBFFI_LIBS= +]) + +dnl _ctypes needs -ldl for dlopen +AS_CASE([$LIBS], + [*-ldl*], [LIBFFI_LIBS="$LIBFFI_LIBS -ldl"] +) + +if test "$with_system_ffi" = yes -a "$have_libffi" = yes; then + WITH_SAVE_ENV([ + CFLAGS="$LIBFFI_CFLAGS $CFLAGS" + LIBS="$LIBFFI_LIBS $LIBS" + + AC_CACHE_CHECK([for ffi_prep_cif_var in ffi.h], [ac_cv_ffi_prep_cif_var], [ + AC_EGREP_HEADER([ffi_prep_cif_var], [ffi.h], [ac_cv_ffi_prep_cif_var=yes], [ac_cv_ffi_prep_cif_var=no]) + ]) + AS_VAR_IF([ac_cv_ffi_prep_cif_var], [yes], [ + AC_DEFINE([HAVE_FFI_PREP_CIF_VAR], [1], + [Define to 1 if you have the ffi_prep_cif_var function in header file.]) + ]) + + AC_CACHE_CHECK([for ffi_prep_closure_loc in ffi.h], [ac_cv_ffi_prep_closure_loc], [ + AC_EGREP_HEADER([ffi_prep_closure_loc], [ffi.h], [ac_cv_ffi_prep_closure_loc=yes], [ac_cv_ffi_prep_closure_loc=no]) + ]) + AS_VAR_IF([ac_cv_ffi_prep_closure_loc], [yes], [ + AC_DEFINE([HAVE_FFI_PREP_CLOSURE_LOC], [1], + [Define to 1 if you have the ffi_prep_closure_loc function in header file.]) + ]) + + AC_CACHE_CHECK([for ffi_closure_alloc in ffi.h], [ac_cv_ffi_closure_alloc], [ + AC_EGREP_HEADER([ffi_closure_alloc], [ffi.h], [ac_cv_ffi_closure_alloc=yes], [ac_cv_ffi_closure_alloc=no]) + ]) + AS_VAR_IF([ac_cv_ffi_closure_alloc], [yes], [ + AC_DEFINE([HAVE_FFI_CLOSURE_ALLOC], [1], + [Define to 1 if you have the ffi_closure_alloc function in header file.]) + ]) + ]) +fi + + if test "$with_system_ffi" = "yes" && test -n "$PKG_CONFIG"; then LIBFFI_INCLUDEDIR="`"$PKG_CONFIG" libffi --cflags-only-I 2>/dev/null | sed -e 's/^-I//;s/ *$//'`" else @@ -6423,6 +6477,9 @@ PY_STDLIB_MOD([_blake2], [test "$with_builtin_blake2" = yes]) PY_STDLIB_MOD([_crypt], [], [test "$ac_cv_crypt_crypt" = yes], [$LIBCRYPT_CFLAGS], [$LIBCRYPT_LIBS]) +PY_STDLIB_MOD([_ctypes], + [], [test "$have_libffi" = yes], + [$LIBFFI_CFLAGS], [$LIBFFI_LIBS]) PY_STDLIB_MOD([_decimal], [], [], [$LIBMPDEC_CFLAGS], [$LIBMPDEC_LDFLAGS]) PY_STDLIB_MOD([_gdbm], [test "$have_gdbm_dbmliborder" = yes], [test "$have_gdbm" = yes], @@ -6461,7 +6518,9 @@ PY_STDLIB_MOD([_testbuffer], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_testimportmultiple], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_testmultiphase], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_xxtestfuzz], [test "$TEST_MODULES" = yes]) -PY_STDLIB_MOD([_ctypes_test], [test "$TEST_MODULES" = yes], [], [], [-lm]) +PY_STDLIB_MOD([_ctypes_test], + [test "$TEST_MODULES" = yes], [test "$have_libffi" = yes], + [], [$LIBM]) dnl Limited API template modules. dnl The limited C API is not compatible with the Py_TRACE_REFS macro. diff --git a/pyconfig.h.in b/pyconfig.h.in index efad243d0af8a..c6cc1fd377762 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -356,6 +356,18 @@ /* Define to 1 if you have the `fexecve' function. */ #undef HAVE_FEXECVE +/* Define to 1 if you have the ffi_closure_alloc function in header + file. */ +#undef HAVE_FFI_CLOSURE_ALLOC + +/* Define to 1 if you have the ffi_prep_cif_var function in header + file. */ +#undef HAVE_FFI_PREP_CIF_VAR + +/* Define to 1 if you have the ffi_prep_closure_loc function in header + file. */ +#undef HAVE_FFI_PREP_CLOSURE_LOC + /* Define to 1 if you have the `flock' function. */ #undef HAVE_FLOCK diff --git a/setup.py b/setup.py index 572f2ac1783b8..ca5d0774e001a 100644 --- a/setup.py +++ b/setup.py @@ -669,12 +669,6 @@ def print_three_column(lst): raise RuntimeError("Failed to build some stdlib modules") def build_extension(self, ext): - - if ext.name == '_ctypes': - if not self.configure_ctypes(ext): - self.failed.append(ext.name) - return - try: build_ext.build_extension(self, ext) except (CCompilerError, DistutilsError) as why: @@ -1738,10 +1732,26 @@ def detect_tkinter(self): library_dirs=added_lib_dirs)) return True - def configure_ctypes(self, ext): - return True - def detect_ctypes(self): + ext = Extension( + '_ctypes', + [ + '_ctypes/_ctypes.c', + '_ctypes/callbacks.c', + '_ctypes/callproc.c', + '_ctypes/stgdict.c', + '_ctypes/cfield.c', + ] + ) + if MACOS: + self._build_ctypes_macos(ext) + else: + self.use_system_libffi = True + self.addext(ext) + + self.addext(Extension('_ctypes_test', ['_ctypes/_ctypes_test.c'])) + + def _build_ctypes_macos(self, ext): # Thomas Heller's _ctypes module if (not sysconfig.get_config_var("LIBFFI_INCLUDEDIR") and MACOS): @@ -1749,20 +1759,11 @@ def detect_ctypes(self): else: self.use_system_libffi = '--with-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS") - include_dirs = [] - extra_compile_args = [] - extra_link_args = [] - sources = ['_ctypes/_ctypes.c', - '_ctypes/callbacks.c', - '_ctypes/callproc.c', - '_ctypes/stgdict.c', - '_ctypes/cfield.c'] - if MACOS: - sources.append('_ctypes/malloc_closure.c') - extra_compile_args.append('-DUSING_MALLOC_CLOSURE_DOT_C=1') - extra_compile_args.append('-DMACOSX') - include_dirs.append('_ctypes/darwin') + ext.sources.append('_ctypes/malloc_closure.c') + ext.extra_compile_args.append('-DUSING_MALLOC_CLOSURE_DOT_C=1') + ext.extra_compile_args.append('-DMACOSX') + ext.include_dirs.append('_ctypes/darwin') elif HOST_PLATFORM == 'sunos5': # XXX This shouldn't be necessary; it appears that some @@ -1773,20 +1774,12 @@ def detect_ctypes(self): # this option. If you want to compile ctypes with the Sun # compiler, please research a proper solution, instead of # finding some -z option for the Sun compiler. - extra_link_args.append('-mimpure-text') + ext.extra_link_args.append('-mimpure-text') elif HOST_PLATFORM.startswith('hp-ux'): - extra_link_args.append('-fPIC') - - ext = Extension('_ctypes', - include_dirs=include_dirs, - extra_compile_args=extra_compile_args, - extra_link_args=extra_link_args, - libraries=[], - sources=sources) + ext.extra_link_args.append('-fPIC') + self.add(ext) - # function my_sqrt() needs libm for sqrt() - self.addext(Extension('_ctypes_test', ['_ctypes/_ctypes_test.c'])) ffi_inc = sysconfig.get_config_var("LIBFFI_INCLUDEDIR") ffi_lib = None From webhook-mailer at python.org Sat Dec 4 09:14:57 2021 From: webhook-mailer at python.org (tiran) Date: Sat, 04 Dec 2021 14:14:57 -0000 Subject: [Python-checkins] bpo-45847: Update whatsnew and add place holder entries for missing extensions (GH-29914) Message-ID: https://github.com/python/cpython/commit/64be8d369b7e3878078dbef466804ae8be49c1cf commit: 64be8d369b7e3878078dbef466804ae8be49c1cf branch: main author: Christian Heimes committer: tiran date: 2021-12-04T15:14:48+01:00 summary: bpo-45847: Update whatsnew and add place holder entries for missing extensions (GH-29914) files: M Doc/whatsnew/3.11.rst M Modules/Setup.stdlib.in M configure.ac diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index c498225591a74..10dc30939414c 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -583,13 +583,12 @@ Build Changes (Contributed by Brett Cannon and Christian Heimes in :issue:`45548`, :issue:`45570`, :issue:`45571`, and :issue:`43974`.) -* The build dependencies for :mod:`zlib`, :mod:`bz2`, and :mod:`lzma` are now - detected by :program:`configure`. - (Contributed by Christian Heimes in :issue:`45763`.) - -* Build dependencies for :mod:`dbm` are now detected by :program:`configure`. - ``libdb`` 3.x and 4.x are no longer supported. - (Contributed by Christian Heimes in :issue:`45747`.) +* Build dependencies, compiler flags, and linker flags for most stdlib + extension modules are now detected by :program:`configure`. libffi, libnsl, + libsqlite3, zlib, bzip2, liblzma, libcrypt, and uuid flags are detected by + ``pkg-config`` (when available). + (Contributed by Christian Heimes and Erlend Egeberg Aasland in + :issue:`bpo-45847`, :issue:`45747`, and :issue:`45763`.) * CPython now has experimental support for cross compiling to WebAssembly platform ``wasm32-emscripten``. The effort is inspired by previous work diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index ff92db3cc3784..eaf624d8bc579 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -68,9 +68,13 @@ # dbm/gdbm # dbm needs either libndbm, libgdbm_compat, or libdb 5.x +#@MODULE__DBM_TRUE at _dbm _dbmmodule.c # gdbm module needs -lgdbm @MODULE__GDBM_TRUE at _gdbm _gdbmmodule.c +# needs -lreadline or -leditline, sometimes termcap, termlib, or tinfo +#@MODULE_READLINE_TRUE at readline readline.c + # hashing builtins, can be disabled with --without-builtin-hashlib-hashes @MODULE__MD5_TRUE at _md5 md5module.c @MODULE__SHA1_TRUE at _sha1 sha1module.c @@ -134,6 +138,11 @@ # needs -lffi and -ldl @MODULE__CTYPES_TRUE at _ctypes _ctypes/_ctypes.c _ctypes/callbacks.c _ctypes/callproc.c _ctypes/stgdict.c _ctypes/cfield.c +# needs -lncurses, -lncursesw or -lcurses, sometimes -ltermcap +#@MODULE__CURSES_TRUE at _curses _cursesmodule.c +# needs -lncurses and -lpanel +#@MODULE__CURSES_PANEL_TRUE at _curses_panel _curses_panel.c + @MODULE__SQLITE3_TRUE at _sqlite3 _sqlite/connection.c _sqlite/cursor.c _sqlite/microprotocols.c _sqlite/module.c _sqlite/prepare_protocol.c _sqlite/row.c _sqlite/statement.c _sqlite/util.c # needs -lssl and -lcrypt @@ -141,6 +150,9 @@ # needs -lcrypt @MODULE__HASHLIB_TRUE at _hashlib _hashopenssl.c +# needs -ltk, -ltcl, and sometimes -lX11 +#@MODULE__TKINTER_TRUE at _tkinter _tkinter.c tkappinit.c + # Linux: -luuid, BSD/AIX: libc's uuid_create() @MODULE__UUID_TRUE at _uuid _uuidmodule.c diff --git a/configure.ac b/configure.ac index 40dc6f425f26f..39890fe38f0a1 100644 --- a/configure.ac +++ b/configure.ac @@ -6480,17 +6480,22 @@ PY_STDLIB_MOD([_crypt], PY_STDLIB_MOD([_ctypes], [], [test "$have_libffi" = yes], [$LIBFFI_CFLAGS], [$LIBFFI_LIBS]) +dnl PY_STDLIB_MOD([_curses], [], [], [], []) +dnl PY_STDLIB_MOD([_curses_panel], [], [], [], []) PY_STDLIB_MOD([_decimal], [], [], [$LIBMPDEC_CFLAGS], [$LIBMPDEC_LDFLAGS]) +dnl PY_STDLIB_MOD([_dbm], [], [], [], []) PY_STDLIB_MOD([_gdbm], [test "$have_gdbm_dbmliborder" = yes], [test "$have_gdbm" = yes], [$GDBM_CFLAGS], [$GDBM_LIBS]) PY_STDLIB_MOD([nis], [], [test "$have_nis" = yes -a "$ac_cv_header_rpc_rpc_h" = yes], [$LIBNSL_CFLAGS], [$LIBNSL_LIBS]) +dnl PY_STDLIB_MOD([readline], [], [], [], []) PY_STDLIB_MOD([_sqlite3], [test "$have_sqlite3" = "yes"], [test "$have_supported_sqlite3" = "yes"], [$LIBSQLITE3_CFLAGS], [$LIBSQLITE3_LIBS]) +dnl PY_STDLIB_MOD([_tkinter], [], [], [], []) PY_STDLIB_MOD([_uuid], [], [test "$have_uuid" = "yes"], [$LIBUUID_CFLAGS], [$LIBUUID_LIBS]) From webhook-mailer at python.org Sat Dec 4 10:38:26 2021 From: webhook-mailer at python.org (corona10) Date: Sat, 04 Dec 2021 15:38:26 -0000 Subject: [Python-checkins] Fixed documentation typo in compileall.py (GH-29912) Message-ID: https://github.com/python/cpython/commit/87a18deda43a9e512e8ca85daf363e9924f6db5f commit: 87a18deda43a9e512e8ca85daf363e9924f6db5f branch: main author: Vishal Pandey committer: corona10 date: 2021-12-05T00:38:17+09:00 summary: Fixed documentation typo in compileall.py (GH-29912) files: M Lib/compileall.py diff --git a/Lib/compileall.py b/Lib/compileall.py index 3755e76ba813f..330a90786efc5 100644 --- a/Lib/compileall.py +++ b/Lib/compileall.py @@ -4,7 +4,7 @@ given as arguments recursively; the -l option prevents it from recursing into directories. -Without arguments, if compiles all modules on sys.path, without +Without arguments, it compiles all modules on sys.path, without recursing into subdirectories. (Even though it should do so for packages -- for now, you'll have to deal with packages separately.) From webhook-mailer at python.org Sat Dec 4 13:57:28 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Sat, 04 Dec 2021 18:57:28 -0000 Subject: [Python-checkins] bpo-13236: Flush the output stream more often in unittest (GH-29864) Message-ID: https://github.com/python/cpython/commit/f42a06ba279c916fb67289e47f9bc60dc5dee4ee commit: f42a06ba279c916fb67289e47f9bc60dc5dee4ee branch: main author: Serhiy Storchaka committer: serhiy-storchaka date: 2021-12-04T20:57:20+02:00 summary: bpo-13236: Flush the output stream more often in unittest (GH-29864) It can prevent some losses when output to buffered stream. files: A Misc/NEWS.d/next/Library/2021-11-30-13-52-02.bpo-13236.FmJIkO.rst M Lib/unittest/runner.py M Lib/unittest/test/test_program.py M Lib/unittest/test/test_result.py diff --git a/Lib/unittest/runner.py b/Lib/unittest/runner.py index b51def8882fc1..120ee6aba3570 100644 --- a/Lib/unittest/runner.py +++ b/Lib/unittest/runner.py @@ -68,6 +68,7 @@ def _write_status(self, test, status): self.stream.write(self.getDescription(test)) self.stream.write(" ... ") self.stream.writeln(status) + self.stream.flush() self._newline = True def addSubTest(self, test, subtest, err): @@ -121,6 +122,7 @@ def addExpectedFailure(self, test, err): super(TextTestResult, self).addExpectedFailure(test, err) if self.showAll: self.stream.writeln("expected failure") + self.stream.flush() elif self.dots: self.stream.write("x") self.stream.flush() @@ -129,6 +131,7 @@ def addUnexpectedSuccess(self, test): super(TextTestResult, self).addUnexpectedSuccess(test) if self.showAll: self.stream.writeln("unexpected success") + self.stream.flush() elif self.dots: self.stream.write("u") self.stream.flush() @@ -136,6 +139,7 @@ def addUnexpectedSuccess(self, test): def printErrors(self): if self.dots or self.showAll: self.stream.writeln() + self.stream.flush() self.printErrorList('ERROR', self.errors) self.printErrorList('FAIL', self.failures) @@ -145,6 +149,7 @@ def printErrorList(self, flavour, errors): self.stream.writeln("%s: %s" % (flavour,self.getDescription(test))) self.stream.writeln(self.separator2) self.stream.writeln("%s" % err) + self.stream.flush() class TextTestRunner(object): @@ -239,4 +244,5 @@ def run(self, test): self.stream.writeln(" (%s)" % (", ".join(infos),)) else: self.stream.write("\n") + self.stream.flush() return result diff --git a/Lib/unittest/test/test_program.py b/Lib/unittest/test/test_program.py index 93a61097e93c7..cc02b227e1da8 100644 --- a/Lib/unittest/test/test_program.py +++ b/Lib/unittest/test/test_program.py @@ -6,6 +6,7 @@ from test import support import unittest import unittest.test +from .test_result import BufferedWriter class Test_TestProgram(unittest.TestCase): @@ -104,30 +105,39 @@ def run(self, test): program.testNames) def test_NonExit(self): + stream = BufferedWriter() program = unittest.main(exit=False, argv=["foobar"], - testRunner=unittest.TextTestRunner(stream=io.StringIO()), + testRunner=unittest.TextTestRunner(stream=stream), testLoader=self.FooBarLoader()) self.assertTrue(hasattr(program, 'result')) + self.assertIn('\nFAIL: testFail ', stream.getvalue()) + self.assertTrue(stream.getvalue().endswith('\n\nFAILED (failures=1)\n')) def test_Exit(self): + stream = BufferedWriter() self.assertRaises( SystemExit, unittest.main, argv=["foobar"], - testRunner=unittest.TextTestRunner(stream=io.StringIO()), + testRunner=unittest.TextTestRunner(stream=stream), exit=True, testLoader=self.FooBarLoader()) + self.assertIn('\nFAIL: testFail ', stream.getvalue()) + self.assertTrue(stream.getvalue().endswith('\n\nFAILED (failures=1)\n')) def test_ExitAsDefault(self): + stream = BufferedWriter() self.assertRaises( SystemExit, unittest.main, argv=["foobar"], - testRunner=unittest.TextTestRunner(stream=io.StringIO()), + testRunner=unittest.TextTestRunner(stream=stream), testLoader=self.FooBarLoader()) + self.assertIn('\nFAIL: testFail ', stream.getvalue()) + self.assertTrue(stream.getvalue().endswith('\n\nFAILED (failures=1)\n')) class InitialisableProgram(unittest.TestProgram): diff --git a/Lib/unittest/test/test_result.py b/Lib/unittest/test/test_result.py index c4a49b48752dc..224a78463edc9 100644 --- a/Lib/unittest/test/test_result.py +++ b/Lib/unittest/test/test_result.py @@ -33,6 +33,22 @@ def bad_cleanup2(): raise ValueError('bad cleanup2') +class BufferedWriter: + def __init__(self): + self.result = '' + self.buffer = '' + + def write(self, arg): + self.buffer += arg + + def flush(self): + self.result += self.buffer + self.buffer = '' + + def getvalue(self): + return self.result + + class Test_TestResult(unittest.TestCase): # Note: there are not separate tests for TestResult.wasSuccessful(), # TestResult.errors, TestResult.failures, TestResult.testsRun or @@ -335,10 +351,13 @@ def testFailFast(self): self.assertTrue(result.shouldStop) def testFailFastSetByRunner(self): - runner = unittest.TextTestRunner(stream=io.StringIO(), failfast=True) + stream = BufferedWriter() + runner = unittest.TextTestRunner(stream=stream, failfast=True) def test(result): self.assertTrue(result.failfast) result = runner.run(test) + stream.flush() + self.assertTrue(stream.getvalue().endswith('\n\nOK\n')) class Test_TextTestResult(unittest.TestCase): @@ -462,6 +481,12 @@ def testFail(self): self.fail('fail') def testError(self): raise Exception('error') + @unittest.expectedFailure + def testExpectedFailure(self): + self.fail('fail') + @unittest.expectedFailure + def testUnexpectedSuccess(self): + pass def testSubTestSuccess(self): with self.subTest('one', a=1): pass @@ -483,7 +508,7 @@ def tearDown(self): raise self.tearDownError def _run_test(self, test_name, verbosity, tearDownError=None): - stream = io.StringIO() + stream = BufferedWriter() stream = unittest.runner._WritelnDecorator(stream) result = unittest.TextTestResult(stream, True, verbosity) test = self.Test(test_name) @@ -496,6 +521,8 @@ def testDotsOutput(self): self.assertEqual(self._run_test('testSkip', 1), 's') self.assertEqual(self._run_test('testFail', 1), 'F') self.assertEqual(self._run_test('testError', 1), 'E') + self.assertEqual(self._run_test('testExpectedFailure', 1), 'x') + self.assertEqual(self._run_test('testUnexpectedSuccess', 1), 'u') def testLongOutput(self): classname = f'{__name__}.{self.Test.__qualname__}' @@ -507,6 +534,10 @@ def testLongOutput(self): f'testFail ({classname}) ... FAIL\n') self.assertEqual(self._run_test('testError', 2), f'testError ({classname}) ... ERROR\n') + self.assertEqual(self._run_test('testExpectedFailure', 2), + f'testExpectedFailure ({classname}) ... expected failure\n') + self.assertEqual(self._run_test('testUnexpectedSuccess', 2), + f'testUnexpectedSuccess ({classname}) ... unexpected success\n') def testDotsOutputSubTestSuccess(self): self.assertEqual(self._run_test('testSubTestSuccess', 1), '.') diff --git a/Misc/NEWS.d/next/Library/2021-11-30-13-52-02.bpo-13236.FmJIkO.rst b/Misc/NEWS.d/next/Library/2021-11-30-13-52-02.bpo-13236.FmJIkO.rst new file mode 100644 index 0000000000000..bfea8d4fca0e0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-30-13-52-02.bpo-13236.FmJIkO.rst @@ -0,0 +1,2 @@ +:class:`unittest.TextTestResult` and :class:`unittest.TextTestRunner` flush +now the output stream more often. From webhook-mailer at python.org Sun Dec 5 07:23:25 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Sun, 05 Dec 2021 12:23:25 -0000 Subject: [Python-checkins] bpo-27946: Fix possible crash in ElementTree.Element (GH-29915) Message-ID: https://github.com/python/cpython/commit/d15cdb2f32f572ce56d7120135da24b9fdce4c99 commit: d15cdb2f32f572ce56d7120135da24b9fdce4c99 branch: main author: Serhiy Storchaka committer: serhiy-storchaka date: 2021-12-05T14:22:54+02:00 summary: bpo-27946: Fix possible crash in ElementTree.Element (GH-29915) Getting an attribute via attrib.get() simultaneously with replacing the attrib dict can lead to access to deallocated dict. files: A Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst M Lib/test/test_xml_etree_c.py M Modules/_elementtree.c diff --git a/Lib/test/test_xml_etree_c.py b/Lib/test/test_xml_etree_c.py index e68613bb910dd..bec8208571902 100644 --- a/Lib/test/test_xml_etree_c.py +++ b/Lib/test/test_xml_etree_c.py @@ -169,6 +169,18 @@ def test_xmlpullparser_leaks(self): del parser support.gc_collect() + def test_dict_disappearing_during_get_item(self): + # test fix for seg fault reported in issue 27946 + class X: + def __hash__(self): + e.attrib = {} # this frees e->extra->attrib + [{i: i} for i in range(1000)] # exhaust the dict keys cache + return 13 + + e = cET.Element("elem", {1: 2}) + r = e.get(X()) + self.assertIsNone(r) + @unittest.skipUnless(cET, 'requires _elementtree') class TestAliasWorking(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst b/Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst new file mode 100644 index 0000000000000..0378efca746bb --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst @@ -0,0 +1,3 @@ +Fix possible crash when getting an attribute of +class:`xml.etree.ElementTree.Element` simultaneously with +replacing the ``attrib`` dict. diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index b4528a90b3e09..9dadeef712938 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -1393,22 +1393,19 @@ _elementtree_Element_get_impl(ElementObject *self, PyObject *key, PyObject *default_value) /*[clinic end generated code: output=523c614142595d75 input=ee153bbf8cdb246e]*/ { - PyObject* value; - - if (!self->extra || !self->extra->attrib) - value = default_value; - else { - value = PyDict_GetItemWithError(self->extra->attrib, key); - if (!value) { - if (PyErr_Occurred()) { - return NULL; - } - value = default_value; + if (self->extra && self->extra->attrib) { + PyObject *attrib = self->extra->attrib; + Py_INCREF(attrib); + PyObject *value = PyDict_GetItemWithError(attrib, key); + Py_XINCREF(value); + Py_DECREF(attrib); + if (value != NULL || PyErr_Occurred()) { + return value; } } - Py_INCREF(value); - return value; + Py_INCREF(default_value); + return default_value; } static PyObject * From webhook-mailer at python.org Sun Dec 5 12:04:16 2021 From: webhook-mailer at python.org (gvanrossum) Date: Sun, 05 Dec 2021 17:04:16 -0000 Subject: [Python-checkins] Delete orphaned comment (#29917) Message-ID: https://github.com/python/cpython/commit/605f4bf7838dbef86b52c955dc21ab489219490f commit: 605f4bf7838dbef86b52c955dc21ab489219490f branch: main author: Guido van Rossum committer: gvanrossum date: 2021-12-05T09:03:58-08:00 summary: Delete orphaned comment (#29917) (The function this described was deleted by PR #23743, the comment was accidentally retained.) files: M Python/compile.c diff --git a/Python/compile.c b/Python/compile.c index 87de7baab4819..6138031833ac9 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -5064,11 +5064,6 @@ compiler_visit_keyword(struct compiler *c, keyword_ty k) return 1; } -/* Test whether expression is constant. For constants, report - whether they are true or false. - - Return values: 1 for true, 0 for false, -1 for non-constant. - */ static int compiler_with_except_finish(struct compiler *c, basicblock * cleanup) { From webhook-mailer at python.org Sun Dec 5 12:41:55 2021 From: webhook-mailer at python.org (tiran) Date: Sun, 05 Dec 2021 17:41:55 -0000 Subject: [Python-checkins] bpo-45582: Fix signature of _Py_Get_Getpath_CodeObject (GH-29921) Message-ID: https://github.com/python/cpython/commit/628abe4463ed40cd54ca952a2b4cc2d6e74073f7 commit: 628abe4463ed40cd54ca952a2b4cc2d6e74073f7 branch: main author: Christian Heimes committer: tiran date: 2021-12-05T18:41:46+01:00 summary: bpo-45582: Fix signature of _Py_Get_Getpath_CodeObject (GH-29921) files: M Modules/getpath.c diff --git a/Modules/getpath.c b/Modules/getpath.c index c8c85a8540d39..f77b18eee95b6 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -783,7 +783,7 @@ library_to_dict(PyObject *dict, const char *key) PyObject * -_Py_Get_Getpath_CodeObject() +_Py_Get_Getpath_CodeObject(void) { return PyMarshal_ReadObjectFromString( (const char*)_Py_M__getpath, sizeof(_Py_M__getpath)); From webhook-mailer at python.org Sun Dec 5 14:05:07 2021 From: webhook-mailer at python.org (miss-islington) Date: Sun, 05 Dec 2021 19:05:07 -0000 Subject: [Python-checkins] bpo-27946: Fix possible crash in ElementTree.Element (GH-29915) Message-ID: https://github.com/python/cpython/commit/52a9a71fe682e47f6c78a9c34aa9a797ca632c86 commit: 52a9a71fe682e47f6c78a9c34aa9a797ca632c86 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-05T11:04:59-08:00 summary: bpo-27946: Fix possible crash in ElementTree.Element (GH-29915) Getting an attribute via attrib.get() simultaneously with replacing the attrib dict can lead to access to deallocated dict. (cherry picked from commit d15cdb2f32f572ce56d7120135da24b9fdce4c99) Co-authored-by: Serhiy Storchaka files: A Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst M Lib/test/test_xml_etree_c.py M Modules/_elementtree.c diff --git a/Lib/test/test_xml_etree_c.py b/Lib/test/test_xml_etree_c.py index e26e1714a540b..82cedfd00a55d 100644 --- a/Lib/test/test_xml_etree_c.py +++ b/Lib/test/test_xml_etree_c.py @@ -169,6 +169,18 @@ def test_xmlpullparser_leaks(self): del parser support.gc_collect() + def test_dict_disappearing_during_get_item(self): + # test fix for seg fault reported in issue 27946 + class X: + def __hash__(self): + e.attrib = {} # this frees e->extra->attrib + [{i: i} for i in range(1000)] # exhaust the dict keys cache + return 13 + + e = cET.Element("elem", {1: 2}) + r = e.get(X()) + self.assertIsNone(r) + @unittest.skipUnless(cET, 'requires _elementtree') class TestAliasWorking(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst b/Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst new file mode 100644 index 0000000000000..0378efca746bb --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst @@ -0,0 +1,3 @@ +Fix possible crash when getting an attribute of +class:`xml.etree.ElementTree.Element` simultaneously with +replacing the ``attrib`` dict. diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 67a00a3413b1d..d9c2a23ccb858 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -1393,22 +1393,19 @@ _elementtree_Element_get_impl(ElementObject *self, PyObject *key, PyObject *default_value) /*[clinic end generated code: output=523c614142595d75 input=ee153bbf8cdb246e]*/ { - PyObject* value; - - if (!self->extra || !self->extra->attrib) - value = default_value; - else { - value = PyDict_GetItemWithError(self->extra->attrib, key); - if (!value) { - if (PyErr_Occurred()) { - return NULL; - } - value = default_value; + if (self->extra && self->extra->attrib) { + PyObject *attrib = self->extra->attrib; + Py_INCREF(attrib); + PyObject *value = PyDict_GetItemWithError(attrib, key); + Py_XINCREF(value); + Py_DECREF(attrib); + if (value != NULL || PyErr_Occurred()) { + return value; } } - Py_INCREF(value); - return value; + Py_INCREF(default_value); + return default_value; } static PyObject * From webhook-mailer at python.org Sun Dec 5 14:05:07 2021 From: webhook-mailer at python.org (miss-islington) Date: Sun, 05 Dec 2021 19:05:07 -0000 Subject: [Python-checkins] bpo-27946: Fix possible crash in ElementTree.Element (GH-29915) Message-ID: https://github.com/python/cpython/commit/beb834292db54fea129dd073cc822179430cee52 commit: beb834292db54fea129dd073cc822179430cee52 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-05T11:04:52-08:00 summary: bpo-27946: Fix possible crash in ElementTree.Element (GH-29915) Getting an attribute via attrib.get() simultaneously with replacing the attrib dict can lead to access to deallocated dict. (cherry picked from commit d15cdb2f32f572ce56d7120135da24b9fdce4c99) Co-authored-by: Serhiy Storchaka files: A Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst M Lib/test/test_xml_etree_c.py M Modules/_elementtree.c diff --git a/Lib/test/test_xml_etree_c.py b/Lib/test/test_xml_etree_c.py index e68613bb910dd..bec8208571902 100644 --- a/Lib/test/test_xml_etree_c.py +++ b/Lib/test/test_xml_etree_c.py @@ -169,6 +169,18 @@ def test_xmlpullparser_leaks(self): del parser support.gc_collect() + def test_dict_disappearing_during_get_item(self): + # test fix for seg fault reported in issue 27946 + class X: + def __hash__(self): + e.attrib = {} # this frees e->extra->attrib + [{i: i} for i in range(1000)] # exhaust the dict keys cache + return 13 + + e = cET.Element("elem", {1: 2}) + r = e.get(X()) + self.assertIsNone(r) + @unittest.skipUnless(cET, 'requires _elementtree') class TestAliasWorking(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst b/Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst new file mode 100644 index 0000000000000..0378efca746bb --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst @@ -0,0 +1,3 @@ +Fix possible crash when getting an attribute of +class:`xml.etree.ElementTree.Element` simultaneously with +replacing the ``attrib`` dict. diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index b4528a90b3e09..9dadeef712938 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -1393,22 +1393,19 @@ _elementtree_Element_get_impl(ElementObject *self, PyObject *key, PyObject *default_value) /*[clinic end generated code: output=523c614142595d75 input=ee153bbf8cdb246e]*/ { - PyObject* value; - - if (!self->extra || !self->extra->attrib) - value = default_value; - else { - value = PyDict_GetItemWithError(self->extra->attrib, key); - if (!value) { - if (PyErr_Occurred()) { - return NULL; - } - value = default_value; + if (self->extra && self->extra->attrib) { + PyObject *attrib = self->extra->attrib; + Py_INCREF(attrib); + PyObject *value = PyDict_GetItemWithError(attrib, key); + Py_XINCREF(value); + Py_DECREF(attrib); + if (value != NULL || PyErr_Occurred()) { + return value; } } - Py_INCREF(value); - return value; + Py_INCREF(default_value); + return default_value; } static PyObject * From webhook-mailer at python.org Sun Dec 5 15:26:20 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Sun, 05 Dec 2021 20:26:20 -0000 Subject: [Python-checkins] bpo-37295: Optimize math.comb() and math.perm() (GH-29090) Message-ID: https://github.com/python/cpython/commit/60c320c38e4e95877cde0b1d8562ebd6bc02ac61 commit: 60c320c38e4e95877cde0b1d8562ebd6bc02ac61 branch: main author: Serhiy Storchaka committer: serhiy-storchaka date: 2021-12-05T22:26:10+02:00 summary: bpo-37295: Optimize math.comb() and math.perm() (GH-29090) For very large numbers use divide-and-conquer algorithm for getting benefit of Karatsuba multiplication of large numbers. Do calculations completely in C unsigned long long instead of Python integers if possible. files: A Misc/NEWS.d/next/Library/2021-10-18-16-08-55.bpo-37295.wBEWH2.rst M Doc/whatsnew/3.11.rst M Modules/mathmodule.c diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 10dc30939414c..b06d8d4215033 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -351,6 +351,11 @@ Optimizations * Pure ASCII strings are now normalized in constant time by :func:`unicodedata.normalize`. (Contributed by Dong-hee Na in :issue:`44987`.) +* :mod:`math` functions :func:`~math.comb` and :func:`~math.perm` are now up + to 10 times or more faster for large arguments (the speed up is larger for + larger *k*). + (Contributed by Serhiy Storchaka in :issue:`37295`.) + CPython bytecode changes ======================== diff --git a/Misc/NEWS.d/next/Library/2021-10-18-16-08-55.bpo-37295.wBEWH2.rst b/Misc/NEWS.d/next/Library/2021-10-18-16-08-55.bpo-37295.wBEWH2.rst new file mode 100644 index 0000000000000..634f0c453884e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-10-18-16-08-55.bpo-37295.wBEWH2.rst @@ -0,0 +1 @@ +Optimize :func:`math.comb` and :func:`math.perm`. diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 64ce4e6a13fd5..84b5b954b1051 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -3221,6 +3221,138 @@ math_prod_impl(PyObject *module, PyObject *iterable, PyObject *start) } +/* Number of permutations and combinations. + * P(n, k) = n! / (n-k)! + * C(n, k) = P(n, k) / k! + */ + +/* Calculate C(n, k) for n in the 63-bit range. */ +static PyObject * +perm_comb_small(unsigned long long n, unsigned long long k, int iscomb) +{ + /* long long is at least 64 bit */ + static const unsigned long long fast_comb_limits[] = { + 0, ULLONG_MAX, 4294967296ULL, 3329022, 102570, 13467, 3612, 1449, // 0-7 + 746, 453, 308, 227, 178, 147, 125, 110, // 8-15 + 99, 90, 84, 79, 75, 72, 69, 68, // 16-23 + 66, 65, 64, 63, 63, 62, 62, 62, // 24-31 + }; + static const unsigned long long fast_perm_limits[] = { + 0, ULLONG_MAX, 4294967296ULL, 2642246, 65537, 7133, 1627, 568, // 0-7 + 259, 142, 88, 61, 45, 36, 30, // 8-14 + }; + + if (k == 0) { + return PyLong_FromLong(1); + } + + /* For small enough n and k the result fits in the 64-bit range and can + * be calculated without allocating intermediate PyLong objects. */ + if (iscomb + ? (k < Py_ARRAY_LENGTH(fast_comb_limits) + && n <= fast_comb_limits[k]) + : (k < Py_ARRAY_LENGTH(fast_perm_limits) + && n <= fast_perm_limits[k])) + { + unsigned long long result = n; + if (iscomb) { + for (unsigned long long i = 1; i < k;) { + result *= --n; + result /= ++i; + } + } + else { + for (unsigned long long i = 1; i < k;) { + result *= --n; + ++i; + } + } + return PyLong_FromUnsignedLongLong(result); + } + + /* For larger n use recursive formula. */ + /* C(n, k) = C(n, j) * C(n-j, k-j) // C(k, j) */ + unsigned long long j = k / 2; + PyObject *a, *b; + a = perm_comb_small(n, j, iscomb); + if (a == NULL) { + return NULL; + } + b = perm_comb_small(n - j, k - j, iscomb); + if (b == NULL) { + goto error; + } + Py_SETREF(a, PyNumber_Multiply(a, b)); + Py_DECREF(b); + if (iscomb && a != NULL) { + b = perm_comb_small(k, j, 1); + if (b == NULL) { + goto error; + } + Py_SETREF(a, PyNumber_FloorDivide(a, b)); + Py_DECREF(b); + } + return a; + +error: + Py_DECREF(a); + return NULL; +} + +/* Calculate P(n, k) or C(n, k) using recursive formulas. + * It is more efficient than sequential multiplication thanks to + * Karatsuba multiplication. + */ +static PyObject * +perm_comb(PyObject *n, unsigned long long k, int iscomb) +{ + if (k == 0) { + return PyLong_FromLong(1); + } + if (k == 1) { + Py_INCREF(n); + return n; + } + + /* P(n, k) = P(n, j) * P(n-j, k-j) */ + /* C(n, k) = C(n, j) * C(n-j, k-j) // C(k, j) */ + unsigned long long j = k / 2; + PyObject *a, *b; + a = perm_comb(n, j, iscomb); + if (a == NULL) { + return NULL; + } + PyObject *t = PyLong_FromUnsignedLongLong(j); + if (t == NULL) { + goto error; + } + n = PyNumber_Subtract(n, t); + Py_DECREF(t); + if (n == NULL) { + goto error; + } + b = perm_comb(n, k - j, iscomb); + Py_DECREF(n); + if (b == NULL) { + goto error; + } + Py_SETREF(a, PyNumber_Multiply(a, b)); + Py_DECREF(b); + if (iscomb && a != NULL) { + b = perm_comb_small(k, j, 1); + if (b == NULL) { + goto error; + } + Py_SETREF(a, PyNumber_FloorDivide(a, b)); + Py_DECREF(b); + } + return a; + +error: + Py_DECREF(a); + return NULL; +} + /*[clinic input] math.perm @@ -3244,9 +3376,9 @@ static PyObject * math_perm_impl(PyObject *module, PyObject *n, PyObject *k) /*[clinic end generated code: output=e021a25469653e23 input=5311c5a00f359b53]*/ { - PyObject *result = NULL, *factor = NULL; + PyObject *result = NULL; int overflow, cmp; - long long i, factors; + long long ki, ni; if (k == Py_None) { return math_factorial(module, n); @@ -3260,6 +3392,7 @@ math_perm_impl(PyObject *module, PyObject *n, PyObject *k) Py_DECREF(n); return NULL; } + assert(PyLong_CheckExact(n) && PyLong_CheckExact(k)); if (Py_SIZE(n) < 0) { PyErr_SetString(PyExc_ValueError, @@ -3281,42 +3414,26 @@ math_perm_impl(PyObject *module, PyObject *n, PyObject *k) goto error; } - factors = PyLong_AsLongLongAndOverflow(k, &overflow); + ki = PyLong_AsLongLongAndOverflow(k, &overflow); + assert(overflow >= 0 && !PyErr_Occurred()); if (overflow > 0) { PyErr_Format(PyExc_OverflowError, "k must not exceed %lld", LLONG_MAX); goto error; } - else if (factors == -1) { - /* k is nonnegative, so a return value of -1 can only indicate error */ - goto error; - } + assert(ki >= 0); - if (factors == 0) { - result = PyLong_FromLong(1); - goto done; + ni = PyLong_AsLongLongAndOverflow(n, &overflow); + assert(overflow >= 0 && !PyErr_Occurred()); + if (!overflow && ki > 1) { + assert(ni >= 0); + result = perm_comb_small((unsigned long long)ni, + (unsigned long long)ki, 0); } - - result = n; - Py_INCREF(result); - if (factors == 1) { - goto done; - } - - factor = Py_NewRef(n); - PyObject *one = _PyLong_GetOne(); // borrowed ref - for (i = 1; i < factors; ++i) { - Py_SETREF(factor, PyNumber_Subtract(factor, one)); - if (factor == NULL) { - goto error; - } - Py_SETREF(result, PyNumber_Multiply(result, factor)); - if (result == NULL) { - goto error; - } + else { + result = perm_comb(n, (unsigned long long)ki, 0); } - Py_DECREF(factor); done: Py_DECREF(n); @@ -3324,14 +3441,11 @@ math_perm_impl(PyObject *module, PyObject *n, PyObject *k) return result; error: - Py_XDECREF(factor); - Py_XDECREF(result); Py_DECREF(n); Py_DECREF(k); return NULL; } - /*[clinic input] math.comb @@ -3357,9 +3471,9 @@ static PyObject * math_comb_impl(PyObject *module, PyObject *n, PyObject *k) /*[clinic end generated code: output=bd2cec8d854f3493 input=9a05315af2518709]*/ { - PyObject *result = NULL, *factor = NULL, *temp; + PyObject *result = NULL, *temp; int overflow, cmp; - long long i, factors; + long long ki, ni; n = PyNumber_Index(n); if (n == NULL) { @@ -3370,6 +3484,7 @@ math_comb_impl(PyObject *module, PyObject *n, PyObject *k) Py_DECREF(n); return NULL; } + assert(PyLong_CheckExact(n) && PyLong_CheckExact(k)); if (Py_SIZE(n) < 0) { PyErr_SetString(PyExc_ValueError, @@ -3382,73 +3497,59 @@ math_comb_impl(PyObject *module, PyObject *n, PyObject *k) goto error; } - /* k = min(k, n - k) */ - temp = PyNumber_Subtract(n, k); - if (temp == NULL) { - goto error; - } - if (Py_SIZE(temp) < 0) { - Py_DECREF(temp); - result = PyLong_FromLong(0); - goto done; - } - cmp = PyObject_RichCompareBool(temp, k, Py_LT); - if (cmp > 0) { - Py_SETREF(k, temp); + ni = PyLong_AsLongLongAndOverflow(n, &overflow); + assert(overflow >= 0 && !PyErr_Occurred()); + if (!overflow) { + assert(ni >= 0); + ki = PyLong_AsLongLongAndOverflow(k, &overflow); + assert(overflow >= 0 && !PyErr_Occurred()); + if (overflow || ki > ni) { + result = PyLong_FromLong(0); + goto done; + } + assert(ki >= 0); + ki = Py_MIN(ki, ni - ki); + if (ki > 1) { + result = perm_comb_small((unsigned long long)ni, + (unsigned long long)ki, 1); + goto done; + } + /* For k == 1 just return the original n in perm_comb(). */ } else { - Py_DECREF(temp); - if (cmp < 0) { + /* k = min(k, n - k) */ + temp = PyNumber_Subtract(n, k); + if (temp == NULL) { goto error; } - } - - factors = PyLong_AsLongLongAndOverflow(k, &overflow); - if (overflow > 0) { - PyErr_Format(PyExc_OverflowError, - "min(n - k, k) must not exceed %lld", - LLONG_MAX); - goto error; - } - if (factors == -1) { - /* k is nonnegative, so a return value of -1 can only indicate error */ - goto error; - } - - if (factors == 0) { - result = PyLong_FromLong(1); - goto done; - } - - result = n; - Py_INCREF(result); - if (factors == 1) { - goto done; - } - - factor = Py_NewRef(n); - PyObject *one = _PyLong_GetOne(); // borrowed ref - for (i = 1; i < factors; ++i) { - Py_SETREF(factor, PyNumber_Subtract(factor, one)); - if (factor == NULL) { - goto error; + if (Py_SIZE(temp) < 0) { + Py_DECREF(temp); + result = PyLong_FromLong(0); + goto done; } - Py_SETREF(result, PyNumber_Multiply(result, factor)); - if (result == NULL) { - goto error; + cmp = PyObject_RichCompareBool(temp, k, Py_LT); + if (cmp > 0) { + Py_SETREF(k, temp); } - - temp = PyLong_FromUnsignedLongLong((unsigned long long)i + 1); - if (temp == NULL) { - goto error; + else { + Py_DECREF(temp); + if (cmp < 0) { + goto error; + } } - Py_SETREF(result, PyNumber_FloorDivide(result, temp)); - Py_DECREF(temp); - if (result == NULL) { + + ki = PyLong_AsLongLongAndOverflow(k, &overflow); + assert(overflow >= 0 && !PyErr_Occurred()); + if (overflow) { + PyErr_Format(PyExc_OverflowError, + "min(n - k, k) must not exceed %lld", + LLONG_MAX); goto error; } + assert(ki >= 0); } - Py_DECREF(factor); + + result = perm_comb(n, (unsigned long long)ki, 1); done: Py_DECREF(n); @@ -3456,8 +3557,6 @@ math_comb_impl(PyObject *module, PyObject *n, PyObject *k) return result; error: - Py_XDECREF(factor); - Py_XDECREF(result); Py_DECREF(n); Py_DECREF(k); return NULL; From webhook-mailer at python.org Sun Dec 5 15:42:06 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Sun, 05 Dec 2021 20:42:06 -0000 Subject: [Python-checkins] bpo-45662: Fix the repr of InitVar with a type alias to the built-in class (GH-29291) Message-ID: https://github.com/python/cpython/commit/1fd4de5bddbbf2a97cdbac4d298c89e1156bdc6c commit: 1fd4de5bddbbf2a97cdbac4d298c89e1156bdc6c branch: main author: Serhiy Storchaka committer: serhiy-storchaka date: 2021-12-05T22:41:58+02:00 summary: bpo-45662: Fix the repr of InitVar with a type alias to the built-in class (GH-29291) For example, InitVar[list[int]]. files: A Misc/NEWS.d/next/Library/2021-10-28-22-58-14.bpo-45662.sJd7Ir.rst M Lib/dataclasses.py M Lib/test/test_dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 8643589077a4a..da06aa69148b7 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -229,7 +229,7 @@ def __init__(self, type): self.type = type def __repr__(self): - if isinstance(self.type, type): + if isinstance(self.type, type) and not isinstance(self.type, GenericAlias): type_name = self.type.__name__ else: # typing objects, e.g. List[int] diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index bcd004f4ec3aa..47075df8d59f3 100644 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -1126,6 +1126,10 @@ def test_init_var_preserve_type(self): self.assertEqual(repr(InitVar[int]), 'dataclasses.InitVar[int]') self.assertEqual(repr(InitVar[List[int]]), 'dataclasses.InitVar[typing.List[int]]') + self.assertEqual(repr(InitVar[list[int]]), + 'dataclasses.InitVar[list[int]]') + self.assertEqual(repr(InitVar[int|str]), + 'dataclasses.InitVar[int | str]') def test_init_var_inheritance(self): # Note that this deliberately tests that a dataclass need not diff --git a/Misc/NEWS.d/next/Library/2021-10-28-22-58-14.bpo-45662.sJd7Ir.rst b/Misc/NEWS.d/next/Library/2021-10-28-22-58-14.bpo-45662.sJd7Ir.rst new file mode 100644 index 0000000000000..050b443dd7cb2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-10-28-22-58-14.bpo-45662.sJd7Ir.rst @@ -0,0 +1,2 @@ +Fix the repr of :data:`dataclasses.InitVar` with a type alias to the +built-in class, e.g. ``InitVar[list[int]]``. From webhook-mailer at python.org Sun Dec 5 15:42:54 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Sun, 05 Dec 2021 20:42:54 -0000 Subject: [Python-checkins] bpo-45663: Fix is_dataclass() for dataclasses which are subclasses of types.GenericAlias (GH-29294) Message-ID: https://github.com/python/cpython/commit/446be166861b2f08f87f74018113dd98ca5fca02 commit: 446be166861b2f08f87f74018113dd98ca5fca02 branch: main author: Serhiy Storchaka committer: serhiy-storchaka date: 2021-12-05T22:42:50+02:00 summary: bpo-45663: Fix is_dataclass() for dataclasses which are subclasses of types.GenericAlias (GH-29294) files: A Misc/NEWS.d/next/Library/2021-10-28-23-11-59.bpo-45663.J90N5R.rst M Lib/dataclasses.py M Lib/test/test_dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index da06aa69148b7..3f85d859b1642 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -1211,7 +1211,7 @@ def _is_dataclass_instance(obj): def is_dataclass(obj): """Returns True if obj is a dataclass or an instance of a dataclass.""" - cls = obj if isinstance(obj, type) else type(obj) + cls = obj if isinstance(obj, type) and not isinstance(obj, GenericAlias) else type(obj) return hasattr(cls, _FIELDS) diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index 47075df8d59f3..ef5009ab11677 100644 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -8,6 +8,7 @@ import pickle import inspect import builtins +import types import unittest from unittest.mock import Mock from typing import ClassVar, Any, List, Union, Tuple, Dict, Generic, TypeVar, Optional, Protocol @@ -1354,6 +1355,17 @@ class B: with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'): replace(obj, x=0) + def test_is_dataclass_genericalias(self): + @dataclass + class A(types.GenericAlias): + origin: type + args: type + self.assertTrue(is_dataclass(A)) + a = A(list, int) + self.assertTrue(is_dataclass(type(a))) + self.assertTrue(is_dataclass(a)) + + def test_helper_fields_with_class_instance(self): # Check that we can call fields() on either a class or instance, # and get back the same thing. diff --git a/Misc/NEWS.d/next/Library/2021-10-28-23-11-59.bpo-45663.J90N5R.rst b/Misc/NEWS.d/next/Library/2021-10-28-23-11-59.bpo-45663.J90N5R.rst new file mode 100644 index 0000000000000..f246f67cf80e5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-10-28-23-11-59.bpo-45663.J90N5R.rst @@ -0,0 +1,2 @@ +Fix :func:`dataclasses.is_dataclass` for dataclasses which are subclasses of +:class:`types.GenericAlias`. From webhook-mailer at python.org Sun Dec 5 15:44:09 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Sun, 05 Dec 2021 20:44:09 -0000 Subject: [Python-checkins] bpo-45664: Fix resolve_bases() and new_class() for GenericAlias instance as a base (GH-29298) Message-ID: https://github.com/python/cpython/commit/2b318ce1c988b7b6e3caf293d55f289e066b6e0f commit: 2b318ce1c988b7b6e3caf293d55f289e066b6e0f branch: main author: Serhiy Storchaka committer: serhiy-storchaka date: 2021-12-05T22:44:01+02:00 summary: bpo-45664: Fix resolve_bases() and new_class() for GenericAlias instance as a base (GH-29298) files: A Misc/NEWS.d/next/Library/2021-10-28-23-40-54.bpo-45664.7dqtxQ.rst M Lib/test/test_types.py M Lib/types.py diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index b1218abc8af5e..3dfda5cb95663 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -1236,6 +1236,17 @@ def __mro_entries__(self, bases): self.assertEqual(D.__orig_bases__, (c,)) self.assertEqual(D.__mro__, (D, A, object)) + def test_new_class_with_mro_entry_genericalias(self): + L1 = types.new_class('L1', (typing.List[int],), {}) + self.assertEqual(L1.__bases__, (list, typing.Generic)) + self.assertEqual(L1.__orig_bases__, (typing.List[int],)) + self.assertEqual(L1.__mro__, (L1, list, typing.Generic, object)) + + L2 = types.new_class('L2', (list[int],), {}) + self.assertEqual(L2.__bases__, (list,)) + self.assertEqual(L2.__orig_bases__, (list[int],)) + self.assertEqual(L2.__mro__, (L2, list, object)) + def test_new_class_with_mro_entry_none(self): class A: pass class B: pass @@ -1351,6 +1362,11 @@ def __mro_entries__(self, bases): for bases in [x, y, z, t]: self.assertIs(types.resolve_bases(bases), bases) + def test_resolve_bases_with_mro_entry(self): + self.assertEqual(types.resolve_bases((typing.List[int],)), + (list, typing.Generic)) + self.assertEqual(types.resolve_bases((list[int],)), (list,)) + def test_metaclass_derivation(self): # issue1294232: correct metaclass calculation new_calls = [] # to check the order of __new__ calls diff --git a/Lib/types.py b/Lib/types.py index ce1c28d5625a2..679c7f638b310 100644 --- a/Lib/types.py +++ b/Lib/types.py @@ -82,7 +82,7 @@ def resolve_bases(bases): updated = False shift = 0 for i, base in enumerate(bases): - if isinstance(base, type): + if isinstance(base, type) and not isinstance(base, GenericAlias): continue if not hasattr(base, "__mro_entries__"): continue diff --git a/Misc/NEWS.d/next/Library/2021-10-28-23-40-54.bpo-45664.7dqtxQ.rst b/Misc/NEWS.d/next/Library/2021-10-28-23-40-54.bpo-45664.7dqtxQ.rst new file mode 100644 index 0000000000000..573a569845a87 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-10-28-23-40-54.bpo-45664.7dqtxQ.rst @@ -0,0 +1,2 @@ +Fix :func:`types.resolve_bases` and :func:`types.new_class` for +:class:`types.GenericAlias` instance as a base. From webhook-mailer at python.org Sun Dec 5 15:49:45 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Sun, 05 Dec 2021 20:49:45 -0000 Subject: [Python-checkins] bpo-45840: Improve cross-references in the data model documentation (GH-29633) Message-ID: https://github.com/python/cpython/commit/c0521fe49fd75e794a38a216813658ab40185834 commit: c0521fe49fd75e794a38a216813658ab40185834 branch: main author: Alex Waygood committer: serhiy-storchaka date: 2021-12-05T22:49:36+02:00 summary: bpo-45840: Improve cross-references in the data model documentation (GH-29633) files: A Misc/NEWS.d/next/Documentation/2021-11-19-02-02-32.bpo-45840.A51B2S.rst M Doc/reference/datamodel.rst diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 41092458102de..597c8ec9f176b 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -188,7 +188,7 @@ Ellipsis representation in computers. The string representations of the numeric classes, computed by - :meth:`__repr__` and :meth:`__str__`, have the following + :meth:`~object.__repr__` and :meth:`~object.__str__`, have the following properties: * They are valid numeric literals which, when passed to their @@ -677,7 +677,8 @@ Callable types returns an :term:`asynchronous iterator` object which can be used in an :keyword:`async for` statement to execute the body of the function. - Calling the asynchronous iterator's :meth:`aiterator.__anext__` method + Calling the asynchronous iterator's + :meth:`aiterator.__anext__ ` method will return an :term:`awaitable` which when awaited will execute until it provides a value using the :keyword:`yield` expression. When the function executes an empty :keyword:`return` @@ -715,13 +716,13 @@ Callable types Classes Classes are callable. These objects normally act as factories for new instances of themselves, but variations are possible for class types that - override :meth:`__new__`. The arguments of the call are passed to - :meth:`__new__` and, in the typical case, to :meth:`__init__` to + override :meth:`~object.__new__`. The arguments of the call are passed to + :meth:`__new__` and, in the typical case, to :meth:`~object.__init__` to initialize the new instance. Class Instances Instances of arbitrary classes can be made callable by defining a - :meth:`__call__` method in their class. + :meth:`~object.__call__` method in their class. Modules @@ -880,14 +881,14 @@ Class instances section :ref:`descriptors` for another way in which attributes of a class retrieved via its instances may differ from the objects actually stored in the class's :attr:`~object.__dict__`. If no class attribute is found, and the - object's class has a :meth:`__getattr__` method, that is called to satisfy + object's class has a :meth:`~object.__getattr__` method, that is called to satisfy the lookup. .. index:: triple: class instance; attribute; assignment Attribute assignments and deletions update the instance's dictionary, never a - class's dictionary. If the class has a :meth:`__setattr__` or - :meth:`__delattr__` method, this is called instead of updating the instance + class's dictionary. If the class has a :meth:`~object.__setattr__` or + :meth:`~object.__delattr__` method, this is called instead of updating the instance dictionary directly. .. index:: @@ -1176,7 +1177,8 @@ Internal types Slice objects .. index:: builtin: slice - Slice objects are used to represent slices for :meth:`__getitem__` + Slice objects are used to represent slices for + :meth:`~object.__getitem__` methods. They are also created by the built-in :func:`slice` function. .. index:: @@ -1229,7 +1231,8 @@ A class can implement certain operations that are invoked by special syntax (such as arithmetic operations or subscripting and slicing) by defining methods with special names. This is Python's approach to :dfn:`operator overloading`, allowing classes to define their own behavior with respect to language -operators. For instance, if a class defines a method named :meth:`__getitem__`, +operators. For instance, if a class defines a method named +:meth:`~object.__getitem__`, and ``x`` is an instance of this class, then ``x[i]`` is roughly equivalent to ``type(x).__getitem__(x, i)``. Except where mentioned, attempts to execute an operation raise an exception when no appropriate method is defined (typically @@ -1237,9 +1240,9 @@ operation raise an exception when no appropriate method is defined (typically Setting a special method to ``None`` indicates that the corresponding operation is not available. For example, if a class sets -:meth:`__iter__` to ``None``, the class is not iterable, so calling +:meth:`~object.__iter__` to ``None``, the class is not iterable, so calling :func:`iter` on its instances will raise a :exc:`TypeError` (without -falling back to :meth:`__getitem__`). [#]_ +falling back to :meth:`~object.__getitem__`). [#]_ When implementing a class that emulates any built-in type, it is important that the emulation only be implemented to the degree that it makes sense for the @@ -1789,7 +1792,8 @@ Invoking Descriptors In general, a descriptor is an object attribute with "binding behavior", one whose attribute access has been overridden by methods in the descriptor -protocol: :meth:`__get__`, :meth:`__set__`, and :meth:`__delete__`. If any of +protocol: :meth:`~object.__get__`, :meth:`~object.__set__`, and +:meth:`~object.__delete__`. If any of those methods are defined for an object, it is said to be a descriptor. The default behavior for attribute access is to get, set, or delete the @@ -1853,7 +1857,8 @@ Super Binding For instance bindings, the precedence of descriptor invocation depends on which descriptor methods are defined. A descriptor can define any combination -of :meth:`__get__`, :meth:`__set__` and :meth:`__delete__`. If it does not +of :meth:`~object.__get__`, :meth:`~object.__set__` and +:meth:`~object.__delete__`. If it does not define :meth:`__get__`, then accessing the attribute will return the descriptor object itself unless there is a value in the object's instance dictionary. If the descriptor defines :meth:`__set__` and/or :meth:`__delete__`, it is a data @@ -1864,7 +1869,8 @@ descriptors have just the :meth:`__get__` method. Data descriptors with instance dictionary. In contrast, non-data descriptors can be overridden by instances. -Python methods (including :func:`staticmethod` and :func:`classmethod`) are +Python methods (including those decorated with +:func:`@staticmethod ` and :func:`@classmethod `) are implemented as non-data descriptors. Accordingly, instances can redefine and override methods. This allows individual instances to acquire behaviors that differ from other instances of the same class. @@ -1879,46 +1885,50 @@ __slots__ ^^^^^^^^^ *__slots__* allow us to explicitly declare data members (like -properties) and deny the creation of *__dict__* and *__weakref__* +properties) and deny the creation of :attr:`~object.__dict__` and *__weakref__* (unless explicitly declared in *__slots__* or available in a parent.) -The space saved over using *__dict__* can be significant. +The space saved over using :attr:`~object.__dict__` can be significant. Attribute lookup speed can be significantly improved as well. .. data:: object.__slots__ This class variable can be assigned a string, iterable, or sequence of strings with variable names used by instances. *__slots__* reserves space - for the declared variables and prevents the automatic creation of *__dict__* + for the declared variables and prevents the automatic creation of + :attr:`~object.__dict__` and *__weakref__* for each instance. Notes on using *__slots__* """""""""""""""""""""""""" -* When inheriting from a class without *__slots__*, the *__dict__* and +* When inheriting from a class without *__slots__*, the + :attr:`~object.__dict__` and *__weakref__* attribute of the instances will always be accessible. -* Without a *__dict__* variable, instances cannot be assigned new variables not +* Without a :attr:`~object.__dict__` variable, instances cannot be assigned new + variables not listed in the *__slots__* definition. Attempts to assign to an unlisted variable name raises :exc:`AttributeError`. If dynamic assignment of new variables is desired, then add ``'__dict__'`` to the sequence of strings in the *__slots__* declaration. * Without a *__weakref__* variable for each instance, classes defining - *__slots__* do not support weak references to its instances. If weak reference + *__slots__* do not support :mod:`weak references ` to its instances. + If weak reference support is needed, then add ``'__weakref__'`` to the sequence of strings in the *__slots__* declaration. -* *__slots__* are implemented at the class level by creating descriptors - (:ref:`descriptors`) for each variable name. As a result, class attributes +* *__slots__* are implemented at the class level by creating :ref:`descriptors ` + for each variable name. As a result, class attributes cannot be used to set default values for instance variables defined by *__slots__*; otherwise, the class attribute would overwrite the descriptor assignment. * The action of a *__slots__* declaration is not limited to the class where it is defined. *__slots__* declared in parents are available in - child classes. However, child subclasses will get a *__dict__* and + child classes. However, child subclasses will get a :attr:`~object.__dict__` and *__weakref__* unless they also define *__slots__* (which should only contain names of any *additional* slots). @@ -1934,14 +1944,17 @@ Notes on using *__slots__* used; however, in the future, special meaning may be assigned to the values corresponding to each key. -* *__class__* assignment works only if both classes have the same *__slots__*. +* :attr:`~instance.__class__` assignment works only if both classes have the + same *__slots__*. -* Multiple inheritance with multiple slotted parent classes can be used, +* :ref:`Multiple inheritance ` with multiple slotted parent + classes can be used, but only one parent is allowed to have attributes created by slots (the other bases must have empty slot layouts) - violations raise :exc:`TypeError`. -* If an iterator is used for *__slots__* then a descriptor is created for each +* If an :term:`iterator` is used for *__slots__* then a :term:`descriptor` is + created for each of the iterator's values. However, the *__slots__* attribute will be an empty iterator. @@ -1950,7 +1963,7 @@ Notes on using *__slots__* Customizing class creation -------------------------- -Whenever a class inherits from another class, *__init_subclass__* is +Whenever a class inherits from another class, :meth:`~object.__init_subclass__` is called on that class. This way, it is possible to write classes which change the behavior of subclasses. This is closely related to class decorators, but where class decorators only affect the specific class they're @@ -1991,7 +2004,7 @@ class defining the method. When a class is created, :meth:`type.__new__` scans the class variables -and makes callbacks to those with a :meth:`__set_name__` hook. +and makes callbacks to those with a :meth:`~object.__set_name__` hook. .. method:: object.__set_name__(self, owner, name) @@ -2103,7 +2116,8 @@ Once the appropriate metaclass has been identified, then the class namespace is prepared. If the metaclass has a ``__prepare__`` attribute, it is called as ``namespace = metaclass.__prepare__(name, bases, **kwds)`` (where the additional keyword arguments, if any, come from the class definition). The -``__prepare__`` method should be implemented as a :func:`classmethod`. The +``__prepare__`` method should be implemented as a +:func:`classmethod `. The namespace returned by ``__prepare__`` is passed in to ``__new__``, but when the final class object is created the namespace is copied into a new ``dict``. @@ -2401,31 +2415,36 @@ Emulating container types ------------------------- The following methods can be defined to implement container objects. Containers -usually are sequences (such as lists or tuples) or mappings (like dictionaries), +usually are :term:`sequences ` (such as :class:`lists ` or +:class:`tuples `) or :term:`mappings ` (like +:class:`dictionaries `), but can represent other containers as well. The first set of methods is used either to emulate a sequence or to emulate a mapping; the difference is that for a sequence, the allowable keys should be the integers *k* for which ``0 <= k < -N`` where *N* is the length of the sequence, or slice objects, which define a +N`` where *N* is the length of the sequence, or :class:`slice` objects, which define a range of items. It is also recommended that mappings provide the methods :meth:`keys`, :meth:`values`, :meth:`items`, :meth:`get`, :meth:`clear`, :meth:`setdefault`, :meth:`pop`, :meth:`popitem`, :meth:`!copy`, and -:meth:`update` behaving similar to those for Python's standard dictionary +:meth:`update` behaving similar to those for Python's standard :class:`dictionary ` objects. The :mod:`collections.abc` module provides a :class:`~collections.abc.MutableMapping` -abstract base class to help create those methods from a base set of -:meth:`__getitem__`, :meth:`__setitem__`, :meth:`__delitem__`, and :meth:`keys`. +:term:`abstract base class` to help create those methods from a base set of +:meth:`~object.__getitem__`, :meth:`~object.__setitem__`, :meth:`~object.__delitem__`, and :meth:`keys`. Mutable sequences should provide methods :meth:`append`, :meth:`count`, :meth:`index`, :meth:`extend`, :meth:`insert`, :meth:`pop`, :meth:`remove`, -:meth:`reverse` and :meth:`sort`, like Python standard list objects. Finally, +:meth:`reverse` and :meth:`sort`, like Python standard :class:`list` +objects. Finally, sequence types should implement addition (meaning concatenation) and -multiplication (meaning repetition) by defining the methods :meth:`__add__`, -:meth:`__radd__`, :meth:`__iadd__`, :meth:`__mul__`, :meth:`__rmul__` and -:meth:`__imul__` described below; they should not define other numerical +multiplication (meaning repetition) by defining the methods +:meth:`~object.__add__`, :meth:`~object.__radd__`, :meth:`~object.__iadd__`, +:meth:`~object.__mul__`, :meth:`~object.__rmul__` and :meth:`~object.__imul__` +described below; they should not define other numerical operators. It is recommended that both mappings and sequences implement the -:meth:`__contains__` method to allow efficient use of the ``in`` operator; for +:meth:`~object.__contains__` method to allow efficient use of the ``in`` +operator; for mappings, ``in`` should search the mapping's keys; for sequences, it should search through the values. It is further recommended that both mappings and -sequences implement the :meth:`__iter__` method to allow efficient iteration +sequences implement the :meth:`~object.__iter__` method to allow efficient iteration through the container; for mappings, :meth:`__iter__` should iterate through the object's keys; for sequences, it should iterate through the values. @@ -2838,7 +2857,8 @@ exception:: TypeError: object of type 'C' has no len() The rationale behind this behaviour lies with a number of special methods such -as :meth:`__hash__` and :meth:`__repr__` that are implemented by all objects, +as :meth:`~object.__hash__` and :meth:`~object.__repr__` that are implemented +by all objects, including type objects. If the implicit lookup of these methods used the conventional lookup process, they would fail when invoked on the type object itself:: @@ -2861,7 +2881,7 @@ the instance when looking up special methods:: In addition to bypassing any instance attributes in the interest of correctness, implicit special method lookup generally also bypasses the -:meth:`__getattribute__` method even of the object's metaclass:: +:meth:`~object.__getattribute__` method even of the object's metaclass:: >>> class Meta(type): ... def __getattribute__(*args): @@ -2885,7 +2905,7 @@ correctness, implicit special method lookup generally also bypasses the >>> len(c) # Implicit lookup 10 -Bypassing the :meth:`__getattribute__` machinery in this fashion +Bypassing the :meth:`~object.__getattribute__` machinery in this fashion provides significant scope for speed optimisations within the interpreter, at the cost of some flexibility in the handling of special methods (the special method *must* be set on the class @@ -2902,7 +2922,7 @@ Coroutines Awaitable Objects ----------------- -An :term:`awaitable` object generally implements an :meth:`__await__` method. +An :term:`awaitable` object generally implements an :meth:`~object.__await__` method. :term:`Coroutine objects ` returned from :keyword:`async def` functions are awaitable. @@ -2910,7 +2930,7 @@ are awaitable. The :term:`generator iterator` objects returned from generators decorated with :func:`types.coroutine` - are also awaitable, but they do not implement :meth:`__await__`. + are also awaitable, but they do not implement :meth:`~object.__await__`. .. method:: object.__await__(self) @@ -2929,7 +2949,7 @@ Coroutine Objects ----------------- :term:`Coroutine objects ` are :term:`awaitable` objects. -A coroutine's execution can be controlled by calling :meth:`__await__` and +A coroutine's execution can be controlled by calling :meth:`~object.__await__` and iterating over the result. When the coroutine has finished executing and returns, the iterator raises :exc:`StopIteration`, and the exception's :attr:`~StopIteration.value` attribute holds the return value. If the @@ -2948,7 +2968,7 @@ generators, coroutines do not directly support iteration. Starts or resumes execution of the coroutine. If *value* is ``None``, this is equivalent to advancing the iterator returned by - :meth:`__await__`. If *value* is not ``None``, this method delegates + :meth:`~object.__await__`. If *value* is not ``None``, this method delegates to the :meth:`~generator.send` method of the iterator that caused the coroutine to suspend. The result (return value, :exc:`StopIteration`, or other exception) is the same as when @@ -2961,7 +2981,7 @@ generators, coroutines do not directly support iteration. the coroutine to suspend, if it has such a method. Otherwise, the exception is raised at the suspension point. The result (return value, :exc:`StopIteration`, or other exception) is the same as - when iterating over the :meth:`__await__` return value, described + when iterating over the :meth:`~object.__await__` return value, described above. If the exception is not caught in the coroutine, it propagates back to the caller. @@ -3015,11 +3035,11 @@ An example of an asynchronous iterable object:: .. versionadded:: 3.5 .. versionchanged:: 3.7 - Prior to Python 3.7, ``__aiter__`` could return an *awaitable* + Prior to Python 3.7, :meth:`~object.__aiter__` could return an *awaitable* that would resolve to an :term:`asynchronous iterator `. - Starting with Python 3.7, ``__aiter__`` must return an + Starting with Python 3.7, :meth:`~object.__aiter__` must return an asynchronous iterator object. Returning anything else will result in a :exc:`TypeError` error. @@ -3062,8 +3082,9 @@ An example of an asynchronous context manager class:: controlled conditions. It generally isn't a good idea though, since it can lead to some very strange behaviour if it is handled incorrectly. -.. [#] The :meth:`__hash__`, :meth:`__iter__`, :meth:`__reversed__`, and - :meth:`__contains__` methods have special handling for this; others +.. [#] The :meth:`~object.__hash__`, :meth:`~object.__iter__`, + :meth:`~object.__reversed__`, and :meth:`~object.__contains__` methods have + special handling for this; others will still raise a :exc:`TypeError`, but may do so by relying on the behavior that ``None`` is not callable. @@ -3074,5 +3095,6 @@ An example of an asynchronous context manager class:: *blocking* such fallback. .. [#] For operands of the same type, it is assumed that if the non-reflected - method -- such as :meth:`__add__` -- fails then the overall operation is not + method -- such as :meth:`~object.__add__` -- fails then the overall + operation is not supported, which is why the reflected method is not called. diff --git a/Misc/NEWS.d/next/Documentation/2021-11-19-02-02-32.bpo-45840.A51B2S.rst b/Misc/NEWS.d/next/Documentation/2021-11-19-02-02-32.bpo-45840.A51B2S.rst new file mode 100644 index 0000000000000..87371e5b76bc1 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-11-19-02-02-32.bpo-45840.A51B2S.rst @@ -0,0 +1 @@ +Improve cross-references in the documentation for the data model. From webhook-mailer at python.org Sun Dec 5 16:02:52 2021 From: webhook-mailer at python.org (miss-islington) Date: Sun, 05 Dec 2021 21:02:52 -0000 Subject: [Python-checkins] bpo-45662: Fix the repr of InitVar with a type alias to the built-in class (GH-29291) Message-ID: https://github.com/python/cpython/commit/f1dd5ed1f35a7ed5c3833c822e9965de2400d77e commit: f1dd5ed1f35a7ed5c3833c822e9965de2400d77e branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-05T13:02:47-08:00 summary: bpo-45662: Fix the repr of InitVar with a type alias to the built-in class (GH-29291) For example, InitVar[list[int]]. (cherry picked from commit 1fd4de5bddbbf2a97cdbac4d298c89e1156bdc6c) Co-authored-by: Serhiy Storchaka files: A Misc/NEWS.d/next/Library/2021-10-28-22-58-14.bpo-45662.sJd7Ir.rst M Lib/dataclasses.py M Lib/test/test_dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index b3a9194d9d068..fe4094b891b4a 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -229,7 +229,7 @@ def __init__(self, type): self.type = type def __repr__(self): - if isinstance(self.type, type): + if isinstance(self.type, type) and not isinstance(self.type, GenericAlias): type_name = self.type.__name__ else: # typing objects, e.g. List[int] diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index bcd004f4ec3aa..47075df8d59f3 100644 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -1126,6 +1126,10 @@ def test_init_var_preserve_type(self): self.assertEqual(repr(InitVar[int]), 'dataclasses.InitVar[int]') self.assertEqual(repr(InitVar[List[int]]), 'dataclasses.InitVar[typing.List[int]]') + self.assertEqual(repr(InitVar[list[int]]), + 'dataclasses.InitVar[list[int]]') + self.assertEqual(repr(InitVar[int|str]), + 'dataclasses.InitVar[int | str]') def test_init_var_inheritance(self): # Note that this deliberately tests that a dataclass need not diff --git a/Misc/NEWS.d/next/Library/2021-10-28-22-58-14.bpo-45662.sJd7Ir.rst b/Misc/NEWS.d/next/Library/2021-10-28-22-58-14.bpo-45662.sJd7Ir.rst new file mode 100644 index 0000000000000..050b443dd7cb2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-10-28-22-58-14.bpo-45662.sJd7Ir.rst @@ -0,0 +1,2 @@ +Fix the repr of :data:`dataclasses.InitVar` with a type alias to the +built-in class, e.g. ``InitVar[list[int]]``. From webhook-mailer at python.org Sun Dec 5 16:04:38 2021 From: webhook-mailer at python.org (miss-islington) Date: Sun, 05 Dec 2021 21:04:38 -0000 Subject: [Python-checkins] bpo-45663: Fix is_dataclass() for dataclasses which are subclasses of types.GenericAlias (GH-29294) Message-ID: https://github.com/python/cpython/commit/abceb66c7e33d165361d8a26efb3770faa721aff commit: abceb66c7e33d165361d8a26efb3770faa721aff branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-05T13:04:29-08:00 summary: bpo-45663: Fix is_dataclass() for dataclasses which are subclasses of types.GenericAlias (GH-29294) (cherry picked from commit 446be166861b2f08f87f74018113dd98ca5fca02) Co-authored-by: Serhiy Storchaka files: A Misc/NEWS.d/next/Library/2021-10-28-23-11-59.bpo-45663.J90N5R.rst M Lib/dataclasses.py M Lib/test/test_dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index fe4094b891b4a..105a95b95540e 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -1211,7 +1211,7 @@ def _is_dataclass_instance(obj): def is_dataclass(obj): """Returns True if obj is a dataclass or an instance of a dataclass.""" - cls = obj if isinstance(obj, type) else type(obj) + cls = obj if isinstance(obj, type) and not isinstance(obj, GenericAlias) else type(obj) return hasattr(cls, _FIELDS) diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index 47075df8d59f3..ef5009ab11677 100644 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -8,6 +8,7 @@ import pickle import inspect import builtins +import types import unittest from unittest.mock import Mock from typing import ClassVar, Any, List, Union, Tuple, Dict, Generic, TypeVar, Optional, Protocol @@ -1354,6 +1355,17 @@ class B: with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'): replace(obj, x=0) + def test_is_dataclass_genericalias(self): + @dataclass + class A(types.GenericAlias): + origin: type + args: type + self.assertTrue(is_dataclass(A)) + a = A(list, int) + self.assertTrue(is_dataclass(type(a))) + self.assertTrue(is_dataclass(a)) + + def test_helper_fields_with_class_instance(self): # Check that we can call fields() on either a class or instance, # and get back the same thing. diff --git a/Misc/NEWS.d/next/Library/2021-10-28-23-11-59.bpo-45663.J90N5R.rst b/Misc/NEWS.d/next/Library/2021-10-28-23-11-59.bpo-45663.J90N5R.rst new file mode 100644 index 0000000000000..f246f67cf80e5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-10-28-23-11-59.bpo-45663.J90N5R.rst @@ -0,0 +1,2 @@ +Fix :func:`dataclasses.is_dataclass` for dataclasses which are subclasses of +:class:`types.GenericAlias`. From webhook-mailer at python.org Sun Dec 5 16:25:55 2021 From: webhook-mailer at python.org (miss-islington) Date: Sun, 05 Dec 2021 21:25:55 -0000 Subject: [Python-checkins] bpo-45663: Fix is_dataclass() for dataclasses which are subclasses of types.GenericAlias (GH-29294) Message-ID: https://github.com/python/cpython/commit/19050711f5a68e50b942b3b7f1f4cf398f27efff commit: 19050711f5a68e50b942b3b7f1f4cf398f27efff branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-05T13:25:43-08:00 summary: bpo-45663: Fix is_dataclass() for dataclasses which are subclasses of types.GenericAlias (GH-29294) (cherry picked from commit 446be166861b2f08f87f74018113dd98ca5fca02) Co-authored-by: Serhiy Storchaka files: A Misc/NEWS.d/next/Library/2021-10-28-23-11-59.bpo-45663.J90N5R.rst M Lib/dataclasses.py M Lib/test/test_dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index c98e74d4ff9cc..68907058403fd 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -1047,7 +1047,7 @@ def _is_dataclass_instance(obj): def is_dataclass(obj): """Returns True if obj is a dataclass or an instance of a dataclass.""" - cls = obj if isinstance(obj, type) else type(obj) + cls = obj if isinstance(obj, type) and not isinstance(obj, GenericAlias) else type(obj) return hasattr(cls, _FIELDS) diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index ad981d1cc654f..fa5adfcea1b43 100644 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -7,6 +7,7 @@ import pickle import inspect import builtins +import types import unittest from unittest.mock import Mock from typing import ClassVar, Any, List, Union, Tuple, Dict, Generic, TypeVar, Optional, Protocol @@ -1348,6 +1349,17 @@ class B: with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'): replace(obj, x=0) + def test_is_dataclass_genericalias(self): + @dataclass + class A(types.GenericAlias): + origin: type + args: type + self.assertTrue(is_dataclass(A)) + a = A(list, int) + self.assertTrue(is_dataclass(type(a))) + self.assertTrue(is_dataclass(a)) + + def test_helper_fields_with_class_instance(self): # Check that we can call fields() on either a class or instance, # and get back the same thing. diff --git a/Misc/NEWS.d/next/Library/2021-10-28-23-11-59.bpo-45663.J90N5R.rst b/Misc/NEWS.d/next/Library/2021-10-28-23-11-59.bpo-45663.J90N5R.rst new file mode 100644 index 0000000000000..f246f67cf80e5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-10-28-23-11-59.bpo-45663.J90N5R.rst @@ -0,0 +1,2 @@ +Fix :func:`dataclasses.is_dataclass` for dataclasses which are subclasses of +:class:`types.GenericAlias`. From webhook-mailer at python.org Sun Dec 5 16:26:47 2021 From: webhook-mailer at python.org (miss-islington) Date: Sun, 05 Dec 2021 21:26:47 -0000 Subject: [Python-checkins] bpo-45664: Fix resolve_bases() and new_class() for GenericAlias instance as a base (GH-29298) Message-ID: https://github.com/python/cpython/commit/cb68c0a3a4aeb4ec58ab1f71b70bc8bfecbceef6 commit: cb68c0a3a4aeb4ec58ab1f71b70bc8bfecbceef6 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-05T13:26:37-08:00 summary: bpo-45664: Fix resolve_bases() and new_class() for GenericAlias instance as a base (GH-29298) (cherry picked from commit 2b318ce1c988b7b6e3caf293d55f289e066b6e0f) Co-authored-by: Serhiy Storchaka files: A Misc/NEWS.d/next/Library/2021-10-28-23-40-54.bpo-45664.7dqtxQ.rst M Lib/test/test_types.py M Lib/types.py diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index b1218abc8af5e..3dfda5cb95663 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -1236,6 +1236,17 @@ def __mro_entries__(self, bases): self.assertEqual(D.__orig_bases__, (c,)) self.assertEqual(D.__mro__, (D, A, object)) + def test_new_class_with_mro_entry_genericalias(self): + L1 = types.new_class('L1', (typing.List[int],), {}) + self.assertEqual(L1.__bases__, (list, typing.Generic)) + self.assertEqual(L1.__orig_bases__, (typing.List[int],)) + self.assertEqual(L1.__mro__, (L1, list, typing.Generic, object)) + + L2 = types.new_class('L2', (list[int],), {}) + self.assertEqual(L2.__bases__, (list,)) + self.assertEqual(L2.__orig_bases__, (list[int],)) + self.assertEqual(L2.__mro__, (L2, list, object)) + def test_new_class_with_mro_entry_none(self): class A: pass class B: pass @@ -1351,6 +1362,11 @@ def __mro_entries__(self, bases): for bases in [x, y, z, t]: self.assertIs(types.resolve_bases(bases), bases) + def test_resolve_bases_with_mro_entry(self): + self.assertEqual(types.resolve_bases((typing.List[int],)), + (list, typing.Generic)) + self.assertEqual(types.resolve_bases((list[int],)), (list,)) + def test_metaclass_derivation(self): # issue1294232: correct metaclass calculation new_calls = [] # to check the order of __new__ calls diff --git a/Lib/types.py b/Lib/types.py index c2dc97dd57ae3..62122a994866f 100644 --- a/Lib/types.py +++ b/Lib/types.py @@ -82,7 +82,7 @@ def resolve_bases(bases): updated = False shift = 0 for i, base in enumerate(bases): - if isinstance(base, type): + if isinstance(base, type) and not isinstance(base, GenericAlias): continue if not hasattr(base, "__mro_entries__"): continue diff --git a/Misc/NEWS.d/next/Library/2021-10-28-23-40-54.bpo-45664.7dqtxQ.rst b/Misc/NEWS.d/next/Library/2021-10-28-23-40-54.bpo-45664.7dqtxQ.rst new file mode 100644 index 0000000000000..573a569845a87 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-10-28-23-40-54.bpo-45664.7dqtxQ.rst @@ -0,0 +1,2 @@ +Fix :func:`types.resolve_bases` and :func:`types.new_class` for +:class:`types.GenericAlias` instance as a base. From webhook-mailer at python.org Mon Dec 6 02:39:16 2021 From: webhook-mailer at python.org (ned-deily) Date: Mon, 06 Dec 2021 07:39:16 -0000 Subject: [Python-checkins] bpo-45732: Update python.org macOS installer to use Tcl/Tk 8.6.12. (GH-29932) Message-ID: https://github.com/python/cpython/commit/20801982fa696a01ad2c116925bddf2fda106338 commit: 20801982fa696a01ad2c116925bddf2fda106338 branch: 3.10 author: Ned Deily committer: ned-deily date: 2021-12-06T02:39:11-05:00 summary: bpo-45732: Update python.org macOS installer to use Tcl/Tk 8.6.12. (GH-29932) files: A Misc/NEWS.d/next/macOS/2021-12-05-23-52-03.bpo-45732.-BWrnh.rst D Mac/BuildScript/bpo-44828-filedialog-crash-monterey.patch M Mac/BuildScript/build-installer.py diff --git a/Mac/BuildScript/bpo-44828-filedialog-crash-monterey.patch b/Mac/BuildScript/bpo-44828-filedialog-crash-monterey.patch deleted file mode 100644 index 059149250f8c8..0000000000000 --- a/Mac/BuildScript/bpo-44828-filedialog-crash-monterey.patch +++ /dev/null @@ -1,203 +0,0 @@ ---- tk8.6.11/macosx/tkMacOSXDialog.c 2020-12-31 01:46:07.000000000 +0000 -+++ tk8.6.11-patched/macosx/tkMacOSXDialog.c 2021-10-28 15:13:03.000000000 +0000 -@@ -221,7 +221,7 @@ - returnCode: (NSModalResponse) returnCode - contextInfo: (void *) contextInfo - { -- FilePanelCallbackInfo *callbackInfo = contextInfo; -+ FilePanelCallbackInfo *callbackInfo = (FilePanelCallbackInfo *)contextInfo; - - if (returnCode == modalOK) { - Tcl_Obj *resultObj; -@@ -266,7 +266,7 @@ - - (void) tkAlertDidEnd: (NSAlert *) alert returnCode: (NSInteger) returnCode - contextInfo: (void *) contextInfo - { -- AlertCallbackInfo *callbackInfo = contextInfo; -+ AlertCallbackInfo *callbackInfo = (AlertCallbackInfo *)contextInfo; - - if (returnCode >= NSAlertFirstButtonReturn) { - Tcl_Obj *resultObj = Tcl_NewStringObj(alertButtonStrings[ -@@ -350,49 +350,42 @@ - FilePanelCallbackInfo *callbackInfo) - { - NSInteger modalReturnCode; -+ int OSVersion = [NSApp macOSVersion]; - -- if (parent && ![parent attachedSheet]) { -- [panel beginSheetModalForWindow:parent -- completionHandler:^(NSModalResponse returnCode) { -- [NSApp tkFilePanelDidEnd:panel -- returnCode:returnCode -- contextInfo:callbackInfo ]; -- }]; -- -- /* -- * The sheet has been prepared, so now we have to run it as a modal -- * window. Using [NSApp runModalForWindow:] on macOS 10.15 or later -- * generates warnings on stderr. But using [NSOpenPanel runModal] or -- * [NSSavePanel runModal] on 10.14 or earler does not cause the -- * completion handler to run when the panel is closed. -- */ -+ /* -+ * Use a sheet if -parent is specified (unless there is already a sheet). -+ */ - -- if ([NSApp macOSVersion] > 101400) { -- modalReturnCode = [panel runModal]; -- } else { -+ if (parent && ![parent attachedSheet]) { -+ if (OSVersion < 101500) { -+ [panel beginSheetModalForWindow:parent -+ completionHandler:^(NSModalResponse returnCode) { -+ [NSApp tkFilePanelDidEnd:panel -+ returnCode:returnCode -+ contextInfo:callbackInfo ]; -+ }]; - modalReturnCode = [NSApp runModalForWindow:panel]; -- } -- } else { -- -- /* -- * For the standalone file dialog, completion handlers do not work -- * at all on macOS 10.14 and earlier. -- */ -- -- if ([NSApp macOSVersion] > 101400) { -- [panel beginWithCompletionHandler:^(NSModalResponse returnCode) { -+ } else if (OSVersion < 110000) { -+ [panel beginSheetModalForWindow:parent -+ completionHandler:^(NSModalResponse returnCode) { - [NSApp tkFilePanelDidEnd:panel -- returnCode:returnCode -- contextInfo:callbackInfo ]; -- }]; -+ returnCode:returnCode -+ contextInfo:callbackInfo ]; -+ }]; - modalReturnCode = [panel runModal]; - } else { -+ [parent beginSheet: panel completionHandler:nil]; - modalReturnCode = [panel runModal]; - [NSApp tkFilePanelDidEnd:panel -- returnCode:modalReturnCode -- contextInfo:callbackInfo ]; -- [panel close]; -+ returnCode:modalReturnCode -+ contextInfo:callbackInfo ]; -+ [parent endSheet:panel]; - } -+ } else { -+ modalReturnCode = [panel runModal]; -+ [NSApp tkFilePanelDidEnd:panel -+ returnCode:modalReturnCode -+ contextInfo:callbackInfo ]; - } - return callbackInfo->cmdObj ? modalOther : modalReturnCode; - } -@@ -422,7 +414,7 @@ - Tcl_Obj *const objv[]) /* Argument objects. */ - { - int result = TCL_ERROR; -- Tk_Window parent, tkwin = clientData; -+ Tk_Window parent, tkwin = (Tk_Window)clientData; - const char *title = NULL; - int i; - NSColor *color = nil, *initialColor = nil; -@@ -677,7 +669,7 @@ - int objc, /* Number of arguments. */ - Tcl_Obj *const objv[]) /* Argument objects. */ - { -- Tk_Window tkwin = clientData; -+ Tk_Window tkwin = (Tk_Window)clientData; - char *str; - int i, result = TCL_ERROR, haveParentOption = 0; - int index, len, multiple = 0; -@@ -1679,10 +1671,10 @@ - if (!fontchooserInterp) { - return; - } -- fcdPtr = Tcl_GetAssocData(fontchooserInterp, "::tk::fontchooser", NULL); -+ fcdPtr = (FontchooserData *)Tcl_GetAssocData(fontchooserInterp, "::tk::fontchooser", NULL); - switch (kind) { - case FontchooserClosed: -- if (fcdPtr->parent != None) { -+ if (fcdPtr->parent != NULL) { - TkSendVirtualEvent(fcdPtr->parent, "TkFontchooserVisibility", NULL); - fontchooserInterp = NULL; - } -@@ -1738,7 +1730,7 @@ - - switch(optionIndex) { - case FontchooserParent: -- if (fcdPtr->parent != None) { -+ if (fcdPtr->parent != NULL) { - resObj = Tcl_NewStringObj( - ((TkWindow *)fcdPtr->parent)->pathName, -1); - } else { -@@ -1801,7 +1793,7 @@ - Tcl_Obj *const objv[]) - { - Tk_Window tkwin = (Tk_Window)clientData; -- FontchooserData *fcdPtr = Tcl_GetAssocData(interp, "::tk::fontchooser", -+ FontchooserData *fcdPtr = (FontchooserData *)Tcl_GetAssocData(interp, "::tk::fontchooser", - NULL); - int i, r = TCL_OK; - -@@ -1858,7 +1850,7 @@ - Tk_Window parent = Tk_NameToWindow(interp, - Tcl_GetString(objv[i+1]), tkwin); - -- if (parent == None) { -+ if (parent == NULL) { - return TCL_ERROR; - } - if (fcdPtr->parent) { -@@ -1885,7 +1877,7 @@ - fcdPtr->titleObj = NULL; - } - break; -- case FontchooserFont: -+ case FontchooserFont: { - Tcl_GetStringFromObj(objv[i+1], &len); - if (len) { - Tk_Font f = Tk_AllocFontFromObj(interp, tkwin, objv[i+1]); -@@ -1919,6 +1911,7 @@ - "TkFontchooserFontChanged", NULL); - } - break; -+ } - case FontchooserCmd: - if (fcdPtr->cmdObj) { - Tcl_DecrRefCount(fcdPtr->cmdObj); -@@ -1964,10 +1957,10 @@ - TCL_UNUSED(int), - TCL_UNUSED(Tcl_Obj *const *)) - { -- FontchooserData *fcdPtr = Tcl_GetAssocData(interp, "::tk::fontchooser", -+ FontchooserData *fcdPtr = (FontchooserData *)Tcl_GetAssocData(interp, "::tk::fontchooser", - NULL); - -- if (fcdPtr->parent == None) { -+ if (fcdPtr->parent == NULL) { - fcdPtr->parent = (Tk_Window)clientData; - Tk_CreateEventHandler(fcdPtr->parent, StructureNotifyMask, - FontchooserParentEventHandler, fcdPtr); -@@ -2042,7 +2035,7 @@ - ClientData clientData, - XEvent *eventPtr) - { -- FontchooserData *fcdPtr = clientData; -+ FontchooserData *fcdPtr = (FontchooserData *)clientData; - - if (eventPtr->type == DestroyNotify) { - Tk_DeleteEventHandler(fcdPtr->parent, StructureNotifyMask, -@@ -2074,7 +2067,7 @@ - ClientData clientData, - Tcl_Interp *interp) - { -- FontchooserData *fcdPtr = clientData; -+ FontchooserData *fcdPtr = (FontchooserData *)clientData; - - if (fcdPtr->titleObj) { - Tcl_DecrRefCount(fcdPtr->titleObj); diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 86d31688da75c..9fefe67753666 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -265,11 +265,11 @@ def library_recipes(): tk_patches = ['tk868_on_10_8_10_9.patch'] else: - tcl_tk_ver='8.6.11' - tcl_checksum='8a4c004f48984a03a7747e9ba06e4da4' + tcl_tk_ver='8.6.12' + tcl_checksum='87ea890821d2221f2ab5157bc5eb885f' - tk_checksum='c7ee71a2d05bba78dfffd76528dc17c6' - tk_patches = ['bpo-44828-filedialog-crash-monterey.patch'] + tk_checksum='1d6dcf6120356e3d211e056dff5e462a' + tk_patches = [ ] result.extend([ diff --git a/Misc/NEWS.d/next/macOS/2021-12-05-23-52-03.bpo-45732.-BWrnh.rst b/Misc/NEWS.d/next/macOS/2021-12-05-23-52-03.bpo-45732.-BWrnh.rst new file mode 100644 index 0000000000000..eb47985f86f95 --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2021-12-05-23-52-03.bpo-45732.-BWrnh.rst @@ -0,0 +1 @@ +Update python.org macOS installer to use Tcl/Tk 8.6.12. From webhook-mailer at python.org Mon Dec 6 02:40:01 2021 From: webhook-mailer at python.org (ned-deily) Date: Mon, 06 Dec 2021 07:40:01 -0000 Subject: [Python-checkins] bpo-45732: Update python.org macOS installer to use Tcl/Tk 8.6.12. (GH-29933) Message-ID: https://github.com/python/cpython/commit/7accb4fdb3dc1b4140089edee290998aff496fe2 commit: 7accb4fdb3dc1b4140089edee290998aff496fe2 branch: 3.9 author: Ned Deily committer: ned-deily date: 2021-12-06T02:39:56-05:00 summary: bpo-45732: Update python.org macOS installer to use Tcl/Tk 8.6.12. (GH-29933) files: A Misc/NEWS.d/next/macOS/2021-12-05-23-52-03.bpo-45732.-BWrnh.rst D Mac/BuildScript/bpo-44828-filedialog-crash-monterey.patch M Mac/BuildScript/build-installer.py diff --git a/Mac/BuildScript/bpo-44828-filedialog-crash-monterey.patch b/Mac/BuildScript/bpo-44828-filedialog-crash-monterey.patch deleted file mode 100644 index 059149250f8c8..0000000000000 --- a/Mac/BuildScript/bpo-44828-filedialog-crash-monterey.patch +++ /dev/null @@ -1,203 +0,0 @@ ---- tk8.6.11/macosx/tkMacOSXDialog.c 2020-12-31 01:46:07.000000000 +0000 -+++ tk8.6.11-patched/macosx/tkMacOSXDialog.c 2021-10-28 15:13:03.000000000 +0000 -@@ -221,7 +221,7 @@ - returnCode: (NSModalResponse) returnCode - contextInfo: (void *) contextInfo - { -- FilePanelCallbackInfo *callbackInfo = contextInfo; -+ FilePanelCallbackInfo *callbackInfo = (FilePanelCallbackInfo *)contextInfo; - - if (returnCode == modalOK) { - Tcl_Obj *resultObj; -@@ -266,7 +266,7 @@ - - (void) tkAlertDidEnd: (NSAlert *) alert returnCode: (NSInteger) returnCode - contextInfo: (void *) contextInfo - { -- AlertCallbackInfo *callbackInfo = contextInfo; -+ AlertCallbackInfo *callbackInfo = (AlertCallbackInfo *)contextInfo; - - if (returnCode >= NSAlertFirstButtonReturn) { - Tcl_Obj *resultObj = Tcl_NewStringObj(alertButtonStrings[ -@@ -350,49 +350,42 @@ - FilePanelCallbackInfo *callbackInfo) - { - NSInteger modalReturnCode; -+ int OSVersion = [NSApp macOSVersion]; - -- if (parent && ![parent attachedSheet]) { -- [panel beginSheetModalForWindow:parent -- completionHandler:^(NSModalResponse returnCode) { -- [NSApp tkFilePanelDidEnd:panel -- returnCode:returnCode -- contextInfo:callbackInfo ]; -- }]; -- -- /* -- * The sheet has been prepared, so now we have to run it as a modal -- * window. Using [NSApp runModalForWindow:] on macOS 10.15 or later -- * generates warnings on stderr. But using [NSOpenPanel runModal] or -- * [NSSavePanel runModal] on 10.14 or earler does not cause the -- * completion handler to run when the panel is closed. -- */ -+ /* -+ * Use a sheet if -parent is specified (unless there is already a sheet). -+ */ - -- if ([NSApp macOSVersion] > 101400) { -- modalReturnCode = [panel runModal]; -- } else { -+ if (parent && ![parent attachedSheet]) { -+ if (OSVersion < 101500) { -+ [panel beginSheetModalForWindow:parent -+ completionHandler:^(NSModalResponse returnCode) { -+ [NSApp tkFilePanelDidEnd:panel -+ returnCode:returnCode -+ contextInfo:callbackInfo ]; -+ }]; - modalReturnCode = [NSApp runModalForWindow:panel]; -- } -- } else { -- -- /* -- * For the standalone file dialog, completion handlers do not work -- * at all on macOS 10.14 and earlier. -- */ -- -- if ([NSApp macOSVersion] > 101400) { -- [panel beginWithCompletionHandler:^(NSModalResponse returnCode) { -+ } else if (OSVersion < 110000) { -+ [panel beginSheetModalForWindow:parent -+ completionHandler:^(NSModalResponse returnCode) { - [NSApp tkFilePanelDidEnd:panel -- returnCode:returnCode -- contextInfo:callbackInfo ]; -- }]; -+ returnCode:returnCode -+ contextInfo:callbackInfo ]; -+ }]; - modalReturnCode = [panel runModal]; - } else { -+ [parent beginSheet: panel completionHandler:nil]; - modalReturnCode = [panel runModal]; - [NSApp tkFilePanelDidEnd:panel -- returnCode:modalReturnCode -- contextInfo:callbackInfo ]; -- [panel close]; -+ returnCode:modalReturnCode -+ contextInfo:callbackInfo ]; -+ [parent endSheet:panel]; - } -+ } else { -+ modalReturnCode = [panel runModal]; -+ [NSApp tkFilePanelDidEnd:panel -+ returnCode:modalReturnCode -+ contextInfo:callbackInfo ]; - } - return callbackInfo->cmdObj ? modalOther : modalReturnCode; - } -@@ -422,7 +414,7 @@ - Tcl_Obj *const objv[]) /* Argument objects. */ - { - int result = TCL_ERROR; -- Tk_Window parent, tkwin = clientData; -+ Tk_Window parent, tkwin = (Tk_Window)clientData; - const char *title = NULL; - int i; - NSColor *color = nil, *initialColor = nil; -@@ -677,7 +669,7 @@ - int objc, /* Number of arguments. */ - Tcl_Obj *const objv[]) /* Argument objects. */ - { -- Tk_Window tkwin = clientData; -+ Tk_Window tkwin = (Tk_Window)clientData; - char *str; - int i, result = TCL_ERROR, haveParentOption = 0; - int index, len, multiple = 0; -@@ -1679,10 +1671,10 @@ - if (!fontchooserInterp) { - return; - } -- fcdPtr = Tcl_GetAssocData(fontchooserInterp, "::tk::fontchooser", NULL); -+ fcdPtr = (FontchooserData *)Tcl_GetAssocData(fontchooserInterp, "::tk::fontchooser", NULL); - switch (kind) { - case FontchooserClosed: -- if (fcdPtr->parent != None) { -+ if (fcdPtr->parent != NULL) { - TkSendVirtualEvent(fcdPtr->parent, "TkFontchooserVisibility", NULL); - fontchooserInterp = NULL; - } -@@ -1738,7 +1730,7 @@ - - switch(optionIndex) { - case FontchooserParent: -- if (fcdPtr->parent != None) { -+ if (fcdPtr->parent != NULL) { - resObj = Tcl_NewStringObj( - ((TkWindow *)fcdPtr->parent)->pathName, -1); - } else { -@@ -1801,7 +1793,7 @@ - Tcl_Obj *const objv[]) - { - Tk_Window tkwin = (Tk_Window)clientData; -- FontchooserData *fcdPtr = Tcl_GetAssocData(interp, "::tk::fontchooser", -+ FontchooserData *fcdPtr = (FontchooserData *)Tcl_GetAssocData(interp, "::tk::fontchooser", - NULL); - int i, r = TCL_OK; - -@@ -1858,7 +1850,7 @@ - Tk_Window parent = Tk_NameToWindow(interp, - Tcl_GetString(objv[i+1]), tkwin); - -- if (parent == None) { -+ if (parent == NULL) { - return TCL_ERROR; - } - if (fcdPtr->parent) { -@@ -1885,7 +1877,7 @@ - fcdPtr->titleObj = NULL; - } - break; -- case FontchooserFont: -+ case FontchooserFont: { - Tcl_GetStringFromObj(objv[i+1], &len); - if (len) { - Tk_Font f = Tk_AllocFontFromObj(interp, tkwin, objv[i+1]); -@@ -1919,6 +1911,7 @@ - "TkFontchooserFontChanged", NULL); - } - break; -+ } - case FontchooserCmd: - if (fcdPtr->cmdObj) { - Tcl_DecrRefCount(fcdPtr->cmdObj); -@@ -1964,10 +1957,10 @@ - TCL_UNUSED(int), - TCL_UNUSED(Tcl_Obj *const *)) - { -- FontchooserData *fcdPtr = Tcl_GetAssocData(interp, "::tk::fontchooser", -+ FontchooserData *fcdPtr = (FontchooserData *)Tcl_GetAssocData(interp, "::tk::fontchooser", - NULL); - -- if (fcdPtr->parent == None) { -+ if (fcdPtr->parent == NULL) { - fcdPtr->parent = (Tk_Window)clientData; - Tk_CreateEventHandler(fcdPtr->parent, StructureNotifyMask, - FontchooserParentEventHandler, fcdPtr); -@@ -2042,7 +2035,7 @@ - ClientData clientData, - XEvent *eventPtr) - { -- FontchooserData *fcdPtr = clientData; -+ FontchooserData *fcdPtr = (FontchooserData *)clientData; - - if (eventPtr->type == DestroyNotify) { - Tk_DeleteEventHandler(fcdPtr->parent, StructureNotifyMask, -@@ -2074,7 +2067,7 @@ - ClientData clientData, - Tcl_Interp *interp) - { -- FontchooserData *fcdPtr = clientData; -+ FontchooserData *fcdPtr = (FontchooserData *)clientData; - - if (fcdPtr->titleObj) { - Tcl_DecrRefCount(fcdPtr->titleObj); diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 10112fe330061..cc24d54753924 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -263,11 +263,11 @@ def library_recipes(): tk_patches = ['tk868_on_10_8_10_9.patch'] else: - tcl_tk_ver='8.6.11' - tcl_checksum='8a4c004f48984a03a7747e9ba06e4da4' + tcl_tk_ver='8.6.12' + tcl_checksum='87ea890821d2221f2ab5157bc5eb885f' - tk_checksum='c7ee71a2d05bba78dfffd76528dc17c6' - tk_patches = ['bpo-44828-filedialog-crash-monterey.patch'] + tk_checksum='1d6dcf6120356e3d211e056dff5e462a' + tk_patches = [ ] result.extend([ diff --git a/Misc/NEWS.d/next/macOS/2021-12-05-23-52-03.bpo-45732.-BWrnh.rst b/Misc/NEWS.d/next/macOS/2021-12-05-23-52-03.bpo-45732.-BWrnh.rst new file mode 100644 index 0000000000000..eb47985f86f95 --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2021-12-05-23-52-03.bpo-45732.-BWrnh.rst @@ -0,0 +1 @@ +Update python.org macOS installer to use Tcl/Tk 8.6.12. From webhook-mailer at python.org Mon Dec 6 02:44:21 2021 From: webhook-mailer at python.org (ned-deily) Date: Mon, 06 Dec 2021 07:44:21 -0000 Subject: [Python-checkins] bpo-45732: Update python.org macOS installer to use Tcl/Tk 8.6.12. (GH-29931) Message-ID: https://github.com/python/cpython/commit/f34d181fa15e1f082140a4e4a8fa3b77118f8e98 commit: f34d181fa15e1f082140a4e4a8fa3b77118f8e98 branch: main author: Ned Deily committer: ned-deily date: 2021-12-06T02:44:09-05:00 summary: bpo-45732: Update python.org macOS installer to use Tcl/Tk 8.6.12. (GH-29931) files: A Misc/NEWS.d/next/macOS/2021-12-05-23-52-03.bpo-45732.-BWrnh.rst D Mac/BuildScript/bpo-44828-filedialog-crash-monterey-8612rc1.patch M Mac/BuildScript/build-installer.py diff --git a/Mac/BuildScript/bpo-44828-filedialog-crash-monterey-8612rc1.patch b/Mac/BuildScript/bpo-44828-filedialog-crash-monterey-8612rc1.patch deleted file mode 100644 index e70e2c35dc113..0000000000000 --- a/Mac/BuildScript/bpo-44828-filedialog-crash-monterey-8612rc1.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- tk8.6.12/macosx/tkMacOSXDialog.c 2021-10-29 17:08:23.000000000 +0000 -+++ tk8.6.12-patched/macosx/tkMacOSXDialog.c 2021-11-02 19:04:59.000000000 +0000 -@@ -379,6 +379,7 @@ - [NSApp tkFilePanelDidEnd:panel - returnCode:modalReturnCode - contextInfo:callbackInfo ]; -+ [parent endSheet:panel]; - } - } else { - modalReturnCode = [panel runModal]; diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 1f6fcafc6f92c..5365f62bf3d0e 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -265,11 +265,11 @@ def library_recipes(): tk_patches = ['tk868_on_10_8_10_9.patch'] else: - tcl_tk_ver='8.6.12rc1' - tcl_checksum='82fd1637c0f7d4b76cb909f8abc373ec' + tcl_tk_ver='8.6.12' + tcl_checksum='87ea890821d2221f2ab5157bc5eb885f' - tk_checksum='d63c3b91b86cd8b6fa54e83ef2c5153e' - tk_patches = ['bpo-44828-filedialog-crash-monterey-8612rc1.patch'] + tk_checksum='1d6dcf6120356e3d211e056dff5e462a' + tk_patches = [ ] result.extend([ diff --git a/Misc/NEWS.d/next/macOS/2021-12-05-23-52-03.bpo-45732.-BWrnh.rst b/Misc/NEWS.d/next/macOS/2021-12-05-23-52-03.bpo-45732.-BWrnh.rst new file mode 100644 index 0000000000000..eb47985f86f95 --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2021-12-05-23-52-03.bpo-45732.-BWrnh.rst @@ -0,0 +1 @@ +Update python.org macOS installer to use Tcl/Tk 8.6.12. From webhook-mailer at python.org Mon Dec 6 05:14:00 2021 From: webhook-mailer at python.org (markshannon) Date: Mon, 06 Dec 2021 10:14:00 -0000 Subject: [Python-checkins] bpo-45963: Make space for the InterpreterFrame of a generator in that generator. (GH-29891) Message-ID: https://github.com/python/cpython/commit/299483c95d601ddcfdce2f96418b6499c1fc7b9f commit: 299483c95d601ddcfdce2f96418b6499c1fc7b9f branch: main author: Mark Shannon committer: markshannon date: 2021-12-06T10:13:49Z summary: bpo-45963: Make space for the InterpreterFrame of a generator in that generator. (GH-29891) * Make generator, coroutine and async gen structs all the same size. * Store interpreter frame in generator (and coroutine). Reduces the number of allocations neeeded for a generator from two to one. files: M Include/cpython/genobject.h M Include/internal/pycore_ceval.h M Include/internal/pycore_frame.h M Lib/test/test_sys.py M Objects/genobject.c M Python/ceval.c M Python/frame.c diff --git a/Include/cpython/genobject.h b/Include/cpython/genobject.h index 8f87cf5fff757..ad2818e881667 100644 --- a/Include/cpython/genobject.h +++ b/Include/cpython/genobject.h @@ -14,7 +14,6 @@ extern "C" { #define _PyGenObject_HEAD(prefix) \ PyObject_HEAD \ /* Note: gi_frame can be NULL if the generator is "finished" */ \ - struct _interpreter_frame *prefix##_xframe; \ /* The code object backing the generator */ \ PyCodeObject *prefix##_code; \ /* List of weak reference. */ \ @@ -23,7 +22,14 @@ extern "C" { PyObject *prefix##_name; \ /* Qualified name of the generator. */ \ PyObject *prefix##_qualname; \ - _PyErr_StackItem prefix##_exc_state; + _PyErr_StackItem prefix##_exc_state; \ + PyObject *prefix##_origin_or_finalizer; \ + char prefix##_hooks_inited; \ + char prefix##_closed; \ + char prefix##_running_async; \ + /* The frame */ \ + char prefix##_frame_valid; \ + PyObject *prefix##_iframe[1]; typedef struct { /* The gi_ prefix is intended to remind of generator-iterator. */ @@ -48,7 +54,6 @@ PyAPI_FUNC(void) _PyGen_Finalize(PyObject *self); typedef struct { _PyGenObject_HEAD(cr) - PyObject *cr_origin; } PyCoroObject; PyAPI_DATA(PyTypeObject) PyCoro_Type; @@ -64,18 +69,6 @@ PyAPI_FUNC(PyObject *) PyCoro_New(PyFrameObject *, typedef struct { _PyGenObject_HEAD(ag) - PyObject *ag_finalizer; - - /* Flag is set to 1 when hooks set up by sys.set_asyncgen_hooks - were called on the generator, to avoid calling them more - than once. */ - int ag_hooks_inited; - - /* Flag is set to 1 when aclose() is called for the first time, or - when a StopAsyncIteration exception is raised. */ - int ag_closed; - - int ag_running_async; } PyAsyncGenObject; PyAPI_DATA(PyTypeObject) PyAsyncGen_Type; diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index 9987f2076cd59..26d5677b12837 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -113,7 +113,7 @@ static inline void _Py_LeaveRecursiveCall_inline(void) { struct _interpreter_frame *_PyEval_GetFrame(void); -PyObject *_Py_MakeCoro(PyFunctionObject *func, struct _interpreter_frame *); +PyObject *_Py_MakeCoro(PyFunctionObject *func); #ifdef __cplusplus } diff --git a/Include/internal/pycore_frame.h b/Include/internal/pycore_frame.h index b0e51a6ddc461..f4f7ab942c1ac 100644 --- a/Include/internal/pycore_frame.h +++ b/Include/internal/pycore_frame.h @@ -74,7 +74,7 @@ static inline void _PyFrame_StackPush(InterpreterFrame *f, PyObject *value) { #define FRAME_SPECIALS_SIZE ((sizeof(InterpreterFrame)-1)/sizeof(PyObject *)) -InterpreterFrame *_PyFrame_Copy(InterpreterFrame *frame); +void _PyFrame_Copy(InterpreterFrame *src, InterpreterFrame *dest); static inline void _PyFrame_InitializeSpecials( diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 2b1ba2457f50d..81802893a8ee5 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1340,7 +1340,7 @@ def bar(cls): check(bar, size('PP')) # generator def get_gen(): yield 1 - check(get_gen(), size('P2PPP4P')) + check(get_gen(), size('P2PPP4P4c8P2iciP')) # iterator check(iter('abc'), size('lP')) # callable-iterator diff --git a/Objects/genobject.c b/Objects/genobject.c index 04d98a2b4edf1..c4ba660530cae 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -36,8 +36,8 @@ gen_traverse(PyGenObject *gen, visitproc visit, void *arg) Py_VISIT(gen->gi_code); Py_VISIT(gen->gi_name); Py_VISIT(gen->gi_qualname); - InterpreterFrame *frame = gen->gi_xframe; - if (frame != NULL) { + if (gen->gi_frame_valid) { + InterpreterFrame *frame = (InterpreterFrame *)(gen->gi_iframe); assert(frame->frame_obj == NULL || frame->frame_obj->f_owns_frame == 0); int err = _PyFrame_Traverse(frame, visit, arg); if (err) { @@ -56,14 +56,14 @@ _PyGen_Finalize(PyObject *self) PyObject *res = NULL; PyObject *error_type, *error_value, *error_traceback; - if (gen->gi_xframe == NULL || _PyFrameHasCompleted(gen->gi_xframe)) { + if (gen->gi_frame_valid == 0 || _PyFrameHasCompleted((InterpreterFrame *)gen->gi_iframe)) { /* Generator isn't paused, so no need to close */ return; } if (PyAsyncGen_CheckExact(self)) { PyAsyncGenObject *agen = (PyAsyncGenObject*)self; - PyObject *finalizer = agen->ag_finalizer; + PyObject *finalizer = agen->ag_origin_or_finalizer; if (finalizer && !agen->ag_closed) { /* Save the current exception, if any. */ PyErr_Fetch(&error_type, &error_value, &error_traceback); @@ -88,7 +88,7 @@ _PyGen_Finalize(PyObject *self) issue a RuntimeWarning. */ if (gen->gi_code != NULL && ((PyCodeObject *)gen->gi_code)->co_flags & CO_COROUTINE && - gen->gi_xframe->f_lasti == -1) + ((InterpreterFrame *)gen->gi_iframe)->f_lasti == -1) { _PyErr_WarnUnawaitedCoroutine((PyObject *)gen); } @@ -129,18 +129,17 @@ gen_dealloc(PyGenObject *gen) /* We have to handle this case for asynchronous generators right here, because this code has to be between UNTRACK and GC_Del. */ - Py_CLEAR(((PyAsyncGenObject*)gen)->ag_finalizer); + Py_CLEAR(((PyAsyncGenObject*)gen)->ag_origin_or_finalizer); } - InterpreterFrame *frame = gen->gi_xframe; - if (frame != NULL) { - gen->gi_xframe = NULL; + if (gen->gi_frame_valid) { + InterpreterFrame *frame = (InterpreterFrame *)gen->gi_iframe; + gen->gi_frame_valid = 0; frame->generator = NULL; frame->previous = NULL; _PyFrame_Clear(frame); - PyMem_Free(frame); } if (((PyCodeObject *)gen->gi_code)->co_flags & CO_COROUTINE) { - Py_CLEAR(((PyCoroObject *)gen)->cr_origin); + Py_CLEAR(((PyCoroObject *)gen)->cr_origin_or_finalizer); } Py_CLEAR(gen->gi_code); Py_CLEAR(gen->gi_name); @@ -154,11 +153,11 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, int exc, int closing) { PyThreadState *tstate = _PyThreadState_GET(); - InterpreterFrame *frame = gen->gi_xframe; + InterpreterFrame *frame = (InterpreterFrame *)gen->gi_iframe; PyObject *result; *presult = NULL; - if (frame != NULL && _PyFrame_IsExecuting(frame)) { + if (gen->gi_frame_valid && _PyFrame_IsExecuting(frame)) { const char *msg = "generator already executing"; if (PyCoro_CheckExact(gen)) { msg = "coroutine already executing"; @@ -169,7 +168,7 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, PyErr_SetString(PyExc_ValueError, msg); return PYGEN_ERROR; } - if (frame == NULL || _PyFrameHasCompleted(frame)) { + if (gen->gi_frame_valid == 0 || _PyFrameHasCompleted(frame)) { if (PyCoro_CheckExact(gen) && !closing) { /* `gen` is an exhausted coroutine: raise an error, except when called from gen_close(), which should @@ -188,6 +187,7 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, return PYGEN_ERROR; } + assert(gen->gi_frame_valid); assert(_PyFrame_IsRunnable(frame)); /* Push arg onto the frame's value stack */ result = arg ? arg : Py_None; @@ -254,9 +254,8 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, _PyErr_ClearExcState(&gen->gi_exc_state); frame->generator = NULL; - gen->gi_xframe = NULL; + gen->gi_frame_valid = 0; _PyFrame_Clear(frame); - PyMem_Free(frame); *presult = result; return result ? PYGEN_RETURN : PYGEN_ERROR; } @@ -337,8 +336,8 @@ _PyGen_yf(PyGenObject *gen) { PyObject *yf = NULL; - if (gen->gi_xframe) { - InterpreterFrame *frame = gen->gi_xframe; + if (gen->gi_frame_valid) { + InterpreterFrame *frame = (InterpreterFrame *)gen->gi_iframe; PyObject *bytecode = gen->gi_code->co_code; unsigned char *code = (unsigned char *)PyBytes_AS_STRING(bytecode); @@ -367,10 +366,11 @@ gen_close(PyGenObject *gen, PyObject *args) int err = 0; if (yf) { - PyFrameState state = gen->gi_xframe->f_state; - gen->gi_xframe->f_state = FRAME_EXECUTING; + InterpreterFrame *frame = (InterpreterFrame *)gen->gi_iframe; + PyFrameState state = frame->f_state; + frame->f_state = FRAME_EXECUTING; err = gen_close_iter(yf); - gen->gi_xframe->f_state = state; + frame->f_state = state; Py_DECREF(yf); } if (err == 0) @@ -408,6 +408,7 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, _Py_IDENTIFIER(throw); if (yf) { + InterpreterFrame *frame = (InterpreterFrame *)gen->gi_iframe; PyObject *ret; int err; if (PyErr_GivenExceptionMatches(typ, PyExc_GeneratorExit) && @@ -417,10 +418,10 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, We have to allow some awaits to work it through, hence the `close_on_genexit` parameter here. */ - PyFrameState state = gen->gi_xframe->f_state; - gen->gi_xframe->f_state = FRAME_EXECUTING; + PyFrameState state = frame->f_state; + frame->f_state = FRAME_EXECUTING; err = gen_close_iter(yf); - gen->gi_xframe->f_state = state; + frame->f_state = state; Py_DECREF(yf); if (err < 0) return gen_send_ex(gen, Py_None, 1, 0); @@ -429,9 +430,6 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, if (PyGen_CheckExact(yf) || PyCoro_CheckExact(yf)) { /* `yf` is a generator or a coroutine. */ PyThreadState *tstate = _PyThreadState_GET(); - InterpreterFrame *frame = gen->gi_xframe; - - /* Since we are fast-tracking things by skipping the eval loop, we need to update the current frame so the stack trace will be reported correctly to the user. */ @@ -442,11 +440,11 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, tstate->cframe->current_frame = frame; /* Close the generator that we are currently iterating with 'yield from' or awaiting on with 'await'. */ - PyFrameState state = gen->gi_xframe->f_state; - gen->gi_xframe->f_state = FRAME_EXECUTING; + PyFrameState state = frame->f_state; + frame->f_state = FRAME_EXECUTING; ret = _gen_throw((PyGenObject *)yf, close_on_genexit, typ, val, tb); - gen->gi_xframe->f_state = state; + frame->f_state = state; tstate->cframe->current_frame = prev; frame->previous = NULL; } else { @@ -460,22 +458,23 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, Py_DECREF(yf); goto throw_here; } - PyFrameState state = gen->gi_xframe->f_state; - gen->gi_xframe->f_state = FRAME_EXECUTING; + PyFrameState state = frame->f_state; + frame->f_state = FRAME_EXECUTING; ret = PyObject_CallFunctionObjArgs(meth, typ, val, tb, NULL); - gen->gi_xframe->f_state = state; + frame->f_state = state; Py_DECREF(meth); } Py_DECREF(yf); if (!ret) { PyObject *val; /* Pop subiterator from stack */ - ret = _PyFrame_StackPop(gen->gi_xframe); + assert(gen->gi_frame_valid); + ret = _PyFrame_StackPop((InterpreterFrame *)gen->gi_iframe); assert(ret == yf); Py_DECREF(ret); /* Termination repetition of YIELD_FROM */ - assert(gen->gi_xframe->f_lasti >= 0); - gen->gi_xframe->f_lasti += 1; + assert(frame->f_lasti >= 0); + frame->f_lasti += 1; if (_PyGen_FetchStopIterationValue(&val) == 0) { ret = gen_send(gen, val); Py_DECREF(val); @@ -732,10 +731,10 @@ gen_getyieldfrom(PyGenObject *gen, void *Py_UNUSED(ignored)) static PyObject * gen_getrunning(PyGenObject *gen, void *Py_UNUSED(ignored)) { - if (gen->gi_xframe == NULL) { + if (gen->gi_frame_valid == 0) { Py_RETURN_FALSE; } - return PyBool_FromLong(_PyFrame_IsExecuting(gen->gi_xframe)); + return PyBool_FromLong(_PyFrame_IsExecuting((InterpreterFrame *)gen->gi_iframe)); } static PyObject * @@ -744,10 +743,10 @@ _gen_getframe(PyGenObject *gen, const char *const name) if (PySys_Audit("object.__getattr__", "Os", gen, name) < 0) { return NULL; } - if (gen->gi_xframe == NULL) { + if (gen->gi_frame_valid == 0) { Py_RETURN_NONE; } - return _Py_XNewRef((PyObject *)_PyFrame_GetFrameObject(gen->gi_xframe)); + return _Py_XNewRef((PyObject *)_PyFrame_GetFrameObject((InterpreterFrame *)gen->gi_iframe)); } static PyObject * @@ -773,10 +772,24 @@ static PyMemberDef gen_memberlist[] = { {NULL} /* Sentinel */ }; +static PyObject * +gen_sizeof(PyGenObject *gen, PyObject *Py_UNUSED(ignored)) +{ + Py_ssize_t res; + res = offsetof(PyGenObject, gi_iframe) + offsetof(InterpreterFrame, localsplus); + PyCodeObject *code = gen->gi_code; + res += (code->co_nlocalsplus+code->co_stacksize) * sizeof(PyObject *); + return PyLong_FromSsize_t(res); +} + +PyDoc_STRVAR(sizeof__doc__, +"gen.__sizeof__() -> size of gen in memory, in bytes"); + static PyMethodDef gen_methods[] = { {"send",(PyCFunction)gen_send, METH_O, send_doc}, {"throw",(PyCFunction)gen_throw, METH_VARARGS, throw_doc}, {"close",(PyCFunction)gen_close, METH_NOARGS, close_doc}, + {"__sizeof__", (PyCFunction)gen_sizeof, METH_NOARGS, sizeof__doc__}, {NULL, NULL} /* Sentinel */ }; @@ -791,8 +804,9 @@ static PyAsyncMethods gen_as_async = { PyTypeObject PyGen_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "generator", /* tp_name */ - sizeof(PyGenObject), /* tp_basicsize */ - 0, /* tp_itemsize */ + offsetof(PyGenObject, gi_iframe) + + offsetof(InterpreterFrame, localsplus), /* tp_basicsize */ + sizeof(PyObject *), /* tp_itemsize */ /* methods */ (destructor)gen_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ @@ -842,18 +856,16 @@ PyTypeObject PyGen_Type = { }; static PyObject * -make_gen(PyTypeObject *type, PyFunctionObject *func, InterpreterFrame *frame) +make_gen(PyTypeObject *type, PyFunctionObject *func) { - PyGenObject *gen = PyObject_GC_New(PyGenObject, type); + PyCodeObject *code = (PyCodeObject *)func->func_code; + int slots = code->co_nlocalsplus + code->co_stacksize; + PyGenObject *gen = PyObject_GC_NewVar(PyGenObject, type, slots); if (gen == NULL) { - assert(frame->frame_obj == NULL); - _PyFrame_Clear(frame); - PyMem_Free(frame); return NULL; } - gen->gi_xframe = frame; - frame->generator = (PyObject *)gen; - gen->gi_code = frame->f_code; + gen->gi_frame_valid = 0; + gen->gi_code = (PyCodeObject *)func->func_code; Py_INCREF(gen->gi_code); gen->gi_weakreflist = NULL; gen->gi_exc_state.exc_type = NULL; @@ -878,28 +890,28 @@ static PyObject * compute_cr_origin(int origin_depth); PyObject * -_Py_MakeCoro(PyFunctionObject *func, InterpreterFrame *frame) +_Py_MakeCoro(PyFunctionObject *func) { int coro_flags = ((PyCodeObject *)func->func_code)->co_flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR); assert(coro_flags); if (coro_flags == CO_GENERATOR) { - return make_gen(&PyGen_Type, func, frame); + return make_gen(&PyGen_Type, func); } if (coro_flags == CO_ASYNC_GENERATOR) { PyAsyncGenObject *o; - o = (PyAsyncGenObject *)make_gen(&PyAsyncGen_Type, func, frame); + o = (PyAsyncGenObject *)make_gen(&PyAsyncGen_Type, func); if (o == NULL) { return NULL; } - o->ag_finalizer = NULL; + o->ag_origin_or_finalizer = NULL; o->ag_closed = 0; o->ag_hooks_inited = 0; o->ag_running_async = 0; return (PyObject*)o; } assert (coro_flags == CO_COROUTINE); - PyObject *coro = make_gen(&PyCoro_Type, func, frame); + PyObject *coro = make_gen(&PyCoro_Type, func); if (!coro) { return NULL; } @@ -907,16 +919,15 @@ _Py_MakeCoro(PyFunctionObject *func, InterpreterFrame *frame) int origin_depth = tstate->coroutine_origin_tracking_depth; if (origin_depth == 0) { - ((PyCoroObject *)coro)->cr_origin = NULL; + ((PyCoroObject *)coro)->cr_origin_or_finalizer = NULL; } else { PyObject *cr_origin = compute_cr_origin(origin_depth); - ((PyCoroObject *)coro)->cr_origin = cr_origin; + ((PyCoroObject *)coro)->cr_origin_or_finalizer = cr_origin; if (!cr_origin) { Py_DECREF(coro); return NULL; } } - return coro; } @@ -924,27 +935,27 @@ static PyObject * gen_new_with_qualname(PyTypeObject *type, PyFrameObject *f, PyObject *name, PyObject *qualname) { - PyGenObject *gen = PyObject_GC_New(PyGenObject, type); + PyCodeObject *code = f->f_frame->f_code; + int size = code->co_nlocalsplus + code->co_stacksize; + PyGenObject *gen = PyObject_GC_NewVar(PyGenObject, type, size); if (gen == NULL) { Py_DECREF(f); return NULL; } - - /* Take ownership of the frame */ + /* Copy the frame */ assert(f->f_frame->frame_obj == NULL); assert(f->f_owns_frame); - gen->gi_xframe = _PyFrame_Copy((InterpreterFrame *)f->_f_frame_data); - if (gen->gi_xframe == NULL) { - Py_DECREF(f); - Py_DECREF(gen); - return NULL; - } - gen->gi_xframe->frame_obj = f; + InterpreterFrame *frame = (InterpreterFrame *)gen->gi_iframe; + _PyFrame_Copy((InterpreterFrame *)f->_f_frame_data, frame); + gen->gi_frame_valid = 1; + assert(frame->frame_obj == f); f->f_owns_frame = 0; - gen->gi_xframe->generator = (PyObject *) gen; + f->f_frame = frame; + frame->generator = (PyObject *) gen; assert(PyObject_GC_IsTracked((PyObject *)f)); - gen->gi_code = PyFrame_GetCode(f); + Py_INCREF(gen->gi_code); + Py_DECREF(f); gen->gi_weakreflist = NULL; gen->gi_exc_state.exc_type = NULL; gen->gi_exc_state.exc_value = NULL; @@ -1077,10 +1088,10 @@ coro_get_cr_await(PyCoroObject *coro, void *Py_UNUSED(ignored)) static PyObject * cr_getrunning(PyCoroObject *coro, void *Py_UNUSED(ignored)) { - if (coro->cr_xframe == NULL) { + if (coro->cr_frame_valid == 0) { Py_RETURN_FALSE; } - return PyBool_FromLong(_PyFrame_IsExecuting(coro->cr_xframe)); + return PyBool_FromLong(_PyFrame_IsExecuting((InterpreterFrame *)coro->cr_iframe)); } static PyObject * @@ -1104,7 +1115,7 @@ static PyGetSetDef coro_getsetlist[] = { static PyMemberDef coro_memberlist[] = { {"cr_code", T_OBJECT, offsetof(PyCoroObject, cr_code), READONLY|PY_AUDIT_READ}, - {"cr_origin", T_OBJECT, offsetof(PyCoroObject, cr_origin), READONLY}, + {"cr_origin", T_OBJECT, offsetof(PyCoroObject, cr_origin_or_finalizer), READONLY}, {NULL} /* Sentinel */ }; @@ -1123,6 +1134,7 @@ static PyMethodDef coro_methods[] = { {"send",(PyCFunction)gen_send, METH_O, coro_send_doc}, {"throw",(PyCFunction)gen_throw, METH_VARARGS, coro_throw_doc}, {"close",(PyCFunction)gen_close, METH_NOARGS, coro_close_doc}, + {"__sizeof__", (PyCFunction)gen_sizeof, METH_NOARGS, sizeof__doc__}, {NULL, NULL} /* Sentinel */ }; @@ -1136,8 +1148,9 @@ static PyAsyncMethods coro_as_async = { PyTypeObject PyCoro_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "coroutine", /* tp_name */ - sizeof(PyCoroObject), /* tp_basicsize */ - 0, /* tp_itemsize */ + offsetof(PyCoroObject, cr_iframe) + + offsetof(InterpreterFrame, localsplus), /* tp_basicsize */ + sizeof(PyObject *), /* tp_itemsize */ /* methods */ (destructor)gen_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ @@ -1318,10 +1331,10 @@ PyCoro_New(PyFrameObject *f, PyObject *name, PyObject *qualname) int origin_depth = tstate->coroutine_origin_tracking_depth; if (origin_depth == 0) { - ((PyCoroObject *)coro)->cr_origin = NULL; + ((PyCoroObject *)coro)->cr_origin_or_finalizer = NULL; } else { PyObject *cr_origin = compute_cr_origin(origin_depth); - ((PyCoroObject *)coro)->cr_origin = cr_origin; + ((PyCoroObject *)coro)->cr_origin_or_finalizer = cr_origin; if (!cr_origin) { Py_DECREF(coro); return NULL; @@ -1382,7 +1395,7 @@ typedef struct _PyAsyncGenWrappedValue { static int async_gen_traverse(PyAsyncGenObject *gen, visitproc visit, void *arg) { - Py_VISIT(gen->ag_finalizer); + Py_VISIT(gen->ag_origin_or_finalizer); return gen_traverse((PyGenObject*)gen, visit, arg); } @@ -1413,7 +1426,7 @@ async_gen_init_hooks(PyAsyncGenObject *o) finalizer = tstate->async_gen_finalizer; if (finalizer) { Py_INCREF(finalizer); - o->ag_finalizer = finalizer; + o->ag_origin_or_finalizer = finalizer; } firstiter = tstate->async_gen_firstiter; @@ -1508,6 +1521,7 @@ static PyMethodDef async_gen_methods[] = { {"asend", (PyCFunction)async_gen_asend, METH_O, async_asend_doc}, {"athrow",(PyCFunction)async_gen_athrow, METH_VARARGS, async_athrow_doc}, {"aclose", (PyCFunction)async_gen_aclose, METH_NOARGS, async_aclose_doc}, + {"__sizeof__", (PyCFunction)gen_sizeof, METH_NOARGS, sizeof__doc__}, {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")}, {NULL, NULL} /* Sentinel */ @@ -1525,8 +1539,9 @@ static PyAsyncMethods async_gen_as_async = { PyTypeObject PyAsyncGen_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "async_generator", /* tp_name */ - sizeof(PyAsyncGenObject), /* tp_basicsize */ - 0, /* tp_itemsize */ + offsetof(PyAsyncGenObject, ag_iframe) + + offsetof(InterpreterFrame, localsplus), /* tp_basicsize */ + sizeof(PyObject *), /* tp_itemsize */ /* methods */ (destructor)gen_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ @@ -1594,7 +1609,7 @@ PyAsyncGen_New(PyFrameObject *f, PyObject *name, PyObject *qualname) if (o == NULL) { return NULL; } - o->ag_finalizer = NULL; + o->ag_origin_or_finalizer = NULL; o->ag_closed = 0; o->ag_hooks_inited = 0; o->ag_running_async = 0; @@ -2011,7 +2026,7 @@ static PyObject * async_gen_athrow_send(PyAsyncGenAThrow *o, PyObject *arg) { PyGenObject *gen = (PyGenObject*)o->agt_gen; - InterpreterFrame *frame = gen->gi_xframe; + InterpreterFrame *frame = (InterpreterFrame *)gen->gi_iframe; PyObject *retval; if (o->agt_state == AWAITABLE_STATE_CLOSED) { @@ -2021,7 +2036,7 @@ async_gen_athrow_send(PyAsyncGenAThrow *o, PyObject *arg) return NULL; } - if (frame == NULL || _PyFrameHasCompleted(frame)) { + if (gen->gi_frame_valid == 0 || _PyFrameHasCompleted(frame)) { o->agt_state = AWAITABLE_STATE_CLOSED; PyErr_SetNone(PyExc_StopIteration); return NULL; diff --git a/Python/ceval.c b/Python/ceval.c index 05897c561a16e..a8bbad33552e4 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -5854,8 +5854,8 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func, return -1; } -static InterpreterFrame * -make_coro_frame(PyThreadState *tstate, +static int +initialize_coro_frame(InterpreterFrame *frame, PyThreadState *tstate, PyFunctionObject *func, PyObject *locals, PyObject *const *args, Py_ssize_t argcount, PyObject *kwnames) @@ -5863,37 +5863,15 @@ make_coro_frame(PyThreadState *tstate, assert(is_tstate_valid(tstate)); assert(func->func_defaults == NULL || PyTuple_CheckExact(func->func_defaults)); PyCodeObject *code = (PyCodeObject *)func->func_code; - int size = code->co_nlocalsplus+code->co_stacksize + FRAME_SPECIALS_SIZE; - InterpreterFrame *frame = (InterpreterFrame *)PyMem_Malloc(sizeof(PyObject *)*size); - if (frame == NULL) { - goto fail_no_memory; - } _PyFrame_InitializeSpecials(frame, func, locals, code->co_nlocalsplus); for (int i = 0; i < code->co_nlocalsplus; i++) { frame->localsplus[i] = NULL; } assert(frame->frame_obj == NULL); - if (initialize_locals(tstate, func, frame->localsplus, args, argcount, kwnames)) { - _PyFrame_Clear(frame); - PyMem_Free(frame); - return NULL; - } - return frame; -fail_no_memory: - /* Consume the references */ - for (Py_ssize_t i = 0; i < argcount; i++) { - Py_DECREF(args[i]); - } - if (kwnames) { - Py_ssize_t kwcount = PyTuple_GET_SIZE(kwnames); - for (Py_ssize_t i = 0; i < kwcount; i++) { - Py_DECREF(args[i+argcount]); - } - } - PyErr_NoMemory(); - return NULL; + return initialize_locals(tstate, func, frame->localsplus, args, argcount, kwnames); } + /* Consumes all the references to the args */ static PyObject * make_coro(PyThreadState *tstate, PyFunctionObject *func, @@ -5902,14 +5880,17 @@ make_coro(PyThreadState *tstate, PyFunctionObject *func, PyObject *kwnames) { assert (((PyCodeObject *)func->func_code)->co_flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR)); - InterpreterFrame *frame = make_coro_frame(tstate, func, locals, args, argcount, kwnames); - if (frame == NULL) { + PyObject *gen = _Py_MakeCoro(func); + if (gen == NULL) { return NULL; } - PyObject *gen = _Py_MakeCoro(func, frame); - if (gen == NULL) { + InterpreterFrame *frame = (InterpreterFrame *)((PyGenObject *)gen)->gi_iframe; + if (initialize_coro_frame(frame, tstate, func, locals, args, argcount, kwnames)) { + Py_DECREF(gen); return NULL; } + frame->generator = gen; + ((PyGenObject *)gen)->gi_frame_valid = 1; return gen; } diff --git a/Python/frame.c b/Python/frame.c index 21f2ced959d80..da2c1c4aec075 100644 --- a/Python/frame.c +++ b/Python/frame.c @@ -43,18 +43,12 @@ _PyFrame_MakeAndSetFrameObject(InterpreterFrame *frame) return f; } -InterpreterFrame * -_PyFrame_Copy(InterpreterFrame *frame) +void +_PyFrame_Copy(InterpreterFrame *src, InterpreterFrame *dest) { - assert(frame->stacktop >= frame->f_code->co_nlocalsplus); - Py_ssize_t size = ((char*)&frame->localsplus[frame->stacktop]) - (char *)frame; - InterpreterFrame *copy = PyMem_Malloc(size); - if (copy == NULL) { - PyErr_NoMemory(); - return NULL; - } - memcpy(copy, frame, size); - return copy; + assert(src->stacktop >= src->f_code->co_nlocalsplus); + Py_ssize_t size = ((char*)&src->localsplus[src->stacktop]) - (char *)src; + memcpy(dest, src, size); } static inline void @@ -112,7 +106,7 @@ _PyFrame_Clear(InterpreterFrame * frame) } Py_DECREF(f); } - assert(_PyFrame_GetStackPointer(frame) >= _PyFrame_Stackbase(frame)); + assert(frame->stacktop >= 0); for (int i = 0; i < frame->stacktop; i++) { Py_XDECREF(frame->localsplus[i]); } From webhook-mailer at python.org Mon Dec 6 07:19:31 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 06 Dec 2021 12:19:31 -0000 Subject: [Python-checkins] bpo-44035: Check autoconf files thoroughly (GH-29935) Message-ID: https://github.com/python/cpython/commit/98fac8bc183c113903403793ffe411358ee40d8a commit: 98fac8bc183c113903403793ffe411358ee40d8a branch: main author: Christian Heimes committer: tiran date: 2021-12-06T13:18:56+01:00 summary: bpo-44035: Check autoconf files thoroughly (GH-29935) Check that users don't push changes with outdated or patched autoconf. The presence of runstatedir option and aclocal 1.16.3 are good markers. Use my container image to regenerate autoconf files. "Check for changes" will fail later when any file is regenerated. Use ccache in check_generated_files to speed up testing. files: A Misc/NEWS.d/next/Build/2021-12-06-09-31-27.bpo-44035.BiO4XC.rst M .github/workflows/build.yml M .gitignore diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fbf7bb6fe2128..99f05f3abec93 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -64,6 +64,18 @@ jobs: - uses: actions/setup-python at v2 - name: Install Dependencies run: sudo ./.github/workflows/posix-deps-apt.sh + - name: Add ccache to PATH + run: echo "PATH=/usr/lib/ccache:$PATH" >> $GITHUB_ENV + - name: Configure ccache action + uses: hendrikmuhs/ccache-action at v1 + - name: Check Autoconf version 2.69 and aclocal 1.16.3 + run: | + grep "Generated by GNU Autoconf 2.69" configure + grep "aclocal 1.16.3" aclocal.m4 + grep -q "runstatedir" configure + grep -q "PKG_PROG_PKG_CONFIG" aclocal.m4 + - name: Regenerate autoconf files + run: docker run --rm -v $(pwd):/src quay.io/tiran/cpython_autoconf:269 - name: Build CPython run: | # Build Python with the libpython dynamic library @@ -75,9 +87,10 @@ jobs: git add -u changes=$(git status --porcelain) # Check for changes in regenerated files - if ! test -z "$changes" - then - echo "Generated files not up to date. Perhaps you forgot to run make regen-all or build.bat --regen ;)" + if test -n "$changes"; then + echo "Generated files not up to date." + echo "Perhaps you forgot to run make regen-all or build.bat --regen. ;)" + echo "configure files must be regenerated with a specific, unpatched version of autoconf." echo "$changes" exit 1 fi @@ -85,10 +98,6 @@ jobs: run: make smelly - name: Check limited ABI symbols run: make check-limited-abi - - name: Check Autoconf version 2.69 - run: | - grep "Generated by GNU Autoconf 2.69" configure - grep "PKG_PROG_PKG_CONFIG" aclocal.m4 build_win32: name: 'Windows (x86)' diff --git a/.gitignore b/.gitignore index cfd3163cd1818..39de8410200ce 100644 --- a/.gitignore +++ b/.gitignore @@ -115,6 +115,8 @@ Tools/unicode/data/ /config.log /config.status /config.status.lineno +# hendrikmuhs/ccache-action at v1 +/.ccache /platform /profile-clean-stamp /profile-run-stamp diff --git a/Misc/NEWS.d/next/Build/2021-12-06-09-31-27.bpo-44035.BiO4XC.rst b/Misc/NEWS.d/next/Build/2021-12-06-09-31-27.bpo-44035.BiO4XC.rst new file mode 100644 index 0000000000000..7530587b73d14 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-12-06-09-31-27.bpo-44035.BiO4XC.rst @@ -0,0 +1,2 @@ +CI now verifies that autoconf files have been regenerated with a current and +unpatched autoconf package. From webhook-mailer at python.org Mon Dec 6 07:47:51 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 06 Dec 2021 12:47:51 -0000 Subject: [Python-checkins] [3.10] bpo-44035: Check autoconf files thoroughly (GH-29935) (GH-29937) Message-ID: https://github.com/python/cpython/commit/1528d249a5f8492801d09755f402618688337006 commit: 1528d249a5f8492801d09755f402618688337006 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: tiran date: 2021-12-06T13:47:42+01:00 summary: [3.10] bpo-44035: Check autoconf files thoroughly (GH-29935) (GH-29937) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Build/2021-12-06-09-31-27.bpo-44035.BiO4XC.rst M .github/workflows/build.yml M .gitignore diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 01b75aedafed5..c91fcc6d05fdb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -85,6 +85,18 @@ jobs: - uses: actions/setup-python at v2 - name: Install Dependencies run: sudo ./.github/workflows/posix-deps-apt.sh + - name: Add ccache to PATH + run: echo "PATH=/usr/lib/ccache:$PATH" >> $GITHUB_ENV + - name: Configure ccache action + uses: hendrikmuhs/ccache-action at v1 + - name: Check Autoconf version 2.69 and aclocal 1.16.3 + run: | + grep "Generated by GNU Autoconf 2.69" configure + grep "aclocal 1.16.3" aclocal.m4 + grep -q "runstatedir" configure + grep -q "PKG_PROG_PKG_CONFIG" aclocal.m4 + - name: Regenerate autoconf files + run: docker run --rm -v $(pwd):/src quay.io/tiran/cpython_autoconf:269 - name: Build CPython run: | # Build Python with the libpython dynamic library @@ -95,9 +107,10 @@ jobs: run: | changes=$(git status --porcelain) # Check for changes in regenerated files - if ! test -z "$changes" - then - echo "Generated files not up to date. Perhaps you forgot to run make regen-all or build.bat --regen ;)" + if test -n "$changes"; then + echo "Generated files not up to date." + echo "Perhaps you forgot to run make regen-all or build.bat --regen. ;)" + echo "configure files must be regenerated with a specific, unpatched version of autoconf." echo "$changes" exit 1 fi @@ -105,10 +118,6 @@ jobs: run: make smelly - name: Check limited ABI symbols run: make check-limited-abi - - name: Check Autoconf version 2.69 - run: | - grep "Generated by GNU Autoconf 2.69" configure - grep "PKG_PROG_PKG_CONFIG" aclocal.m4 build_win32: name: 'Windows (x86)' diff --git a/.gitignore b/.gitignore index 19b4214a9aea0..09d08c8050cb2 100644 --- a/.gitignore +++ b/.gitignore @@ -112,6 +112,8 @@ Tools/unicode/data/ /config.log /config.status /config.status.lineno +# hendrikmuhs/ccache-action at v1 +/.ccache /platform /profile-clean-stamp /profile-run-stamp diff --git a/Misc/NEWS.d/next/Build/2021-12-06-09-31-27.bpo-44035.BiO4XC.rst b/Misc/NEWS.d/next/Build/2021-12-06-09-31-27.bpo-44035.BiO4XC.rst new file mode 100644 index 0000000000000..7530587b73d14 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-12-06-09-31-27.bpo-44035.BiO4XC.rst @@ -0,0 +1,2 @@ +CI now verifies that autoconf files have been regenerated with a current and +unpatched autoconf package. From webhook-mailer at python.org Mon Dec 6 07:48:58 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 06 Dec 2021 12:48:58 -0000 Subject: [Python-checkins] [3.9] bpo-44035: Check autoconf files thoroughly (GH-29935) (GH-29938) Message-ID: https://github.com/python/cpython/commit/f147248795bf22be05bbc891053d60ef6a2f035d commit: f147248795bf22be05bbc891053d60ef6a2f035d branch: 3.9 author: Christian Heimes committer: tiran date: 2021-12-06T13:48:54+01:00 summary: [3.9] bpo-44035: Check autoconf files thoroughly (GH-29935) (GH-29938) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Build/2021-12-06-09-31-27.bpo-44035.BiO4XC.rst M .github/workflows/build.yml M .gitignore M aclocal.m4 M configure M pyconfig.h.in diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bb56a42a5e340..295b24c2cf136 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -83,6 +83,18 @@ jobs: - uses: actions/setup-python at v2 - name: Install Dependencies run: sudo ./.github/workflows/posix-deps-apt.sh + - name: Add ccache to PATH + run: echo "PATH=/usr/lib/ccache:$PATH" >> $GITHUB_ENV + - name: Configure ccache action + uses: hendrikmuhs/ccache-action at v1 + - name: Check Autoconf version 2.69 and aclocal 1.16.3 + run: | + grep "Generated by GNU Autoconf 2.69" configure + grep "aclocal 1.16.3" aclocal.m4 + grep -q "runstatedir" configure + grep -q "PKG_PROG_PKG_CONFIG" aclocal.m4 + - name: Regenerate autoconf files + run: docker run --rm -v $(pwd):/src quay.io/tiran/cpython_autoconf:269 - name: Build CPython run: | ./configure --with-pydebug @@ -91,16 +103,15 @@ jobs: run: | changes=$(git status --porcelain) # Check for changes in regenerated files - if ! test -z "$changes" - then - echo "Generated files not up to date. Perhaps you forgot to run make regen-all or build.bat --regen ;)" + if test -n "$changes"; then + echo "Generated files not up to date." + echo "Perhaps you forgot to run make regen-all or build.bat --regen. ;)" + echo "configure files must be regenerated with a specific, unpatched version of autoconf." echo "$changes" exit 1 fi - name: Check exported libpython symbols run: make smelly - - name: Check Autoconf version 2.69 - run: grep "Generated by GNU Autoconf 2.69" configure build_win32: name: 'Windows (x86)' diff --git a/.gitignore b/.gitignore index 0dd3aee5c3151..1ba44ec5d635b 100644 --- a/.gitignore +++ b/.gitignore @@ -112,6 +112,8 @@ Tools/unicode/data/ /config.log /config.status /config.status.lineno +# hendrikmuhs/ccache-action at v1 +/.ccache /platform /profile-clean-stamp /profile-run-stamp diff --git a/Misc/NEWS.d/next/Build/2021-12-06-09-31-27.bpo-44035.BiO4XC.rst b/Misc/NEWS.d/next/Build/2021-12-06-09-31-27.bpo-44035.BiO4XC.rst new file mode 100644 index 0000000000000..7530587b73d14 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-12-06-09-31-27.bpo-44035.BiO4XC.rst @@ -0,0 +1,2 @@ +CI now verifies that autoconf files have been regenerated with a current and +unpatched autoconf package. diff --git a/aclocal.m4 b/aclocal.m4 index 04342a4982e2d..e5e804276f501 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1,4 +1,4 @@ -# generated automatically by aclocal 1.16.2 -*- Autoconf -*- +# generated automatically by aclocal 1.16.3 -*- Autoconf -*- # Copyright (C) 1996-2020 Free Software Foundation, Inc. diff --git a/configure b/configure index 33ecb16f71452..1b1caf84de7d5 100755 --- a/configure +++ b/configure @@ -788,6 +788,7 @@ infodir docdir oldincludedir includedir +runstatedir localstatedir sharedstatedir sysconfdir @@ -905,6 +906,7 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -1157,6 +1159,15 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1294,7 +1305,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir + libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1447,6 +1458,7 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -9920,13 +9932,15 @@ $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +# check for libuuid from util-linux save_LIBS=$LIBS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing uuid_generate_time_safe" >&5 -$as_echo_n "checking for library containing uuid_generate_time_safe... " >&6; } -if ${ac_cv_search_uuid_generate_time_safe+:} false; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time in -luuid" >&5 +$as_echo_n "checking for uuid_generate_time in -luuid... " >&6; } +if ${ac_cv_lib_uuid_uuid_generate_time+:} false; then : $as_echo_n "(cached) " >&6 else - ac_func_search_save_LIBS=$LIBS + ac_check_lib_save_LIBS=$LIBS +LIBS="-luuid $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -9936,61 +9950,39 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext #ifdef __cplusplus extern "C" #endif -char uuid_generate_time_safe (); +char uuid_generate_time (); int main () { -return uuid_generate_time_safe (); +return uuid_generate_time (); ; return 0; } _ACEOF -for ac_lib in '' uuid; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_uuid_generate_time_safe=$ac_res -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_uuid_generate_time_safe+:} false; then : - break -fi -done -if ${ac_cv_search_uuid_generate_time_safe+:} false; then : - +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_uuid_uuid_generate_time=yes else - ac_cv_search_uuid_generate_time_safe=no + ac_cv_lib_uuid_uuid_generate_time=no fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_uuid_generate_time_safe" >&5 -$as_echo "$ac_cv_search_uuid_generate_time_safe" >&6; } -ac_res=$ac_cv_search_uuid_generate_time_safe -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - - -$as_echo "#define HAVE_LIBUUID 1" >>confdefs.h -, - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_uuid_uuid_generate_time" >&5 +$as_echo "$ac_cv_lib_uuid_uuid_generate_time" >&6; } +if test "x$ac_cv_lib_uuid_uuid_generate_time" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBUUID 1 +_ACEOF -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + LIBS="-luuid $LIBS" fi LIBS=$save_LIBS # AIX provides support for RFC4122 (uuid) in libc.a starting with AIX 6.1 (anno 2007) -# FreeBSD and OpenBSD provides support as well +# FreeBSD and OpenBSD provides support in libc as well. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_create" >&5 $as_echo_n "checking for uuid_create... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext diff --git a/pyconfig.h.in b/pyconfig.h.in index 63b013823cbf1..188faeeb12020 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -613,7 +613,7 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LIBUTIL_H -/* Define you have libuuid. */ +/* Define to 1 if you have the `uuid' library (-luuid). */ #undef HAVE_LIBUUID /* Define if you have the 'link' function. */ From webhook-mailer at python.org Mon Dec 6 11:14:04 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 06 Dec 2021 16:14:04 -0000 Subject: [Python-checkins] bpo-45950: Fix macOS framework builds of _bootstrap_python (GH-29936) Message-ID: https://github.com/python/cpython/commit/612e59b53f0c730ce1b881f7c08dc6d49f02c123 commit: 612e59b53f0c730ce1b881f7c08dc6d49f02c123 branch: main author: Christian Heimes committer: tiran date: 2021-12-06T17:13:53+01:00 summary: bpo-45950: Fix macOS framework builds of _bootstrap_python (GH-29936) files: M Makefile.pre.in M Modules/getpath.c M configure M configure.ac diff --git a/Makefile.pre.in b/Makefile.pre.in index 8e6e553554de1..94fc5c37209ef 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -954,9 +954,9 @@ BOOTSTRAP_HEADERS = \ Programs/_bootstrap_python.o: Programs/_bootstrap_python.c $(BOOTSTRAP_HEADERS) $(PYTHON_HEADERS) -_bootstrap_python: $(LIBRARY_OBJS_OMIT_FROZEN) Programs/_bootstrap_python.o Modules/getpath.o Modules/Setup.local +_bootstrap_python: $(LIBRARY_OBJS_OMIT_FROZEN) Programs/_bootstrap_python.o Modules/getpath_bootstrap.o Modules/Setup.local $(LINKCC) $(PY_LDFLAGS_NOLTO) -o $@ $(LIBRARY_OBJS_OMIT_FROZEN) \ - Programs/_bootstrap_python.o Modules/getpath.o $(LIBS) $(MODLIBS) $(SYSLIBS) + Programs/_bootstrap_python.o Modules/getpath_bootstrap.o $(LIBS) $(MODLIBS) $(SYSLIBS) ############################################################################ # Deepfreeze targets @@ -1205,6 +1205,18 @@ Modules/getpath.o: $(srcdir)/Modules/getpath.c Python/frozen_modules/getpath.h M -DPLATLIBDIR='"$(PLATLIBDIR)"' \ -o $@ $(srcdir)/Modules/getpath.c +# like getpath.o with additional -DPY_BOOTSTRAP_PYTHON=1 +Modules/getpath_bootstrap.o: $(srcdir)/Modules/getpath.c Python/frozen_modules/getpath.h Makefile $(PYTHON_HEADERS) + $(CC) -c $(PY_CORE_CFLAGS) -DPYTHONPATH='"$(PYTHONPATH)"' \ + -DPREFIX='"$(prefix)"' \ + -DEXEC_PREFIX='"$(exec_prefix)"' \ + -DVERSION='"$(VERSION)"' \ + -DVPATH='"$(VPATH)"' \ + -DPLATLIBDIR='"$(PLATLIBDIR)"' \ + -DPY_BOOTSTRAP_PYTHON=1 \ + -o $@ $(srcdir)/Modules/getpath.c + + Programs/python.o: $(srcdir)/Programs/python.c $(MAINCC) -c $(PY_CORE_CFLAGS) -o $@ $(srcdir)/Programs/python.c diff --git a/Modules/getpath.c b/Modules/getpath.c index f77b18eee95b6..8f90a7008625f 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -754,7 +754,8 @@ library_to_dict(PyObject *dict, const char *key) if (PyWin_DLLhModule) { return winmodule_to_dict(dict, key, PyWin_DLLhModule); } -#elif defined(WITH_NEXT_FRAMEWORK) +#elif defined(WITH_NEXT_FRAMEWORK) && !defined(PY_BOOTSTRAP_PYTHON) + // _bootstrap_python does not use framework and crashes static const char modPath[MAXPATHLEN + 1]; static int modPathInitialized = -1; if (modPathInitialized < 0) { diff --git a/configure b/configure index 8582224dfd28f..fca9567c7102f 100755 --- a/configure +++ b/configure @@ -1736,7 +1736,7 @@ Optional Packages: path to _freeze_module binary for cross compiling --with-build-python=python3.11 path to build python binary for cross compiling - (default: python3.11) + (default: _bootstrap_python or python3.11) --with-pkg-config=[yes|no|check] use pkg-config to detect build options (default is check) @@ -3243,14 +3243,11 @@ if test "${with_build_python+set}" = set; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-build-python" >&5 $as_echo_n "checking for --with-build-python... " >&6; } - if test "x$cross_compiling" = xno; then : - as_fn_error $? "--with-build-python only applies to cross compiling" "$LINENO" 5 -fi if test "x$with_build_python" = xyes; then : with_build_python=python$PACKAGE_VERSION fi if test "x$with_build_python" = xno; then : - as_fn_error $? "invalid --with-build-python option: expected path, not \"no\"" "$LINENO" 5 + as_fn_error $? "invalid --with-build-python option: expected path or \"yes\", not \"no\"" "$LINENO" 5 fi if ! $(command -v "$with_build_python" >/dev/null 2>&1); then diff --git a/configure.ac b/configure.ac index 39890fe38f0a1..c7c71255a3a4c 100644 --- a/configure.ac +++ b/configure.ac @@ -125,16 +125,16 @@ AC_ARG_WITH( ) AC_SUBST([FREEZE_MODULE]) +dnl build-python is used for cross compiling and macOS framework builds. AC_ARG_WITH( [build-python], [AS_HELP_STRING([--with-build-python=python]PYTHON_VERSION, - [path to build python binary for cross compiling (default: python]PYTHON_VERSION[)])], + [path to build python binary for cross compiling (default: _bootstrap_python or python]PYTHON_VERSION[)])], [ AC_MSG_CHECKING([for --with-build-python]) - AS_VAR_IF([cross_compiling], [no], AC_MSG_ERROR([--with-build-python only applies to cross compiling])) AS_VAR_IF([with_build_python], [yes], [with_build_python=python$PACKAGE_VERSION]) - AS_VAR_IF([with_build_python], [no], [AC_MSG_ERROR([invalid --with-build-python option: expected path, not "no"])]) + AS_VAR_IF([with_build_python], [no], [AC_MSG_ERROR([invalid --with-build-python option: expected path or "yes", not "no"])]) if ! $(command -v "$with_build_python" >/dev/null 2>&1); then AC_MSG_ERROR([invalid or missing build python binary "$with_build_python"]) From webhook-mailer at python.org Mon Dec 6 12:25:34 2021 From: webhook-mailer at python.org (zooba) Date: Mon, 06 Dec 2021 17:25:34 -0000 Subject: [Python-checkins] bpo-45582: Fix getpath_isxfile() and test_embed on Windows (GH-29930) Message-ID: https://github.com/python/cpython/commit/af1db4eb555e02d2bff3476f99f7a653764203b0 commit: af1db4eb555e02d2bff3476f99f7a653764203b0 branch: main author: neonene <53406459+neonene at users.noreply.github.com> committer: zooba date: 2021-12-06T17:25:19Z summary: bpo-45582: Fix getpath_isxfile() and test_embed on Windows (GH-29930) files: M Lib/test/test_embed.py M Modules/getpath.c diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index 3620a7619601d..94161b651ff86 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -575,7 +575,7 @@ def _get_expected_config(self): return configs def get_expected_config(self, expected_preconfig, expected, - env, api, modify_path_cb=None): + env, api, modify_path_cb=None, cwd=None): configs = self._get_expected_config() pre_config = configs['pre_config'] @@ -618,6 +618,14 @@ def get_expected_config(self, expected_preconfig, expected, expected['base_executable'] = default_executable if expected['program_name'] is self.GET_DEFAULT_CONFIG: expected['program_name'] = './_testembed' + if MS_WINDOWS: + # follow the calculation in getpath.py + tmpname = expected['program_name'] + '.exe' + if cwd: + tmpname = os.path.join(cwd, tmpname) + if os.path.isfile(tmpname): + expected['program_name'] += '.exe' + del tmpname config = configs['config'] for key, value in expected.items(): @@ -711,7 +719,7 @@ def check_all_configs(self, testname, expected_config=None, self.get_expected_config(expected_preconfig, expected_config, env, - api, modify_path_cb) + api, modify_path_cb, cwd) out, err = self.run_embedded_interpreter(testname, env=env, cwd=cwd) diff --git a/Modules/getpath.c b/Modules/getpath.c index 8f90a7008625f..2e46226a08531 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -230,7 +230,7 @@ getpath_isxfile(PyObject *Py_UNUSED(self), PyObject *args) DWORD attr = GetFileAttributesW(path); r = (attr != INVALID_FILE_ATTRIBUTES) && !(attr & FILE_ATTRIBUTE_DIRECTORY) && - SUCCEEDED(PathCchFindExtension(path, cchPath, &ext)) && + SUCCEEDED(PathCchFindExtension(path, cchPath + 1, &ext)) && (CompareStringOrdinal(ext, -1, L".exe", -1, 1 /* ignore case */) == CSTR_EQUAL) ? Py_True : Py_False; #else From webhook-mailer at python.org Mon Dec 6 13:13:22 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 06 Dec 2021 18:13:22 -0000 Subject: [Python-checkins] bpo-45582: framework build: modPath must not be const (GH-29944) Message-ID: https://github.com/python/cpython/commit/f16f93e5279f957ca25dd8b91233a44833167a8a commit: f16f93e5279f957ca25dd8b91233a44833167a8a branch: main author: Christian Heimes committer: tiran date: 2021-12-06T19:13:12+01:00 summary: bpo-45582: framework build: modPath must not be const (GH-29944) Co-authored-by: Ronald Oussoren files: M Modules/getpath.c diff --git a/Modules/getpath.c b/Modules/getpath.c index 2e46226a08531..9ce7260f77826 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -756,7 +756,7 @@ library_to_dict(PyObject *dict, const char *key) } #elif defined(WITH_NEXT_FRAMEWORK) && !defined(PY_BOOTSTRAP_PYTHON) // _bootstrap_python does not use framework and crashes - static const char modPath[MAXPATHLEN + 1]; + static char modPath[MAXPATHLEN + 1]; static int modPathInitialized = -1; if (modPathInitialized < 0) { NSModule pythonModule; From webhook-mailer at python.org Mon Dec 6 15:43:54 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 06 Dec 2021 20:43:54 -0000 Subject: [Python-checkins] bpo-45847: Fix uuid detection on macOS (GH-29946) Message-ID: https://github.com/python/cpython/commit/fc012d801202a9ea139df143b934778060d51a60 commit: fc012d801202a9ea139df143b934778060d51a60 branch: main author: Christian Heimes committer: tiran date: 2021-12-06T21:43:44+01:00 summary: bpo-45847: Fix uuid detection on macOS (GH-29946) files: M configure M configure.ac diff --git a/configure b/configure index fca9567c7102f..2237e6ed8ce2a 100755 --- a/configure +++ b/configure @@ -10623,7 +10623,6 @@ fi LIBUUID_LIBS="-luuid" LIBUUID_CFLAGS= - have_uuid=no for ac_header in uuid/uuid.h do : ac_fn_c_check_header_mongrel "$LINENO" "uuid/uuid.h" "ac_cv_header_uuid_uuid_h" "$ac_includes_default" @@ -10754,7 +10753,6 @@ $as_echo "no" >&6; } LIBUUID_LIBS="-luuid" LIBUUID_CFLAGS= - have_uuid=no for ac_header in uuid/uuid.h do : ac_fn_c_check_header_mongrel "$LINENO" "uuid/uuid.h" "ac_cv_header_uuid_uuid_h" "$ac_includes_default" @@ -10895,6 +10893,37 @@ fi fi +if test "x$have_uuid" = xmissing; then : + + for ac_header in uuid/uuid.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "uuid/uuid.h" "ac_cv_header_uuid_uuid_h" "$ac_includes_default" +if test "x$ac_cv_header_uuid_uuid_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_UUID_UUID_H 1 +_ACEOF + + ac_fn_c_check_func "$LINENO" "uuid_generate_time" "ac_cv_func_uuid_generate_time" +if test "x$ac_cv_func_uuid_generate_time" = xyes; then : + + have_uuid=yes + LIBUUID_CFLAGS= + LIBUUID_LIBS= + +fi + + +fi + +done + + +fi + +if test "x$have_uuid" = xmissing; then : + have_uuid=no +fi + # 'Real Time' functions on Solaris # posix4 on Solaris 2.6 # pthread (first!) on Linux diff --git a/configure.ac b/configure.ac index c7c71255a3a4c..f1aac2db71f5d 100644 --- a/configure.ac +++ b/configure.ac @@ -2963,7 +2963,6 @@ AS_VAR_IF([have_uuid], [missing], [ ], [ LIBUUID_LIBS="-luuid" LIBUUID_CFLAGS= - have_uuid=no AC_CHECK_HEADERS([uuid/uuid.h], [ WITH_SAVE_ENV( [AC_CHECK_LIB([uuid], [uuid_generate_time], [have_uuid=yes]) @@ -2979,6 +2978,19 @@ AS_VAR_IF([have_uuid], [missing], [ ) ]) +dnl macOS has uuid/uuid.h but uuid_generate_time is in libc +AS_VAR_IF([have_uuid], [missing], [ + AC_CHECK_HEADERS([uuid/uuid.h], [ + AC_CHECK_FUNC([uuid_generate_time], [ + have_uuid=yes + LIBUUID_CFLAGS= + LIBUUID_LIBS= + ]) + ]) +]) + +AS_VAR_IF([have_uuid], [missing], [have_uuid=no]) + # 'Real Time' functions on Solaris # posix4 on Solaris 2.6 # pthread (first!) on Linux From webhook-mailer at python.org Mon Dec 6 15:46:49 2021 From: webhook-mailer at python.org (pablogsal) Date: Mon, 06 Dec 2021 20:46:49 -0000 Subject: [Python-checkins] Python 3.10.1 Message-ID: https://github.com/python/cpython/commit/2cd268a3a9340346dd86b66db2e9b428b3f878fc commit: 2cd268a3a9340346dd86b66db2e9b428b3f878fc branch: 3.10 author: Pablo Galindo committer: pablogsal date: 2021-12-06T18:23:39Z summary: Python 3.10.1 files: A Misc/NEWS.d/3.10.1.rst D Misc/NEWS.d/next/Build/2021-09-09-16-45-26.bpo-45067.mFmY92.rst D Misc/NEWS.d/next/Build/2021-09-16-18-00-43.bpo-45220.TgbkvW.rst D Misc/NEWS.d/next/Build/2021-10-11-16-27-38.bpo-45405.iSfdW5.rst D Misc/NEWS.d/next/Build/2021-10-18-10-25-56.bpo-45221.rnulhf.rst D Misc/NEWS.d/next/Build/2021-10-20-12-42-39.bpo-45536.oQNYHB.rst D Misc/NEWS.d/next/Build/2021-10-20-16-07-39.bpo-45532.kyhvis.rst D Misc/NEWS.d/next/Build/2021-10-21-14-38-30.bpo-45561.PVqhZE.rst D Misc/NEWS.d/next/Build/2021-10-22-15-28-29.bpo-45571.yY8NsJ.rst D Misc/NEWS.d/next/Build/2021-11-01-12-51-46.bpo-43158.fghS6w.rst D Misc/NEWS.d/next/Build/2021-11-24-17-14-06.bpo-45881.GTXXLk.rst D Misc/NEWS.d/next/Build/2021-11-25-09-15-04.bpo-41498.qAk5eo.rst D Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst D Misc/NEWS.d/next/Build/2021-11-25-20-26-06.bpo-33393.24YNtM.rst D Misc/NEWS.d/next/Build/2021-12-06-09-31-27.bpo-44035.BiO4XC.rst D Misc/NEWS.d/next/C API/2021-07-27-17-29-12.bpo-44751.4qmbDG.rst D Misc/NEWS.d/next/C API/2021-09-19-17-18-25.bpo-44687.3fqDRC.rst D Misc/NEWS.d/next/C API/2021-09-28-12-00-55.bpo-45307.3ETFfX.rst D Misc/NEWS.d/next/C API/2021-11-09-15-42-11.bpo-39026.sUnYWn.rst D Misc/NEWS.d/next/Core and Builtins/2021-09-01-16-55-43.bpo-45056.7AK2d9.rst D Misc/NEWS.d/next/Core and Builtins/2021-09-01-23-55-49.bpo-45083.cLi9G3.rst D Misc/NEWS.d/next/Core and Builtins/2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst D Misc/NEWS.d/next/Core and Builtins/2021-09-08-00-30-09.bpo-44050.mFI15u.rst D Misc/NEWS.d/next/Core and Builtins/2021-09-08-08-29-41.bpo-44959.OSwwPf.rst D Misc/NEWS.d/next/Core and Builtins/2021-09-09-10-32-33.bpo-44219.WiYyjz.rst D Misc/NEWS.d/next/Core and Builtins/2021-09-14-09-23-59.bpo-45167.CPSSoV.rst D Misc/NEWS.d/next/Core and Builtins/2021-10-06-21-20-11.bpo-45385.CTUT8s.rst D Misc/NEWS.d/next/Core and Builtins/2021-10-07-21-26-44.bpo-45408.qUqzcd.rst D Misc/NEWS.d/next/Core and Builtins/2021-10-16-17-27-48.bpo-45494.vMt1g4.rst D Misc/NEWS.d/next/Core and Builtins/2021-10-18-22-40-33.bpo-45521.GdMiuW.rst D Misc/NEWS.d/next/Core and Builtins/2021-10-19-01-04-08.bpo-30570._G30Ms.rst D Misc/NEWS.d/next/Core and Builtins/2021-11-02-09-27-46.bpo-45688.v5Der1.rst D Misc/NEWS.d/next/Core and Builtins/2021-11-04-20-19-07.bpo-45716.5C0pA1.rst D Misc/NEWS.d/next/Core and Builtins/2021-11-09-13-01-35.bpo-45773.POU8A4.rst D Misc/NEWS.d/next/Core and Builtins/2021-11-14-00-14-45.bpo-45738.e0cgKd.rst D Misc/NEWS.d/next/Core and Builtins/2021-11-15-12-08-27.bpo-42540.V2w107.rst D Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-00-27.bpo-45820.2X6Psr.rst D Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-41-04.bpo-45822.OT6ueS.rst D Misc/NEWS.d/next/Core and Builtins/2021-11-17-08-05-27.bpo-45826.OERoTm.rst D Misc/NEWS.d/next/Core and Builtins/2021-11-19-22-57-42.bpo-45848.HgVBJ5.rst D Misc/NEWS.d/next/Core and Builtins/2021-11-23-12-06-41.bpo-45614.fIekgI.rst D Misc/NEWS.d/next/Core and Builtins/2021-11-24-18-24-49.bpo-45727._xVbbo.rst D Misc/NEWS.d/next/Core and Builtins/2021-11-26-22-31-22.bpo-42268.3wl-09.rst D Misc/NEWS.d/next/Documentation/2021-05-24-05-00-12.bpo-43905.tBIndE.rst D Misc/NEWS.d/next/Documentation/2021-06-21-17-51-51.bpo-25381.7Kn-_H.rst D Misc/NEWS.d/next/Documentation/2021-09-08-17-20-19.bpo-45024.dkNPNi.rst D Misc/NEWS.d/next/Documentation/2021-09-18-13-45-19.bpo-45216.o56nyt.rst D Misc/NEWS.d/next/Documentation/2021-10-13-00-42-54.bpo-20692.K5rGtP.rst D Misc/NEWS.d/next/Documentation/2021-10-18-20-12-18.bpo-45516.EJh4K8.rst D Misc/NEWS.d/next/Documentation/2021-10-19-01-41-40.bpo-45449.fjHZJc.rst D Misc/NEWS.d/next/Documentation/2021-10-20-16-26-53.bpo-45464.mOISBs.rst D Misc/NEWS.d/next/Documentation/2021-10-22-12-09-18.bpo-45250.Iit5-Y.rst D Misc/NEWS.d/next/Documentation/2021-10-26-10-00-45.bpo-45604.Dm-YhV.rst D Misc/NEWS.d/next/Documentation/2021-10-28-19-22-55.bpo-45655.aPYGaS.rst D Misc/NEWS.d/next/Documentation/2021-11-03-14-51-03.bpo-45680.9_NTFU.rst D Misc/NEWS.d/next/Documentation/2021-11-05-12-15-24.bpo-45726.GwRr7e.rst D Misc/NEWS.d/next/Documentation/2021-11-06-10-54-17.bpo-45392.JZnVOz.rst D Misc/NEWS.d/next/Documentation/2021-11-09-13-10-55.bpo-45772.EdrM3t.rst D Misc/NEWS.d/next/Documentation/2021-11-18-00-07-40.bpo-45788.qibUoB.rst D Misc/NEWS.d/next/Documentation/2021-11-18-16-44-12.bpo-45640.lSpc2A.rst D Misc/NEWS.d/next/IDLE/2021-09-15-03-20-06.bpo-45193.G61_GV.rst D Misc/NEWS.d/next/IDLE/2021-09-27-01-21-59.bpo-45296.9H8rdY.rst D Misc/NEWS.d/next/IDLE/2021-10-16-17-20-32.bpo-45495.ST8RFt.rst D Misc/NEWS.d/next/Library/2021-04-20-14-14-16.bpo-43498.L_Hq-8.rst D Misc/NEWS.d/next/Library/2021-06-02-16-39-42.bpo-44295.erg01m.rst D Misc/NEWS.d/next/Library/2021-07-12-10-32-48.bpo-44594.eEa5zi.rst D Misc/NEWS.d/next/Library/2021-08-18-10-36-14.bpo-39039.A63LYh.rst D Misc/NEWS.d/next/Library/2021-08-28-13-00-12.bpo-45021.rReeaj.rst D Misc/NEWS.d/next/Library/2021-08-30-00-19-23.bpo-24444.Ki4bgz.rst D Misc/NEWS.d/next/Library/2021-09-08-01-19-31.bpo-20499.tSxx8Y.rst D Misc/NEWS.d/next/Library/2021-09-10-21-35-53.bpo-45166.UHipXF.rst D Misc/NEWS.d/next/Library/2021-09-11-10-45-12.bpo-35474.tEY3SD.rst D Misc/NEWS.d/next/Library/2021-09-11-14-47-05.bpo-45160.VzMXbW.rst D Misc/NEWS.d/next/Library/2021-09-13-19-32-58.bpo-42135.1ZAHqR.rst D Misc/NEWS.d/next/Library/2021-09-14-15-52-47.bpo-45192.DjA-BI.rst D Misc/NEWS.d/next/Library/2021-09-17-09-59-33.bpo-45228.WV1dcT.rst D Misc/NEWS.d/next/Library/2021-09-17-11-20-55.bpo-45234.qUcTVt.rst D Misc/NEWS.d/next/Library/2021-09-17-15-58-53.bpo-45183.Vv_vch.rst D Misc/NEWS.d/next/Library/2021-09-17-16-55-37.bpo-45235.sXnmPA.rst D Misc/NEWS.d/next/Library/2021-09-18-13-14-57.bpo-36674.a2k5Zb.rst D Misc/NEWS.d/next/Library/2021-09-18-16-56-33.bpo-45238.Hng_9V.rst D Misc/NEWS.d/next/Library/2021-09-23-22-17-26.bpo-45274.gPpa4E.rst D Misc/NEWS.d/next/Library/2021-09-24-17-20-23.bpo-1596321.3nhPUk.rst D Misc/NEWS.d/next/Library/2021-09-30-08-22-44.bpo-45328.8Z-Q0B.rst D Misc/NEWS.d/next/Library/2021-09-30-23-00-18.bpo-41710.svuloZ.rst D Misc/NEWS.d/next/Library/2021-10-01-13-09-53.bpo-45329.9iMYaO.rst D Misc/NEWS.d/next/Library/2021-10-01-23-07-02.bpo-45343.ixmctD.rst D Misc/NEWS.d/next/Library/2021-10-03-21-14-37.bpo-20028.zBA4RK.rst D Misc/NEWS.d/next/Library/2021-10-05-11-03-48.bpo-45371.NOwcDJ.rst D Misc/NEWS.d/next/Library/2021-10-07-00-05-05.bpo-45386.q9ORpA.rst D Misc/NEWS.d/next/Library/2021-10-07-14-04-10.bpo-45262.HqF71Z.rst D Misc/NEWS.d/next/Library/2021-10-08-19-24-48.bpo-45406.Qh_Mz4.rst D Misc/NEWS.d/next/Library/2021-10-09-18-42-27.bpo-44904.RlW5h8.rst D Misc/NEWS.d/next/Library/2021-10-09-20-53-13.bpo-45419.CauCgt.rst D Misc/NEWS.d/next/Library/2021-10-10-09-42-34.bpo-45416.n35O0_.rst D Misc/NEWS.d/next/Library/2021-10-10-16-14-33.bpo-45249.xqLliz.rst D Misc/NEWS.d/next/Library/2021-10-13-17-52-48.bpo-45239.7li1_0.rst D Misc/NEWS.d/next/Library/2021-10-14-00-19-02.bpo-45461.4LB_tJ.rst D Misc/NEWS.d/next/Library/2021-10-14-13-31-19.bpo-45467.Q7Ma6A.rst D Misc/NEWS.d/next/Library/2021-10-14-18-04-17.bpo-45428.mM2War.rst D Misc/NEWS.d/next/Library/2021-10-18-10-46-47.bpo-45475.sb9KDF.rst D Misc/NEWS.d/next/Library/2021-10-18-14-52-48.bpo-45515.aXdvm_.rst D Misc/NEWS.d/next/Library/2021-10-21-16-18-51.bpo-45557.4MQt4r.rst D Misc/NEWS.d/next/Library/2021-10-22-21-57-02.bpo-45581.rlH6ay.rst D Misc/NEWS.d/next/Library/2021-10-22-23-06-33.bpo-45574.svqA84.rst D Misc/NEWS.d/next/Library/2021-10-27-10-05-39.bpo-45438.Xz5lGU.rst D Misc/NEWS.d/next/Library/2021-10-28-22-58-14.bpo-45662.sJd7Ir.rst D Misc/NEWS.d/next/Library/2021-10-28-23-11-59.bpo-45663.J90N5R.rst D Misc/NEWS.d/next/Library/2021-10-28-23-40-54.bpo-45664.7dqtxQ.rst D Misc/NEWS.d/next/Library/2021-10-30-21-11-37.bpo-45679.Dq8Cpu.rst D Misc/NEWS.d/next/Library/2021-11-06-17-47-46.bpo-45644.ZMqHD_.rst D Misc/NEWS.d/next/Library/2021-11-08-23-22-14.bpo-45757.MHZHt3.rst D Misc/NEWS.d/next/Library/2021-11-09-09-04-19.bpo-45765.JVobxK.rst D Misc/NEWS.d/next/Library/2021-11-11-13-03-17.bpo-45235.8ZbkHa.rst D Misc/NEWS.d/next/Library/2021-11-16-18-13-49.bpo-41735.D72UY1.rst D Misc/NEWS.d/next/Library/2021-11-17-19-25-37.bpo-45831.9-TojK.rst D Misc/NEWS.d/next/Library/2021-11-20-17-04-25.bpo-45803.wSgFOy.rst D Misc/NEWS.d/next/Library/2021-11-21-20-50-42.bpo-44649.E8M936.rst D Misc/NEWS.d/next/Library/2021-11-28-15-30-34.bpo-37658.8Hno7d.rst D Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst D Misc/NEWS.d/next/Tests/2021-08-27-22-37-19.bpo-25130.ig4oJe.rst D Misc/NEWS.d/next/Tests/2021-09-08-13-01-37.bpo-44860.qXd0kx.rst D Misc/NEWS.d/next/Tests/2021-09-11-22-08-18.bpo-45125.FVSzs2.rst D Misc/NEWS.d/next/Tests/2021-09-13-00-28-17.bpo-45156.8oomV3.rst D Misc/NEWS.d/next/Tests/2021-09-14-13-16-18.bpo-45195.EyQR1G.rst D Misc/NEWS.d/next/Tests/2021-09-15-23-32-39.bpo-45209.55ntL5.rst D Misc/NEWS.d/next/Tests/2021-09-16-17-22-35.bpo-45128.Jz6fl2.rst D Misc/NEWS.d/next/Tests/2021-09-24-10-41-49.bpo-45269.8jKEr8.rst D Misc/NEWS.d/next/Tests/2021-09-25-11-05-31.bpo-45280.3MA6lC.rst D Misc/NEWS.d/next/Tests/2021-09-30-16-54-39.bpo-40173.J_slCw.rst D Misc/NEWS.d/next/Tests/2021-10-07-13-11-45.bpo-45400.h3iT7V.rst D Misc/NEWS.d/next/Tests/2021-10-18-16-18-41.bpo-39679.F18qcE.rst D Misc/NEWS.d/next/Tests/2021-10-21-17-22-26.bpo-43592.kHRsra.rst D Misc/NEWS.d/next/Tests/2021-10-22-12-05-21.bpo-45566.2gQ3ZB.rst D Misc/NEWS.d/next/Tests/2021-10-22-19-44-13.bpo-45577.dSaNvK.rst D Misc/NEWS.d/next/Tests/2021-10-30-13-12-20.bpo-45678.bKrYeS.rst D Misc/NEWS.d/next/Tests/2021-10-30-19-00-25.bpo-45578.bvu6X2.rst D Misc/NEWS.d/next/Tests/2021-11-04-20-03-32.bpo-45678.1xNMjN.rst D Misc/NEWS.d/next/Tests/2021-11-17-14-28-08.bpo-45835.Mgyhjx.rst D Misc/NEWS.d/next/Tests/2021-11-28-15-25-02.bpo-19460.lr0aWs.rst D Misc/NEWS.d/next/Tools-Demos/2021-09-14-11-44-26.bpo-44786.DU0LC0.rst D Misc/NEWS.d/next/Windows/2021-09-30-23-17-27.bpo-45337.qg7U_h.rst D Misc/NEWS.d/next/Windows/2021-11-04-00-41-50.bpo-43652.RnqV7I.rst D Misc/NEWS.d/next/Windows/2021-11-05-01-05-46.bpo-45720.47Nc5I.rst D Misc/NEWS.d/next/Windows/2021-11-08-21-53-11.bpo-45732.idl5kx.rst D Misc/NEWS.d/next/Windows/2021-11-23-11-44-42.bpo-45616.K52PLZ.rst D Misc/NEWS.d/next/Windows/2021-11-26-18-17-41.bpo-45901.c5IBqM.rst D Misc/NEWS.d/next/macOS/2021-08-27-16-55-10.bpo-34602.ZjHsYJ.rst D Misc/NEWS.d/next/macOS/2021-10-25-02-02-21.bpo-44828.XBdXlJ.rst D Misc/NEWS.d/next/macOS/2021-12-05-23-52-03.bpo-45732.-BWrnh.rst M Include/patchlevel.h M Lib/pydoc_data/topics.py M README.rst diff --git a/Include/patchlevel.h b/Include/patchlevel.h index 56869c5fa74ab..9e8a56099cc5a 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -18,12 +18,12 @@ /*--start constants--*/ #define PY_MAJOR_VERSION 3 #define PY_MINOR_VERSION 10 -#define PY_MICRO_VERSION 0 +#define PY_MICRO_VERSION 1 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL #define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "3.10.0+" +#define PY_VERSION "3.10.1" /*--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 7720694bd592e..00c98ad51072c 100644 --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Mon Oct 4 18:28:12 2021 +# Autogenerated by Sphinx on Mon Dec 6 17:57:38 2021 topics = {'assert': 'The "assert" statement\n' '**********************\n' '\n' @@ -3339,9 +3339,9 @@ '\n' 'The same keyword should not be repeated in class patterns.\n' '\n' - 'The following is the logical flow for matching a mapping ' - 'pattern\n' - 'against a subject value:\n' + 'The following is the logical flow for matching a class pattern ' + 'against\n' + 'a subject value:\n' '\n' '1. If "name_or_attr" is not an instance of the builtin "type" , ' 'raise\n' @@ -5488,20 +5488,32 @@ 'binding\n' 'operations.\n' '\n' - 'The following constructs bind names: formal parameters to ' - 'functions,\n' - '"import" statements, class and function definitions (these bind ' - 'the\n' - 'class or function name in the defining block), and targets that ' - 'are\n' - 'identifiers if occurring in an assignment, "for" loop header, ' - 'or after\n' - '"as" in a "with" statement or "except" clause. The "import" ' - 'statement\n' - 'of the form "from ... import *" binds all names defined in the\n' - 'imported module, except those beginning with an underscore. ' - 'This form\n' - 'may only be used at the module level.\n' + 'The following constructs bind names:\n' + '\n' + '* formal parameters to functions,\n' + '\n' + '* class definitions,\n' + '\n' + '* function definitions,\n' + '\n' + '* assignment expressions,\n' + '\n' + '* targets that are identifiers if occurring in an assignment:\n' + '\n' + ' * "for" loop header,\n' + '\n' + ' * after "as" in a "with" statement, "except" clause or in the ' + 'as-\n' + ' pattern in structural pattern matching,\n' + '\n' + ' * in a capture pattern in structural pattern matching\n' + '\n' + '* "import" statements.\n' + '\n' + 'The "import" statement of the form "from ... import *" binds ' + 'all names\n' + 'defined in the imported module, except those beginning with an\n' + 'underscore. This form may only be used at the module level.\n' '\n' 'A target occurring in a "del" statement is also considered ' 'bound for\n' @@ -5574,9 +5586,9 @@ 'operations.\n' '\n' 'If the "global" statement occurs within a block, all uses of ' - 'the name\n' - 'specified in the statement refer to the binding of that name in ' - 'the\n' + 'the names\n' + 'specified in the statement refer to the bindings of those names ' + 'in the\n' 'top-level namespace. Names are resolved in the top-level ' 'namespace by\n' 'searching the global namespace, i.e. the namespace of the ' @@ -5585,9 +5597,10 @@ 'namespace\n' 'of the module "builtins". The global namespace is searched ' 'first. If\n' - 'the name is not found there, the builtins namespace is ' - 'searched. The\n' - '"global" statement must precede all uses of the name.\n' + 'the names are not found there, the builtins namespace is ' + 'searched.\n' + 'The "global" statement must precede all uses of the listed ' + 'names.\n' '\n' 'The "global" statement has the same scope as a name binding ' 'operation\n' @@ -6943,22 +6956,31 @@ 'trailing underscore characters:\n' '\n' '"_*"\n' - ' Not imported by "from module import *". The special ' - 'identifier "_"\n' - ' is used in the interactive interpreter to store the result ' - 'of the\n' - ' last evaluation; it is stored in the "builtins" module. ' - 'When not\n' - ' in interactive mode, "_" has no special meaning and is not ' - 'defined.\n' - ' See section The import statement.\n' + ' Not imported by "from module import *".\n' + '\n' + '"_"\n' + ' In a "case" pattern within a "match" statement, "_" is a ' + 'soft\n' + ' keyword that denotes a wildcard.\n' + '\n' + ' Separately, the interactive interpreter makes the result of ' + 'the\n' + ' last evaluation available in the variable "_". (It is ' + 'stored in the\n' + ' "builtins" module, alongside built-in functions like ' + '"print".)\n' + '\n' + ' Elsewhere, "_" is a regular identifier. It is often used to ' + 'name\n' + ' ?special? items, but it is not special to Python itself.\n' '\n' ' Note:\n' '\n' ' The name "_" is often used in conjunction with\n' ' internationalization; refer to the documentation for the\n' ' "gettext" module for more information on this ' - 'convention.\n' + 'convention.It is\n' + ' also commonly used for unused variables.\n' '\n' '"__*__"\n' ' System-defined names, informally known as ?dunder? names. ' @@ -7113,15 +7135,23 @@ 'trailing underscore characters:\n' '\n' '"_*"\n' - ' Not imported by "from module import *". The special ' - 'identifier "_"\n' - ' is used in the interactive interpreter to store the result ' + ' Not imported by "from module import *".\n' + '\n' + '"_"\n' + ' In a "case" pattern within a "match" statement, "_" is a ' + 'soft\n' + ' keyword that denotes a wildcard.\n' + '\n' + ' Separately, the interactive interpreter makes the result ' 'of the\n' - ' last evaluation; it is stored in the "builtins" module. ' - 'When not\n' - ' in interactive mode, "_" has no special meaning and is not ' - 'defined.\n' - ' See section The import statement.\n' + ' last evaluation available in the variable "_". (It is ' + 'stored in the\n' + ' "builtins" module, alongside built-in functions like ' + '"print".)\n' + '\n' + ' Elsewhere, "_" is a regular identifier. It is often used ' + 'to name\n' + ' ?special? items, but it is not special to Python itself.\n' '\n' ' Note:\n' '\n' @@ -7129,7 +7159,8 @@ ' internationalization; refer to the documentation for ' 'the\n' ' "gettext" module for more information on this ' - 'convention.\n' + 'convention.It is\n' + ' also commonly used for unused variables.\n' '\n' '"__*__"\n' ' System-defined names, informally known as ?dunder? names. ' @@ -7590,20 +7621,32 @@ '*Names* refer to objects. Names are introduced by name binding\n' 'operations.\n' '\n' - 'The following constructs bind names: formal parameters to ' - 'functions,\n' - '"import" statements, class and function definitions (these bind ' - 'the\n' - 'class or function name in the defining block), and targets that ' - 'are\n' - 'identifiers if occurring in an assignment, "for" loop header, or ' - 'after\n' - '"as" in a "with" statement or "except" clause. The "import" ' - 'statement\n' - 'of the form "from ... import *" binds all names defined in the\n' - 'imported module, except those beginning with an underscore. This ' - 'form\n' - 'may only be used at the module level.\n' + 'The following constructs bind names:\n' + '\n' + '* formal parameters to functions,\n' + '\n' + '* class definitions,\n' + '\n' + '* function definitions,\n' + '\n' + '* assignment expressions,\n' + '\n' + '* targets that are identifiers if occurring in an assignment:\n' + '\n' + ' * "for" loop header,\n' + '\n' + ' * after "as" in a "with" statement, "except" clause or in the ' + 'as-\n' + ' pattern in structural pattern matching,\n' + '\n' + ' * in a capture pattern in structural pattern matching\n' + '\n' + '* "import" statements.\n' + '\n' + 'The "import" statement of the form "from ... import *" binds all ' + 'names\n' + 'defined in the imported module, except those beginning with an\n' + 'underscore. This form may only be used at the module level.\n' '\n' 'A target occurring in a "del" statement is also considered bound ' 'for\n' @@ -7673,8 +7716,8 @@ 'operations.\n' '\n' 'If the "global" statement occurs within a block, all uses of the ' - 'name\n' - 'specified in the statement refer to the binding of that name in ' + 'names\n' + 'specified in the statement refer to the bindings of those names in ' 'the\n' 'top-level namespace. Names are resolved in the top-level ' 'namespace by\n' @@ -7683,9 +7726,9 @@ 'namespace\n' 'of the module "builtins". The global namespace is searched ' 'first. If\n' - 'the name is not found there, the builtins namespace is searched. ' - 'The\n' - '"global" statement must precede all uses of the name.\n' + 'the names are not found there, the builtins namespace is ' + 'searched.\n' + 'The "global" statement must precede all uses of the listed names.\n' '\n' 'The "global" statement has the same scope as a name binding ' 'operation\n' @@ -8020,9 +8063,9 @@ ' of the object truncated to an "Integral" (typically an ' '"int").\n' '\n' - ' If "__int__()" is not defined then the built-in function ' - '"int()"\n' - ' falls back to "__trunc__()".\n', + ' The built-in function "int()" falls back to ' + '"__trunc__()" if\n' + ' neither "__int__()" nor "__index__()" is defined.\n', 'objects': 'Objects, values and types\n' '*************************\n' '\n' @@ -8644,22 +8687,24 @@ 'object.__getitem__(self, key)\n' '\n' ' Called to implement evaluation of "self[key]". For ' - 'sequence types,\n' - ' the accepted keys should be integers and slice ' - 'objects. Note that\n' - ' the special interpretation of negative indexes (if the ' - 'class wishes\n' - ' to emulate a sequence type) is up to the ' - '"__getitem__()" method. If\n' - ' *key* is of an inappropriate type, "TypeError" may be ' - 'raised; if of\n' - ' a value outside the set of indexes for the sequence ' - '(after any\n' - ' special interpretation of negative values), ' - '"IndexError" should be\n' - ' raised. For mapping types, if *key* is missing (not in ' + '*sequence*\n' + ' types, the accepted keys should be integers and slice ' + 'objects.\n' + ' Note that the special interpretation of negative ' + 'indexes (if the\n' + ' class wishes to emulate a *sequence* type) is up to ' 'the\n' - ' container), "KeyError" should be raised.\n' + ' "__getitem__()" method. If *key* is of an inappropriate ' + 'type,\n' + ' "TypeError" may be raised; if of a value outside the ' + 'set of indexes\n' + ' for the sequence (after any special interpretation of ' + 'negative\n' + ' values), "IndexError" should be raised. For *mapping* ' + 'types, if\n' + ' *key* is missing (not in the container), "KeyError" ' + 'should be\n' + ' raised.\n' '\n' ' Note:\n' '\n' @@ -8669,6 +8714,15 @@ 'of the\n' ' sequence.\n' '\n' + ' Note:\n' + '\n' + ' When subscripting a *class*, the special class ' + 'method\n' + ' "__class_getitem__()" may be called instead of ' + '"__getitem__()".\n' + ' See __class_getitem__ versus __getitem__ for more ' + 'details.\n' + '\n' 'object.__setitem__(self, key, value)\n' '\n' ' Called to implement assignment to "self[key]". Same ' @@ -8704,19 +8758,13 @@ '\n' 'object.__iter__(self)\n' '\n' - ' This method is called when an iterator is required for ' - 'a container.\n' - ' This method should return a new iterator object that ' - 'can iterate\n' - ' over all the objects in the container. For mappings, ' - 'it should\n' - ' iterate over the keys of the container.\n' - '\n' - ' Iterator objects also need to implement this method; ' - 'they are\n' - ' required to return themselves. For more information on ' - 'iterator\n' - ' objects, see Iterator Types.\n' + ' This method is called when an *iterator* is required ' + 'for a\n' + ' container. This method should return a new iterator ' + 'object that can\n' + ' iterate over all the objects in the container. For ' + 'mappings, it\n' + ' should iterate over the keys of the container.\n' '\n' 'object.__reversed__(self)\n' '\n' @@ -10294,9 +10342,33 @@ 'Emulating generic types\n' '=======================\n' '\n' - 'One can implement the generic class syntax as specified by ' - '**PEP 484**\n' - '(for example "List[int]") by defining a special method:\n' + 'When using *type annotations*, it is often useful to ' + '*parameterize* a\n' + '*generic type* using Python?s square-brackets notation. For ' + 'example,\n' + 'the annotation "list[int]" might be used to signify a "list" ' + 'in which\n' + 'all the elements are of type "int".\n' + '\n' + 'See also:\n' + '\n' + ' **PEP 484** - Type Hints\n' + ' Introducing Python?s framework for type annotations\n' + '\n' + ' Generic Alias Types\n' + ' Documentation for objects representing parameterized ' + 'generic\n' + ' classes\n' + '\n' + ' Generics, user-defined generics and "typing.Generic"\n' + ' Documentation on how to implement generic classes that ' + 'can be\n' + ' parameterized at runtime and understood by static ' + 'type-checkers.\n' + '\n' + 'A class can *generally* only be parameterized if it defines ' + 'the\n' + 'special class method "__class_getitem__()".\n' '\n' 'classmethod object.__class_getitem__(cls, key)\n' '\n' @@ -10304,18 +10376,144 @@ 'generic class\n' ' by type arguments found in *key*.\n' '\n' - 'This method is looked up on the class object itself, and ' - 'when defined\n' - 'in the class body, this method is implicitly a class ' - 'method. Note,\n' - 'this mechanism is primarily reserved for use with static ' - 'type hints,\n' - 'other usage is discouraged.\n' + ' When defined on a class, "__class_getitem__()" is ' + 'automatically a\n' + ' class method. As such, there is no need for it to be ' + 'decorated with\n' + ' "@classmethod" when it is defined.\n' + '\n' + '\n' + 'The purpose of *__class_getitem__*\n' + '----------------------------------\n' + '\n' + 'The purpose of "__class_getitem__()" is to allow runtime\n' + 'parameterization of standard-library generic classes in ' + 'order to more\n' + 'easily apply *type hints* to these classes.\n' + '\n' + 'To implement custom generic classes that can be ' + 'parameterized at\n' + 'runtime and understood by static type-checkers, users should ' + 'either\n' + 'inherit from a standard library class that already ' + 'implements\n' + '"__class_getitem__()", or inherit from "typing.Generic", ' + 'which has its\n' + 'own implementation of "__class_getitem__()".\n' + '\n' + 'Custom implementations of "__class_getitem__()" on classes ' + 'defined\n' + 'outside of the standard library may not be understood by ' + 'third-party\n' + 'type-checkers such as mypy. Using "__class_getitem__()" on ' + 'any class\n' + 'for purposes other than type hinting is discouraged.\n' + '\n' + '\n' + '*__class_getitem__* versus *__getitem__*\n' + '----------------------------------------\n' + '\n' + 'Usually, the subscription of an object using square brackets ' + 'will call\n' + 'the "__getitem__()" instance method defined on the object?s ' + 'class.\n' + 'However, if the object being subscribed is itself a class, ' + 'the class\n' + 'method "__class_getitem__()" may be called instead.\n' + '"__class_getitem__()" should return a GenericAlias object if ' + 'it is\n' + 'properly defined.\n' + '\n' + 'Presented with the *expression* "obj[x]", the Python ' + 'interpreter\n' + 'follows something like the following process to decide ' + 'whether\n' + '"__getitem__()" or "__class_getitem__()" should be called:\n' + '\n' + ' from inspect import isclass\n' + '\n' + ' def subscribe(obj, x):\n' + ' """Return the result of the expression `obj[x]`"""\n' + '\n' + ' class_of_obj = type(obj)\n' + '\n' + ' # If the class of obj defines __getitem__,\n' + ' # call class_of_obj.__getitem__(obj, x)\n' + " if hasattr(class_of_obj, '__getitem__'):\n" + ' return class_of_obj.__getitem__(obj, x)\n' + '\n' + ' # Else, if obj is a class and defines ' + '__class_getitem__,\n' + ' # call obj.__class_getitem__(x)\n' + ' elif isclass(obj) and hasattr(obj, ' + "'__class_getitem__'):\n" + ' return obj.__class_getitem__(x)\n' + '\n' + ' # Else, raise an exception\n' + ' else:\n' + ' raise TypeError(\n' + ' f"\'{class_of_obj.__name__}\' object is not ' + 'subscriptable"\n' + ' )\n' + '\n' + 'In Python, all classes are themselves instances of other ' + 'classes. The\n' + 'class of a class is known as that class?s *metaclass*, and ' + 'most\n' + 'classes have the "type" class as their metaclass. "type" ' + 'does not\n' + 'define "__getitem__()", meaning that expressions such as ' + '"list[int]",\n' + '"dict[str, float]" and "tuple[str, bytes]" all result in\n' + '"__class_getitem__()" being called:\n' + '\n' + ' >>> # list has class "type" as its metaclass, like most ' + 'classes:\n' + ' >>> type(list)\n' + " \n" + ' >>> type(dict) == type(list) == type(tuple) == type(str) ' + '== type(bytes)\n' + ' True\n' + ' >>> # "list[int]" calls "list.__class_getitem__(int)"\n' + ' >>> list[int]\n' + ' list[int]\n' + ' >>> # list.__class_getitem__ returns a GenericAlias ' + 'object:\n' + ' >>> type(list[int])\n' + " \n" + '\n' + 'However, if a class has a custom metaclass that defines\n' + '"__getitem__()", subscribing the class may result in ' + 'different\n' + 'behaviour. An example of this can be found in the "enum" ' + 'module:\n' + '\n' + ' >>> from enum import Enum\n' + ' >>> class Menu(Enum):\n' + ' ... """A breakfast menu"""\n' + " ... SPAM = 'spam'\n" + " ... BACON = 'bacon'\n" + ' ...\n' + ' >>> # Enum classes have a custom metaclass:\n' + ' >>> type(Menu)\n' + " \n" + ' >>> # EnumMeta defines __getitem__,\n' + ' >>> # so __class_getitem__ is not called,\n' + ' >>> # and the result is not a GenericAlias object:\n' + " >>> Menu['SPAM']\n" + " \n" + " >>> type(Menu['SPAM'])\n" + " \n" '\n' 'See also:\n' '\n' - ' **PEP 560** - Core support for typing module and generic ' + ' **PEP 560** - Core Support for typing module and generic ' 'types\n' + ' Introducing "__class_getitem__()", and outlining when ' + 'a\n' + ' subscription results in "__class_getitem__()" being ' + 'called\n' + ' instead of "__getitem__()"\n' '\n' '\n' 'Emulating callable objects\n' @@ -10445,22 +10643,23 @@ 'object.__getitem__(self, key)\n' '\n' ' Called to implement evaluation of "self[key]". For ' - 'sequence types,\n' - ' the accepted keys should be integers and slice objects. ' - 'Note that\n' - ' the special interpretation of negative indexes (if the ' - 'class wishes\n' - ' to emulate a sequence type) is up to the "__getitem__()" ' - 'method. If\n' - ' *key* is of an inappropriate type, "TypeError" may be ' - 'raised; if of\n' - ' a value outside the set of indexes for the sequence ' - '(after any\n' - ' special interpretation of negative values), "IndexError" ' + '*sequence*\n' + ' types, the accepted keys should be integers and slice ' + 'objects.\n' + ' Note that the special interpretation of negative indexes ' + '(if the\n' + ' class wishes to emulate a *sequence* type) is up to the\n' + ' "__getitem__()" method. If *key* is of an inappropriate ' + 'type,\n' + ' "TypeError" may be raised; if of a value outside the set ' + 'of indexes\n' + ' for the sequence (after any special interpretation of ' + 'negative\n' + ' values), "IndexError" should be raised. For *mapping* ' + 'types, if\n' + ' *key* is missing (not in the container), "KeyError" ' 'should be\n' - ' raised. For mapping types, if *key* is missing (not in ' - 'the\n' - ' container), "KeyError" should be raised.\n' + ' raised.\n' '\n' ' Note:\n' '\n' @@ -10470,6 +10669,14 @@ 'the\n' ' sequence.\n' '\n' + ' Note:\n' + '\n' + ' When subscripting a *class*, the special class method\n' + ' "__class_getitem__()" may be called instead of ' + '"__getitem__()".\n' + ' See __class_getitem__ versus __getitem__ for more ' + 'details.\n' + '\n' 'object.__setitem__(self, key, value)\n' '\n' ' Called to implement assignment to "self[key]". Same note ' @@ -10505,19 +10712,13 @@ '\n' 'object.__iter__(self)\n' '\n' - ' This method is called when an iterator is required for a ' - 'container.\n' - ' This method should return a new iterator object that can ' - 'iterate\n' - ' over all the objects in the container. For mappings, it ' - 'should\n' - ' iterate over the keys of the container.\n' - '\n' - ' Iterator objects also need to implement this method; they ' - 'are\n' - ' required to return themselves. For more information on ' - 'iterator\n' - ' objects, see Iterator Types.\n' + ' This method is called when an *iterator* is required for ' + 'a\n' + ' container. This method should return a new iterator ' + 'object that can\n' + ' iterate over all the objects in the container. For ' + 'mappings, it\n' + ' should iterate over the keys of the container.\n' '\n' 'object.__reversed__(self)\n' '\n' @@ -10760,9 +10961,9 @@ ' of the object truncated to an "Integral" (typically an ' '"int").\n' '\n' - ' If "__int__()" is not defined then the built-in function ' - '"int()"\n' - ' falls back to "__trunc__()".\n' + ' The built-in function "int()" falls back to "__trunc__()" ' + 'if\n' + ' neither "__int__()" nor "__index__()" is defined.\n' '\n' '\n' 'With Statement Context Managers\n' @@ -12971,20 +13172,18 @@ ' A function or method which uses the "yield" statement (see\n' ' section The yield statement) is called a *generator ' 'function*.\n' - ' Such a function, when called, always returns an iterator ' - 'object\n' - ' which can be used to execute the body of the function: ' - 'calling\n' - ' the iterator?s "iterator.__next__()" method will cause the\n' - ' function to execute until it provides a value using the ' - '"yield"\n' - ' statement. When the function executes a "return" statement ' - 'or\n' - ' falls off the end, a "StopIteration" exception is raised and ' - 'the\n' - ' iterator will have reached the end of the set of values to ' - 'be\n' - ' returned.\n' + ' Such a function, when called, always returns an *iterator*\n' + ' object which can be used to execute the body of the ' + 'function:\n' + ' calling the iterator?s "iterator.__next__()" method will ' + 'cause\n' + ' the function to execute until it provides a value using the\n' + ' "yield" statement. When the function executes a "return"\n' + ' statement or falls off the end, a "StopIteration" exception ' + 'is\n' + ' raised and the iterator will have reached the end of the set ' + 'of\n' + ' values to be returned.\n' '\n' ' Coroutine functions\n' ' A function or method which is defined using "async def" is\n' @@ -13000,9 +13199,9 @@ ' which uses the "yield" statement is called a *asynchronous\n' ' generator function*. Such a function, when called, returns ' 'an\n' - ' asynchronous iterator object which can be used in an "async ' - 'for"\n' - ' statement to execute the body of the function.\n' + ' *asynchronous iterator* object which can be used in an ' + '"async\n' + ' for" statement to execute the body of the function.\n' '\n' ' Calling the asynchronous iterator?s "aiterator.__anext__()"\n' ' method will return an *awaitable* which when awaited will\n' diff --git a/Misc/NEWS.d/3.10.1.rst b/Misc/NEWS.d/3.10.1.rst new file mode 100644 index 0000000000000..0f8938ab6154d --- /dev/null +++ b/Misc/NEWS.d/3.10.1.rst @@ -0,0 +1,1530 @@ +.. bpo: 42268 +.. date: 2021-11-26-22-31-22 +.. nonce: 3wl-09 +.. release date: 2021-12-06 +.. section: Core and Builtins + +Fail the configure step if the selected compiler doesn't support memory +sanitizer. Patch by Pablo Galindo + +.. + +.. bpo: 45727 +.. date: 2021-11-24-18-24-49 +.. nonce: _xVbbo +.. section: Core and Builtins + +Refine the custom syntax error that suggests that a comma may be missing to +trigger only when the expressions are detected between parentheses or +brackets. Patch by Pablo Galindo + +.. + +.. bpo: 45614 +.. date: 2021-11-23-12-06-41 +.. nonce: fIekgI +.. section: Core and Builtins + +Fix :mod:`traceback` display for exceptions with invalid module name. + +.. + +.. bpo: 45848 +.. date: 2021-11-19-22-57-42 +.. nonce: HgVBJ5 +.. section: Core and Builtins + +Allow the parser to obtain error lines directly from encoded files. Patch by +Pablo Galindo + +.. + +.. bpo: 45826 +.. date: 2021-11-17-08-05-27 +.. nonce: OERoTm +.. section: Core and Builtins + +Fixed a crash when calling ``.with_traceback(None)`` on ``NameError``. This +occurs internally in ``unittest.TestCase.assertRaises()``. + +.. + +.. bpo: 45822 +.. date: 2021-11-16-19-41-04 +.. nonce: OT6ueS +.. section: Core and Builtins + +Fixed a bug in the parser that was causing it to not respect :pep:`263` +coding cookies when no flags are provided. Patch by Pablo Galindo + +.. + +.. bpo: 45820 +.. date: 2021-11-16-19-00-27 +.. nonce: 2X6Psr +.. section: Core and Builtins + +Fix a segfault when the parser fails without reading any input. Patch by +Pablo Galindo + +.. + +.. bpo: 42540 +.. date: 2021-11-15-12-08-27 +.. nonce: V2w107 +.. section: Core and Builtins + +Fix crash when :func:`os.fork` is called with an active non-default memory +allocator. + +.. + +.. bpo: 45738 +.. date: 2021-11-14-00-14-45 +.. nonce: e0cgKd +.. section: Core and Builtins + +Fix computation of error location for invalid continuation characters in the +parser. Patch by Pablo Galindo. + +.. + +.. bpo: 45773 +.. date: 2021-11-09-13-01-35 +.. nonce: POU8A4 +.. section: Core and Builtins + +Fix a compiler hang when attempting to optimize certain jump patterns. + +.. + +.. bpo: 45716 +.. date: 2021-11-04-20-19-07 +.. nonce: 5C0pA1 +.. section: Core and Builtins + +Improve the :exc:`SyntaxError` message when using ``True``, ``None`` or +``False`` as keywords in a function call. Patch by Pablo Galindo. + +.. + +.. bpo: 45688 +.. date: 2021-11-02-09-27-46 +.. nonce: v5Der1 +.. section: Core and Builtins + +:data:`sys.stdlib_module_names` now contains the macOS-specific module +:mod:`_scproxy`. + +.. + +.. bpo: 30570 +.. date: 2021-10-19-01-04-08 +.. nonce: _G30Ms +.. section: Core and Builtins + +Fixed a crash in ``issubclass()`` from infinite recursion when searching +pathological ``__bases__`` tuples. + +.. + +.. bpo: 45521 +.. date: 2021-10-18-22-40-33 +.. nonce: GdMiuW +.. section: Core and Builtins + +Fix a bug in the obmalloc radix tree code. On 64-bit machines, the bug +causes the tree to hold 46-bits of virtual addresses, rather than the +intended 48-bits. + +.. + +.. bpo: 45494 +.. date: 2021-10-16-17-27-48 +.. nonce: vMt1g4 +.. section: Core and Builtins + +Fix parser crash when reporting errors involving invalid continuation +characters. Patch by Pablo Galindo. + +.. + +.. bpo: 45408 +.. date: 2021-10-07-21-26-44 +.. nonce: qUqzcd +.. section: Core and Builtins + +Fix a crash in the parser when reporting tokenizer errors that occur at the +same time unclosed parentheses are detected. Patch by Pablo Galindo. + +.. + +.. bpo: 45385 +.. date: 2021-10-06-21-20-11 +.. nonce: CTUT8s +.. section: Core and Builtins + +Fix reference leak from descr_check. Patch by Dong-hee Na. + +.. + +.. bpo: 45167 +.. date: 2021-09-14-09-23-59 +.. nonce: CPSSoV +.. section: Core and Builtins + +Fix deepcopying of :class:`types.GenericAlias` objects. + +.. + +.. bpo: 44219 +.. date: 2021-09-09-10-32-33 +.. nonce: WiYyjz +.. section: Core and Builtins + +Release the GIL while performing ``isatty`` system calls on arbitrary file +descriptors. In particular, this affects :func:`os.isatty`, +:func:`os.device_encoding` and :class:`io.TextIOWrapper`. By extension, +:func:`io.open` in text mode is also affected. This change solves a deadlock +in :func:`os.isatty`. Patch by Vincent Michel in :issue:`44219`. + +.. + +.. bpo: 44959 +.. date: 2021-09-08-08-29-41 +.. nonce: OSwwPf +.. section: Core and Builtins + +Added fallback to extension modules with '.sl' suffix on HP-UX + +.. + +.. bpo: 44050 +.. date: 2021-09-08-00-30-09 +.. nonce: mFI15u +.. section: Core and Builtins + +Extensions that indicate they use global state (by setting ``m_size`` to -1) +can again be used in multiple interpreters. This reverts to behavior of +Python 3.8. + +.. + +.. bpo: 45121 +.. date: 2021-09-07-17-10-16 +.. nonce: iG-Hsf +.. section: Core and Builtins + +Fix issue where ``Protocol.__init__`` raises ``RecursionError`` when it's +called directly or via ``super()``. Patch provided by Yurii Karabas. + +.. + +.. bpo: 45083 +.. date: 2021-09-01-23-55-49 +.. nonce: cLi9G3 +.. section: Core and Builtins + +When the interpreter renders an exception, its name now has a complete +qualname. Previously only the class name was concatenated to the module +name, which sometimes resulted in an incorrect full name being displayed. + +(This issue impacted only the C code exception rendering, the +:mod:`traceback` module was using qualname already). + +.. + +.. bpo: 45056 +.. date: 2021-09-01-16-55-43 +.. nonce: 7AK2d9 +.. section: Core and Builtins + +Compiler now removes trailing unused constants from co_consts. + +.. + +.. bpo: 27946 +.. date: 2021-12-04-20-08-42 +.. nonce: -Vuarf +.. section: Library + +Fix possible crash when getting an attribute of +class:`xml.etree.ElementTree.Element` simultaneously with replacing the +``attrib`` dict. + +.. + +.. bpo: 37658 +.. date: 2021-11-28-15-30-34 +.. nonce: 8Hno7d +.. section: Library + +Fix issue when on certain conditions ``asyncio.wait_for()`` may allow a +coroutine to complete successfully, but fail to return the result, +potentially causing memory leaks or other issues. + +.. + +.. bpo: 44649 +.. date: 2021-11-21-20-50-42 +.. nonce: E8M936 +.. section: Library + +Handle dataclass(slots=True) with a field that has default a default value, +but for which init=False. + +.. + +.. bpo: 45803 +.. date: 2021-11-20-17-04-25 +.. nonce: wSgFOy +.. section: Library + +Added missing kw_only parameter to dataclasses.make_dataclass(). + +.. + +.. bpo: 45831 +.. date: 2021-11-17-19-25-37 +.. nonce: 9-TojK +.. section: Library + +:mod:`faulthandler` can now write ASCII-only strings (like filenames and +function names) with a single write() syscall when dumping a traceback. It +reduces the risk of getting an unreadable dump when two threads or two +processes dump a traceback to the same file (like stderr) at the same time. +Patch by Victor Stinner. + +.. + +.. bpo: 41735 +.. date: 2021-11-16-18-13-49 +.. nonce: D72UY1 +.. section: Library + +Fix thread lock in ``zlib.Decompress.flush()`` method before +``PyObject_GetBuffer``. + +.. + +.. bpo: 45235 +.. date: 2021-11-11-13-03-17 +.. nonce: 8ZbkHa +.. section: Library + +Reverted an argparse bugfix that caused regression in the handling of +default arguments for subparsers. This prevented leaf level arguments from +taking precedence over root level arguments. + +.. + +.. bpo: 45765 +.. date: 2021-11-09-09-04-19 +.. nonce: JVobxK +.. section: Library + +In importlib.metadata, fix distribution discovery for an empty path. + +.. + +.. bpo: 45757 +.. date: 2021-11-08-23-22-14 +.. nonce: MHZHt3 +.. section: Library + +Fix bug where :mod:`dis` produced an incorrect oparg when +:opcode:`EXTENDED_ARG` is followed by an opcode that does not use its +argument. + +.. + +.. bpo: 45644 +.. date: 2021-11-06-17-47-46 +.. nonce: ZMqHD_ +.. section: Library + +In-place JSON file formatting using ``python3 -m json.tool infile infile`` +now works correctly, previously it left the file empty. Patch by Chris +Wesseling. + +.. + +.. bpo: 45679 +.. date: 2021-10-30-21-11-37 +.. nonce: Dq8Cpu +.. section: Library + +Fix caching of multi-value :data:`typing.Literal`. ``Literal[True, 2]`` is +no longer equal to ``Literal[1, 2]``. + +.. + +.. bpo: 45664 +.. date: 2021-10-28-23-40-54 +.. nonce: 7dqtxQ +.. section: Library + +Fix :func:`types.resolve_bases` and :func:`types.new_class` for +:class:`types.GenericAlias` instance as a base. + +.. + +.. bpo: 45663 +.. date: 2021-10-28-23-11-59 +.. nonce: J90N5R +.. section: Library + +Fix :func:`dataclasses.is_dataclass` for dataclasses which are subclasses of +:class:`types.GenericAlias`. + +.. + +.. bpo: 45662 +.. date: 2021-10-28-22-58-14 +.. nonce: sJd7Ir +.. section: Library + +Fix the repr of :data:`dataclasses.InitVar` with a type alias to the +built-in class, e.g. ``InitVar[list[int]]``. + +.. + +.. bpo: 45438 +.. date: 2021-10-27-10-05-39 +.. nonce: Xz5lGU +.. section: Library + +Fix typing.Signature string representation for generic builtin types. + +.. + +.. bpo: 45574 +.. date: 2021-10-22-23-06-33 +.. nonce: svqA84 +.. section: Library + +Fix warning about ``print_escape`` being unused. + +.. + +.. bpo: 45581 +.. date: 2021-10-22-21-57-02 +.. nonce: rlH6ay +.. section: Library + +:meth:`sqlite3.connect` now correctly raises :exc:`MemoryError` if the +underlying SQLite API signals memory error. Patch by Erlend E. Aasland. + +.. + +.. bpo: 45557 +.. date: 2021-10-21-16-18-51 +.. nonce: 4MQt4r +.. section: Library + +pprint.pprint() now handles underscore_numbers correctly. Previously it was +always setting it to False. + +.. + +.. bpo: 45515 +.. date: 2021-10-18-14-52-48 +.. nonce: aXdvm_ +.. section: Library + +Add references to :mod:`zoneinfo` in the :mod:`datetime` documentation, +mostly replacing outdated references to ``dateutil.tz``. Change by Paul +Ganssle. + +.. + +.. bpo: 45475 +.. date: 2021-10-18-10-46-47 +.. nonce: sb9KDF +.. section: Library + +Reverted optimization of iterating :class:`gzip.GzipFile`, +:class:`bz2.BZ2File`, and :class:`lzma.LZMAFile` (see bpo-43787) because it +caused regression when user iterate them without having reference of them. +Patch by Inada Naoki. + +.. + +.. bpo: 45428 +.. date: 2021-10-14-18-04-17 +.. nonce: mM2War +.. section: Library + +Fix a regression in py_compile when reading filenames from standard input. + +.. + +.. bpo: 45467 +.. date: 2021-10-14-13-31-19 +.. nonce: Q7Ma6A +.. section: Library + +Fix incremental decoder and stream reader in the "raw-unicode-escape" codec. +Previously they failed if the escape sequence was split. + +.. + +.. bpo: 45461 +.. date: 2021-10-14-00-19-02 +.. nonce: 4LB_tJ +.. section: Library + +Fix incremental decoder and stream reader in the "unicode-escape" codec. +Previously they failed if the escape sequence was split. + +.. + +.. bpo: 45239 +.. date: 2021-10-13-17-52-48 +.. nonce: 7li1_0 +.. section: Library + +Fixed :func:`email.utils.parsedate_tz` crashing with +:exc:`UnboundLocalError` on certain invalid input instead of returning +``None``. Patch by Ben Hoyt. + +.. + +.. bpo: 45249 +.. date: 2021-10-10-16-14-33 +.. nonce: xqLliz +.. section: Library + +Fix the behaviour of :func:`traceback.print_exc` when displaying the caret +when the ``end_offset`` in the exception is set to 0. Patch by Pablo Galindo + +.. + +.. bpo: 45416 +.. date: 2021-10-10-09-42-34 +.. nonce: n35O0_ +.. section: Library + +Fix use of :class:`asyncio.Condition` with explicit :class:`asyncio.Lock` +objects, which was a regression due to removal of explicit loop arguments. +Patch by Joongi Kim. + +.. + +.. bpo: 45419 +.. date: 2021-10-09-20-53-13 +.. nonce: CauCgt +.. section: Library + +Correct interfaces on DegenerateFiles.Path. + +.. + +.. bpo: 44904 +.. date: 2021-10-09-18-42-27 +.. nonce: RlW5h8 +.. section: Library + +Fix bug in the :mod:`doctest` module that caused it to fail if a docstring +included an example with a ``classmethod`` ``property``. Patch by Alex +Waygood. + +.. + +.. bpo: 45406 +.. date: 2021-10-08-19-24-48 +.. nonce: Qh_Mz4 +.. section: Library + +Make :func:`inspect.getmodule` catch ``FileNotFoundError`` raised by +:'func:`inspect.getabsfile`, and return ``None`` to indicate that the module +could not be determined. + +.. + +.. bpo: 45262 +.. date: 2021-10-07-14-04-10 +.. nonce: HqF71Z +.. section: Library + +Prevent use-after-free in asyncio. Make sure the cached running loop holder +gets cleared on dealloc to prevent use-after-free in get_running_loop + +.. + +.. bpo: 45386 +.. date: 2021-10-07-00-05-05 +.. nonce: q9ORpA +.. section: Library + +Make :mod:`xmlrpc.client` more robust to C runtimes where the underlying C +``strftime`` function results in a ``ValueError`` when testing for year +formatting options. + +.. + +.. bpo: 45371 +.. date: 2021-10-05-11-03-48 +.. nonce: NOwcDJ +.. section: Library + +Fix clang rpath issue in :mod:`distutils`. The UnixCCompiler now uses +correct clang option to add a runtime library directory (rpath) to a shared +library. + +.. + +.. bpo: 20028 +.. date: 2021-10-03-21-14-37 +.. nonce: zBA4RK +.. section: Library + +Improve error message of :class:`csv.Dialect` when initializing. Patch by +Vajrasky Kok and Dong-hee Na. + +.. + +.. bpo: 45343 +.. date: 2021-10-01-23-07-02 +.. nonce: ixmctD +.. section: Library + +Update bundled pip to 21.2.4 and setuptools to 58.1.0 + +.. + +.. bpo: 45329 +.. date: 2021-10-01-13-09-53 +.. nonce: 9iMYaO +.. section: Library + +Fix freed memory access in :class:`pyexpat.xmlparser` when building it with +an installed expat library <= 2.2.0. + +.. + +.. bpo: 41710 +.. date: 2021-09-30-23-00-18 +.. nonce: svuloZ +.. section: Library + +On Unix, if the ``sem_clockwait()`` function is available in the C library +(glibc 2.30 and newer), the :meth:`threading.Lock.acquire` method now uses +the monotonic clock (:data:`time.CLOCK_MONOTONIC`) for the timeout, rather +than using the system clock (:data:`time.CLOCK_REALTIME`), to not be +affected by system clock changes. Patch by Victor Stinner. + +.. + +.. bpo: 45328 +.. date: 2021-09-30-08-22-44 +.. nonce: 8Z-Q0B +.. section: Library + +Fixed :class:`http.client.HTTPConnection` to work properly in OSs that don't +support the ``TCP_NODELAY`` socket option. + +.. + +.. bpo: 1596321 +.. date: 2021-09-24-17-20-23 +.. nonce: 3nhPUk +.. section: Library + +Fix the :func:`threading._shutdown` function when the :mod:`threading` +module was imported first from a thread different than the main thread: no +longer log an error at Python exit. + +.. + +.. bpo: 45274 +.. date: 2021-09-23-22-17-26 +.. nonce: gPpa4E +.. section: Library + +Fix a race condition in the :meth:`Thread.join() ` +method of the :mod:`threading` module. If the function is interrupted by a +signal and the signal handler raises an exception, make sure that the thread +remains in a consistent state to prevent a deadlock. Patch by Victor +Stinner. + +.. + +.. bpo: 45238 +.. date: 2021-09-18-16-56-33 +.. nonce: Hng_9V +.. section: Library + +Fix :meth:`unittest.IsolatedAsyncioTestCase.debug`: it runs now asynchronous +methods and callbacks. + +.. + +.. bpo: 36674 +.. date: 2021-09-18-13-14-57 +.. nonce: a2k5Zb +.. section: Library + +:meth:`unittest.TestCase.debug` raises now a :class:`unittest.SkipTest` if +the class or the test method are decorated with the skipping decorator. + +.. + +.. bpo: 45235 +.. date: 2021-09-17-16-55-37 +.. nonce: sXnmPA +.. section: Library + +Fix an issue where argparse would not preserve values in a provided +namespace when using a subparser with defaults. + +.. + +.. bpo: 45183 +.. date: 2021-09-17-15-58-53 +.. nonce: Vv_vch +.. section: Library + +Have zipimport.zipimporter.find_spec() not raise an exception when the +underlying zip file has been deleted and the internal cache has been reset +via invalidate_cache(). + +.. + +.. bpo: 45234 +.. date: 2021-09-17-11-20-55 +.. nonce: qUcTVt +.. section: Library + +Fixed a regression in :func:`~shutil.copyfile`, :func:`~shutil.copy`, +:func:`~shutil.copy2` raising :exc:`FileNotFoundError` when source is a +directory, which should raise :exc:`IsADirectoryError` + +.. + +.. bpo: 45228 +.. date: 2021-09-17-09-59-33 +.. nonce: WV1dcT +.. section: Library + +Fix stack buffer overflow in parsing J1939 network address. + +.. + +.. bpo: 45192 +.. date: 2021-09-14-15-52-47 +.. nonce: DjA-BI +.. section: Library + +Fix the ``tempfile._infer_return_type`` function so that the ``dir`` +argument of the :mod:`tempfile` functions accepts an object implementing the +``os.PathLike`` protocol. + +Patch by Kyungmin Lee. + +.. + +.. bpo: 42135 +.. date: 2021-09-13-19-32-58 +.. nonce: 1ZAHqR +.. section: Library + +Fix typo: ``importlib.find_loader`` is really slated for removal in Python +3.12 not 3.10, like the others in GH-25169. + +Patch by Hugo van Kemenade. + +.. + +.. bpo: 45160 +.. date: 2021-09-11-14-47-05 +.. nonce: VzMXbW +.. section: Library + +When tracing a tkinter variable used by a ttk OptionMenu, callbacks are no +longer made twice. + +.. + +.. bpo: 35474 +.. date: 2021-09-11-10-45-12 +.. nonce: tEY3SD +.. section: Library + +Calling :func:`mimetypes.guess_all_extensions` with ``strict=False`` no +longer affects the result of the following call with ``strict=True``. Also, +mutating the returned list no longer affects the global state. + +.. + +.. bpo: 45166 +.. date: 2021-09-10-21-35-53 +.. nonce: UHipXF +.. section: Library + +:func:`typing.get_type_hints` now works with :data:`~typing.Final` wrapped +in :class:`~typing.ForwardRef`. + +.. + +.. bpo: 20499 +.. date: 2021-09-08-01-19-31 +.. nonce: tSxx8Y +.. section: Library + +Improve the speed and accuracy of statistics.pvariance(). + +.. + +.. bpo: 24444 +.. date: 2021-08-30-00-19-23 +.. nonce: Ki4bgz +.. section: Library + +Fixed an error raised in :mod:`argparse` help display when help for an +option is set to 1+ blank spaces or when *choices* arg is an empty +container. + +.. + +.. bpo: 45021 +.. date: 2021-08-28-13-00-12 +.. nonce: rReeaj +.. section: Library + +Fix a potential deadlock at shutdown of forked children when using +:mod:`concurrent.futures` module + +.. + +.. bpo: 39039 +.. date: 2021-08-18-10-36-14 +.. nonce: A63LYh +.. section: Library + +tarfile.open raises :exc:`~tarfile.ReadError` when a zlib error occurs +during file extraction. + +.. + +.. bpo: 44594 +.. date: 2021-07-12-10-32-48 +.. nonce: eEa5zi +.. section: Library + +Fix an edge case of :class:`ExitStack` and :class:`AsyncExitStack` exception +chaining. They will now match ``with`` block behavior when ``__context__`` +is explicitly set to ``None`` when the exception is in flight. + +.. + +.. bpo: 44295 +.. date: 2021-06-02-16-39-42 +.. nonce: erg01m +.. section: Library + +Ensure deprecation warning from :func:`assertDictContainsSubset` points at +calling code - by Anthony Sottile. + +.. + +.. bpo: 43498 +.. date: 2021-04-20-14-14-16 +.. nonce: L_Hq-8 +.. section: Library + +Avoid a possible *"RuntimeError: dictionary changed size during iteration"* +when adjusting the process count of :class:`ProcessPoolExecutor`. + +.. + +.. bpo: 45640 +.. date: 2021-11-18-16-44-12 +.. nonce: lSpc2A +.. section: Documentation + +Properly marked-up grammar tokens in the documentation are now clickable and +take you to the definition of a given piece of grammar. Patch by Arthur +Milchior. + +.. + +.. bpo: 45788 +.. date: 2021-11-18-00-07-40 +.. nonce: qibUoB +.. section: Documentation + +Link doc for sys.prefix to sysconfig doc on installation paths. + +.. + +.. bpo: 45772 +.. date: 2021-11-09-13-10-55 +.. nonce: EdrM3t +.. section: Documentation + +``socket.socket`` documentation is corrected to a class from a function. + +.. + +.. bpo: 45392 +.. date: 2021-11-06-10-54-17 +.. nonce: JZnVOz +.. section: Documentation + +Update the docstring of the :class:`type` built-in to remove a redundant +line and to mention keyword arguments for the constructor. + +.. + +.. bpo: 45726 +.. date: 2021-11-05-12-15-24 +.. nonce: GwRr7e +.. section: Documentation + +Improve documentation for :func:`functools.singledispatch` and +:class:`functools.singledispatchmethod`. + +.. + +.. bpo: 45680 +.. date: 2021-11-03-14-51-03 +.. nonce: 9_NTFU +.. section: Documentation + +Amend the docs on ``GenericAlias`` objects to clarify that non-container +classes can also implement ``__class_getitem__``. Patch contributed by Alex +Waygood. + +.. + +.. bpo: 45655 +.. date: 2021-10-28-19-22-55 +.. nonce: aPYGaS +.. section: Documentation + +Add a new "relevant PEPs" section to the top of the documentation for the +``typing`` module. Patch by Alex Waygood. + +.. + +.. bpo: 45604 +.. date: 2021-10-26-10-00-45 +.. nonce: Dm-YhV +.. section: Documentation + +Add ``level`` argument to ``multiprocessing.log_to_stderr`` function docs. + +.. + +.. bpo: 45250 +.. date: 2021-10-22-12-09-18 +.. nonce: Iit5-Y +.. section: Documentation + +Update the documentation to note that CPython does not consistently require +iterators to define ``__iter__``. + +.. + +.. bpo: 45464 +.. date: 2021-10-20-16-26-53 +.. nonce: mOISBs +.. section: Documentation + +Mention in the documentation of :ref:`Built-in Exceptions +` that inheriting from multiple exception types in a +single subclass is not recommended due to possible memory layout +incompatibility. + +.. + +.. bpo: 45449 +.. date: 2021-10-19-01-41-40 +.. nonce: fjHZJc +.. section: Documentation + +Add note about :pep:`585` in :mod:`collections.abc`. + +.. + +.. bpo: 45516 +.. date: 2021-10-18-20-12-18 +.. nonce: EJh4K8 +.. section: Documentation + +Add protocol description to the :class:`importlib.abc.Traversable` +documentation. + +.. + +.. bpo: 20692 +.. date: 2021-10-13-00-42-54 +.. nonce: K5rGtP +.. section: Documentation + +Add Programming FAQ entry explaining that int literal attribute access +requires either a space after or parentheses around the literal. + +.. + +.. bpo: 45216 +.. date: 2021-09-18-13-45-19 +.. nonce: o56nyt +.. section: Documentation + +Remove extra documentation listing methods in ``difflib``. It was rendering +twice in pydoc and was outdated in some places. + +.. + +.. bpo: 45024 +.. date: 2021-09-08-17-20-19 +.. nonce: dkNPNi +.. section: Documentation + +:mod:`collections.abc` documentation has been expanded to explicitly cover +how instance and subclass checks work, with additional doctest examples and +an exhaustive list of ABCs which test membership purely by presence of the +right :term:`special method`\s. Patch by Raymond Hettinger. + +.. + +.. bpo: 25381 +.. date: 2021-06-21-17-51-51 +.. nonce: 7Kn-_H +.. section: Documentation + +In the extending chapter of the extending doc, update a paragraph about the +global variables containing exception information. + +.. + +.. bpo: 43905 +.. date: 2021-05-24-05-00-12 +.. nonce: tBIndE +.. section: Documentation + +Expanded :func:`~dataclasses.astuple` and :func:`~dataclasses.asdict` docs, +warning about deepcopy being applied and providing a workaround. + +.. + +.. bpo: 19460 +.. date: 2021-11-28-15-25-02 +.. nonce: lr0aWs +.. section: Tests + +Add new Test for :class:`email.mime.nonmultipart.MIMENonMultipart`. + +.. + +.. bpo: 45835 +.. date: 2021-11-17-14-28-08 +.. nonce: Mgyhjx +.. section: Tests + +Fix race condition in test_queue tests with multiple "feeder" threads. + +.. + +.. bpo: 45678 +.. date: 2021-11-04-20-03-32 +.. nonce: 1xNMjN +.. section: Tests + +Add tests for scenarios in which :class:`functools.singledispatchmethod` is +stacked on top of a method that has already been wrapped by two other +decorators. Patch by Alex Waygood. + +.. + +.. bpo: 45578 +.. date: 2021-10-30-19-00-25 +.. nonce: bvu6X2 +.. section: Tests + +Add tests for :func:`dis.distb` + +.. + +.. bpo: 45678 +.. date: 2021-10-30-13-12-20 +.. nonce: bKrYeS +.. section: Tests + +Add tests to ensure that ``functools.singledispatchmethod`` correctly wraps +the attributes of the target function. + +.. + +.. bpo: 45577 +.. date: 2021-10-22-19-44-13 +.. nonce: dSaNvK +.. section: Tests + +Add subtests for all ``pickle`` protocols in ``test_zoneinfo``. + +.. + +.. bpo: 45566 +.. date: 2021-10-22-12-05-21 +.. nonce: 2gQ3ZB +.. section: Tests + +Fix ``test_frozen_pickle`` in ``test_dataclasses`` to check all ``pickle`` +versions. + +.. + +.. bpo: 43592 +.. date: 2021-10-21-17-22-26 +.. nonce: kHRsra +.. section: Tests + +:mod:`test.libregrtest` now raises the soft resource limit for the maximum +number of file descriptors when the default is too low for our test suite as +was often the case on macOS. + +.. + +.. bpo: 39679 +.. date: 2021-10-18-16-18-41 +.. nonce: F18qcE +.. section: Tests + +Add more test cases for `@functools.singledispatchmethod` when combined with +`@classmethod` or `@staticmethod`. + +.. + +.. bpo: 45400 +.. date: 2021-10-07-13-11-45 +.. nonce: h3iT7V +.. section: Tests + +Fix test_name_error_suggestions_do_not_trigger_for_too_many_locals() of +test_exceptions if a directory name contains "a1" (like "Python-3.11.0a1"): +use a stricter regular expression. Patch by Victor Stinner. + +.. + +.. bpo: 40173 +.. date: 2021-09-30-16-54-39 +.. nonce: J_slCw +.. section: Tests + +Fix :func:`test.support.import_helper.import_fresh_module`. + +.. + +.. bpo: 45280 +.. date: 2021-09-25-11-05-31 +.. nonce: 3MA6lC +.. section: Tests + +Add a test case for empty :class:`typing.NamedTuple`. + +.. + +.. bpo: 45269 +.. date: 2021-09-24-10-41-49 +.. nonce: 8jKEr8 +.. section: Tests + +Cover case when invalid ``markers`` type is supplied to ``c_make_encoder``. + +.. + +.. bpo: 45128 +.. date: 2021-09-16-17-22-35 +.. nonce: Jz6fl2 +.. section: Tests + +Fix ``test_multiprocessing_fork`` failure due to ``test_logging`` and +``sys.modules`` manipulation. + +.. + +.. bpo: 45209 +.. date: 2021-09-15-23-32-39 +.. nonce: 55ntL5 +.. section: Tests + +Fix ``UserWarning: resource_tracker`` warning in +``_test_multiprocessing._TestSharedMemory.test_shared_memory_cleaned_after_process_termination`` + +.. + +.. bpo: 45195 +.. date: 2021-09-14-13-16-18 +.. nonce: EyQR1G +.. section: Tests + +Fix test_readline.test_nonascii(): sometimes, the newline character is not +written at the end, so don't expect it in the output. Patch by Victor +Stinner. + +.. + +.. bpo: 45156 +.. date: 2021-09-13-00-28-17 +.. nonce: 8oomV3 +.. section: Tests + +Fixes infinite loop on :func:`unittest.mock.seal` of mocks created by +:func:`~unittest.create_autospec`. + +.. + +.. bpo: 45125 +.. date: 2021-09-11-22-08-18 +.. nonce: FVSzs2 +.. section: Tests + +Improves pickling tests and docs of ``SharedMemory`` and ``SharableList`` +objects. + +.. + +.. bpo: 44860 +.. date: 2021-09-08-13-01-37 +.. nonce: qXd0kx +.. section: Tests + +Update ``test_sysconfig.test_user_similar()`` for the posix_user scheme: +``platlib`` doesn't use :data:`sys.platlibdir`. Patch by Victor Stinner. + +.. + +.. bpo: 25130 +.. date: 2021-08-27-22-37-19 +.. nonce: ig4oJe +.. section: Tests + +Add calls of :func:`gc.collect` in tests to support PyPy. + +.. + +.. bpo: 44035 +.. date: 2021-12-06-09-31-27 +.. nonce: BiO4XC +.. section: Build + +CI now verifies that autoconf files have been regenerated with a current and +unpatched autoconf package. + +.. + +.. bpo: 33393 +.. date: 2021-11-25-20-26-06 +.. nonce: 24YNtM +.. section: Build + +Update ``config.guess`` to 2021-06-03 and ``config.sub`` to 2021-08-14. +``Makefile`` now has an ``update-config`` target to make updating more +convenient. + +.. + +.. bpo: 45866 +.. date: 2021-11-25-13-53-36 +.. nonce: ZH1W8N +.. section: Build + +``make regen-all`` now produces the same output when run from a directory +other than the source tree: when building Python out of the source tree. +pegen now strips directory of the "generated by pygen from " +header Patch by Victor Stinner. + +.. + +.. bpo: 41498 +.. date: 2021-11-25-09-15-04 +.. nonce: qAk5eo +.. section: Build + +Python now compiles on platforms without ``sigset_t``. Several functions in +:mod:`signal` are not available when ``sigset_t`` is missing. + +Based on patch by Roman Yurchak for pyodide. + +.. + +.. bpo: 45881 +.. date: 2021-11-24-17-14-06 +.. nonce: GTXXLk +.. section: Build + +``setup.py`` now uses ``CC`` from environment first to discover multiarch +and cross compile paths. + +.. + +.. bpo: 43158 +.. date: 2021-11-01-12-51-46 +.. nonce: fghS6w +.. section: Build + +``setup.py`` now uses values from configure script to build the ``_uuid`` +extension module. Configure now detects util-linux's ``libuuid``, too. + +.. + +.. bpo: 45571 +.. date: 2021-10-22-15-28-29 +.. nonce: yY8NsJ +.. section: Build + +``Modules/Setup`` now use ``PY_CFLAGS_NODIST`` instead of ``PY_CFLAGS`` to +compile shared modules. + +.. + +.. bpo: 45561 +.. date: 2021-10-21-14-38-30 +.. nonce: PVqhZE +.. section: Build + +Run smelly.py tool from $(srcdir). + +.. + +.. bpo: 45532 +.. date: 2021-10-20-16-07-39 +.. nonce: kyhvis +.. section: Build + +Update :data:`sys.version` to use ``main`` as fallback information. Patch by +Jeong YunWon. + +.. + +.. bpo: 45536 +.. date: 2021-10-20-12-42-39 +.. nonce: oQNYHB +.. section: Build + +The ``configure`` script now checks whether OpenSSL headers and libraries +provide required APIs. Most common APIs are verified. The check detects +outdated or missing OpenSSL. Failures do not stop configure. + +.. + +.. bpo: 45221 +.. date: 2021-10-18-10-25-56 +.. nonce: rnulhf +.. section: Build + +Fixed regression in handling of ``LDFLAGS`` and ``CPPFLAGS`` options where +:meth:`argparse.parse_known_args` could interpret an option as one of the +built-in command line argument, for example ``-h`` for help. + +.. + +.. bpo: 45405 +.. date: 2021-10-11-16-27-38 +.. nonce: iSfdW5 +.. section: Build + +Prevent ``internal configure error`` when running ``configure`` with recent +versions of non-Apple clang. Patch by David Bohman. + +.. + +.. bpo: 45220 +.. date: 2021-09-16-18-00-43 +.. nonce: TgbkvW +.. section: Build + +Avoid building with the Windows 11 SDK previews automatically. This may be +overridden by setting the ``DefaultWindowsSDKVersion`` environment variable +before building. + +.. + +.. bpo: 45067 +.. date: 2021-09-09-16-45-26 +.. nonce: mFmY92 +.. section: Build + +The ncurses function extended_color_content was introduced in 2017 + +(https://invisible-island.net/ncurses/NEWS.html#index-t20170401). The + +ncurses-devel package in CentOS 7 had a older version ncurses resulted in +compilation error. For compiling ncurses with extended color support, we +verify the version of the ncurses library >= 20170401. + +.. + +.. bpo: 45901 +.. date: 2021-11-26-18-17-41 +.. nonce: c5IBqM +.. section: Windows + +When installed through the Microsoft Store and set as the default app for +:file:`*.py` files, command line arguments will now be passed to Python when +invoking a script without explicitly launching Python (that is, ``script.py +args`` rather than ``python script.py args``). + +.. + +.. bpo: 45616 +.. date: 2021-11-23-11-44-42 +.. nonce: K52PLZ +.. section: Windows + +Fix Python Launcher's ability to distinguish between versions 3.1 and 3.10 +when either one is explicitly requested. Previously, 3.1 would be used if +3.10 was requested but not installed, and 3.10 would be used if 3.1 was +requested but 3.10 was installed. + +.. + +.. bpo: 45732 +.. date: 2021-11-08-21-53-11 +.. nonce: idl5kx +.. section: Windows + +Updates bundled Tcl/Tk to 8.6.12. + +.. + +.. bpo: 45720 +.. date: 2021-11-05-01-05-46 +.. nonce: 47Nc5I +.. section: Windows + +Internal reference to :file:`shlwapi.dll` was dropped to help improve +startup time. This DLL will no longer be loaded at the start of every Python +process. + +.. + +.. bpo: 43652 +.. date: 2021-11-04-00-41-50 +.. nonce: RnqV7I +.. section: Windows + +Update Tcl/Tk to 8.6.11, actually this time. The previous update incorrectly +included 8.6.10. + +.. + +.. bpo: 45337 +.. date: 2021-09-30-23-17-27 +.. nonce: qg7U_h +.. section: Windows + +venv now warns when the created environment may need to be accessed at a +different path, due to redirections, links or junctions. It also now +correctly installs or upgrades components when the alternate path is +required. + +.. + +.. bpo: 45732 +.. date: 2021-12-05-23-52-03 +.. nonce: -BWrnh +.. section: macOS + +Update python.org macOS installer to use Tcl/Tk 8.6.12. + +.. + +.. bpo: 44828 +.. date: 2021-10-25-02-02-21 +.. nonce: XBdXlJ +.. section: macOS + +Avoid tkinter file dialog failure on macOS 12 Monterey when using the Tk +8.6.11 provided by python.org macOS installers. Patch by Marc Culler of the +Tk project. + +.. + +.. bpo: 34602 +.. date: 2021-08-27-16-55-10 +.. nonce: ZjHsYJ +.. section: macOS + +When building CPython on macOS with ``./configure +--with-undefined-behavior-sanitizer --with-pydebug``, the stack size is now +quadrupled to allow for the entire test suite to pass. + +.. + +.. bpo: 45495 +.. date: 2021-10-16-17-20-32 +.. nonce: ST8RFt +.. section: IDLE + +Add context keywords 'case' and 'match' to completions list. + +.. + +.. bpo: 45296 +.. date: 2021-09-27-01-21-59 +.. nonce: 9H8rdY +.. section: IDLE + +On Windows, change exit/quit message to suggest Ctrl-D, which works, instead +of , which does not work in IDLE. + +.. + +.. bpo: 45193 +.. date: 2021-09-15-03-20-06 +.. nonce: G61_GV +.. section: IDLE + +Make completion boxes appear on Ubuntu again. + +.. + +.. bpo: 44786 +.. date: 2021-09-14-11-44-26 +.. nonce: DU0LC0 +.. section: Tools/Demos + +Fix a warning in regular expression in the c-analyzer script. + +.. + +.. bpo: 39026 +.. date: 2021-11-09-15-42-11 +.. nonce: sUnYWn +.. section: C API + +Fix Python.h to build C extensions with Xcode: remove a relative include +from ``Include/cpython/pystate.h``. + +.. + +.. bpo: 45307 +.. date: 2021-09-28-12-00-55 +.. nonce: 3ETFfX +.. section: C API + +Restore the private C API function :func:`_PyImport_FindExtensionObject`. It +will be removed in Python 3.11. + +.. + +.. bpo: 44687 +.. date: 2021-09-19-17-18-25 +.. nonce: 3fqDRC +.. section: C API + +:meth:`BufferedReader.peek` no longer raises :exc:`ValueError` when the +entire file has already been buffered. + +.. + +.. bpo: 44751 +.. date: 2021-07-27-17-29-12 +.. nonce: 4qmbDG +.. section: C API + +Remove ``crypt.h`` include from the public ``Python.h`` header. diff --git a/Misc/NEWS.d/next/Build/2021-09-09-16-45-26.bpo-45067.mFmY92.rst b/Misc/NEWS.d/next/Build/2021-09-09-16-45-26.bpo-45067.mFmY92.rst deleted file mode 100644 index a89736eb33e82..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-09-09-16-45-26.bpo-45067.mFmY92.rst +++ /dev/null @@ -1,7 +0,0 @@ -The ncurses function extended_color_content was introduced in 2017 - -(https://invisible-island.net/ncurses/NEWS.html#index-t20170401). The - -ncurses-devel package in CentOS 7 had a older version ncurses resulted in -compilation error. For compiling ncurses with extended color support, we -verify the version of the ncurses library >= 20170401. diff --git a/Misc/NEWS.d/next/Build/2021-09-16-18-00-43.bpo-45220.TgbkvW.rst b/Misc/NEWS.d/next/Build/2021-09-16-18-00-43.bpo-45220.TgbkvW.rst deleted file mode 100644 index 8bbd634fa61a3..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-09-16-18-00-43.bpo-45220.TgbkvW.rst +++ /dev/null @@ -1,3 +0,0 @@ -Avoid building with the Windows 11 SDK previews automatically. This may be -overridden by setting the ``DefaultWindowsSDKVersion`` environment variable -before building. diff --git a/Misc/NEWS.d/next/Build/2021-10-11-16-27-38.bpo-45405.iSfdW5.rst b/Misc/NEWS.d/next/Build/2021-10-11-16-27-38.bpo-45405.iSfdW5.rst deleted file mode 100644 index a2dc5bcc32217..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-10-11-16-27-38.bpo-45405.iSfdW5.rst +++ /dev/null @@ -1,2 +0,0 @@ -Prevent ``internal configure error`` when running ``configure`` -with recent versions of non-Apple clang. Patch by David Bohman. diff --git a/Misc/NEWS.d/next/Build/2021-10-18-10-25-56.bpo-45221.rnulhf.rst b/Misc/NEWS.d/next/Build/2021-10-18-10-25-56.bpo-45221.rnulhf.rst deleted file mode 100644 index cb981d96f3047..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-10-18-10-25-56.bpo-45221.rnulhf.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fixed regression in handling of ``LDFLAGS`` and ``CPPFLAGS`` options -where :meth:`argparse.parse_known_args` could interpret an option as -one of the built-in command line argument, for example ``-h`` for help. diff --git a/Misc/NEWS.d/next/Build/2021-10-20-12-42-39.bpo-45536.oQNYHB.rst b/Misc/NEWS.d/next/Build/2021-10-20-12-42-39.bpo-45536.oQNYHB.rst deleted file mode 100644 index e560b71ede2d2..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-10-20-12-42-39.bpo-45536.oQNYHB.rst +++ /dev/null @@ -1,3 +0,0 @@ -The ``configure`` script now checks whether OpenSSL headers and libraries -provide required APIs. Most common APIs are verified. The check detects -outdated or missing OpenSSL. Failures do not stop configure. diff --git a/Misc/NEWS.d/next/Build/2021-10-20-16-07-39.bpo-45532.kyhvis.rst b/Misc/NEWS.d/next/Build/2021-10-20-16-07-39.bpo-45532.kyhvis.rst deleted file mode 100644 index 575e2fb9ae93b..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-10-20-16-07-39.bpo-45532.kyhvis.rst +++ /dev/null @@ -1,2 +0,0 @@ -Update :data:`sys.version` to use ``main`` as fallback information. -Patch by Jeong YunWon. diff --git a/Misc/NEWS.d/next/Build/2021-10-21-14-38-30.bpo-45561.PVqhZE.rst b/Misc/NEWS.d/next/Build/2021-10-21-14-38-30.bpo-45561.PVqhZE.rst deleted file mode 100644 index cf5d8686b9840..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-10-21-14-38-30.bpo-45561.PVqhZE.rst +++ /dev/null @@ -1 +0,0 @@ -Run smelly.py tool from $(srcdir). diff --git a/Misc/NEWS.d/next/Build/2021-10-22-15-28-29.bpo-45571.yY8NsJ.rst b/Misc/NEWS.d/next/Build/2021-10-22-15-28-29.bpo-45571.yY8NsJ.rst deleted file mode 100644 index f2042d11e24b7..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-10-22-15-28-29.bpo-45571.yY8NsJ.rst +++ /dev/null @@ -1,2 +0,0 @@ -``Modules/Setup`` now use ``PY_CFLAGS_NODIST`` instead of ``PY_CFLAGS`` to -compile shared modules. diff --git a/Misc/NEWS.d/next/Build/2021-11-01-12-51-46.bpo-43158.fghS6w.rst b/Misc/NEWS.d/next/Build/2021-11-01-12-51-46.bpo-43158.fghS6w.rst deleted file mode 100644 index 3b1de478e7fd4..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-11-01-12-51-46.bpo-43158.fghS6w.rst +++ /dev/null @@ -1,2 +0,0 @@ -``setup.py`` now uses values from configure script to build the ``_uuid`` -extension module. Configure now detects util-linux's ``libuuid``, too. diff --git a/Misc/NEWS.d/next/Build/2021-11-24-17-14-06.bpo-45881.GTXXLk.rst b/Misc/NEWS.d/next/Build/2021-11-24-17-14-06.bpo-45881.GTXXLk.rst deleted file mode 100644 index b697658cf3aaa..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-11-24-17-14-06.bpo-45881.GTXXLk.rst +++ /dev/null @@ -1,2 +0,0 @@ -``setup.py`` now uses ``CC`` from environment first to discover multiarch -and cross compile paths. diff --git a/Misc/NEWS.d/next/Build/2021-11-25-09-15-04.bpo-41498.qAk5eo.rst b/Misc/NEWS.d/next/Build/2021-11-25-09-15-04.bpo-41498.qAk5eo.rst deleted file mode 100644 index 18dc290dafd02..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-11-25-09-15-04.bpo-41498.qAk5eo.rst +++ /dev/null @@ -1,4 +0,0 @@ -Python now compiles on platforms without ``sigset_t``. Several functions -in :mod:`signal` are not available when ``sigset_t`` is missing. - -Based on patch by Roman Yurchak for pyodide. diff --git a/Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst b/Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst deleted file mode 100644 index e87b93932ffa1..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst +++ /dev/null @@ -1,4 +0,0 @@ -``make regen-all`` now produces the same output when run from a directory -other than the source tree: when building Python out of the source tree. -pegen now strips directory of the "generated by pygen from " header -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Build/2021-11-25-20-26-06.bpo-33393.24YNtM.rst b/Misc/NEWS.d/next/Build/2021-11-25-20-26-06.bpo-33393.24YNtM.rst deleted file mode 100644 index c27869c9b6ded..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-11-25-20-26-06.bpo-33393.24YNtM.rst +++ /dev/null @@ -1,3 +0,0 @@ -Update ``config.guess`` to 2021-06-03 and ``config.sub`` to 2021-08-14. -``Makefile`` now has an ``update-config`` target to make updating more -convenient. diff --git a/Misc/NEWS.d/next/Build/2021-12-06-09-31-27.bpo-44035.BiO4XC.rst b/Misc/NEWS.d/next/Build/2021-12-06-09-31-27.bpo-44035.BiO4XC.rst deleted file mode 100644 index 7530587b73d14..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-12-06-09-31-27.bpo-44035.BiO4XC.rst +++ /dev/null @@ -1,2 +0,0 @@ -CI now verifies that autoconf files have been regenerated with a current and -unpatched autoconf package. diff --git a/Misc/NEWS.d/next/C API/2021-07-27-17-29-12.bpo-44751.4qmbDG.rst b/Misc/NEWS.d/next/C API/2021-07-27-17-29-12.bpo-44751.4qmbDG.rst deleted file mode 100644 index d7b9f09819669..0000000000000 --- a/Misc/NEWS.d/next/C API/2021-07-27-17-29-12.bpo-44751.4qmbDG.rst +++ /dev/null @@ -1 +0,0 @@ -Remove ``crypt.h`` include from the public ``Python.h`` header. diff --git a/Misc/NEWS.d/next/C API/2021-09-19-17-18-25.bpo-44687.3fqDRC.rst b/Misc/NEWS.d/next/C API/2021-09-19-17-18-25.bpo-44687.3fqDRC.rst deleted file mode 100644 index d38fa6057f6f9..0000000000000 --- a/Misc/NEWS.d/next/C API/2021-09-19-17-18-25.bpo-44687.3fqDRC.rst +++ /dev/null @@ -1 +0,0 @@ -:meth:`BufferedReader.peek` no longer raises :exc:`ValueError` when the entire file has already been buffered. diff --git a/Misc/NEWS.d/next/C API/2021-09-28-12-00-55.bpo-45307.3ETFfX.rst b/Misc/NEWS.d/next/C API/2021-09-28-12-00-55.bpo-45307.3ETFfX.rst deleted file mode 100644 index aa2bd7af54d26..0000000000000 --- a/Misc/NEWS.d/next/C API/2021-09-28-12-00-55.bpo-45307.3ETFfX.rst +++ /dev/null @@ -1,2 +0,0 @@ -Restore the private C API function :func:`_PyImport_FindExtensionObject`. It -will be removed in Python 3.11. diff --git a/Misc/NEWS.d/next/C API/2021-11-09-15-42-11.bpo-39026.sUnYWn.rst b/Misc/NEWS.d/next/C API/2021-11-09-15-42-11.bpo-39026.sUnYWn.rst deleted file mode 100644 index 77a0119792152..0000000000000 --- a/Misc/NEWS.d/next/C API/2021-11-09-15-42-11.bpo-39026.sUnYWn.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix Python.h to build C extensions with Xcode: remove a relative include -from ``Include/cpython/pystate.h``. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-09-01-16-55-43.bpo-45056.7AK2d9.rst b/Misc/NEWS.d/next/Core and Builtins/2021-09-01-16-55-43.bpo-45056.7AK2d9.rst deleted file mode 100644 index 6c790f5c50c48..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-09-01-16-55-43.bpo-45056.7AK2d9.rst +++ /dev/null @@ -1 +0,0 @@ -Compiler now removes trailing unused constants from co_consts. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-09-01-23-55-49.bpo-45083.cLi9G3.rst b/Misc/NEWS.d/next/Core and Builtins/2021-09-01-23-55-49.bpo-45083.cLi9G3.rst deleted file mode 100644 index 7bfd87b942059..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-09-01-23-55-49.bpo-45083.cLi9G3.rst +++ /dev/null @@ -1,3 +0,0 @@ -When the interpreter renders an exception, its name now has a complete qualname. Previously only the class name was concatenated to the module name, which sometimes resulted in an incorrect full name being displayed. - -(This issue impacted only the C code exception rendering, the :mod:`traceback` module was using qualname already). \ No newline at end of file diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst b/Misc/NEWS.d/next/Core and Builtins/2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst deleted file mode 100644 index 19eb331412516..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix issue where ``Protocol.__init__`` raises ``RecursionError`` when it's -called directly or via ``super()``. Patch provided by Yurii Karabas. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-09-08-00-30-09.bpo-44050.mFI15u.rst b/Misc/NEWS.d/next/Core and Builtins/2021-09-08-00-30-09.bpo-44050.mFI15u.rst deleted file mode 100644 index d6eed9f1bcfe9..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-09-08-00-30-09.bpo-44050.mFI15u.rst +++ /dev/null @@ -1,3 +0,0 @@ -Extensions that indicate they use global state (by setting ``m_size`` to -1) -can again be used in multiple interpreters. This reverts to behavior of -Python 3.8. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-09-08-08-29-41.bpo-44959.OSwwPf.rst b/Misc/NEWS.d/next/Core and Builtins/2021-09-08-08-29-41.bpo-44959.OSwwPf.rst deleted file mode 100644 index 02e11ae94e430..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-09-08-08-29-41.bpo-44959.OSwwPf.rst +++ /dev/null @@ -1 +0,0 @@ -Added fallback to extension modules with '.sl' suffix on HP-UX \ No newline at end of file diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-09-09-10-32-33.bpo-44219.WiYyjz.rst b/Misc/NEWS.d/next/Core and Builtins/2021-09-09-10-32-33.bpo-44219.WiYyjz.rst deleted file mode 100644 index 2abd81673663b..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-09-09-10-32-33.bpo-44219.WiYyjz.rst +++ /dev/null @@ -1,5 +0,0 @@ -Release the GIL while performing ``isatty`` system calls on arbitrary file -descriptors. In particular, this affects :func:`os.isatty`, -:func:`os.device_encoding` and :class:`io.TextIOWrapper`. By extension, -:func:`io.open` in text mode is also affected. This change solves -a deadlock in :func:`os.isatty`. Patch by Vincent Michel in :issue:`44219`. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-09-14-09-23-59.bpo-45167.CPSSoV.rst b/Misc/NEWS.d/next/Core and Builtins/2021-09-14-09-23-59.bpo-45167.CPSSoV.rst deleted file mode 100644 index 47755ae59be2b..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-09-14-09-23-59.bpo-45167.CPSSoV.rst +++ /dev/null @@ -1 +0,0 @@ -Fix deepcopying of :class:`types.GenericAlias` objects. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-06-21-20-11.bpo-45385.CTUT8s.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-06-21-20-11.bpo-45385.CTUT8s.rst deleted file mode 100644 index 8047c102634f0..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-10-06-21-20-11.bpo-45385.CTUT8s.rst +++ /dev/null @@ -1 +0,0 @@ -Fix reference leak from descr_check. Patch by Dong-hee Na. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-07-21-26-44.bpo-45408.qUqzcd.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-07-21-26-44.bpo-45408.qUqzcd.rst deleted file mode 100644 index e4d4db9cb9536..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-10-07-21-26-44.bpo-45408.qUqzcd.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix a crash in the parser when reporting tokenizer errors that occur at the -same time unclosed parentheses are detected. Patch by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-16-17-27-48.bpo-45494.vMt1g4.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-16-17-27-48.bpo-45494.vMt1g4.rst deleted file mode 100644 index 97e29813ab266..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-10-16-17-27-48.bpo-45494.vMt1g4.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix parser crash when reporting errors involving invalid continuation -characters. Patch by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-18-22-40-33.bpo-45521.GdMiuW.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-18-22-40-33.bpo-45521.GdMiuW.rst deleted file mode 100644 index 3a082a4ffdbcb..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-10-18-22-40-33.bpo-45521.GdMiuW.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix a bug in the obmalloc radix tree code. On 64-bit machines, the bug -causes the tree to hold 46-bits of virtual addresses, rather than the -intended 48-bits. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-19-01-04-08.bpo-30570._G30Ms.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-19-01-04-08.bpo-30570._G30Ms.rst deleted file mode 100644 index d9ab60cd08f56..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-10-19-01-04-08.bpo-30570._G30Ms.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed a crash in ``issubclass()`` from infinite recursion when searching pathological ``__bases__`` tuples. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-02-09-27-46.bpo-45688.v5Der1.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-02-09-27-46.bpo-45688.v5Der1.rst deleted file mode 100644 index afd73a1266279..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-11-02-09-27-46.bpo-45688.v5Der1.rst +++ /dev/null @@ -1,2 +0,0 @@ -:data:`sys.stdlib_module_names` now contains the macOS-specific module -:mod:`_scproxy`. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-04-20-19-07.bpo-45716.5C0pA1.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-04-20-19-07.bpo-45716.5C0pA1.rst deleted file mode 100644 index 682900c295416..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-11-04-20-19-07.bpo-45716.5C0pA1.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve the :exc:`SyntaxError` message when using ``True``, ``None`` or -``False`` as keywords in a function call. Patch by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-09-13-01-35.bpo-45773.POU8A4.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-09-13-01-35.bpo-45773.POU8A4.rst deleted file mode 100644 index 2b9ba81be233f..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-11-09-13-01-35.bpo-45773.POU8A4.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a compiler hang when attempting to optimize certain jump patterns. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-14-00-14-45.bpo-45738.e0cgKd.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-14-00-14-45.bpo-45738.e0cgKd.rst deleted file mode 100644 index b238034323c77..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-11-14-00-14-45.bpo-45738.e0cgKd.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix computation of error location for invalid continuation characters in the -parser. Patch by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-15-12-08-27.bpo-42540.V2w107.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-15-12-08-27.bpo-42540.V2w107.rst deleted file mode 100644 index 91160598bd3f4..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-11-15-12-08-27.bpo-42540.V2w107.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix crash when :func:`os.fork` is called with an active non-default -memory allocator. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-00-27.bpo-45820.2X6Psr.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-00-27.bpo-45820.2X6Psr.rst deleted file mode 100644 index c2ec3d690cd4b..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-00-27.bpo-45820.2X6Psr.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix a segfault when the parser fails without reading any input. Patch by -Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-41-04.bpo-45822.OT6ueS.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-41-04.bpo-45822.OT6ueS.rst deleted file mode 100644 index 1ac7a8becee40..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-41-04.bpo-45822.OT6ueS.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed a bug in the parser that was causing it to not respect :pep:`263` -coding cookies when no flags are provided. Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-17-08-05-27.bpo-45826.OERoTm.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-17-08-05-27.bpo-45826.OERoTm.rst deleted file mode 100644 index f04373bf2fc59..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-11-17-08-05-27.bpo-45826.OERoTm.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed a crash when calling ``.with_traceback(None)`` on ``NameError``. This occurs internally in ``unittest.TestCase.assertRaises()``. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-19-22-57-42.bpo-45848.HgVBJ5.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-19-22-57-42.bpo-45848.HgVBJ5.rst deleted file mode 100644 index d9394c9c1f08b..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-11-19-22-57-42.bpo-45848.HgVBJ5.rst +++ /dev/null @@ -1,2 +0,0 @@ -Allow the parser to obtain error lines directly from encoded files. Patch by -Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-23-12-06-41.bpo-45614.fIekgI.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-23-12-06-41.bpo-45614.fIekgI.rst deleted file mode 100644 index 4255e1885ad67..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-11-23-12-06-41.bpo-45614.fIekgI.rst +++ /dev/null @@ -1 +0,0 @@ -Fix :mod:`traceback` display for exceptions with invalid module name. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-24-18-24-49.bpo-45727._xVbbo.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-24-18-24-49.bpo-45727._xVbbo.rst deleted file mode 100644 index d4b149ddccf5d..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-11-24-18-24-49.bpo-45727._xVbbo.rst +++ /dev/null @@ -1,3 +0,0 @@ -Refine the custom syntax error that suggests that a comma may be missing to -trigger only when the expressions are detected between parentheses or -brackets. Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-26-22-31-22.bpo-42268.3wl-09.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-26-22-31-22.bpo-42268.3wl-09.rst deleted file mode 100644 index 615bbb22ae2eb..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-11-26-22-31-22.bpo-42268.3wl-09.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fail the configure step if the selected compiler doesn't support memory -sanitizer. Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Documentation/2021-05-24-05-00-12.bpo-43905.tBIndE.rst b/Misc/NEWS.d/next/Documentation/2021-05-24-05-00-12.bpo-43905.tBIndE.rst deleted file mode 100644 index 760e1eea0deb7..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-05-24-05-00-12.bpo-43905.tBIndE.rst +++ /dev/null @@ -1,2 +0,0 @@ -Expanded :func:`~dataclasses.astuple` and :func:`~dataclasses.asdict` docs, -warning about deepcopy being applied and providing a workaround. diff --git a/Misc/NEWS.d/next/Documentation/2021-06-21-17-51-51.bpo-25381.7Kn-_H.rst b/Misc/NEWS.d/next/Documentation/2021-06-21-17-51-51.bpo-25381.7Kn-_H.rst deleted file mode 100644 index f009f880e917d..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-06-21-17-51-51.bpo-25381.7Kn-_H.rst +++ /dev/null @@ -1,2 +0,0 @@ -In the extending chapter of the extending doc, update a paragraph about the -global variables containing exception information. diff --git a/Misc/NEWS.d/next/Documentation/2021-09-08-17-20-19.bpo-45024.dkNPNi.rst b/Misc/NEWS.d/next/Documentation/2021-09-08-17-20-19.bpo-45024.dkNPNi.rst deleted file mode 100644 index e73d52b8cc514..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-09-08-17-20-19.bpo-45024.dkNPNi.rst +++ /dev/null @@ -1,4 +0,0 @@ -:mod:`collections.abc` documentation has been expanded to explicitly cover -how instance and subclass checks work, with additional doctest examples and -an exhaustive list of ABCs which test membership purely by presence of the -right :term:`special method`\s. Patch by Raymond Hettinger. diff --git a/Misc/NEWS.d/next/Documentation/2021-09-18-13-45-19.bpo-45216.o56nyt.rst b/Misc/NEWS.d/next/Documentation/2021-09-18-13-45-19.bpo-45216.o56nyt.rst deleted file mode 100644 index d10b18ecdb8fd..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-09-18-13-45-19.bpo-45216.o56nyt.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove extra documentation listing methods in ``difflib``. It was rendering -twice in pydoc and was outdated in some places. diff --git a/Misc/NEWS.d/next/Documentation/2021-10-13-00-42-54.bpo-20692.K5rGtP.rst b/Misc/NEWS.d/next/Documentation/2021-10-13-00-42-54.bpo-20692.K5rGtP.rst deleted file mode 100644 index 44ae468d1bccf..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-10-13-00-42-54.bpo-20692.K5rGtP.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add Programming FAQ entry explaining that int literal attribute access -requires either a space after or parentheses around the literal. diff --git a/Misc/NEWS.d/next/Documentation/2021-10-18-20-12-18.bpo-45516.EJh4K8.rst b/Misc/NEWS.d/next/Documentation/2021-10-18-20-12-18.bpo-45516.EJh4K8.rst deleted file mode 100644 index 98f5d3432db05..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-10-18-20-12-18.bpo-45516.EJh4K8.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add protocol description to the :class:`importlib.abc.Traversable` -documentation. diff --git a/Misc/NEWS.d/next/Documentation/2021-10-19-01-41-40.bpo-45449.fjHZJc.rst b/Misc/NEWS.d/next/Documentation/2021-10-19-01-41-40.bpo-45449.fjHZJc.rst deleted file mode 100644 index fb817757a1487..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-10-19-01-41-40.bpo-45449.fjHZJc.rst +++ /dev/null @@ -1 +0,0 @@ -Add note about :pep:`585` in :mod:`collections.abc`. diff --git a/Misc/NEWS.d/next/Documentation/2021-10-20-16-26-53.bpo-45464.mOISBs.rst b/Misc/NEWS.d/next/Documentation/2021-10-20-16-26-53.bpo-45464.mOISBs.rst deleted file mode 100644 index 1721aa2c2dfc4..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-10-20-16-26-53.bpo-45464.mOISBs.rst +++ /dev/null @@ -1,4 +0,0 @@ -Mention in the documentation of :ref:`Built-in Exceptions -` that inheriting from multiple exception types in a -single subclass is not recommended due to possible memory layout -incompatibility. diff --git a/Misc/NEWS.d/next/Documentation/2021-10-22-12-09-18.bpo-45250.Iit5-Y.rst b/Misc/NEWS.d/next/Documentation/2021-10-22-12-09-18.bpo-45250.Iit5-Y.rst deleted file mode 100644 index 0c2bf18b20010..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-10-22-12-09-18.bpo-45250.Iit5-Y.rst +++ /dev/null @@ -1,2 +0,0 @@ -Update the documentation to note that CPython does not consistently -require iterators to define ``__iter__``. diff --git a/Misc/NEWS.d/next/Documentation/2021-10-26-10-00-45.bpo-45604.Dm-YhV.rst b/Misc/NEWS.d/next/Documentation/2021-10-26-10-00-45.bpo-45604.Dm-YhV.rst deleted file mode 100644 index 9da9cca7bf1ea..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-10-26-10-00-45.bpo-45604.Dm-YhV.rst +++ /dev/null @@ -1 +0,0 @@ -Add ``level`` argument to ``multiprocessing.log_to_stderr`` function docs. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Documentation/2021-10-28-19-22-55.bpo-45655.aPYGaS.rst b/Misc/NEWS.d/next/Documentation/2021-10-28-19-22-55.bpo-45655.aPYGaS.rst deleted file mode 100644 index fc5b3d0788817..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-10-28-19-22-55.bpo-45655.aPYGaS.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add a new "relevant PEPs" section to the top of the documentation for the -``typing`` module. Patch by Alex Waygood. diff --git a/Misc/NEWS.d/next/Documentation/2021-11-03-14-51-03.bpo-45680.9_NTFU.rst b/Misc/NEWS.d/next/Documentation/2021-11-03-14-51-03.bpo-45680.9_NTFU.rst deleted file mode 100644 index 79ea6e308e54a..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-11-03-14-51-03.bpo-45680.9_NTFU.rst +++ /dev/null @@ -1,3 +0,0 @@ -Amend the docs on ``GenericAlias`` objects to clarify that non-container -classes can also implement ``__class_getitem__``. Patch contributed by Alex -Waygood. diff --git a/Misc/NEWS.d/next/Documentation/2021-11-05-12-15-24.bpo-45726.GwRr7e.rst b/Misc/NEWS.d/next/Documentation/2021-11-05-12-15-24.bpo-45726.GwRr7e.rst deleted file mode 100644 index 7ff6283a2a34d..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-11-05-12-15-24.bpo-45726.GwRr7e.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve documentation for :func:`functools.singledispatch` and -:class:`functools.singledispatchmethod`. diff --git a/Misc/NEWS.d/next/Documentation/2021-11-06-10-54-17.bpo-45392.JZnVOz.rst b/Misc/NEWS.d/next/Documentation/2021-11-06-10-54-17.bpo-45392.JZnVOz.rst deleted file mode 100644 index 09c16578ff478..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-11-06-10-54-17.bpo-45392.JZnVOz.rst +++ /dev/null @@ -1,2 +0,0 @@ -Update the docstring of the :class:`type` built-in to remove a redundant -line and to mention keyword arguments for the constructor. diff --git a/Misc/NEWS.d/next/Documentation/2021-11-09-13-10-55.bpo-45772.EdrM3t.rst b/Misc/NEWS.d/next/Documentation/2021-11-09-13-10-55.bpo-45772.EdrM3t.rst deleted file mode 100644 index 47679521df30b..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-11-09-13-10-55.bpo-45772.EdrM3t.rst +++ /dev/null @@ -1 +0,0 @@ -``socket.socket`` documentation is corrected to a class from a function. diff --git a/Misc/NEWS.d/next/Documentation/2021-11-18-00-07-40.bpo-45788.qibUoB.rst b/Misc/NEWS.d/next/Documentation/2021-11-18-00-07-40.bpo-45788.qibUoB.rst deleted file mode 100644 index 8aa3293673e1f..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-11-18-00-07-40.bpo-45788.qibUoB.rst +++ /dev/null @@ -1 +0,0 @@ -Link doc for sys.prefix to sysconfig doc on installation paths. diff --git a/Misc/NEWS.d/next/Documentation/2021-11-18-16-44-12.bpo-45640.lSpc2A.rst b/Misc/NEWS.d/next/Documentation/2021-11-18-16-44-12.bpo-45640.lSpc2A.rst deleted file mode 100644 index 532288df7c76e..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-11-18-16-44-12.bpo-45640.lSpc2A.rst +++ /dev/null @@ -1,3 +0,0 @@ -Properly marked-up grammar tokens in the documentation are now clickable and -take you to the definition of a given piece of grammar. Patch by Arthur -Milchior. diff --git a/Misc/NEWS.d/next/IDLE/2021-09-15-03-20-06.bpo-45193.G61_GV.rst b/Misc/NEWS.d/next/IDLE/2021-09-15-03-20-06.bpo-45193.G61_GV.rst deleted file mode 100644 index 94729640c71eb..0000000000000 --- a/Misc/NEWS.d/next/IDLE/2021-09-15-03-20-06.bpo-45193.G61_GV.rst +++ /dev/null @@ -1 +0,0 @@ -Make completion boxes appear on Ubuntu again. diff --git a/Misc/NEWS.d/next/IDLE/2021-09-27-01-21-59.bpo-45296.9H8rdY.rst b/Misc/NEWS.d/next/IDLE/2021-09-27-01-21-59.bpo-45296.9H8rdY.rst deleted file mode 100644 index 52bade1e5327b..0000000000000 --- a/Misc/NEWS.d/next/IDLE/2021-09-27-01-21-59.bpo-45296.9H8rdY.rst +++ /dev/null @@ -1,2 +0,0 @@ -On Windows, change exit/quit message to suggest Ctrl-D, which works, instead -of , which does not work in IDLE. diff --git a/Misc/NEWS.d/next/IDLE/2021-10-16-17-20-32.bpo-45495.ST8RFt.rst b/Misc/NEWS.d/next/IDLE/2021-10-16-17-20-32.bpo-45495.ST8RFt.rst deleted file mode 100644 index 3868f8d136a04..0000000000000 --- a/Misc/NEWS.d/next/IDLE/2021-10-16-17-20-32.bpo-45495.ST8RFt.rst +++ /dev/null @@ -1 +0,0 @@ -Add context keywords 'case' and 'match' to completions list. diff --git a/Misc/NEWS.d/next/Library/2021-04-20-14-14-16.bpo-43498.L_Hq-8.rst b/Misc/NEWS.d/next/Library/2021-04-20-14-14-16.bpo-43498.L_Hq-8.rst deleted file mode 100644 index 4713d1427ccd3..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-20-14-14-16.bpo-43498.L_Hq-8.rst +++ /dev/null @@ -1,2 +0,0 @@ -Avoid a possible *"RuntimeError: dictionary changed size during iteration"* -when adjusting the process count of :class:`ProcessPoolExecutor`. diff --git a/Misc/NEWS.d/next/Library/2021-06-02-16-39-42.bpo-44295.erg01m.rst b/Misc/NEWS.d/next/Library/2021-06-02-16-39-42.bpo-44295.erg01m.rst deleted file mode 100644 index 86501c15d86f4..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-06-02-16-39-42.bpo-44295.erg01m.rst +++ /dev/null @@ -1,2 +0,0 @@ -Ensure deprecation warning from :func:`assertDictContainsSubset` points at -calling code - by Anthony Sottile. diff --git a/Misc/NEWS.d/next/Library/2021-07-12-10-32-48.bpo-44594.eEa5zi.rst b/Misc/NEWS.d/next/Library/2021-07-12-10-32-48.bpo-44594.eEa5zi.rst deleted file mode 100644 index a2bfd8ff5b51b..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-07-12-10-32-48.bpo-44594.eEa5zi.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix an edge case of :class:`ExitStack` and :class:`AsyncExitStack` exception -chaining. They will now match ``with`` block behavior when ``__context__`` is -explicitly set to ``None`` when the exception is in flight. diff --git a/Misc/NEWS.d/next/Library/2021-08-18-10-36-14.bpo-39039.A63LYh.rst b/Misc/NEWS.d/next/Library/2021-08-18-10-36-14.bpo-39039.A63LYh.rst deleted file mode 100644 index 7250055c2a4a9..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-08-18-10-36-14.bpo-39039.A63LYh.rst +++ /dev/null @@ -1,2 +0,0 @@ -tarfile.open raises :exc:`~tarfile.ReadError` when a zlib error occurs -during file extraction. diff --git a/Misc/NEWS.d/next/Library/2021-08-28-13-00-12.bpo-45021.rReeaj.rst b/Misc/NEWS.d/next/Library/2021-08-28-13-00-12.bpo-45021.rReeaj.rst deleted file mode 100644 index 54fd9109a9ae5..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-08-28-13-00-12.bpo-45021.rReeaj.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a potential deadlock at shutdown of forked children when using :mod:`concurrent.futures` module \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2021-08-30-00-19-23.bpo-24444.Ki4bgz.rst b/Misc/NEWS.d/next/Library/2021-08-30-00-19-23.bpo-24444.Ki4bgz.rst deleted file mode 100644 index efcacb8f0eb59..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-08-30-00-19-23.bpo-24444.Ki4bgz.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed an error raised in :mod:`argparse` help display when help for an -option is set to 1+ blank spaces or when *choices* arg is an empty container. diff --git a/Misc/NEWS.d/next/Library/2021-09-08-01-19-31.bpo-20499.tSxx8Y.rst b/Misc/NEWS.d/next/Library/2021-09-08-01-19-31.bpo-20499.tSxx8Y.rst deleted file mode 100644 index cbbe61ac4a269..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-08-01-19-31.bpo-20499.tSxx8Y.rst +++ /dev/null @@ -1 +0,0 @@ -Improve the speed and accuracy of statistics.pvariance(). diff --git a/Misc/NEWS.d/next/Library/2021-09-10-21-35-53.bpo-45166.UHipXF.rst b/Misc/NEWS.d/next/Library/2021-09-10-21-35-53.bpo-45166.UHipXF.rst deleted file mode 100644 index b7242d45ea9be..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-10-21-35-53.bpo-45166.UHipXF.rst +++ /dev/null @@ -1,2 +0,0 @@ -:func:`typing.get_type_hints` now works with :data:`~typing.Final` wrapped in -:class:`~typing.ForwardRef`. diff --git a/Misc/NEWS.d/next/Library/2021-09-11-10-45-12.bpo-35474.tEY3SD.rst b/Misc/NEWS.d/next/Library/2021-09-11-10-45-12.bpo-35474.tEY3SD.rst deleted file mode 100644 index f4dd3b947a493..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-11-10-45-12.bpo-35474.tEY3SD.rst +++ /dev/null @@ -1,3 +0,0 @@ -Calling :func:`mimetypes.guess_all_extensions` with ``strict=False`` no -longer affects the result of the following call with ``strict=True``. -Also, mutating the returned list no longer affects the global state. diff --git a/Misc/NEWS.d/next/Library/2021-09-11-14-47-05.bpo-45160.VzMXbW.rst b/Misc/NEWS.d/next/Library/2021-09-11-14-47-05.bpo-45160.VzMXbW.rst deleted file mode 100644 index 9d11ed0e55d24..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-11-14-47-05.bpo-45160.VzMXbW.rst +++ /dev/null @@ -1 +0,0 @@ -When tracing a tkinter variable used by a ttk OptionMenu, callbacks are no longer made twice. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2021-09-13-19-32-58.bpo-42135.1ZAHqR.rst b/Misc/NEWS.d/next/Library/2021-09-13-19-32-58.bpo-42135.1ZAHqR.rst deleted file mode 100644 index 983b46e140e74..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-13-19-32-58.bpo-42135.1ZAHqR.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix typo: ``importlib.find_loader`` is really slated for removal in Python 3.12 not 3.10, like the others in GH-25169. - -Patch by Hugo van Kemenade. diff --git a/Misc/NEWS.d/next/Library/2021-09-14-15-52-47.bpo-45192.DjA-BI.rst b/Misc/NEWS.d/next/Library/2021-09-14-15-52-47.bpo-45192.DjA-BI.rst deleted file mode 100644 index 7dd9795aaa170..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-14-15-52-47.bpo-45192.DjA-BI.rst +++ /dev/null @@ -1,5 +0,0 @@ -Fix the ``tempfile._infer_return_type`` function so that the ``dir`` -argument of the :mod:`tempfile` functions accepts an object implementing the -``os.PathLike`` protocol. - -Patch by Kyungmin Lee. diff --git a/Misc/NEWS.d/next/Library/2021-09-17-09-59-33.bpo-45228.WV1dcT.rst b/Misc/NEWS.d/next/Library/2021-09-17-09-59-33.bpo-45228.WV1dcT.rst deleted file mode 100644 index 9336c0aed92bc..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-17-09-59-33.bpo-45228.WV1dcT.rst +++ /dev/null @@ -1 +0,0 @@ -Fix stack buffer overflow in parsing J1939 network address. diff --git a/Misc/NEWS.d/next/Library/2021-09-17-11-20-55.bpo-45234.qUcTVt.rst b/Misc/NEWS.d/next/Library/2021-09-17-11-20-55.bpo-45234.qUcTVt.rst deleted file mode 100644 index 3817b5de6449d..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-17-11-20-55.bpo-45234.qUcTVt.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fixed a regression in :func:`~shutil.copyfile`, :func:`~shutil.copy`, -:func:`~shutil.copy2` raising :exc:`FileNotFoundError` when source is a -directory, which should raise :exc:`IsADirectoryError` diff --git a/Misc/NEWS.d/next/Library/2021-09-17-15-58-53.bpo-45183.Vv_vch.rst b/Misc/NEWS.d/next/Library/2021-09-17-15-58-53.bpo-45183.Vv_vch.rst deleted file mode 100644 index f3194b34318f4..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-17-15-58-53.bpo-45183.Vv_vch.rst +++ /dev/null @@ -1,3 +0,0 @@ -Have zipimport.zipimporter.find_spec() not raise an exception when the underlying zip -file has been deleted and the internal cache has been reset via -invalidate_cache(). diff --git a/Misc/NEWS.d/next/Library/2021-09-17-16-55-37.bpo-45235.sXnmPA.rst b/Misc/NEWS.d/next/Library/2021-09-17-16-55-37.bpo-45235.sXnmPA.rst deleted file mode 100644 index 871ec5281d334..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-17-16-55-37.bpo-45235.sXnmPA.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix an issue where argparse would not preserve values in a provided namespace -when using a subparser with defaults. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2021-09-18-13-14-57.bpo-36674.a2k5Zb.rst b/Misc/NEWS.d/next/Library/2021-09-18-13-14-57.bpo-36674.a2k5Zb.rst deleted file mode 100644 index bc8c9247b080d..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-18-13-14-57.bpo-36674.a2k5Zb.rst +++ /dev/null @@ -1,2 +0,0 @@ -:meth:`unittest.TestCase.debug` raises now a :class:`unittest.SkipTest` if -the class or the test method are decorated with the skipping decorator. diff --git a/Misc/NEWS.d/next/Library/2021-09-18-16-56-33.bpo-45238.Hng_9V.rst b/Misc/NEWS.d/next/Library/2021-09-18-16-56-33.bpo-45238.Hng_9V.rst deleted file mode 100644 index 857f315c520bb..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-18-16-56-33.bpo-45238.Hng_9V.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix :meth:`unittest.IsolatedAsyncioTestCase.debug`: it runs now asynchronous -methods and callbacks. diff --git a/Misc/NEWS.d/next/Library/2021-09-23-22-17-26.bpo-45274.gPpa4E.rst b/Misc/NEWS.d/next/Library/2021-09-23-22-17-26.bpo-45274.gPpa4E.rst deleted file mode 100644 index 94d06cef89b7b..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-23-22-17-26.bpo-45274.gPpa4E.rst +++ /dev/null @@ -1,5 +0,0 @@ -Fix a race condition in the :meth:`Thread.join() ` -method of the :mod:`threading` module. If the function is interrupted by a -signal and the signal handler raises an exception, make sure that the thread -remains in a consistent state to prevent a deadlock. Patch by Victor -Stinner. diff --git a/Misc/NEWS.d/next/Library/2021-09-24-17-20-23.bpo-1596321.3nhPUk.rst b/Misc/NEWS.d/next/Library/2021-09-24-17-20-23.bpo-1596321.3nhPUk.rst deleted file mode 100644 index 61a3e5abf395e..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-24-17-20-23.bpo-1596321.3nhPUk.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix the :func:`threading._shutdown` function when the :mod:`threading` module -was imported first from a thread different than the main thread: no longer log -an error at Python exit. diff --git a/Misc/NEWS.d/next/Library/2021-09-30-08-22-44.bpo-45328.8Z-Q0B.rst b/Misc/NEWS.d/next/Library/2021-09-30-08-22-44.bpo-45328.8Z-Q0B.rst deleted file mode 100644 index eeb49310e8f66..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-30-08-22-44.bpo-45328.8Z-Q0B.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed :class:`http.client.HTTPConnection` to work properly in OSs that don't support the ``TCP_NODELAY`` socket option. diff --git a/Misc/NEWS.d/next/Library/2021-09-30-23-00-18.bpo-41710.svuloZ.rst b/Misc/NEWS.d/next/Library/2021-09-30-23-00-18.bpo-41710.svuloZ.rst deleted file mode 100644 index d8a4f9507c189..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-30-23-00-18.bpo-41710.svuloZ.rst +++ /dev/null @@ -1,5 +0,0 @@ -On Unix, if the ``sem_clockwait()`` function is available in the C library -(glibc 2.30 and newer), the :meth:`threading.Lock.acquire` method now uses the -monotonic clock (:data:`time.CLOCK_MONOTONIC`) for the timeout, rather than -using the system clock (:data:`time.CLOCK_REALTIME`), to not be affected by -system clock changes. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2021-10-01-13-09-53.bpo-45329.9iMYaO.rst b/Misc/NEWS.d/next/Library/2021-10-01-13-09-53.bpo-45329.9iMYaO.rst deleted file mode 100644 index b4bedbc278edf..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-01-13-09-53.bpo-45329.9iMYaO.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix freed memory access in :class:`pyexpat.xmlparser` when building it with an -installed expat library <= 2.2.0. diff --git a/Misc/NEWS.d/next/Library/2021-10-01-23-07-02.bpo-45343.ixmctD.rst b/Misc/NEWS.d/next/Library/2021-10-01-23-07-02.bpo-45343.ixmctD.rst deleted file mode 100644 index 8dac4e6a25271..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-01-23-07-02.bpo-45343.ixmctD.rst +++ /dev/null @@ -1 +0,0 @@ -Update bundled pip to 21.2.4 and setuptools to 58.1.0 diff --git a/Misc/NEWS.d/next/Library/2021-10-03-21-14-37.bpo-20028.zBA4RK.rst b/Misc/NEWS.d/next/Library/2021-10-03-21-14-37.bpo-20028.zBA4RK.rst deleted file mode 100644 index e75612116e942..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-03-21-14-37.bpo-20028.zBA4RK.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve error message of :class:`csv.Dialect` when initializing. -Patch by Vajrasky Kok and Dong-hee Na. diff --git a/Misc/NEWS.d/next/Library/2021-10-05-11-03-48.bpo-45371.NOwcDJ.rst b/Misc/NEWS.d/next/Library/2021-10-05-11-03-48.bpo-45371.NOwcDJ.rst deleted file mode 100644 index 045489be81a19..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-05-11-03-48.bpo-45371.NOwcDJ.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix clang rpath issue in :mod:`distutils`. The UnixCCompiler now uses -correct clang option to add a runtime library directory (rpath) to a shared -library. diff --git a/Misc/NEWS.d/next/Library/2021-10-07-00-05-05.bpo-45386.q9ORpA.rst b/Misc/NEWS.d/next/Library/2021-10-07-00-05-05.bpo-45386.q9ORpA.rst deleted file mode 100644 index eec77ceccf933..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-07-00-05-05.bpo-45386.q9ORpA.rst +++ /dev/null @@ -1,3 +0,0 @@ -Make :mod:`xmlrpc.client` more robust to C runtimes where the underlying C -``strftime`` function results in a ``ValueError`` when testing for year -formatting options. diff --git a/Misc/NEWS.d/next/Library/2021-10-07-14-04-10.bpo-45262.HqF71Z.rst b/Misc/NEWS.d/next/Library/2021-10-07-14-04-10.bpo-45262.HqF71Z.rst deleted file mode 100644 index 4cd949fe1ed5d..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-07-14-04-10.bpo-45262.HqF71Z.rst +++ /dev/null @@ -1 +0,0 @@ -Prevent use-after-free in asyncio. Make sure the cached running loop holder gets cleared on dealloc to prevent use-after-free in get_running_loop \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2021-10-08-19-24-48.bpo-45406.Qh_Mz4.rst b/Misc/NEWS.d/next/Library/2021-10-08-19-24-48.bpo-45406.Qh_Mz4.rst deleted file mode 100644 index 2c3a8165aeb49..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-08-19-24-48.bpo-45406.Qh_Mz4.rst +++ /dev/null @@ -1 +0,0 @@ -Make :func:`inspect.getmodule` catch ``FileNotFoundError`` raised by :'func:`inspect.getabsfile`, and return ``None`` to indicate that the module could not be determined. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2021-10-09-18-42-27.bpo-44904.RlW5h8.rst b/Misc/NEWS.d/next/Library/2021-10-09-18-42-27.bpo-44904.RlW5h8.rst deleted file mode 100644 index b02d499d23500..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-09-18-42-27.bpo-44904.RlW5h8.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix bug in the :mod:`doctest` module that caused it to fail if a docstring -included an example with a ``classmethod`` ``property``. Patch by Alex -Waygood. diff --git a/Misc/NEWS.d/next/Library/2021-10-09-20-53-13.bpo-45419.CauCgt.rst b/Misc/NEWS.d/next/Library/2021-10-09-20-53-13.bpo-45419.CauCgt.rst deleted file mode 100644 index a901d7453819f..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-09-20-53-13.bpo-45419.CauCgt.rst +++ /dev/null @@ -1 +0,0 @@ -Correct interfaces on DegenerateFiles.Path. diff --git a/Misc/NEWS.d/next/Library/2021-10-10-09-42-34.bpo-45416.n35O0_.rst b/Misc/NEWS.d/next/Library/2021-10-10-09-42-34.bpo-45416.n35O0_.rst deleted file mode 100644 index cf335d1bcd2c9..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-10-09-42-34.bpo-45416.n35O0_.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix use of :class:`asyncio.Condition` with explicit :class:`asyncio.Lock` objects, which was a regression due to removal of explicit loop arguments. -Patch by Joongi Kim. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2021-10-10-16-14-33.bpo-45249.xqLliz.rst b/Misc/NEWS.d/next/Library/2021-10-10-16-14-33.bpo-45249.xqLliz.rst deleted file mode 100644 index 1d5a857e25435..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-10-16-14-33.bpo-45249.xqLliz.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix the behaviour of :func:`traceback.print_exc` when displaying the caret -when the ``end_offset`` in the exception is set to 0. Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Library/2021-10-13-17-52-48.bpo-45239.7li1_0.rst b/Misc/NEWS.d/next/Library/2021-10-13-17-52-48.bpo-45239.7li1_0.rst deleted file mode 100644 index 9e5ec561c362a..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-13-17-52-48.bpo-45239.7li1_0.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fixed :func:`email.utils.parsedate_tz` crashing with -:exc:`UnboundLocalError` on certain invalid input instead of returning -``None``. Patch by Ben Hoyt. diff --git a/Misc/NEWS.d/next/Library/2021-10-14-00-19-02.bpo-45461.4LB_tJ.rst b/Misc/NEWS.d/next/Library/2021-10-14-00-19-02.bpo-45461.4LB_tJ.rst deleted file mode 100644 index c1c4ed1ace248..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-14-00-19-02.bpo-45461.4LB_tJ.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix incremental decoder and stream reader in the "unicode-escape" codec. -Previously they failed if the escape sequence was split. diff --git a/Misc/NEWS.d/next/Library/2021-10-14-13-31-19.bpo-45467.Q7Ma6A.rst b/Misc/NEWS.d/next/Library/2021-10-14-13-31-19.bpo-45467.Q7Ma6A.rst deleted file mode 100644 index f2c0ae4ae51fb..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-14-13-31-19.bpo-45467.Q7Ma6A.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix incremental decoder and stream reader in the "raw-unicode-escape" codec. -Previously they failed if the escape sequence was split. diff --git a/Misc/NEWS.d/next/Library/2021-10-14-18-04-17.bpo-45428.mM2War.rst b/Misc/NEWS.d/next/Library/2021-10-14-18-04-17.bpo-45428.mM2War.rst deleted file mode 100644 index 556eca43ed3c7..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-14-18-04-17.bpo-45428.mM2War.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a regression in py_compile when reading filenames from standard input. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2021-10-18-10-46-47.bpo-45475.sb9KDF.rst b/Misc/NEWS.d/next/Library/2021-10-18-10-46-47.bpo-45475.sb9KDF.rst deleted file mode 100644 index 6fce894e6e4d4..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-18-10-46-47.bpo-45475.sb9KDF.rst +++ /dev/null @@ -1,4 +0,0 @@ -Reverted optimization of iterating :class:`gzip.GzipFile`, -:class:`bz2.BZ2File`, and :class:`lzma.LZMAFile` (see bpo-43787) because it -caused regression when user iterate them without having reference of them. -Patch by Inada Naoki. diff --git a/Misc/NEWS.d/next/Library/2021-10-18-14-52-48.bpo-45515.aXdvm_.rst b/Misc/NEWS.d/next/Library/2021-10-18-14-52-48.bpo-45515.aXdvm_.rst deleted file mode 100644 index 382733ff91883..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-18-14-52-48.bpo-45515.aXdvm_.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add references to :mod:`zoneinfo` in the :mod:`datetime` documentation, -mostly replacing outdated references to ``dateutil.tz``. Change by Paul -Ganssle. diff --git a/Misc/NEWS.d/next/Library/2021-10-21-16-18-51.bpo-45557.4MQt4r.rst b/Misc/NEWS.d/next/Library/2021-10-21-16-18-51.bpo-45557.4MQt4r.rst deleted file mode 100644 index 7472b08d1b08e..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-21-16-18-51.bpo-45557.4MQt4r.rst +++ /dev/null @@ -1,2 +0,0 @@ -pprint.pprint() now handles underscore_numbers correctly. Previously it was -always setting it to False. diff --git a/Misc/NEWS.d/next/Library/2021-10-22-21-57-02.bpo-45581.rlH6ay.rst b/Misc/NEWS.d/next/Library/2021-10-22-21-57-02.bpo-45581.rlH6ay.rst deleted file mode 100644 index 13a3b237434eb..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-22-21-57-02.bpo-45581.rlH6ay.rst +++ /dev/null @@ -1,2 +0,0 @@ -:meth:`sqlite3.connect` now correctly raises :exc:`MemoryError` if the -underlying SQLite API signals memory error. Patch by Erlend E. Aasland. diff --git a/Misc/NEWS.d/next/Library/2021-10-22-23-06-33.bpo-45574.svqA84.rst b/Misc/NEWS.d/next/Library/2021-10-22-23-06-33.bpo-45574.svqA84.rst deleted file mode 100644 index b404d24473960..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-22-23-06-33.bpo-45574.svqA84.rst +++ /dev/null @@ -1 +0,0 @@ -Fix warning about ``print_escape`` being unused. diff --git a/Misc/NEWS.d/next/Library/2021-10-27-10-05-39.bpo-45438.Xz5lGU.rst b/Misc/NEWS.d/next/Library/2021-10-27-10-05-39.bpo-45438.Xz5lGU.rst deleted file mode 100644 index cd6cfc1fcd407..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-27-10-05-39.bpo-45438.Xz5lGU.rst +++ /dev/null @@ -1 +0,0 @@ -Fix typing.Signature string representation for generic builtin types. diff --git a/Misc/NEWS.d/next/Library/2021-10-28-22-58-14.bpo-45662.sJd7Ir.rst b/Misc/NEWS.d/next/Library/2021-10-28-22-58-14.bpo-45662.sJd7Ir.rst deleted file mode 100644 index 050b443dd7cb2..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-28-22-58-14.bpo-45662.sJd7Ir.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix the repr of :data:`dataclasses.InitVar` with a type alias to the -built-in class, e.g. ``InitVar[list[int]]``. diff --git a/Misc/NEWS.d/next/Library/2021-10-28-23-11-59.bpo-45663.J90N5R.rst b/Misc/NEWS.d/next/Library/2021-10-28-23-11-59.bpo-45663.J90N5R.rst deleted file mode 100644 index f246f67cf80e5..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-28-23-11-59.bpo-45663.J90N5R.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix :func:`dataclasses.is_dataclass` for dataclasses which are subclasses of -:class:`types.GenericAlias`. diff --git a/Misc/NEWS.d/next/Library/2021-10-28-23-40-54.bpo-45664.7dqtxQ.rst b/Misc/NEWS.d/next/Library/2021-10-28-23-40-54.bpo-45664.7dqtxQ.rst deleted file mode 100644 index 573a569845a87..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-28-23-40-54.bpo-45664.7dqtxQ.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix :func:`types.resolve_bases` and :func:`types.new_class` for -:class:`types.GenericAlias` instance as a base. diff --git a/Misc/NEWS.d/next/Library/2021-10-30-21-11-37.bpo-45679.Dq8Cpu.rst b/Misc/NEWS.d/next/Library/2021-10-30-21-11-37.bpo-45679.Dq8Cpu.rst deleted file mode 100644 index a644492a12d17..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-30-21-11-37.bpo-45679.Dq8Cpu.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix caching of multi-value :data:`typing.Literal`. ``Literal[True, 2]`` is no -longer equal to ``Literal[1, 2]``. diff --git a/Misc/NEWS.d/next/Library/2021-11-06-17-47-46.bpo-45644.ZMqHD_.rst b/Misc/NEWS.d/next/Library/2021-11-06-17-47-46.bpo-45644.ZMqHD_.rst deleted file mode 100644 index 2cf4eae02c449..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-11-06-17-47-46.bpo-45644.ZMqHD_.rst +++ /dev/null @@ -1,3 +0,0 @@ -In-place JSON file formatting using ``python3 -m json.tool infile infile`` -now works correctly, previously it left the file empty. Patch by Chris -Wesseling. diff --git a/Misc/NEWS.d/next/Library/2021-11-08-23-22-14.bpo-45757.MHZHt3.rst b/Misc/NEWS.d/next/Library/2021-11-08-23-22-14.bpo-45757.MHZHt3.rst deleted file mode 100644 index f25638cc68f85..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-11-08-23-22-14.bpo-45757.MHZHt3.rst +++ /dev/null @@ -1 +0,0 @@ -Fix bug where :mod:`dis` produced an incorrect oparg when :opcode:`EXTENDED_ARG` is followed by an opcode that does not use its argument. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2021-11-09-09-04-19.bpo-45765.JVobxK.rst b/Misc/NEWS.d/next/Library/2021-11-09-09-04-19.bpo-45765.JVobxK.rst deleted file mode 100644 index a1f4a1f7aa91c..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-11-09-09-04-19.bpo-45765.JVobxK.rst +++ /dev/null @@ -1 +0,0 @@ -In importlib.metadata, fix distribution discovery for an empty path. diff --git a/Misc/NEWS.d/next/Library/2021-11-11-13-03-17.bpo-45235.8ZbkHa.rst b/Misc/NEWS.d/next/Library/2021-11-11-13-03-17.bpo-45235.8ZbkHa.rst deleted file mode 100644 index f73589ccc8872..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-11-11-13-03-17.bpo-45235.8ZbkHa.rst +++ /dev/null @@ -1,3 +0,0 @@ -Reverted an argparse bugfix that caused regression in the handling of -default arguments for subparsers. This prevented leaf level arguments from -taking precedence over root level arguments. diff --git a/Misc/NEWS.d/next/Library/2021-11-16-18-13-49.bpo-41735.D72UY1.rst b/Misc/NEWS.d/next/Library/2021-11-16-18-13-49.bpo-41735.D72UY1.rst deleted file mode 100644 index 101da0e9ce648..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-11-16-18-13-49.bpo-41735.D72UY1.rst +++ /dev/null @@ -1 +0,0 @@ -Fix thread lock in ``zlib.Decompress.flush()`` method before ``PyObject_GetBuffer``. diff --git a/Misc/NEWS.d/next/Library/2021-11-17-19-25-37.bpo-45831.9-TojK.rst b/Misc/NEWS.d/next/Library/2021-11-17-19-25-37.bpo-45831.9-TojK.rst deleted file mode 100644 index 049449ff0a4a1..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-11-17-19-25-37.bpo-45831.9-TojK.rst +++ /dev/null @@ -1,5 +0,0 @@ -:mod:`faulthandler` can now write ASCII-only strings (like filenames and -function names) with a single write() syscall when dumping a traceback. It -reduces the risk of getting an unreadable dump when two threads or two -processes dump a traceback to the same file (like stderr) at the same time. -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2021-11-20-17-04-25.bpo-45803.wSgFOy.rst b/Misc/NEWS.d/next/Library/2021-11-20-17-04-25.bpo-45803.wSgFOy.rst deleted file mode 100644 index 77479d7db476b..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-11-20-17-04-25.bpo-45803.wSgFOy.rst +++ /dev/null @@ -1 +0,0 @@ -Added missing kw_only parameter to dataclasses.make_dataclass(). diff --git a/Misc/NEWS.d/next/Library/2021-11-21-20-50-42.bpo-44649.E8M936.rst b/Misc/NEWS.d/next/Library/2021-11-21-20-50-42.bpo-44649.E8M936.rst deleted file mode 100644 index f6391a915a821..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-11-21-20-50-42.bpo-44649.E8M936.rst +++ /dev/null @@ -1,2 +0,0 @@ -Handle dataclass(slots=True) with a field that has default a default value, -but for which init=False. diff --git a/Misc/NEWS.d/next/Library/2021-11-28-15-30-34.bpo-37658.8Hno7d.rst b/Misc/NEWS.d/next/Library/2021-11-28-15-30-34.bpo-37658.8Hno7d.rst deleted file mode 100644 index 97d1e961ac2be..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-11-28-15-30-34.bpo-37658.8Hno7d.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix issue when on certain conditions ``asyncio.wait_for()`` may allow a -coroutine to complete successfully, but fail to return the result, -potentially causing memory leaks or other issues. diff --git a/Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst b/Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst deleted file mode 100644 index 0378efca746bb..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix possible crash when getting an attribute of -class:`xml.etree.ElementTree.Element` simultaneously with -replacing the ``attrib`` dict. diff --git a/Misc/NEWS.d/next/Tests/2021-08-27-22-37-19.bpo-25130.ig4oJe.rst b/Misc/NEWS.d/next/Tests/2021-08-27-22-37-19.bpo-25130.ig4oJe.rst deleted file mode 100644 index 43ce68bef4609..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-08-27-22-37-19.bpo-25130.ig4oJe.rst +++ /dev/null @@ -1 +0,0 @@ -Add calls of :func:`gc.collect` in tests to support PyPy. diff --git a/Misc/NEWS.d/next/Tests/2021-09-08-13-01-37.bpo-44860.qXd0kx.rst b/Misc/NEWS.d/next/Tests/2021-09-08-13-01-37.bpo-44860.qXd0kx.rst deleted file mode 100644 index 153a9c55733fb..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-09-08-13-01-37.bpo-44860.qXd0kx.rst +++ /dev/null @@ -1,2 +0,0 @@ -Update ``test_sysconfig.test_user_similar()`` for the posix_user scheme: -``platlib`` doesn't use :data:`sys.platlibdir`. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Tests/2021-09-11-22-08-18.bpo-45125.FVSzs2.rst b/Misc/NEWS.d/next/Tests/2021-09-11-22-08-18.bpo-45125.FVSzs2.rst deleted file mode 100644 index 5dfbe0e5db463..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-09-11-22-08-18.bpo-45125.FVSzs2.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improves pickling tests and docs of ``SharedMemory`` and ``SharableList`` -objects. diff --git a/Misc/NEWS.d/next/Tests/2021-09-13-00-28-17.bpo-45156.8oomV3.rst b/Misc/NEWS.d/next/Tests/2021-09-13-00-28-17.bpo-45156.8oomV3.rst deleted file mode 100644 index b2094b5765331..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-09-13-00-28-17.bpo-45156.8oomV3.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixes infinite loop on :func:`unittest.mock.seal` of mocks created by -:func:`~unittest.create_autospec`. diff --git a/Misc/NEWS.d/next/Tests/2021-09-14-13-16-18.bpo-45195.EyQR1G.rst b/Misc/NEWS.d/next/Tests/2021-09-14-13-16-18.bpo-45195.EyQR1G.rst deleted file mode 100644 index 16a1f4440483c..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-09-14-13-16-18.bpo-45195.EyQR1G.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix test_readline.test_nonascii(): sometimes, the newline character is not -written at the end, so don't expect it in the output. Patch by Victor -Stinner. diff --git a/Misc/NEWS.d/next/Tests/2021-09-15-23-32-39.bpo-45209.55ntL5.rst b/Misc/NEWS.d/next/Tests/2021-09-15-23-32-39.bpo-45209.55ntL5.rst deleted file mode 100644 index 4c3bed0983b89..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-09-15-23-32-39.bpo-45209.55ntL5.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix ``UserWarning: resource_tracker`` warning in -``_test_multiprocessing._TestSharedMemory.test_shared_memory_cleaned_after_process_termination`` diff --git a/Misc/NEWS.d/next/Tests/2021-09-16-17-22-35.bpo-45128.Jz6fl2.rst b/Misc/NEWS.d/next/Tests/2021-09-16-17-22-35.bpo-45128.Jz6fl2.rst deleted file mode 100644 index b50eb32b3faa8..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-09-16-17-22-35.bpo-45128.Jz6fl2.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix ``test_multiprocessing_fork`` failure due to ``test_logging`` and -``sys.modules`` manipulation. diff --git a/Misc/NEWS.d/next/Tests/2021-09-24-10-41-49.bpo-45269.8jKEr8.rst b/Misc/NEWS.d/next/Tests/2021-09-24-10-41-49.bpo-45269.8jKEr8.rst deleted file mode 100644 index 72dd9471134ff..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-09-24-10-41-49.bpo-45269.8jKEr8.rst +++ /dev/null @@ -1 +0,0 @@ -Cover case when invalid ``markers`` type is supplied to ``c_make_encoder``. diff --git a/Misc/NEWS.d/next/Tests/2021-09-25-11-05-31.bpo-45280.3MA6lC.rst b/Misc/NEWS.d/next/Tests/2021-09-25-11-05-31.bpo-45280.3MA6lC.rst deleted file mode 100644 index 71691f5ba2b89..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-09-25-11-05-31.bpo-45280.3MA6lC.rst +++ /dev/null @@ -1 +0,0 @@ -Add a test case for empty :class:`typing.NamedTuple`. diff --git a/Misc/NEWS.d/next/Tests/2021-09-30-16-54-39.bpo-40173.J_slCw.rst b/Misc/NEWS.d/next/Tests/2021-09-30-16-54-39.bpo-40173.J_slCw.rst deleted file mode 100644 index 21671473c16cc..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-09-30-16-54-39.bpo-40173.J_slCw.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix :func:`test.support.import_helper.import_fresh_module`. - diff --git a/Misc/NEWS.d/next/Tests/2021-10-07-13-11-45.bpo-45400.h3iT7V.rst b/Misc/NEWS.d/next/Tests/2021-10-07-13-11-45.bpo-45400.h3iT7V.rst deleted file mode 100644 index 61b6653320dfc..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-10-07-13-11-45.bpo-45400.h3iT7V.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix test_name_error_suggestions_do_not_trigger_for_too_many_locals() of -test_exceptions if a directory name contains "a1" (like "Python-3.11.0a1"): -use a stricter regular expression. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Tests/2021-10-18-16-18-41.bpo-39679.F18qcE.rst b/Misc/NEWS.d/next/Tests/2021-10-18-16-18-41.bpo-39679.F18qcE.rst deleted file mode 100644 index b0d1b686392ef..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-10-18-16-18-41.bpo-39679.F18qcE.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add more test cases for `@functools.singledispatchmethod` when combined with -`@classmethod` or `@staticmethod`. diff --git a/Misc/NEWS.d/next/Tests/2021-10-21-17-22-26.bpo-43592.kHRsra.rst b/Misc/NEWS.d/next/Tests/2021-10-21-17-22-26.bpo-43592.kHRsra.rst deleted file mode 100644 index 2528857caf9c0..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-10-21-17-22-26.bpo-43592.kHRsra.rst +++ /dev/null @@ -1,3 +0,0 @@ -:mod:`test.libregrtest` now raises the soft resource limit for the maximum -number of file descriptors when the default is too low for our test suite as -was often the case on macOS. diff --git a/Misc/NEWS.d/next/Tests/2021-10-22-12-05-21.bpo-45566.2gQ3ZB.rst b/Misc/NEWS.d/next/Tests/2021-10-22-12-05-21.bpo-45566.2gQ3ZB.rst deleted file mode 100644 index a2ecf721800d9..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-10-22-12-05-21.bpo-45566.2gQ3ZB.rst +++ /dev/null @@ -1 +0,0 @@ -Fix ``test_frozen_pickle`` in ``test_dataclasses`` to check all ``pickle`` versions. diff --git a/Misc/NEWS.d/next/Tests/2021-10-22-19-44-13.bpo-45577.dSaNvK.rst b/Misc/NEWS.d/next/Tests/2021-10-22-19-44-13.bpo-45577.dSaNvK.rst deleted file mode 100644 index fc9783eb9ddaa..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-10-22-19-44-13.bpo-45577.dSaNvK.rst +++ /dev/null @@ -1 +0,0 @@ -Add subtests for all ``pickle`` protocols in ``test_zoneinfo``. diff --git a/Misc/NEWS.d/next/Tests/2021-10-30-13-12-20.bpo-45678.bKrYeS.rst b/Misc/NEWS.d/next/Tests/2021-10-30-13-12-20.bpo-45678.bKrYeS.rst deleted file mode 100644 index 885b2fa64ad0f..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-10-30-13-12-20.bpo-45678.bKrYeS.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add tests to ensure that ``functools.singledispatchmethod`` correctly wraps -the attributes of the target function. diff --git a/Misc/NEWS.d/next/Tests/2021-10-30-19-00-25.bpo-45578.bvu6X2.rst b/Misc/NEWS.d/next/Tests/2021-10-30-19-00-25.bpo-45578.bvu6X2.rst deleted file mode 100644 index 3d0e0ca3f04a1..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-10-30-19-00-25.bpo-45578.bvu6X2.rst +++ /dev/null @@ -1 +0,0 @@ -Add tests for :func:`dis.distb` diff --git a/Misc/NEWS.d/next/Tests/2021-11-04-20-03-32.bpo-45678.1xNMjN.rst b/Misc/NEWS.d/next/Tests/2021-11-04-20-03-32.bpo-45678.1xNMjN.rst deleted file mode 100644 index 736d5f65f961b..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-11-04-20-03-32.bpo-45678.1xNMjN.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add tests for scenarios in which :class:`functools.singledispatchmethod` is -stacked on top of a method that has already been wrapped by two other -decorators. Patch by Alex Waygood. diff --git a/Misc/NEWS.d/next/Tests/2021-11-17-14-28-08.bpo-45835.Mgyhjx.rst b/Misc/NEWS.d/next/Tests/2021-11-17-14-28-08.bpo-45835.Mgyhjx.rst deleted file mode 100644 index 6a73b01959065..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-11-17-14-28-08.bpo-45835.Mgyhjx.rst +++ /dev/null @@ -1 +0,0 @@ -Fix race condition in test_queue tests with multiple "feeder" threads. diff --git a/Misc/NEWS.d/next/Tests/2021-11-28-15-25-02.bpo-19460.lr0aWs.rst b/Misc/NEWS.d/next/Tests/2021-11-28-15-25-02.bpo-19460.lr0aWs.rst deleted file mode 100644 index b082d6de20c07..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-11-28-15-25-02.bpo-19460.lr0aWs.rst +++ /dev/null @@ -1 +0,0 @@ -Add new Test for :class:`email.mime.nonmultipart.MIMENonMultipart`. diff --git a/Misc/NEWS.d/next/Tools-Demos/2021-09-14-11-44-26.bpo-44786.DU0LC0.rst b/Misc/NEWS.d/next/Tools-Demos/2021-09-14-11-44-26.bpo-44786.DU0LC0.rst deleted file mode 100644 index 96ebf2c33cc5a..0000000000000 --- a/Misc/NEWS.d/next/Tools-Demos/2021-09-14-11-44-26.bpo-44786.DU0LC0.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a warning in regular expression in the c-analyzer script. diff --git a/Misc/NEWS.d/next/Windows/2021-09-30-23-17-27.bpo-45337.qg7U_h.rst b/Misc/NEWS.d/next/Windows/2021-09-30-23-17-27.bpo-45337.qg7U_h.rst deleted file mode 100644 index 007ee87195d6e..0000000000000 --- a/Misc/NEWS.d/next/Windows/2021-09-30-23-17-27.bpo-45337.qg7U_h.rst +++ /dev/null @@ -1,4 +0,0 @@ -venv now warns when the created environment may need to be accessed at a -different path, due to redirections, links or junctions. It also now -correctly installs or upgrades components when the alternate path is -required. diff --git a/Misc/NEWS.d/next/Windows/2021-11-04-00-41-50.bpo-43652.RnqV7I.rst b/Misc/NEWS.d/next/Windows/2021-11-04-00-41-50.bpo-43652.RnqV7I.rst deleted file mode 100644 index 7da8fc79a9dab..0000000000000 --- a/Misc/NEWS.d/next/Windows/2021-11-04-00-41-50.bpo-43652.RnqV7I.rst +++ /dev/null @@ -1,2 +0,0 @@ -Update Tcl/Tk to 8.6.11, actually this time. The previous update incorrectly -included 8.6.10. diff --git a/Misc/NEWS.d/next/Windows/2021-11-05-01-05-46.bpo-45720.47Nc5I.rst b/Misc/NEWS.d/next/Windows/2021-11-05-01-05-46.bpo-45720.47Nc5I.rst deleted file mode 100644 index 315759b07e147..0000000000000 --- a/Misc/NEWS.d/next/Windows/2021-11-05-01-05-46.bpo-45720.47Nc5I.rst +++ /dev/null @@ -1,3 +0,0 @@ -Internal reference to :file:`shlwapi.dll` was dropped to help improve -startup time. This DLL will no longer be loaded at the start of every Python -process. diff --git a/Misc/NEWS.d/next/Windows/2021-11-08-21-53-11.bpo-45732.idl5kx.rst b/Misc/NEWS.d/next/Windows/2021-11-08-21-53-11.bpo-45732.idl5kx.rst deleted file mode 100644 index 563bcd33a401a..0000000000000 --- a/Misc/NEWS.d/next/Windows/2021-11-08-21-53-11.bpo-45732.idl5kx.rst +++ /dev/null @@ -1 +0,0 @@ -Updates bundled Tcl/Tk to 8.6.12. diff --git a/Misc/NEWS.d/next/Windows/2021-11-23-11-44-42.bpo-45616.K52PLZ.rst b/Misc/NEWS.d/next/Windows/2021-11-23-11-44-42.bpo-45616.K52PLZ.rst deleted file mode 100644 index 000f2fd3cc989..0000000000000 --- a/Misc/NEWS.d/next/Windows/2021-11-23-11-44-42.bpo-45616.K52PLZ.rst +++ /dev/null @@ -1,4 +0,0 @@ -Fix Python Launcher's ability to distinguish between versions 3.1 and 3.10 -when either one is explicitly requested. Previously, 3.1 would be used if -3.10 was requested but not installed, and 3.10 would be used if 3.1 was -requested but 3.10 was installed. diff --git a/Misc/NEWS.d/next/Windows/2021-11-26-18-17-41.bpo-45901.c5IBqM.rst b/Misc/NEWS.d/next/Windows/2021-11-26-18-17-41.bpo-45901.c5IBqM.rst deleted file mode 100644 index 2cb872bffe072..0000000000000 --- a/Misc/NEWS.d/next/Windows/2021-11-26-18-17-41.bpo-45901.c5IBqM.rst +++ /dev/null @@ -1,4 +0,0 @@ -When installed through the Microsoft Store and set as the default app for -:file:`*.py` files, command line arguments will now be passed to Python when -invoking a script without explicitly launching Python (that is, ``script.py -args`` rather than ``python script.py args``). diff --git a/Misc/NEWS.d/next/macOS/2021-08-27-16-55-10.bpo-34602.ZjHsYJ.rst b/Misc/NEWS.d/next/macOS/2021-08-27-16-55-10.bpo-34602.ZjHsYJ.rst deleted file mode 100644 index 29a6ff92554e1..0000000000000 --- a/Misc/NEWS.d/next/macOS/2021-08-27-16-55-10.bpo-34602.ZjHsYJ.rst +++ /dev/null @@ -1,3 +0,0 @@ -When building CPython on macOS with ``./configure ---with-undefined-behavior-sanitizer --with-pydebug``, the stack size is now -quadrupled to allow for the entire test suite to pass. diff --git a/Misc/NEWS.d/next/macOS/2021-10-25-02-02-21.bpo-44828.XBdXlJ.rst b/Misc/NEWS.d/next/macOS/2021-10-25-02-02-21.bpo-44828.XBdXlJ.rst deleted file mode 100644 index 021d7e4d73782..0000000000000 --- a/Misc/NEWS.d/next/macOS/2021-10-25-02-02-21.bpo-44828.XBdXlJ.rst +++ /dev/null @@ -1,3 +0,0 @@ -Avoid tkinter file dialog failure on macOS 12 Monterey when using the Tk -8.6.11 provided by python.org macOS installers. Patch by Marc Culler of the -Tk project. diff --git a/Misc/NEWS.d/next/macOS/2021-12-05-23-52-03.bpo-45732.-BWrnh.rst b/Misc/NEWS.d/next/macOS/2021-12-05-23-52-03.bpo-45732.-BWrnh.rst deleted file mode 100644 index eb47985f86f95..0000000000000 --- a/Misc/NEWS.d/next/macOS/2021-12-05-23-52-03.bpo-45732.-BWrnh.rst +++ /dev/null @@ -1 +0,0 @@ -Update python.org macOS installer to use Tcl/Tk 8.6.12. diff --git a/README.rst b/README.rst index 74e7629eb4037..d2189e5c361e6 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -This is Python version 3.10.0 +This is Python version 3.10.1 ============================= .. image:: https://travis-ci.com/python/cpython.svg?branch=master From webhook-mailer at python.org Mon Dec 6 18:12:40 2021 From: webhook-mailer at python.org (asvetlov) Date: Mon, 06 Dec 2021 23:12:40 -0000 Subject: [Python-checkins] removal of duplicated text paragraph (#29666) Message-ID: https://github.com/python/cpython/commit/8518ee348c18da7e150f5e42b3424c86f7c0a3d8 commit: 8518ee348c18da7e150f5e42b3424c86f7c0a3d8 branch: main author: Taras Sereda committer: asvetlov date: 2021-12-07T01:12:29+02:00 summary: removal of duplicated text paragraph (#29666) files: M Doc/library/asyncio-task.rst diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 36e13f9295652..bfc983e304bcc 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -299,12 +299,6 @@ Sleeping tasks to run. This can be used by long-running functions to avoid blocking the event loop for the full duration of the function call. - .. deprecated-removed:: 3.8 3.10 - The ``loop`` parameter. This function has been implicitly getting the - current running loop since 3.7. See - :ref:`What's New in 3.10's Removed section ` - for more information. - .. _asyncio_example_sleep: Example of coroutine displaying the current date every second From webhook-mailer at python.org Mon Dec 6 18:40:41 2021 From: webhook-mailer at python.org (asvetlov) Date: Mon, 06 Dec 2021 23:40:41 -0000 Subject: [Python-checkins] bpo-23819: asyncio: Replace AssertionError with TypeError where it makes sense (GH-29894) Message-ID: https://github.com/python/cpython/commit/265918bb1d782ab85c7dbc835eb62d6cfc2145b7 commit: 265918bb1d782ab85c7dbc835eb62d6cfc2145b7 branch: main author: Kumar Aditya committer: asvetlov date: 2021-12-07T01:40:35+02:00 summary: bpo-23819: asyncio: Replace AssertionError with TypeError where it makes sense (GH-29894) files: A Misc/NEWS.d/next/Library/2021-12-02-14-37-30.bpo-23819.An6vkT.rst M Lib/asyncio/base_events.py M Lib/asyncio/events.py M Lib/test/test_asyncio/test_base_events.py M Lib/test/test_asyncio/test_events.py diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index 054d7b45ec2d6..cfaf082587bb2 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -706,6 +706,8 @@ def call_later(self, delay, callback, *args, context=None): Any positional arguments after the callback will be passed to the callback when it is called. """ + if delay is None: + raise TypeError('delay must not be None') timer = self.call_at(self.time() + delay, callback, *args, context=context) if timer._source_traceback: @@ -717,6 +719,8 @@ def call_at(self, when, callback, *args, context=None): Absolute time corresponds to the event loop's time() method. """ + if when is None: + raise TypeError("when cannot be None") self._check_closed() if self._debug: self._check_thread() diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index 7abaaca2d2b28..d91fe8db2b020 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -101,7 +101,6 @@ class TimerHandle(Handle): __slots__ = ['_scheduled', '_when'] def __init__(self, when, callback, args, loop, context=None): - assert when is not None super().__init__(callback, args, loop, context) if self._source_traceback: del self._source_traceback[-1] @@ -661,7 +660,8 @@ def get_event_loop(self): def set_event_loop(self, loop): """Set the event loop.""" self._local._set_called = True - assert loop is None or isinstance(loop, AbstractEventLoop) + if loop is not None and not isinstance(loop, AbstractEventLoop): + raise TypeError(f"loop must be an instance of AbstractEventLoop or None, not '{type(loop).__name__}'") self._local._loop = loop def new_event_loop(self): @@ -745,7 +745,8 @@ def set_event_loop_policy(policy): If policy is None, the default policy is restored.""" global _event_loop_policy - assert policy is None or isinstance(policy, AbstractEventLoopPolicy) + if policy is not None and not isinstance(policy, AbstractEventLoopPolicy): + raise TypeError(f"policy must be an instance of AbstractEventLoopPolicy or None, not '{type(policy).__name__}'") _event_loop_policy = policy diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index b522fac23a23b..d812bc9edea57 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -255,6 +255,8 @@ def cb(): self.assertIsInstance(h, asyncio.TimerHandle) self.assertIn(h, self.loop._scheduled) self.assertNotIn(h, self.loop._ready) + with self.assertRaises(TypeError, msg="delay must not be None"): + self.loop.call_later(None, cb) def test_call_later_negative_delays(self): calls = [] @@ -286,6 +288,8 @@ def cb(): # tolerate a difference of +800 ms because some Python buildbots # are really slow self.assertLessEqual(dt, 0.9, dt) + with self.assertRaises(TypeError, msg="when cannot be None"): + self.loop.call_at(None, cb) def check_thread(self, loop, debug): def cb(): diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index e50a53d706784..fe791fa4232c0 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -2322,10 +2322,6 @@ def callback(*args): self.assertIsNone(h._callback) self.assertIsNone(h._args) - # when cannot be None - self.assertRaises(AssertionError, - asyncio.TimerHandle, None, callback, args, - self.loop) def test_timer_repr(self): self.loop.get_debug.return_value = False @@ -2592,7 +2588,7 @@ def test_set_event_loop(self): policy = asyncio.DefaultEventLoopPolicy() old_loop = policy.get_event_loop() - self.assertRaises(AssertionError, policy.set_event_loop, object()) + self.assertRaises(TypeError, policy.set_event_loop, object()) loop = policy.new_event_loop() policy.set_event_loop(loop) @@ -2608,7 +2604,7 @@ def test_get_event_loop_policy(self): def test_set_event_loop_policy(self): self.assertRaises( - AssertionError, asyncio.set_event_loop_policy, object()) + TypeError, asyncio.set_event_loop_policy, object()) old_policy = asyncio.get_event_loop_policy() diff --git a/Misc/NEWS.d/next/Library/2021-12-02-14-37-30.bpo-23819.An6vkT.rst b/Misc/NEWS.d/next/Library/2021-12-02-14-37-30.bpo-23819.An6vkT.rst new file mode 100644 index 0000000000000..d1ec505193d41 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-02-14-37-30.bpo-23819.An6vkT.rst @@ -0,0 +1 @@ +Replaced asserts with exceptions in asyncio, patch by Kumar Aditya. \ No newline at end of file From webhook-mailer at python.org Mon Dec 6 19:07:46 2021 From: webhook-mailer at python.org (zooba) Date: Tue, 07 Dec 2021 00:07:46 -0000 Subject: [Python-checkins] bpo-45582: Ensure PYTHONHOME still overrides detected build prefixes (GH-29948) Message-ID: https://github.com/python/cpython/commit/b7ef27bc084665ce58d89fc69530c6f9d2d37754 commit: b7ef27bc084665ce58d89fc69530c6f9d2d37754 branch: main author: Steve Dower committer: zooba date: 2021-12-07T00:07:35Z summary: bpo-45582: Ensure PYTHONHOME still overrides detected build prefixes (GH-29948) files: M Lib/test/test_getpath.py M Modules/getpath.py diff --git a/Lib/test/test_getpath.py b/Lib/test/test_getpath.py index c18689c0590d4..9dd167b9975c0 100644 --- a/Lib/test/test_getpath.py +++ b/Lib/test/test_getpath.py @@ -208,6 +208,36 @@ def test_symlink_buildtree_win32(self): actual = getpath(ns, expected) self.assertEqual(expected, actual) + def test_buildtree_pythonhome_win32(self): + "Test an out-of-build-tree layout on Windows with PYTHONHOME override." + ns = MockNTNamespace( + argv0=r"C:\Out\python.exe", + real_executable=r"C:\Out\python.exe", + ENV_PYTHONHOME=r"C:\CPython", + ) + ns.add_known_xfile(r"C:\Out\python.exe") + ns.add_known_file(r"C:\CPython\Lib\os.py") + ns.add_known_file(r"C:\Out\pybuilddir.txt", [""]) + expected = dict( + executable=r"C:\Out\python.exe", + base_executable=r"C:\Out\python.exe", + prefix=r"C:\CPython", + exec_prefix=r"C:\CPython", + # This build_prefix is a miscalculation, because we have + # moved the output direction out of the prefix. + # Specify PYTHONHOME to get the correct prefix/exec_prefix + build_prefix="C:\\", + _is_python_build=1, + module_search_paths_set=1, + module_search_paths=[ + r"C:\Out\python98.zip", + r"C:\CPython\Lib", + r"C:\Out", + ], + ) + actual = getpath(ns, expected) + self.assertEqual(expected, actual) + def test_normal_posix(self): "Test a 'standard' install layout on *nix" ns = MockPosixNamespace( diff --git a/Modules/getpath.py b/Modules/getpath.py index 2eadfba1dfda2..4ef49a8847dd2 100644 --- a/Modules/getpath.py +++ b/Modules/getpath.py @@ -500,6 +500,8 @@ def search_up(prefix, *landmarks, test=isfile): prefix, had_delim, exec_prefix = home.partition(DELIM) if not had_delim: exec_prefix = prefix + # Reset the standard library directory if it was already set + stdlib_dir = None # First try to detect prefix by looking alongside our runtime library, if known From webhook-mailer at python.org Mon Dec 6 19:10:57 2021 From: webhook-mailer at python.org (miss-islington) Date: Tue, 07 Dec 2021 00:10:57 -0000 Subject: [Python-checkins] bpo-28953: Use `raise from` when raising new IncompleteRead (GH-29861) Message-ID: https://github.com/python/cpython/commit/c5c365220ed2c867fe81078f70b827de22db2ee6 commit: c5c365220ed2c867fe81078f70b827de22db2ee6 branch: main author: 180909 <734461790 at qq.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-06T16:10:49-08:00 summary: bpo-28953: Use `raise from` when raising new IncompleteRead (GH-29861) Automerge-Triggered-By: GH:asvetlov files: M Lib/http/client.py diff --git a/Lib/http/client.py b/Lib/http/client.py index a6ab135b2c387..f54172fd0deea 100644 --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -593,8 +593,8 @@ def _read_chunked(self, amt=None): amt -= chunk_left self.chunk_left = 0 return b''.join(value) - except IncompleteRead: - raise IncompleteRead(b''.join(value)) + except IncompleteRead as exc: + raise IncompleteRead(b''.join(value)) from exc def _readinto_chunked(self, b): assert self.chunked != _UNKNOWN From webhook-mailer at python.org Mon Dec 6 21:35:55 2021 From: webhook-mailer at python.org (ned-deily) Date: Tue, 07 Dec 2021 02:35:55 -0000 Subject: [Python-checkins] bpo-45798: Let libmpdec decide which archs to build on macOS as done previously. (GH-29949) Message-ID: https://github.com/python/cpython/commit/ddbab69b6d44085564a9b5022b96b002a52b2f2b commit: ddbab69b6d44085564a9b5022b96b002a52b2f2b branch: main author: Ned Deily committer: ned-deily date: 2021-12-06T21:35:50-05:00 summary: bpo-45798: Let libmpdec decide which archs to build on macOS as done previously. (GH-29949) files: M configure M configure.ac diff --git a/configure b/configure index 2237e6ed8ce2a..608055d91fac3 100755 --- a/configure +++ b/configure @@ -11815,21 +11815,9 @@ esac libmpdec_machine=unknown if test "$libmpdec_system" = Darwin; then - case $MACOSX_DEFAULT_ARCH in #( - i386) : - libmpdec_machine=ansi32 ;; #( - ppc) : - libmpdec_machine=ansi32 ;; #( - x86_64) : - libmpdec_machine=x64 ;; #( - ppc64) : - libmpdec_machine=ansi64 ;; #( - arm64) : - libmpdec_machine=ansi64 ;; #( - *) : + # universal here means: build libmpdec with the same arch options + # the python interpreter was built with libmpdec_machine=universal - ;; -esac elif test $ac_cv_sizeof_size_t -eq 8; then if test "$ac_cv_gcc_asm_for_x64" = yes; then libmpdec_machine=x64 diff --git a/configure.ac b/configure.ac index f1aac2db71f5d..7cc6c0c2f592a 100644 --- a/configure.ac +++ b/configure.ac @@ -3295,14 +3295,9 @@ AS_CASE([$ac_sys_system], libmpdec_machine=unknown if test "$libmpdec_system" = Darwin; then - AS_CASE([$MACOSX_DEFAULT_ARCH], - [i386], [libmpdec_machine=ansi32], - [ppc], [libmpdec_machine=ansi32], - [x86_64], [libmpdec_machine=x64], - [ppc64], [libmpdec_machine=ansi64], - [arm64], [libmpdec_machine=ansi64], - [libmpdec_machine=universal] - ) + # universal here means: build libmpdec with the same arch options + # the python interpreter was built with + libmpdec_machine=universal elif test $ac_cv_sizeof_size_t -eq 8; then if test "$ac_cv_gcc_asm_for_x64" = yes; then libmpdec_machine=x64 From webhook-mailer at python.org Tue Dec 7 04:58:57 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Tue, 07 Dec 2021 09:58:57 -0000 Subject: [Python-checkins] bpo-46001: Change OverflowError to RecursionError in JSON library docstrings (GH-29943) Message-ID: https://github.com/python/cpython/commit/8db06528cacc94e67eb1fb2e4c2acc061a515671 commit: 8db06528cacc94e67eb1fb2e4c2acc061a515671 branch: main author: James Gerity committer: serhiy-storchaka date: 2021-12-07T11:58:40+02:00 summary: bpo-46001: Change OverflowError to RecursionError in JSON library docstrings (GH-29943) files: M Doc/library/json.rst M Lib/json/__init__.py M Lib/json/encoder.py diff --git a/Doc/library/json.rst b/Doc/library/json.rst index 6fa89f578a2cf..1810e04cc8349 100644 --- a/Doc/library/json.rst +++ b/Doc/library/json.rst @@ -159,7 +159,7 @@ Basic Usage If *check_circular* is false (default: ``True``), then the circular reference check for container types will be skipped and a circular reference - will result in an :exc:`OverflowError` (or worse). + will result in an :exc:`RecursionError` (or worse). If *allow_nan* is false (default: ``True``), then it will be a :exc:`ValueError` to serialize out of range :class:`float` values (``nan``, @@ -432,7 +432,7 @@ Encoders and Decoders If *check_circular* is true (the default), then lists, dicts, and custom encoded objects will be checked for circular references during encoding to - prevent an infinite recursion (which would cause an :exc:`OverflowError`). + prevent an infinite recursion (which would cause an :exc:`RecursionError`). Otherwise, no such check takes place. If *allow_nan* is true (the default), then ``NaN``, ``Infinity``, and diff --git a/Lib/json/__init__.py b/Lib/json/__init__.py index 2c52bdeba6754..e4c21daaf3e47 100644 --- a/Lib/json/__init__.py +++ b/Lib/json/__init__.py @@ -133,7 +133,7 @@ def dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, If ``check_circular`` is false, then the circular reference check for container types will be skipped and a circular reference will - result in an ``OverflowError`` (or worse). + result in an ``RecursionError`` (or worse). If ``allow_nan`` is false, then it will be a ``ValueError`` to serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) @@ -195,7 +195,7 @@ def dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, If ``check_circular`` is false, then the circular reference check for container types will be skipped and a circular reference will - result in an ``OverflowError`` (or worse). + result in an ``RecursionError`` (or worse). If ``allow_nan`` is false, then it will be a ``ValueError`` to serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in diff --git a/Lib/json/encoder.py b/Lib/json/encoder.py index c8c78b9c23765..21bff2c1a1fca 100644 --- a/Lib/json/encoder.py +++ b/Lib/json/encoder.py @@ -116,7 +116,7 @@ def __init__(self, *, skipkeys=False, ensure_ascii=True, If check_circular is true, then lists, dicts, and custom encoded objects will be checked for circular references during encoding to - prevent an infinite recursion (which would cause an OverflowError). + prevent an infinite recursion (which would cause an RecursionError). Otherwise, no such check takes place. If allow_nan is true, then NaN, Infinity, and -Infinity will be From webhook-mailer at python.org Tue Dec 7 05:20:21 2021 From: webhook-mailer at python.org (miss-islington) Date: Tue, 07 Dec 2021 10:20:21 -0000 Subject: [Python-checkins] bpo-46001: Change OverflowError to RecursionError in JSON library docstrings (GH-29943) Message-ID: https://github.com/python/cpython/commit/15da2a2723245710f1bd2c7cbd5b450532ae7728 commit: 15da2a2723245710f1bd2c7cbd5b450532ae7728 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-07T02:20:10-08:00 summary: bpo-46001: Change OverflowError to RecursionError in JSON library docstrings (GH-29943) (cherry picked from commit 8db06528cacc94e67eb1fb2e4c2acc061a515671) Co-authored-by: James Gerity files: M Doc/library/json.rst M Lib/json/__init__.py M Lib/json/encoder.py diff --git a/Doc/library/json.rst b/Doc/library/json.rst index 6fa89f578a2cf..1810e04cc8349 100644 --- a/Doc/library/json.rst +++ b/Doc/library/json.rst @@ -159,7 +159,7 @@ Basic Usage If *check_circular* is false (default: ``True``), then the circular reference check for container types will be skipped and a circular reference - will result in an :exc:`OverflowError` (or worse). + will result in an :exc:`RecursionError` (or worse). If *allow_nan* is false (default: ``True``), then it will be a :exc:`ValueError` to serialize out of range :class:`float` values (``nan``, @@ -432,7 +432,7 @@ Encoders and Decoders If *check_circular* is true (the default), then lists, dicts, and custom encoded objects will be checked for circular references during encoding to - prevent an infinite recursion (which would cause an :exc:`OverflowError`). + prevent an infinite recursion (which would cause an :exc:`RecursionError`). Otherwise, no such check takes place. If *allow_nan* is true (the default), then ``NaN``, ``Infinity``, and diff --git a/Lib/json/__init__.py b/Lib/json/__init__.py index 2c52bdeba6754..e4c21daaf3e47 100644 --- a/Lib/json/__init__.py +++ b/Lib/json/__init__.py @@ -133,7 +133,7 @@ def dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, If ``check_circular`` is false, then the circular reference check for container types will be skipped and a circular reference will - result in an ``OverflowError`` (or worse). + result in an ``RecursionError`` (or worse). If ``allow_nan`` is false, then it will be a ``ValueError`` to serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) @@ -195,7 +195,7 @@ def dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, If ``check_circular`` is false, then the circular reference check for container types will be skipped and a circular reference will - result in an ``OverflowError`` (or worse). + result in an ``RecursionError`` (or worse). If ``allow_nan`` is false, then it will be a ``ValueError`` to serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in diff --git a/Lib/json/encoder.py b/Lib/json/encoder.py index c8c78b9c23765..21bff2c1a1fca 100644 --- a/Lib/json/encoder.py +++ b/Lib/json/encoder.py @@ -116,7 +116,7 @@ def __init__(self, *, skipkeys=False, ensure_ascii=True, If check_circular is true, then lists, dicts, and custom encoded objects will be checked for circular references during encoding to - prevent an infinite recursion (which would cause an OverflowError). + prevent an infinite recursion (which would cause an RecursionError). Otherwise, no such check takes place. If allow_nan is true, then NaN, Infinity, and -Infinity will be From webhook-mailer at python.org Tue Dec 7 05:25:07 2021 From: webhook-mailer at python.org (miss-islington) Date: Tue, 07 Dec 2021 10:25:07 -0000 Subject: [Python-checkins] bpo-46001: Change OverflowError to RecursionError in JSON library docstrings (GH-29943) Message-ID: https://github.com/python/cpython/commit/2e360832d7ed2697d715e93cb9f859a52264d60b commit: 2e360832d7ed2697d715e93cb9f859a52264d60b branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-07T02:25:02-08:00 summary: bpo-46001: Change OverflowError to RecursionError in JSON library docstrings (GH-29943) (cherry picked from commit 8db06528cacc94e67eb1fb2e4c2acc061a515671) Co-authored-by: James Gerity files: M Doc/library/json.rst M Lib/json/__init__.py M Lib/json/encoder.py diff --git a/Doc/library/json.rst b/Doc/library/json.rst index 6fa89f578a2cf..1810e04cc8349 100644 --- a/Doc/library/json.rst +++ b/Doc/library/json.rst @@ -159,7 +159,7 @@ Basic Usage If *check_circular* is false (default: ``True``), then the circular reference check for container types will be skipped and a circular reference - will result in an :exc:`OverflowError` (or worse). + will result in an :exc:`RecursionError` (or worse). If *allow_nan* is false (default: ``True``), then it will be a :exc:`ValueError` to serialize out of range :class:`float` values (``nan``, @@ -432,7 +432,7 @@ Encoders and Decoders If *check_circular* is true (the default), then lists, dicts, and custom encoded objects will be checked for circular references during encoding to - prevent an infinite recursion (which would cause an :exc:`OverflowError`). + prevent an infinite recursion (which would cause an :exc:`RecursionError`). Otherwise, no such check takes place. If *allow_nan* is true (the default), then ``NaN``, ``Infinity``, and diff --git a/Lib/json/__init__.py b/Lib/json/__init__.py index 2c52bdeba6754..e4c21daaf3e47 100644 --- a/Lib/json/__init__.py +++ b/Lib/json/__init__.py @@ -133,7 +133,7 @@ def dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, If ``check_circular`` is false, then the circular reference check for container types will be skipped and a circular reference will - result in an ``OverflowError`` (or worse). + result in an ``RecursionError`` (or worse). If ``allow_nan`` is false, then it will be a ``ValueError`` to serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) @@ -195,7 +195,7 @@ def dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, If ``check_circular`` is false, then the circular reference check for container types will be skipped and a circular reference will - result in an ``OverflowError`` (or worse). + result in an ``RecursionError`` (or worse). If ``allow_nan`` is false, then it will be a ``ValueError`` to serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in diff --git a/Lib/json/encoder.py b/Lib/json/encoder.py index c8c78b9c23765..21bff2c1a1fca 100644 --- a/Lib/json/encoder.py +++ b/Lib/json/encoder.py @@ -116,7 +116,7 @@ def __init__(self, *, skipkeys=False, ensure_ascii=True, If check_circular is true, then lists, dicts, and custom encoded objects will be checked for circular references during encoding to - prevent an infinite recursion (which would cause an OverflowError). + prevent an infinite recursion (which would cause an RecursionError). Otherwise, no such check takes place. If allow_nan is true, then NaN, Infinity, and -Infinity will be From webhook-mailer at python.org Tue Dec 7 05:50:52 2021 From: webhook-mailer at python.org (markshannon) Date: Tue, 07 Dec 2021 10:50:52 -0000 Subject: [Python-checkins] bpo-45890: Add tests for tracing try-except-finally blocks (GH-29746) Message-ID: https://github.com/python/cpython/commit/a310fd83a014484b8c680de83540c4908b344c6c commit: a310fd83a014484b8c680de83540c4908b344c6c branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: markshannon date: 2021-12-07T10:50:37Z summary: bpo-45890: Add tests for tracing try-except-finally blocks (GH-29746) files: M Lib/test/test_sys_settrace.py M Lib/test/test_trace.py diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py index b565bef4c4423..15c33a28ff2ac 100644 --- a/Lib/test/test_sys_settrace.py +++ b/Lib/test/test_sys_settrace.py @@ -642,15 +642,18 @@ def func(): 2 except: 4 - finally: + else: 6 + finally: + 8 self.run_and_compare(func, [(0, 'call'), (1, 'line'), (2, 'line'), (6, 'line'), - (6, 'return')]) + (8, 'line'), + (8, 'return')]) def test_nested_loops(self): @@ -1016,6 +1019,47 @@ def func(): (3, 'line'), (3, 'return')]) + def test_try_in_try_with_exception(self): + + def func(): + try: + try: + raise TypeError + except ValueError as ex: + 5 + except TypeError: + 7 + + self.run_and_compare(func, + [(0, 'call'), + (1, 'line'), + (2, 'line'), + (3, 'line'), + (3, 'exception'), + (4, 'line'), + (6, 'line'), + (7, 'line'), + (7, 'return')]) + + def func(): + try: + try: + raise ValueError + except ValueError as ex: + 5 + except TypeError: + 7 + + self.run_and_compare(func, + [(0, 'call'), + (1, 'line'), + (2, 'line'), + (3, 'line'), + (3, 'exception'), + (4, 'line'), + (5, 'line'), + (5, 'return')]) + def test_if_in_if_in_if(self): def func(a=0, p=1, z=1): if p: diff --git a/Lib/test/test_trace.py b/Lib/test/test_trace.py index dbfefca7ee5cd..d63c1778c9d08 100644 --- a/Lib/test/test_trace.py +++ b/Lib/test/test_trace.py @@ -11,6 +11,11 @@ from test.tracedmodules import testmod +## +## See also test_sys_settrace.py, which contains tests that cover +## tracing of many more code blocks. +## + #------------------------------- Utilities -----------------------------------# def fix_ext_py(filename): From webhook-mailer at python.org Tue Dec 7 06:15:54 2021 From: webhook-mailer at python.org (vsajip) Date: Tue, 07 Dec 2021 11:15:54 -0000 Subject: [Python-checkins] bpo-35821: Add an example to Logger.propagate documentation. (GH-29841) Message-ID: https://github.com/python/cpython/commit/2bf551757e0a7e3cc6ce2ebed2178b82438ac6b5 commit: 2bf551757e0a7e3cc6ce2ebed2178b82438ac6b5 branch: main author: Vinay Sajip committer: vsajip date: 2021-12-07T11:15:44Z summary: bpo-35821: Add an example to Logger.propagate documentation. (GH-29841) files: M Doc/library/logging.rst diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index 3f3a8534f54d0..e7c64e5ba4036 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -80,6 +80,15 @@ is the module's name in the Python package namespace. If this evaluates to false, logging messages are not passed to the handlers of ancestor loggers. + Spelling it out with an example: If the propagate attribute of the logger named + `A.B.C` evaluates to true, any event logged to `A.B.C` via a method call such as + `logging.getLogger('A.B.C').error(...)` will [subject to passing that logger's + level and filter settings] be passed in turn to any handlers attached to loggers + named `A.B`, `A` and the root logger, after first being passed to any handlers + attached to `A.B.C`. If any logger in the chain `A.B.C`, `A.B`, `A` has its + `propagate` attribute set to false, then that is the last logger whose handlers + are offered the event to handle, and propagation stops at that point. + The constructor sets this attribute to ``True``. .. note:: If you attach a handler to a logger *and* one or more of its From webhook-mailer at python.org Tue Dec 7 06:31:11 2021 From: webhook-mailer at python.org (vstinner) Date: Tue, 07 Dec 2021 11:31:11 -0000 Subject: [Python-checkins] Revert "bpo-28533: Remove asyncore, asynchat, smtpd modules (GH-29521)" (GH-29951) Message-ID: https://github.com/python/cpython/commit/cf7eaa4617295747ee5646c4e2b7e7a16d7c64ab commit: cf7eaa4617295747ee5646c4e2b7e7a16d7c64ab branch: main author: Victor Stinner committer: vstinner date: 2021-12-07T12:31:04+01:00 summary: Revert "bpo-28533: Remove asyncore, asynchat, smtpd modules (GH-29521)" (GH-29951) This reverts commit 9bf2cbc4c498812e14f20d86acb61c53928a5a57. files: A Doc/library/asynchat.rst A Doc/library/asyncore.rst A Doc/library/smtpd.rst A Lib/asynchat.py A Lib/asyncore.py A Lib/smtpd.py A Lib/test/test_asynchat.py A Lib/test/test_asyncore.py A Lib/test/test_smtpd.py D Lib/test/support/_asynchat.py D Lib/test/support/_asyncore.py D Lib/test/support/_smtpd.py D Misc/NEWS.d/next/Library/2021-11-11-12-59-10.bpo-28533.68mMZa.rst D Misc/NEWS.d/next/Library/2021-11-11-12-59-49.bpo-28533.LvIFCQ.rst M .github/CODEOWNERS M Doc/library/email.rst M Doc/library/internet.rst M Doc/library/ipc.rst M Doc/library/socketserver.rst M Doc/license.rst M Doc/whatsnew/3.11.rst M Lib/test/libregrtest/save_env.py M Lib/test/mock_socket.py M Lib/test/test_ftplib.py M Lib/test/test_logging.py M Lib/test/test_os.py M Lib/test/test_poplib.py M Lib/test/test_smtplib.py M Lib/test/test_ssl.py M PCbuild/lib.pyproj M Python/stdlib_module_names.h diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 82f81e3452995..ce5121e7ac8f8 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -130,6 +130,8 @@ Lib/ast.py @isidentical **/*typing* @gvanrossum @Fidget-Spinner +**/*asyncore @giampaolo +**/*asynchat @giampaolo **/*ftplib @giampaolo **/*shutil @giampaolo diff --git a/Doc/library/asynchat.rst b/Doc/library/asynchat.rst new file mode 100644 index 0000000000000..9e51416b83a57 --- /dev/null +++ b/Doc/library/asynchat.rst @@ -0,0 +1,213 @@ +:mod:`asynchat` --- Asynchronous socket command/response handler +================================================================ + +.. module:: asynchat + :synopsis: Support for asynchronous command/response protocols. + +.. moduleauthor:: Sam Rushing +.. sectionauthor:: Steve Holden + +**Source code:** :source:`Lib/asynchat.py` + +.. deprecated:: 3.6 + Please use :mod:`asyncio` instead. + +-------------- + +.. note:: + + This module exists for backwards compatibility only. For new code we + recommend using :mod:`asyncio`. + +This module builds on the :mod:`asyncore` infrastructure, simplifying +asynchronous clients and servers and making it easier to handle protocols +whose elements are terminated by arbitrary strings, or are of variable length. +:mod:`asynchat` defines the abstract class :class:`async_chat` that you +subclass, providing implementations of the :meth:`collect_incoming_data` and +:meth:`found_terminator` methods. It uses the same asynchronous loop as +:mod:`asyncore`, and the two types of channel, :class:`asyncore.dispatcher` +and :class:`asynchat.async_chat`, can freely be mixed in the channel map. +Typically an :class:`asyncore.dispatcher` server channel generates new +:class:`asynchat.async_chat` channel objects as it receives incoming +connection requests. + + +.. class:: async_chat() + + This class is an abstract subclass of :class:`asyncore.dispatcher`. To make + practical use of the code you must subclass :class:`async_chat`, providing + meaningful :meth:`collect_incoming_data` and :meth:`found_terminator` + methods. + The :class:`asyncore.dispatcher` methods can be used, although not all make + sense in a message/response context. + + Like :class:`asyncore.dispatcher`, :class:`async_chat` defines a set of + events that are generated by an analysis of socket conditions after a + :c:func:`select` call. Once the polling loop has been started the + :class:`async_chat` object's methods are called by the event-processing + framework with no action on the part of the programmer. + + Two class attributes can be modified, to improve performance, or possibly + even to conserve memory. + + + .. data:: ac_in_buffer_size + + The asynchronous input buffer size (default ``4096``). + + + .. data:: ac_out_buffer_size + + The asynchronous output buffer size (default ``4096``). + + Unlike :class:`asyncore.dispatcher`, :class:`async_chat` allows you to + define a :abbr:`FIFO (first-in, first-out)` queue of *producers*. A producer need + have only one method, :meth:`more`, which should return data to be + transmitted on the channel. + The producer indicates exhaustion (*i.e.* that it contains no more data) by + having its :meth:`more` method return the empty bytes object. At this point + the :class:`async_chat` object removes the producer from the queue and starts + using the next producer, if any. When the producer queue is empty the + :meth:`handle_write` method does nothing. You use the channel object's + :meth:`set_terminator` method to describe how to recognize the end of, or + an important breakpoint in, an incoming transmission from the remote + endpoint. + + To build a functioning :class:`async_chat` subclass your input methods + :meth:`collect_incoming_data` and :meth:`found_terminator` must handle the + data that the channel receives asynchronously. The methods are described + below. + + +.. method:: async_chat.close_when_done() + + Pushes a ``None`` on to the producer queue. When this producer is popped off + the queue it causes the channel to be closed. + + +.. method:: async_chat.collect_incoming_data(data) + + Called with *data* holding an arbitrary amount of received data. The + default method, which must be overridden, raises a + :exc:`NotImplementedError` exception. + + +.. method:: async_chat.discard_buffers() + + In emergencies this method will discard any data held in the input and/or + output buffers and the producer queue. + + +.. method:: async_chat.found_terminator() + + Called when the incoming data stream matches the termination condition set + by :meth:`set_terminator`. The default method, which must be overridden, + raises a :exc:`NotImplementedError` exception. The buffered input data + should be available via an instance attribute. + + +.. method:: async_chat.get_terminator() + + Returns the current terminator for the channel. + + +.. method:: async_chat.push(data) + + Pushes data on to the channel's queue to ensure its transmission. + This is all you need to do to have the channel write the data out to the + network, although it is possible to use your own producers in more complex + schemes to implement encryption and chunking, for example. + + +.. method:: async_chat.push_with_producer(producer) + + Takes a producer object and adds it to the producer queue associated with + the channel. When all currently-pushed producers have been exhausted the + channel will consume this producer's data by calling its :meth:`more` + method and send the data to the remote endpoint. + + +.. method:: async_chat.set_terminator(term) + + Sets the terminating condition to be recognized on the channel. ``term`` + may be any of three types of value, corresponding to three different ways + to handle incoming protocol data. + + +-----------+---------------------------------------------+ + | term | Description | + +===========+=============================================+ + | *string* | Will call :meth:`found_terminator` when the | + | | string is found in the input stream | + +-----------+---------------------------------------------+ + | *integer* | Will call :meth:`found_terminator` when the | + | | indicated number of characters have been | + | | received | + +-----------+---------------------------------------------+ + | ``None`` | The channel continues to collect data | + | | forever | + +-----------+---------------------------------------------+ + + Note that any data following the terminator will be available for reading + by the channel after :meth:`found_terminator` is called. + + +.. _asynchat-example: + +asynchat Example +---------------- + +The following partial example shows how HTTP requests can be read with +:class:`async_chat`. A web server might create an +:class:`http_request_handler` object for each incoming client connection. +Notice that initially the channel terminator is set to match the blank line at +the end of the HTTP headers, and a flag indicates that the headers are being +read. + +Once the headers have been read, if the request is of type POST (indicating +that further data are present in the input stream) then the +``Content-Length:`` header is used to set a numeric terminator to read the +right amount of data from the channel. + +The :meth:`handle_request` method is called once all relevant input has been +marshalled, after setting the channel terminator to ``None`` to ensure that +any extraneous data sent by the web client are ignored. :: + + + import asynchat + + class http_request_handler(asynchat.async_chat): + + def __init__(self, sock, addr, sessions, log): + asynchat.async_chat.__init__(self, sock=sock) + self.addr = addr + self.sessions = sessions + self.ibuffer = [] + self.obuffer = b"" + self.set_terminator(b"\r\n\r\n") + self.reading_headers = True + self.handling = False + self.cgi_data = None + self.log = log + + def collect_incoming_data(self, data): + """Buffer the data""" + self.ibuffer.append(data) + + def found_terminator(self): + if self.reading_headers: + self.reading_headers = False + self.parse_headers(b"".join(self.ibuffer)) + self.ibuffer = [] + if self.op.upper() == b"POST": + clen = self.headers.getheader("content-length") + self.set_terminator(int(clen)) + else: + self.handling = True + self.set_terminator(None) + self.handle_request() + elif not self.handling: + self.set_terminator(None) # browsers sometimes over-send + self.cgi_data = parse(self.headers, b"".join(self.ibuffer)) + self.handling = True + self.ibuffer = [] + self.handle_request() diff --git a/Doc/library/asyncore.rst b/Doc/library/asyncore.rst new file mode 100644 index 0000000000000..a86518ebff277 --- /dev/null +++ b/Doc/library/asyncore.rst @@ -0,0 +1,360 @@ +:mod:`asyncore` --- Asynchronous socket handler +=============================================== + +.. module:: asyncore + :synopsis: A base class for developing asynchronous socket handling + services. + +.. moduleauthor:: Sam Rushing +.. sectionauthor:: Christopher Petrilli +.. sectionauthor:: Steve Holden +.. heavily adapted from original documentation by Sam Rushing + +**Source code:** :source:`Lib/asyncore.py` + +.. deprecated:: 3.6 + Please use :mod:`asyncio` instead. + +-------------- + +.. note:: + + This module exists for backwards compatibility only. For new code we + recommend using :mod:`asyncio`. + +This module provides the basic infrastructure for writing asynchronous socket +service clients and servers. + +There are only two ways to have a program on a single processor do "more than +one thing at a time." Multi-threaded programming is the simplest and most +popular way to do it, but there is another very different technique, that lets +you have nearly all the advantages of multi-threading, without actually using +multiple threads. It's really only practical if your program is largely I/O +bound. If your program is processor bound, then pre-emptive scheduled threads +are probably what you really need. Network servers are rarely processor +bound, however. + +If your operating system supports the :c:func:`select` system call in its I/O +library (and nearly all do), then you can use it to juggle multiple +communication channels at once; doing other work while your I/O is taking +place in the "background." Although this strategy can seem strange and +complex, especially at first, it is in many ways easier to understand and +control than multi-threaded programming. The :mod:`asyncore` module solves +many of the difficult problems for you, making the task of building +sophisticated high-performance network servers and clients a snap. For +"conversational" applications and protocols the companion :mod:`asynchat` +module is invaluable. + +The basic idea behind both modules is to create one or more network +*channels*, instances of class :class:`asyncore.dispatcher` and +:class:`asynchat.async_chat`. Creating the channels adds them to a global +map, used by the :func:`loop` function if you do not provide it with your own +*map*. + +Once the initial channel(s) is(are) created, calling the :func:`loop` function +activates channel service, which continues until the last channel (including +any that have been added to the map during asynchronous service) is closed. + + +.. function:: loop([timeout[, use_poll[, map[,count]]]]) + + Enter a polling loop that terminates after count passes or all open + channels have been closed. All arguments are optional. The *count* + parameter defaults to ``None``, resulting in the loop terminating only when all + channels have been closed. The *timeout* argument sets the timeout + parameter for the appropriate :func:`~select.select` or :func:`~select.poll` + call, measured in seconds; the default is 30 seconds. The *use_poll* + parameter, if true, indicates that :func:`~select.poll` should be used in + preference to :func:`~select.select` (the default is ``False``). + + The *map* parameter is a dictionary whose items are the channels to watch. + As channels are closed they are deleted from their map. If *map* is + omitted, a global map is used. Channels (instances of + :class:`asyncore.dispatcher`, :class:`asynchat.async_chat` and subclasses + thereof) can freely be mixed in the map. + + +.. class:: dispatcher() + + The :class:`dispatcher` class is a thin wrapper around a low-level socket + object. To make it more useful, it has a few methods for event-handling + which are called from the asynchronous loop. Otherwise, it can be treated + as a normal non-blocking socket object. + + The firing of low-level events at certain times or in certain connection + states tells the asynchronous loop that certain higher-level events have + taken place. For example, if we have asked for a socket to connect to + another host, we know that the connection has been made when the socket + becomes writable for the first time (at this point you know that you may + write to it with the expectation of success). The implied higher-level + events are: + + +----------------------+----------------------------------------+ + | Event | Description | + +======================+========================================+ + | ``handle_connect()`` | Implied by the first read or write | + | | event | + +----------------------+----------------------------------------+ + | ``handle_close()`` | Implied by a read event with no data | + | | available | + +----------------------+----------------------------------------+ + | ``handle_accepted()``| Implied by a read event on a listening | + | | socket | + +----------------------+----------------------------------------+ + + During asynchronous processing, each mapped channel's :meth:`readable` and + :meth:`writable` methods are used to determine whether the channel's socket + should be added to the list of channels :c:func:`select`\ ed or + :c:func:`poll`\ ed for read and write events. + + Thus, the set of channel events is larger than the basic socket events. The + full set of methods that can be overridden in your subclass follows: + + + .. method:: handle_read() + + Called when the asynchronous loop detects that a :meth:`read` call on the + channel's socket will succeed. + + + .. method:: handle_write() + + Called when the asynchronous loop detects that a writable socket can be + written. Often this method will implement the necessary buffering for + performance. For example:: + + def handle_write(self): + sent = self.send(self.buffer) + self.buffer = self.buffer[sent:] + + + .. method:: handle_expt() + + Called when there is out of band (OOB) data for a socket connection. This + will almost never happen, as OOB is tenuously supported and rarely used. + + + .. method:: handle_connect() + + Called when the active opener's socket actually makes a connection. Might + send a "welcome" banner, or initiate a protocol negotiation with the + remote endpoint, for example. + + + .. method:: handle_close() + + Called when the socket is closed. + + + .. method:: handle_error() + + Called when an exception is raised and not otherwise handled. The default + version prints a condensed traceback. + + + .. method:: handle_accept() + + Called on listening channels (passive openers) when a connection can be + established with a new remote endpoint that has issued a :meth:`connect` + call for the local endpoint. Deprecated in version 3.2; use + :meth:`handle_accepted` instead. + + .. deprecated:: 3.2 + + + .. method:: handle_accepted(sock, addr) + + Called on listening channels (passive openers) when a connection has been + established with a new remote endpoint that has issued a :meth:`connect` + call for the local endpoint. *sock* is a *new* socket object usable to + send and receive data on the connection, and *addr* is the address + bound to the socket on the other end of the connection. + + .. versionadded:: 3.2 + + + .. method:: readable() + + Called each time around the asynchronous loop to determine whether a + channel's socket should be added to the list on which read events can + occur. The default method simply returns ``True``, indicating that by + default, all channels will be interested in read events. + + + .. method:: writable() + + Called each time around the asynchronous loop to determine whether a + channel's socket should be added to the list on which write events can + occur. The default method simply returns ``True``, indicating that by + default, all channels will be interested in write events. + + + In addition, each channel delegates or extends many of the socket methods. + Most of these are nearly identical to their socket partners. + + + .. method:: create_socket(family=socket.AF_INET, type=socket.SOCK_STREAM) + + This is identical to the creation of a normal socket, and will use the + same options for creation. Refer to the :mod:`socket` documentation for + information on creating sockets. + + .. versionchanged:: 3.3 + *family* and *type* arguments can be omitted. + + + .. method:: connect(address) + + As with the normal socket object, *address* is a tuple with the first + element the host to connect to, and the second the port number. + + + .. method:: send(data) + + Send *data* to the remote end-point of the socket. + + + .. method:: recv(buffer_size) + + Read at most *buffer_size* bytes from the socket's remote end-point. An + empty bytes object implies that the channel has been closed from the + other end. + + Note that :meth:`recv` may raise :exc:`BlockingIOError` , even though + :func:`select.select` or :func:`select.poll` has reported the socket + ready for reading. + + + .. method:: listen(backlog) + + Listen for connections made to the socket. The *backlog* argument + specifies the maximum number of queued connections and should be at least + 1; the maximum value is system-dependent (usually 5). + + + .. method:: bind(address) + + Bind the socket to *address*. The socket must not already be bound. (The + format of *address* depends on the address family --- refer to the + :mod:`socket` documentation for more information.) To mark + the socket as re-usable (setting the :const:`SO_REUSEADDR` option), call + the :class:`dispatcher` object's :meth:`set_reuse_addr` method. + + + .. method:: accept() + + Accept a connection. The socket must be bound to an address and listening + for connections. The return value can be either ``None`` or a pair + ``(conn, address)`` where *conn* is a *new* socket object usable to send + and receive data on the connection, and *address* is the address bound to + the socket on the other end of the connection. + When ``None`` is returned it means the connection didn't take place, in + which case the server should just ignore this event and keep listening + for further incoming connections. + + + .. method:: close() + + Close the socket. All future operations on the socket object will fail. + The remote end-point will receive no more data (after queued data is + flushed). Sockets are automatically closed when they are + garbage-collected. + + +.. class:: dispatcher_with_send() + + A :class:`dispatcher` subclass which adds simple buffered output capability, + useful for simple clients. For more sophisticated usage use + :class:`asynchat.async_chat`. + +.. class:: file_dispatcher() + + A file_dispatcher takes a file descriptor or :term:`file object` along + with an optional map argument and wraps it for use with the :c:func:`poll` + or :c:func:`loop` functions. If provided a file object or anything with a + :c:func:`fileno` method, that method will be called and passed to the + :class:`file_wrapper` constructor. + + .. availability:: Unix. + +.. class:: file_wrapper() + + A file_wrapper takes an integer file descriptor and calls :func:`os.dup` to + duplicate the handle so that the original handle may be closed independently + of the file_wrapper. This class implements sufficient methods to emulate a + socket for use by the :class:`file_dispatcher` class. + + .. availability:: Unix. + + +.. _asyncore-example-1: + +asyncore Example basic HTTP client +---------------------------------- + +Here is a very basic HTTP client that uses the :class:`dispatcher` class to +implement its socket handling:: + + import asyncore + + class HTTPClient(asyncore.dispatcher): + + def __init__(self, host, path): + asyncore.dispatcher.__init__(self) + self.create_socket() + self.connect( (host, 80) ) + self.buffer = bytes('GET %s HTTP/1.0\r\nHost: %s\r\n\r\n' % + (path, host), 'ascii') + + def handle_connect(self): + pass + + def handle_close(self): + self.close() + + def handle_read(self): + print(self.recv(8192)) + + def writable(self): + return (len(self.buffer) > 0) + + def handle_write(self): + sent = self.send(self.buffer) + self.buffer = self.buffer[sent:] + + + client = HTTPClient('www.python.org', '/') + asyncore.loop() + +.. _asyncore-example-2: + +asyncore Example basic echo server +---------------------------------- + +Here is a basic echo server that uses the :class:`dispatcher` class to accept +connections and dispatches the incoming connections to a handler:: + + import asyncore + + class EchoHandler(asyncore.dispatcher_with_send): + + def handle_read(self): + data = self.recv(8192) + if data: + self.send(data) + + class EchoServer(asyncore.dispatcher): + + def __init__(self, host, port): + asyncore.dispatcher.__init__(self) + self.create_socket() + self.set_reuse_addr() + self.bind((host, port)) + self.listen(5) + + def handle_accepted(self, sock, addr): + print('Incoming connection from %s' % repr(addr)) + handler = EchoHandler(sock) + + server = EchoServer('localhost', 8080) + asyncore.loop() diff --git a/Doc/library/email.rst b/Doc/library/email.rst index 816fae991d24c..5eebcd9e896d9 100644 --- a/Doc/library/email.rst +++ b/Doc/library/email.rst @@ -147,3 +147,6 @@ Legacy API: Module :mod:`mailbox` Tools for creating, reading, and managing collections of messages on disk using a variety standard formats. + + Module :mod:`smtpd` + SMTP server framework (primarily useful for testing) diff --git a/Doc/library/internet.rst b/Doc/library/internet.rst index 65693c9b3b200..e745dd1243512 100644 --- a/Doc/library/internet.rst +++ b/Doc/library/internet.rst @@ -35,6 +35,7 @@ is currently supported on most popular platforms. Here is an overview: imaplib.rst nntplib.rst smtplib.rst + smtpd.rst telnetlib.rst uuid.rst socketserver.rst diff --git a/Doc/library/ipc.rst b/Doc/library/ipc.rst index 4849c82f317d9..b88a174eb97f1 100644 --- a/Doc/library/ipc.rst +++ b/Doc/library/ipc.rst @@ -22,5 +22,7 @@ The list of modules described in this chapter is: ssl.rst select.rst selectors.rst + asyncore.rst + asynchat.rst signal.rst mmap.rst diff --git a/Doc/library/smtpd.rst b/Doc/library/smtpd.rst new file mode 100644 index 0000000000000..611411ddd295b --- /dev/null +++ b/Doc/library/smtpd.rst @@ -0,0 +1,264 @@ +:mod:`smtpd` --- SMTP Server +============================ + +.. module:: smtpd + :synopsis: A SMTP server implementation in Python. + +.. moduleauthor:: Barry Warsaw +.. sectionauthor:: Moshe Zadka + +**Source code:** :source:`Lib/smtpd.py` + +-------------- + +This module offers several classes to implement SMTP (email) servers. + +.. deprecated:: 3.6 + The `aiosmtpd `_ package is a recommended + replacement for this module. It is based on :mod:`asyncio` and provides a + more straightforward API. + +Several server implementations are present; one is a generic +do-nothing implementation, which can be overridden, while the other two offer +specific mail-sending strategies. + +Additionally the SMTPChannel may be extended to implement very specific +interaction behaviour with SMTP clients. + +The code supports :RFC:`5321`, plus the :rfc:`1870` SIZE and :rfc:`6531` +SMTPUTF8 extensions. + + +SMTPServer Objects +------------------ + + +.. class:: SMTPServer(localaddr, remoteaddr, data_size_limit=33554432,\ + map=None, enable_SMTPUTF8=False, decode_data=False) + + Create a new :class:`SMTPServer` object, which binds to local address + *localaddr*. It will treat *remoteaddr* as an upstream SMTP relayer. Both + *localaddr* and *remoteaddr* should be a :ref:`(host, port) ` + tuple. The object inherits from :class:`asyncore.dispatcher`, and so will + insert itself into :mod:`asyncore`'s event loop on instantiation. + + *data_size_limit* specifies the maximum number of bytes that will be + accepted in a ``DATA`` command. A value of ``None`` or ``0`` means no + limit. + + *map* is the socket map to use for connections (an initially empty + dictionary is a suitable value). If not specified the :mod:`asyncore` + global socket map is used. + + *enable_SMTPUTF8* determines whether the ``SMTPUTF8`` extension (as defined + in :RFC:`6531`) should be enabled. The default is ``False``. + When ``True``, ``SMTPUTF8`` is accepted as a parameter to the ``MAIL`` + command and when present is passed to :meth:`process_message` in the + ``kwargs['mail_options']`` list. *decode_data* and *enable_SMTPUTF8* + cannot be set to ``True`` at the same time. + + *decode_data* specifies whether the data portion of the SMTP transaction + should be decoded using UTF-8. When *decode_data* is ``False`` (the + default), the server advertises the ``8BITMIME`` + extension (:rfc:`6152`), accepts the ``BODY=8BITMIME`` parameter to + the ``MAIL`` command, and when present passes it to :meth:`process_message` + in the ``kwargs['mail_options']`` list. *decode_data* and *enable_SMTPUTF8* + cannot be set to ``True`` at the same time. + + .. method:: process_message(peer, mailfrom, rcpttos, data, **kwargs) + + Raise a :exc:`NotImplementedError` exception. Override this in subclasses to + do something useful with this message. Whatever was passed in the + constructor as *remoteaddr* will be available as the :attr:`_remoteaddr` + attribute. *peer* is the remote host's address, *mailfrom* is the envelope + originator, *rcpttos* are the envelope recipients and *data* is a string + containing the contents of the e-mail (which should be in :rfc:`5321` + format). + + If the *decode_data* constructor keyword is set to ``True``, the *data* + argument will be a unicode string. If it is set to ``False``, it + will be a bytes object. + + *kwargs* is a dictionary containing additional information. It is empty + if ``decode_data=True`` was given as an init argument, otherwise + it contains the following keys: + + *mail_options*: + a list of all received parameters to the ``MAIL`` + command (the elements are uppercase strings; example: + ``['BODY=8BITMIME', 'SMTPUTF8']``). + + *rcpt_options*: + same as *mail_options* but for the ``RCPT`` command. + Currently no ``RCPT TO`` options are supported, so for now + this will always be an empty list. + + Implementations of ``process_message`` should use the ``**kwargs`` + signature to accept arbitrary keyword arguments, since future feature + enhancements may add keys to the kwargs dictionary. + + Return ``None`` to request a normal ``250 Ok`` response; otherwise + return the desired response string in :RFC:`5321` format. + + .. attribute:: channel_class + + Override this in subclasses to use a custom :class:`SMTPChannel` for + managing SMTP clients. + + .. versionadded:: 3.4 + The *map* constructor argument. + + .. versionchanged:: 3.5 + *localaddr* and *remoteaddr* may now contain IPv6 addresses. + + .. versionadded:: 3.5 + The *decode_data* and *enable_SMTPUTF8* constructor parameters, and the + *kwargs* parameter to :meth:`process_message` when *decode_data* is + ``False``. + + .. versionchanged:: 3.6 + *decode_data* is now ``False`` by default. + + +DebuggingServer Objects +----------------------- + + +.. class:: DebuggingServer(localaddr, remoteaddr) + + Create a new debugging server. Arguments are as per :class:`SMTPServer`. + Messages will be discarded, and printed on stdout. + + +PureProxy Objects +----------------- + + +.. class:: PureProxy(localaddr, remoteaddr) + + Create a new pure proxy server. Arguments are as per :class:`SMTPServer`. + Everything will be relayed to *remoteaddr*. Note that running this has a good + chance to make you into an open relay, so please be careful. + + +SMTPChannel Objects +------------------- + +.. class:: SMTPChannel(server, conn, addr, data_size_limit=33554432,\ + map=None, enable_SMTPUTF8=False, decode_data=False) + + Create a new :class:`SMTPChannel` object which manages the communication + between the server and a single SMTP client. + + *conn* and *addr* are as per the instance variables described below. + + *data_size_limit* specifies the maximum number of bytes that will be + accepted in a ``DATA`` command. A value of ``None`` or ``0`` means no + limit. + + *enable_SMTPUTF8* determines whether the ``SMTPUTF8`` extension (as defined + in :RFC:`6531`) should be enabled. The default is ``False``. + *decode_data* and *enable_SMTPUTF8* cannot be set to ``True`` at the same + time. + + A dictionary can be specified in *map* to avoid using a global socket map. + + *decode_data* specifies whether the data portion of the SMTP transaction + should be decoded using UTF-8. The default is ``False``. + *decode_data* and *enable_SMTPUTF8* cannot be set to ``True`` at the same + time. + + To use a custom SMTPChannel implementation you need to override the + :attr:`SMTPServer.channel_class` of your :class:`SMTPServer`. + + .. versionchanged:: 3.5 + The *decode_data* and *enable_SMTPUTF8* parameters were added. + + .. versionchanged:: 3.6 + *decode_data* is now ``False`` by default. + + The :class:`SMTPChannel` has the following instance variables: + + .. attribute:: smtp_server + + Holds the :class:`SMTPServer` that spawned this channel. + + .. attribute:: conn + + Holds the socket object connecting to the client. + + .. attribute:: addr + + Holds the address of the client, the second value returned by + :func:`socket.accept ` + + .. attribute:: received_lines + + Holds a list of the line strings (decoded using UTF-8) received from + the client. The lines have their ``"\r\n"`` line ending translated to + ``"\n"``. + + .. attribute:: smtp_state + + Holds the current state of the channel. This will be either + :attr:`COMMAND` initially and then :attr:`DATA` after the client sends + a "DATA" line. + + .. attribute:: seen_greeting + + Holds a string containing the greeting sent by the client in its "HELO". + + .. attribute:: mailfrom + + Holds a string containing the address identified in the "MAIL FROM:" line + from the client. + + .. attribute:: rcpttos + + Holds a list of strings containing the addresses identified in the + "RCPT TO:" lines from the client. + + .. attribute:: received_data + + Holds a string containing all of the data sent by the client during the + DATA state, up to but not including the terminating ``"\r\n.\r\n"``. + + .. attribute:: fqdn + + Holds the fully-qualified domain name of the server as returned by + :func:`socket.getfqdn`. + + .. attribute:: peer + + Holds the name of the client peer as returned by ``conn.getpeername()`` + where ``conn`` is :attr:`conn`. + + The :class:`SMTPChannel` operates by invoking methods named ``smtp_`` + upon reception of a command line from the client. Built into the base + :class:`SMTPChannel` class are methods for handling the following commands + (and responding to them appropriately): + + ======== =================================================================== + Command Action taken + ======== =================================================================== + HELO Accepts the greeting from the client and stores it in + :attr:`seen_greeting`. Sets server to base command mode. + EHLO Accepts the greeting from the client and stores it in + :attr:`seen_greeting`. Sets server to extended command mode. + NOOP Takes no action. + QUIT Closes the connection cleanly. + MAIL Accepts the "MAIL FROM:" syntax and stores the supplied address as + :attr:`mailfrom`. In extended command mode, accepts the + :rfc:`1870` SIZE attribute and responds appropriately based on the + value of *data_size_limit*. + RCPT Accepts the "RCPT TO:" syntax and stores the supplied addresses in + the :attr:`rcpttos` list. + RSET Resets the :attr:`mailfrom`, :attr:`rcpttos`, and + :attr:`received_data`, but not the greeting. + DATA Sets the internal state to :attr:`DATA` and stores remaining lines + from the client in :attr:`received_data` until the terminator + ``"\r\n.\r\n"`` is received. + HELP Returns minimal information on command syntax + VRFY Returns code 252 (the server doesn't know if the address is valid) + EXPN Reports that the command is not implemented. + ======== =================================================================== diff --git a/Doc/library/socketserver.rst b/Doc/library/socketserver.rst index 8aa72bd7332ef..b65a3e8fb2b97 100644 --- a/Doc/library/socketserver.rst +++ b/Doc/library/socketserver.rst @@ -176,7 +176,7 @@ partially finished requests and to use :mod:`selectors` to decide which request to work on next (or whether to handle a new incoming request). This is particularly important for stream services where each client can potentially be connected for a long time (if threads or subprocesses cannot be used). See -:mod:`asyncio` for another way to manage this. +:mod:`asyncore` for another way to manage this. .. XXX should data and methods be intermingled, or separate? how should the distinction between class and instance variables be drawn? diff --git a/Doc/license.rst b/Doc/license.rst index 1d086b6fdd3fe..cd03411d6c94a 100644 --- a/Doc/license.rst +++ b/Doc/license.rst @@ -383,6 +383,33 @@ Project, http://www.wide.ad.jp/. :: SUCH DAMAGE. +Asynchronous socket services +---------------------------- + +The :mod:`asynchat` and :mod:`asyncore` modules contain the following notice:: + + Copyright 1996 by Sam Rushing + + All Rights Reserved + + Permission to use, copy, modify, and distribute this software and + its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that copyright notice and this permission + notice appear in supporting documentation, and that the name of Sam + Rushing not be used in advertising or publicity pertaining to + distribution of the software without specific, written prior + permission. + + SAM RUSHING DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + NO EVENT SHALL SAM RUSHING BE LIABLE FOR ANY SPECIAL, INDIRECT OR + CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + Cookie management ----------------- diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index b06d8d4215033..a570864743d47 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -518,15 +518,6 @@ Removed (Contributed by Hugo van Kemenade in :issue:`45320`.) -* Remove the ``asyncore`` and ``asynchat`` modules, deprecated in Python 3.6: - use the :mod:`asyncio` module instead. - (Contributed by Victor Stinner in :issue:`28533`.) - -* Remove the ``smtpd`` module, deprecated in Python 3.6: the `aiosmtpd - `__ module can be used instead, it is based - on asyncio. - (Contributed by Victor Stinner in :issue:`28533`.) - Porting to Python 3.11 ====================== diff --git a/Lib/test/support/_asynchat.py b/Lib/asynchat.py similarity index 98% rename from Lib/test/support/_asynchat.py rename to Lib/asynchat.py index 941cc1d22e6b0..de26ffa648ffe 100644 --- a/Lib/test/support/_asynchat.py +++ b/Lib/asynchat.py @@ -45,9 +45,17 @@ method) up to the terminator, and then control will be returned to you - by calling your self.found_terminator() method. """ -from test.support import _asyncore as asyncore +import asyncore from collections import deque +from warnings import warn +warn( + 'The asynchat module is deprecated. ' + 'The recommended replacement is asyncio', + DeprecationWarning, + stacklevel=2) + + class async_chat(asyncore.dispatcher): """This is an abstract class. You must derive from this class, and add diff --git a/Lib/test/support/_asyncore.py b/Lib/asyncore.py similarity index 99% rename from Lib/test/support/_asyncore.py rename to Lib/asyncore.py index 7863efaea66c8..b1eea4bf65211 100644 --- a/Lib/test/support/_asyncore.py +++ b/Lib/asyncore.py @@ -57,6 +57,12 @@ ENOTCONN, ESHUTDOWN, EISCONN, EBADF, ECONNABORTED, EPIPE, EAGAIN, \ errorcode +warnings.warn( + 'The asyncore module is deprecated. ' + 'The recommended replacement is asyncio', + DeprecationWarning, + stacklevel=2) + _DISCONNECTED = frozenset({ECONNRESET, ENOTCONN, ESHUTDOWN, ECONNABORTED, EPIPE, EBADF}) diff --git a/Lib/test/support/_smtpd.py b/Lib/smtpd.py similarity index 83% rename from Lib/test/support/_smtpd.py rename to Lib/smtpd.py index 0e37d08f2be34..1cd004fbc6fe5 100755 --- a/Lib/test/support/_smtpd.py +++ b/Lib/smtpd.py @@ -80,13 +80,22 @@ from warnings import warn from email._header_value_parser import get_addr_spec, get_angle_addr -from test.support import _asyncore as asyncore -from test.support import _asynchat as asynchat - __all__ = [ "SMTPChannel", "SMTPServer", "DebuggingServer", "PureProxy", ] +warn( + 'The smtpd module is deprecated and unmaintained. Please see aiosmtpd ' + '(https://aiosmtpd.readthedocs.io/) for the recommended replacement.', + DeprecationWarning, + stacklevel=2) + + +# These are imported after the above warning so that users get the correct +# deprecation warning. +import asyncore +import asynchat + program = sys.argv[0] __version__ = 'Python SMTP proxy version 0.3' @@ -179,6 +188,128 @@ def _set_rset_state(self): self.received_lines = [] + # properties for backwards-compatibility + @property + def __server(self): + warn("Access to __server attribute on SMTPChannel is deprecated, " + "use 'smtp_server' instead", DeprecationWarning, 2) + return self.smtp_server + @__server.setter + def __server(self, value): + warn("Setting __server attribute on SMTPChannel is deprecated, " + "set 'smtp_server' instead", DeprecationWarning, 2) + self.smtp_server = value + + @property + def __line(self): + warn("Access to __line attribute on SMTPChannel is deprecated, " + "use 'received_lines' instead", DeprecationWarning, 2) + return self.received_lines + @__line.setter + def __line(self, value): + warn("Setting __line attribute on SMTPChannel is deprecated, " + "set 'received_lines' instead", DeprecationWarning, 2) + self.received_lines = value + + @property + def __state(self): + warn("Access to __state attribute on SMTPChannel is deprecated, " + "use 'smtp_state' instead", DeprecationWarning, 2) + return self.smtp_state + @__state.setter + def __state(self, value): + warn("Setting __state attribute on SMTPChannel is deprecated, " + "set 'smtp_state' instead", DeprecationWarning, 2) + self.smtp_state = value + + @property + def __greeting(self): + warn("Access to __greeting attribute on SMTPChannel is deprecated, " + "use 'seen_greeting' instead", DeprecationWarning, 2) + return self.seen_greeting + @__greeting.setter + def __greeting(self, value): + warn("Setting __greeting attribute on SMTPChannel is deprecated, " + "set 'seen_greeting' instead", DeprecationWarning, 2) + self.seen_greeting = value + + @property + def __mailfrom(self): + warn("Access to __mailfrom attribute on SMTPChannel is deprecated, " + "use 'mailfrom' instead", DeprecationWarning, 2) + return self.mailfrom + @__mailfrom.setter + def __mailfrom(self, value): + warn("Setting __mailfrom attribute on SMTPChannel is deprecated, " + "set 'mailfrom' instead", DeprecationWarning, 2) + self.mailfrom = value + + @property + def __rcpttos(self): + warn("Access to __rcpttos attribute on SMTPChannel is deprecated, " + "use 'rcpttos' instead", DeprecationWarning, 2) + return self.rcpttos + @__rcpttos.setter + def __rcpttos(self, value): + warn("Setting __rcpttos attribute on SMTPChannel is deprecated, " + "set 'rcpttos' instead", DeprecationWarning, 2) + self.rcpttos = value + + @property + def __data(self): + warn("Access to __data attribute on SMTPChannel is deprecated, " + "use 'received_data' instead", DeprecationWarning, 2) + return self.received_data + @__data.setter + def __data(self, value): + warn("Setting __data attribute on SMTPChannel is deprecated, " + "set 'received_data' instead", DeprecationWarning, 2) + self.received_data = value + + @property + def __fqdn(self): + warn("Access to __fqdn attribute on SMTPChannel is deprecated, " + "use 'fqdn' instead", DeprecationWarning, 2) + return self.fqdn + @__fqdn.setter + def __fqdn(self, value): + warn("Setting __fqdn attribute on SMTPChannel is deprecated, " + "set 'fqdn' instead", DeprecationWarning, 2) + self.fqdn = value + + @property + def __peer(self): + warn("Access to __peer attribute on SMTPChannel is deprecated, " + "use 'peer' instead", DeprecationWarning, 2) + return self.peer + @__peer.setter + def __peer(self, value): + warn("Setting __peer attribute on SMTPChannel is deprecated, " + "set 'peer' instead", DeprecationWarning, 2) + self.peer = value + + @property + def __conn(self): + warn("Access to __conn attribute on SMTPChannel is deprecated, " + "use 'conn' instead", DeprecationWarning, 2) + return self.conn + @__conn.setter + def __conn(self, value): + warn("Setting __conn attribute on SMTPChannel is deprecated, " + "set 'conn' instead", DeprecationWarning, 2) + self.conn = value + + @property + def __addr(self): + warn("Access to __addr attribute on SMTPChannel is deprecated, " + "use 'addr' instead", DeprecationWarning, 2) + return self.addr + @__addr.setter + def __addr(self, value): + warn("Setting __addr attribute on SMTPChannel is deprecated, " + "set 'addr' instead", DeprecationWarning, 2) + self.addr = value + # Overrides base class for convenience. def push(self, msg): asynchat.async_chat.push(self, bytes( diff --git a/Lib/test/libregrtest/save_env.py b/Lib/test/libregrtest/save_env.py index 17dda99b64582..60c9be24617a6 100644 --- a/Lib/test/libregrtest/save_env.py +++ b/Lib/test/libregrtest/save_env.py @@ -52,7 +52,7 @@ def __init__(self, testname, verbose=0, quiet=False, *, pgo=False): resources = ('sys.argv', 'cwd', 'sys.stdin', 'sys.stdout', 'sys.stderr', 'os.environ', 'sys.path', 'sys.path_hooks', '__import__', - 'warnings.filters', + 'warnings.filters', 'asyncore.socket_map', 'logging._handlers', 'logging._handlerList', 'sys.gettrace', 'sys.warnoptions', # multiprocessing.process._cleanup() may release ref @@ -160,6 +160,16 @@ def restore_warnings_filters(self, saved_filters): warnings.filters = saved_filters[1] warnings.filters[:] = saved_filters[2] + def get_asyncore_socket_map(self): + asyncore = sys.modules.get('asyncore') + # XXX Making a copy keeps objects alive until __exit__ gets called. + return asyncore and asyncore.socket_map.copy() or {} + def restore_asyncore_socket_map(self, saved_map): + asyncore = sys.modules.get('asyncore') + if asyncore is not None: + asyncore.close_all(ignore_all=True) + asyncore.socket_map.update(saved_map) + def get_shutil_archive_formats(self): shutil = self.try_get_module('shutil') # we could call get_archives_formats() but that only returns the diff --git a/Lib/test/mock_socket.py b/Lib/test/mock_socket.py index 9788d58b4c765..c7abddcf5fafd 100644 --- a/Lib/test/mock_socket.py +++ b/Lib/test/mock_socket.py @@ -1,4 +1,4 @@ -"""Mock socket module used by the smtplib tests. +"""Mock socket module used by the smtpd and smtplib tests. """ # imported for _GLOBAL_DEFAULT_TIMEOUT @@ -33,7 +33,7 @@ def close(self): class MockSocket: - """Mock socket object used by smtplib tests. + """Mock socket object used by smtpd and smtplib tests. """ def __init__(self, family=None): global _reply_data diff --git a/Lib/test/test_asynchat.py b/Lib/test/test_asynchat.py new file mode 100644 index 0000000000000..973ac1f7d97c9 --- /dev/null +++ b/Lib/test/test_asynchat.py @@ -0,0 +1,292 @@ +# test asynchat + +from test import support +from test.support import socket_helper +from test.support import threading_helper + +import errno +import socket +import sys +import threading +import time +import unittest +import unittest.mock + +import warnings +with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + import asynchat + import asyncore + +HOST = socket_helper.HOST +SERVER_QUIT = b'QUIT\n' + + +class echo_server(threading.Thread): + # parameter to determine the number of bytes passed back to the + # client each send + chunk_size = 1 + + def __init__(self, event): + threading.Thread.__init__(self) + self.event = event + self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.port = socket_helper.bind_port(self.sock) + # This will be set if the client wants us to wait before echoing + # data back. + self.start_resend_event = None + + def run(self): + self.sock.listen() + self.event.set() + conn, client = self.sock.accept() + self.buffer = b"" + # collect data until quit message is seen + while SERVER_QUIT not in self.buffer: + data = conn.recv(1) + if not data: + break + self.buffer = self.buffer + data + + # remove the SERVER_QUIT message + self.buffer = self.buffer.replace(SERVER_QUIT, b'') + + if self.start_resend_event: + self.start_resend_event.wait() + + # re-send entire set of collected data + try: + # this may fail on some tests, such as test_close_when_done, + # since the client closes the channel when it's done sending + while self.buffer: + n = conn.send(self.buffer[:self.chunk_size]) + time.sleep(0.001) + self.buffer = self.buffer[n:] + except: + pass + + conn.close() + self.sock.close() + +class echo_client(asynchat.async_chat): + + def __init__(self, terminator, server_port): + asynchat.async_chat.__init__(self) + self.contents = [] + self.create_socket(socket.AF_INET, socket.SOCK_STREAM) + self.connect((HOST, server_port)) + self.set_terminator(terminator) + self.buffer = b"" + + def handle_connect(self): + pass + + if sys.platform == 'darwin': + # select.poll returns a select.POLLHUP at the end of the tests + # on darwin, so just ignore it + def handle_expt(self): + pass + + def collect_incoming_data(self, data): + self.buffer += data + + def found_terminator(self): + self.contents.append(self.buffer) + self.buffer = b"" + +def start_echo_server(): + event = threading.Event() + s = echo_server(event) + s.start() + event.wait() + event.clear() + time.sleep(0.01) # Give server time to start accepting. + return s, event + + +class TestAsynchat(unittest.TestCase): + usepoll = False + + def setUp(self): + self._threads = threading_helper.threading_setup() + + def tearDown(self): + threading_helper.threading_cleanup(*self._threads) + + def line_terminator_check(self, term, server_chunk): + event = threading.Event() + s = echo_server(event) + s.chunk_size = server_chunk + s.start() + event.wait() + event.clear() + time.sleep(0.01) # Give server time to start accepting. + c = echo_client(term, s.port) + c.push(b"hello ") + c.push(b"world" + term) + c.push(b"I'm not dead yet!" + term) + c.push(SERVER_QUIT) + asyncore.loop(use_poll=self.usepoll, count=300, timeout=.01) + threading_helper.join_thread(s) + + self.assertEqual(c.contents, [b"hello world", b"I'm not dead yet!"]) + + # the line terminator tests below check receiving variously-sized + # chunks back from the server in order to exercise all branches of + # async_chat.handle_read + + def test_line_terminator1(self): + # test one-character terminator + for l in (1, 2, 3): + self.line_terminator_check(b'\n', l) + + def test_line_terminator2(self): + # test two-character terminator + for l in (1, 2, 3): + self.line_terminator_check(b'\r\n', l) + + def test_line_terminator3(self): + # test three-character terminator + for l in (1, 2, 3): + self.line_terminator_check(b'qqq', l) + + def numeric_terminator_check(self, termlen): + # Try reading a fixed number of bytes + s, event = start_echo_server() + c = echo_client(termlen, s.port) + data = b"hello world, I'm not dead yet!\n" + c.push(data) + c.push(SERVER_QUIT) + asyncore.loop(use_poll=self.usepoll, count=300, timeout=.01) + threading_helper.join_thread(s) + + self.assertEqual(c.contents, [data[:termlen]]) + + def test_numeric_terminator1(self): + # check that ints & longs both work (since type is + # explicitly checked in async_chat.handle_read) + self.numeric_terminator_check(1) + + def test_numeric_terminator2(self): + self.numeric_terminator_check(6) + + def test_none_terminator(self): + # Try reading a fixed number of bytes + s, event = start_echo_server() + c = echo_client(None, s.port) + data = b"hello world, I'm not dead yet!\n" + c.push(data) + c.push(SERVER_QUIT) + asyncore.loop(use_poll=self.usepoll, count=300, timeout=.01) + threading_helper.join_thread(s) + + self.assertEqual(c.contents, []) + self.assertEqual(c.buffer, data) + + def test_simple_producer(self): + s, event = start_echo_server() + c = echo_client(b'\n', s.port) + data = b"hello world\nI'm not dead yet!\n" + p = asynchat.simple_producer(data+SERVER_QUIT, buffer_size=8) + c.push_with_producer(p) + asyncore.loop(use_poll=self.usepoll, count=300, timeout=.01) + threading_helper.join_thread(s) + + self.assertEqual(c.contents, [b"hello world", b"I'm not dead yet!"]) + + def test_string_producer(self): + s, event = start_echo_server() + c = echo_client(b'\n', s.port) + data = b"hello world\nI'm not dead yet!\n" + c.push_with_producer(data+SERVER_QUIT) + asyncore.loop(use_poll=self.usepoll, count=300, timeout=.01) + threading_helper.join_thread(s) + + self.assertEqual(c.contents, [b"hello world", b"I'm not dead yet!"]) + + def test_empty_line(self): + # checks that empty lines are handled correctly + s, event = start_echo_server() + c = echo_client(b'\n', s.port) + c.push(b"hello world\n\nI'm not dead yet!\n") + c.push(SERVER_QUIT) + asyncore.loop(use_poll=self.usepoll, count=300, timeout=.01) + threading_helper.join_thread(s) + + self.assertEqual(c.contents, + [b"hello world", b"", b"I'm not dead yet!"]) + + def test_close_when_done(self): + s, event = start_echo_server() + s.start_resend_event = threading.Event() + c = echo_client(b'\n', s.port) + c.push(b"hello world\nI'm not dead yet!\n") + c.push(SERVER_QUIT) + c.close_when_done() + asyncore.loop(use_poll=self.usepoll, count=300, timeout=.01) + + # Only allow the server to start echoing data back to the client after + # the client has closed its connection. This prevents a race condition + # where the server echoes all of its data before we can check that it + # got any down below. + s.start_resend_event.set() + threading_helper.join_thread(s) + + self.assertEqual(c.contents, []) + # the server might have been able to send a byte or two back, but this + # at least checks that it received something and didn't just fail + # (which could still result in the client not having received anything) + self.assertGreater(len(s.buffer), 0) + + def test_push(self): + # Issue #12523: push() should raise a TypeError if it doesn't get + # a bytes string + s, event = start_echo_server() + c = echo_client(b'\n', s.port) + data = b'bytes\n' + c.push(data) + c.push(bytearray(data)) + c.push(memoryview(data)) + self.assertRaises(TypeError, c.push, 10) + self.assertRaises(TypeError, c.push, 'unicode') + c.push(SERVER_QUIT) + asyncore.loop(use_poll=self.usepoll, count=300, timeout=.01) + threading_helper.join_thread(s) + self.assertEqual(c.contents, [b'bytes', b'bytes', b'bytes']) + + +class TestAsynchat_WithPoll(TestAsynchat): + usepoll = True + + +class TestAsynchatMocked(unittest.TestCase): + def test_blockingioerror(self): + # Issue #16133: handle_read() must ignore BlockingIOError + sock = unittest.mock.Mock() + sock.recv.side_effect = BlockingIOError(errno.EAGAIN) + + dispatcher = asynchat.async_chat() + dispatcher.set_socket(sock) + self.addCleanup(dispatcher.del_channel) + + with unittest.mock.patch.object(dispatcher, 'handle_error') as error: + dispatcher.handle_read() + self.assertFalse(error.called) + + +class TestHelperFunctions(unittest.TestCase): + def test_find_prefix_at_end(self): + self.assertEqual(asynchat.find_prefix_at_end("qwerty\r", "\r\n"), 1) + self.assertEqual(asynchat.find_prefix_at_end("qwertydkjf", "\r\n"), 0) + + +class TestNotConnected(unittest.TestCase): + def test_disallow_negative_terminator(self): + # Issue #11259 + client = asynchat.async_chat() + self.assertRaises(ValueError, client.set_terminator, -1) + + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_asyncore.py b/Lib/test/test_asyncore.py new file mode 100644 index 0000000000000..ecd1e120ecb51 --- /dev/null +++ b/Lib/test/test_asyncore.py @@ -0,0 +1,841 @@ +import unittest +import select +import os +import socket +import sys +import time +import errno +import struct +import threading + +from test import support +from test.support import os_helper +from test.support import socket_helper +from test.support import threading_helper +from test.support import warnings_helper +from io import BytesIO + +if support.PGO: + raise unittest.SkipTest("test is not helpful for PGO") + +import warnings +with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + import asyncore + + +HAS_UNIX_SOCKETS = hasattr(socket, 'AF_UNIX') + +class dummysocket: + def __init__(self): + self.closed = False + + def close(self): + self.closed = True + + def fileno(self): + return 42 + +class dummychannel: + def __init__(self): + self.socket = dummysocket() + + def close(self): + self.socket.close() + +class exitingdummy: + def __init__(self): + pass + + def handle_read_event(self): + raise asyncore.ExitNow() + + handle_write_event = handle_read_event + handle_close = handle_read_event + handle_expt_event = handle_read_event + +class crashingdummy: + def __init__(self): + self.error_handled = False + + def handle_read_event(self): + raise Exception() + + handle_write_event = handle_read_event + handle_close = handle_read_event + handle_expt_event = handle_read_event + + def handle_error(self): + self.error_handled = True + +# used when testing senders; just collects what it gets until newline is sent +def capture_server(evt, buf, serv): + try: + serv.listen() + conn, addr = serv.accept() + except TimeoutError: + pass + else: + n = 200 + start = time.monotonic() + while n > 0 and time.monotonic() - start < 3.0: + r, w, e = select.select([conn], [], [], 0.1) + if r: + n -= 1 + data = conn.recv(10) + # keep everything except for the newline terminator + buf.write(data.replace(b'\n', b'')) + if b'\n' in data: + break + time.sleep(0.01) + + conn.close() + finally: + serv.close() + evt.set() + +def bind_af_aware(sock, addr): + """Helper function to bind a socket according to its family.""" + if HAS_UNIX_SOCKETS and sock.family == socket.AF_UNIX: + # Make sure the path doesn't exist. + os_helper.unlink(addr) + socket_helper.bind_unix_socket(sock, addr) + else: + sock.bind(addr) + + +class HelperFunctionTests(unittest.TestCase): + def test_readwriteexc(self): + # Check exception handling behavior of read, write and _exception + + # check that ExitNow exceptions in the object handler method + # bubbles all the way up through asyncore read/write/_exception calls + tr1 = exitingdummy() + self.assertRaises(asyncore.ExitNow, asyncore.read, tr1) + self.assertRaises(asyncore.ExitNow, asyncore.write, tr1) + self.assertRaises(asyncore.ExitNow, asyncore._exception, tr1) + + # check that an exception other than ExitNow in the object handler + # method causes the handle_error method to get called + tr2 = crashingdummy() + asyncore.read(tr2) + self.assertEqual(tr2.error_handled, True) + + tr2 = crashingdummy() + asyncore.write(tr2) + self.assertEqual(tr2.error_handled, True) + + tr2 = crashingdummy() + asyncore._exception(tr2) + self.assertEqual(tr2.error_handled, True) + + # asyncore.readwrite uses constants in the select module that + # are not present in Windows systems (see this thread: + # http://mail.python.org/pipermail/python-list/2001-October/109973.html) + # These constants should be present as long as poll is available + + @unittest.skipUnless(hasattr(select, 'poll'), 'select.poll required') + def test_readwrite(self): + # Check that correct methods are called by readwrite() + + attributes = ('read', 'expt', 'write', 'closed', 'error_handled') + + expected = ( + (select.POLLIN, 'read'), + (select.POLLPRI, 'expt'), + (select.POLLOUT, 'write'), + (select.POLLERR, 'closed'), + (select.POLLHUP, 'closed'), + (select.POLLNVAL, 'closed'), + ) + + class testobj: + def __init__(self): + self.read = False + self.write = False + self.closed = False + self.expt = False + self.error_handled = False + + def handle_read_event(self): + self.read = True + + def handle_write_event(self): + self.write = True + + def handle_close(self): + self.closed = True + + def handle_expt_event(self): + self.expt = True + + def handle_error(self): + self.error_handled = True + + for flag, expectedattr in expected: + tobj = testobj() + self.assertEqual(getattr(tobj, expectedattr), False) + asyncore.readwrite(tobj, flag) + + # Only the attribute modified by the routine we expect to be + # called should be True. + for attr in attributes: + self.assertEqual(getattr(tobj, attr), attr==expectedattr) + + # check that ExitNow exceptions in the object handler method + # bubbles all the way up through asyncore readwrite call + tr1 = exitingdummy() + self.assertRaises(asyncore.ExitNow, asyncore.readwrite, tr1, flag) + + # check that an exception other than ExitNow in the object handler + # method causes the handle_error method to get called + tr2 = crashingdummy() + self.assertEqual(tr2.error_handled, False) + asyncore.readwrite(tr2, flag) + self.assertEqual(tr2.error_handled, True) + + def test_closeall(self): + self.closeall_check(False) + + def test_closeall_default(self): + self.closeall_check(True) + + def closeall_check(self, usedefault): + # Check that close_all() closes everything in a given map + + l = [] + testmap = {} + for i in range(10): + c = dummychannel() + l.append(c) + self.assertEqual(c.socket.closed, False) + testmap[i] = c + + if usedefault: + socketmap = asyncore.socket_map + try: + asyncore.socket_map = testmap + asyncore.close_all() + finally: + testmap, asyncore.socket_map = asyncore.socket_map, socketmap + else: + asyncore.close_all(testmap) + + self.assertEqual(len(testmap), 0) + + for c in l: + self.assertEqual(c.socket.closed, True) + + def test_compact_traceback(self): + try: + raise Exception("I don't like spam!") + except: + real_t, real_v, real_tb = sys.exc_info() + r = asyncore.compact_traceback() + else: + self.fail("Expected exception") + + (f, function, line), t, v, info = r + self.assertEqual(os.path.split(f)[-1], 'test_asyncore.py') + self.assertEqual(function, 'test_compact_traceback') + self.assertEqual(t, real_t) + self.assertEqual(v, real_v) + self.assertEqual(info, '[%s|%s|%s]' % (f, function, line)) + + +class DispatcherTests(unittest.TestCase): + def setUp(self): + pass + + def tearDown(self): + asyncore.close_all() + + def test_basic(self): + d = asyncore.dispatcher() + self.assertEqual(d.readable(), True) + self.assertEqual(d.writable(), True) + + def test_repr(self): + d = asyncore.dispatcher() + self.assertEqual(repr(d), '' % id(d)) + + def test_log(self): + d = asyncore.dispatcher() + + # capture output of dispatcher.log() (to stderr) + l1 = "Lovely spam! Wonderful spam!" + l2 = "I don't like spam!" + with support.captured_stderr() as stderr: + d.log(l1) + d.log(l2) + + lines = stderr.getvalue().splitlines() + self.assertEqual(lines, ['log: %s' % l1, 'log: %s' % l2]) + + def test_log_info(self): + d = asyncore.dispatcher() + + # capture output of dispatcher.log_info() (to stdout via print) + l1 = "Have you got anything without spam?" + l2 = "Why can't she have egg bacon spam and sausage?" + l3 = "THAT'S got spam in it!" + with support.captured_stdout() as stdout: + d.log_info(l1, 'EGGS') + d.log_info(l2) + d.log_info(l3, 'SPAM') + + lines = stdout.getvalue().splitlines() + expected = ['EGGS: %s' % l1, 'info: %s' % l2, 'SPAM: %s' % l3] + self.assertEqual(lines, expected) + + def test_unhandled(self): + d = asyncore.dispatcher() + d.ignore_log_types = () + + # capture output of dispatcher.log_info() (to stdout via print) + with support.captured_stdout() as stdout: + d.handle_expt() + d.handle_read() + d.handle_write() + d.handle_connect() + + lines = stdout.getvalue().splitlines() + expected = ['warning: unhandled incoming priority event', + 'warning: unhandled read event', + 'warning: unhandled write event', + 'warning: unhandled connect event'] + self.assertEqual(lines, expected) + + def test_strerror(self): + # refers to bug #8573 + err = asyncore._strerror(errno.EPERM) + if hasattr(os, 'strerror'): + self.assertEqual(err, os.strerror(errno.EPERM)) + err = asyncore._strerror(-1) + self.assertTrue(err != "") + + +class dispatcherwithsend_noread(asyncore.dispatcher_with_send): + def readable(self): + return False + + def handle_connect(self): + pass + + +class DispatcherWithSendTests(unittest.TestCase): + def setUp(self): + pass + + def tearDown(self): + asyncore.close_all() + + @threading_helper.reap_threads + def test_send(self): + evt = threading.Event() + sock = socket.socket() + sock.settimeout(3) + port = socket_helper.bind_port(sock) + + cap = BytesIO() + args = (evt, cap, sock) + t = threading.Thread(target=capture_server, args=args) + t.start() + try: + # wait a little longer for the server to initialize (it sometimes + # refuses connections on slow machines without this wait) + time.sleep(0.2) + + data = b"Suppose there isn't a 16-ton weight?" + d = dispatcherwithsend_noread() + d.create_socket() + d.connect((socket_helper.HOST, port)) + + # give time for socket to connect + time.sleep(0.1) + + d.send(data) + d.send(data) + d.send(b'\n') + + n = 1000 + while d.out_buffer and n > 0: + asyncore.poll() + n -= 1 + + evt.wait() + + self.assertEqual(cap.getvalue(), data*2) + finally: + threading_helper.join_thread(t) + + + at unittest.skipUnless(hasattr(asyncore, 'file_wrapper'), + 'asyncore.file_wrapper required') +class FileWrapperTest(unittest.TestCase): + def setUp(self): + self.d = b"It's not dead, it's sleeping!" + with open(os_helper.TESTFN, 'wb') as file: + file.write(self.d) + + def tearDown(self): + os_helper.unlink(os_helper.TESTFN) + + def test_recv(self): + fd = os.open(os_helper.TESTFN, os.O_RDONLY) + w = asyncore.file_wrapper(fd) + os.close(fd) + + self.assertNotEqual(w.fd, fd) + self.assertNotEqual(w.fileno(), fd) + self.assertEqual(w.recv(13), b"It's not dead") + self.assertEqual(w.read(6), b", it's") + w.close() + self.assertRaises(OSError, w.read, 1) + + def test_send(self): + d1 = b"Come again?" + d2 = b"I want to buy some cheese." + fd = os.open(os_helper.TESTFN, os.O_WRONLY | os.O_APPEND) + w = asyncore.file_wrapper(fd) + os.close(fd) + + w.write(d1) + w.send(d2) + w.close() + with open(os_helper.TESTFN, 'rb') as file: + self.assertEqual(file.read(), self.d + d1 + d2) + + @unittest.skipUnless(hasattr(asyncore, 'file_dispatcher'), + 'asyncore.file_dispatcher required') + def test_dispatcher(self): + fd = os.open(os_helper.TESTFN, os.O_RDONLY) + data = [] + class FileDispatcher(asyncore.file_dispatcher): + def handle_read(self): + data.append(self.recv(29)) + s = FileDispatcher(fd) + os.close(fd) + asyncore.loop(timeout=0.01, use_poll=True, count=2) + self.assertEqual(b"".join(data), self.d) + + def test_resource_warning(self): + # Issue #11453 + fd = os.open(os_helper.TESTFN, os.O_RDONLY) + f = asyncore.file_wrapper(fd) + + os.close(fd) + with warnings_helper.check_warnings(('', ResourceWarning)): + f = None + support.gc_collect() + + def test_close_twice(self): + fd = os.open(os_helper.TESTFN, os.O_RDONLY) + f = asyncore.file_wrapper(fd) + os.close(fd) + + os.close(f.fd) # file_wrapper dupped fd + with self.assertRaises(OSError): + f.close() + + self.assertEqual(f.fd, -1) + # calling close twice should not fail + f.close() + + +class BaseTestHandler(asyncore.dispatcher): + + def __init__(self, sock=None): + asyncore.dispatcher.__init__(self, sock) + self.flag = False + + def handle_accept(self): + raise Exception("handle_accept not supposed to be called") + + def handle_accepted(self): + raise Exception("handle_accepted not supposed to be called") + + def handle_connect(self): + raise Exception("handle_connect not supposed to be called") + + def handle_expt(self): + raise Exception("handle_expt not supposed to be called") + + def handle_close(self): + raise Exception("handle_close not supposed to be called") + + def handle_error(self): + raise + + +class BaseServer(asyncore.dispatcher): + """A server which listens on an address and dispatches the + connection to a handler. + """ + + def __init__(self, family, addr, handler=BaseTestHandler): + asyncore.dispatcher.__init__(self) + self.create_socket(family) + self.set_reuse_addr() + bind_af_aware(self.socket, addr) + self.listen(5) + self.handler = handler + + @property + def address(self): + return self.socket.getsockname() + + def handle_accepted(self, sock, addr): + self.handler(sock) + + def handle_error(self): + raise + + +class BaseClient(BaseTestHandler): + + def __init__(self, family, address): + BaseTestHandler.__init__(self) + self.create_socket(family) + self.connect(address) + + def handle_connect(self): + pass + + +class BaseTestAPI: + + def tearDown(self): + asyncore.close_all(ignore_all=True) + + def loop_waiting_for_flag(self, instance, timeout=5): + timeout = float(timeout) / 100 + count = 100 + while asyncore.socket_map and count > 0: + asyncore.loop(timeout=0.01, count=1, use_poll=self.use_poll) + if instance.flag: + return + count -= 1 + time.sleep(timeout) + self.fail("flag not set") + + def test_handle_connect(self): + # make sure handle_connect is called on connect() + + class TestClient(BaseClient): + def handle_connect(self): + self.flag = True + + server = BaseServer(self.family, self.addr) + client = TestClient(self.family, server.address) + self.loop_waiting_for_flag(client) + + def test_handle_accept(self): + # make sure handle_accept() is called when a client connects + + class TestListener(BaseTestHandler): + + def __init__(self, family, addr): + BaseTestHandler.__init__(self) + self.create_socket(family) + bind_af_aware(self.socket, addr) + self.listen(5) + self.address = self.socket.getsockname() + + def handle_accept(self): + self.flag = True + + server = TestListener(self.family, self.addr) + client = BaseClient(self.family, server.address) + self.loop_waiting_for_flag(server) + + def test_handle_accepted(self): + # make sure handle_accepted() is called when a client connects + + class TestListener(BaseTestHandler): + + def __init__(self, family, addr): + BaseTestHandler.__init__(self) + self.create_socket(family) + bind_af_aware(self.socket, addr) + self.listen(5) + self.address = self.socket.getsockname() + + def handle_accept(self): + asyncore.dispatcher.handle_accept(self) + + def handle_accepted(self, sock, addr): + sock.close() + self.flag = True + + server = TestListener(self.family, self.addr) + client = BaseClient(self.family, server.address) + self.loop_waiting_for_flag(server) + + + def test_handle_read(self): + # make sure handle_read is called on data received + + class TestClient(BaseClient): + def handle_read(self): + self.flag = True + + class TestHandler(BaseTestHandler): + def __init__(self, conn): + BaseTestHandler.__init__(self, conn) + self.send(b'x' * 1024) + + server = BaseServer(self.family, self.addr, TestHandler) + client = TestClient(self.family, server.address) + self.loop_waiting_for_flag(client) + + def test_handle_write(self): + # make sure handle_write is called + + class TestClient(BaseClient): + def handle_write(self): + self.flag = True + + server = BaseServer(self.family, self.addr) + client = TestClient(self.family, server.address) + self.loop_waiting_for_flag(client) + + def test_handle_close(self): + # make sure handle_close is called when the other end closes + # the connection + + class TestClient(BaseClient): + + def handle_read(self): + # in order to make handle_close be called we are supposed + # to make at least one recv() call + self.recv(1024) + + def handle_close(self): + self.flag = True + self.close() + + class TestHandler(BaseTestHandler): + def __init__(self, conn): + BaseTestHandler.__init__(self, conn) + self.close() + + server = BaseServer(self.family, self.addr, TestHandler) + client = TestClient(self.family, server.address) + self.loop_waiting_for_flag(client) + + def test_handle_close_after_conn_broken(self): + # Check that ECONNRESET/EPIPE is correctly handled (issues #5661 and + # #11265). + + data = b'\0' * 128 + + class TestClient(BaseClient): + + def handle_write(self): + self.send(data) + + def handle_close(self): + self.flag = True + self.close() + + def handle_expt(self): + self.flag = True + self.close() + + class TestHandler(BaseTestHandler): + + def handle_read(self): + self.recv(len(data)) + self.close() + + def writable(self): + return False + + server = BaseServer(self.family, self.addr, TestHandler) + client = TestClient(self.family, server.address) + self.loop_waiting_for_flag(client) + + @unittest.skipIf(sys.platform.startswith("sunos"), + "OOB support is broken on Solaris") + def test_handle_expt(self): + # Make sure handle_expt is called on OOB data received. + # Note: this might fail on some platforms as OOB data is + # tenuously supported and rarely used. + if HAS_UNIX_SOCKETS and self.family == socket.AF_UNIX: + self.skipTest("Not applicable to AF_UNIX sockets.") + + if sys.platform == "darwin" and self.use_poll: + self.skipTest("poll may fail on macOS; see issue #28087") + + class TestClient(BaseClient): + def handle_expt(self): + self.socket.recv(1024, socket.MSG_OOB) + self.flag = True + + class TestHandler(BaseTestHandler): + def __init__(self, conn): + BaseTestHandler.__init__(self, conn) + self.socket.send(bytes(chr(244), 'latin-1'), socket.MSG_OOB) + + server = BaseServer(self.family, self.addr, TestHandler) + client = TestClient(self.family, server.address) + self.loop_waiting_for_flag(client) + + def test_handle_error(self): + + class TestClient(BaseClient): + def handle_write(self): + 1.0 / 0 + def handle_error(self): + self.flag = True + try: + raise + except ZeroDivisionError: + pass + else: + raise Exception("exception not raised") + + server = BaseServer(self.family, self.addr) + client = TestClient(self.family, server.address) + self.loop_waiting_for_flag(client) + + def test_connection_attributes(self): + server = BaseServer(self.family, self.addr) + client = BaseClient(self.family, server.address) + + # we start disconnected + self.assertFalse(server.connected) + self.assertTrue(server.accepting) + # this can't be taken for granted across all platforms + #self.assertFalse(client.connected) + self.assertFalse(client.accepting) + + # execute some loops so that client connects to server + asyncore.loop(timeout=0.01, use_poll=self.use_poll, count=100) + self.assertFalse(server.connected) + self.assertTrue(server.accepting) + self.assertTrue(client.connected) + self.assertFalse(client.accepting) + + # disconnect the client + client.close() + self.assertFalse(server.connected) + self.assertTrue(server.accepting) + self.assertFalse(client.connected) + self.assertFalse(client.accepting) + + # stop serving + server.close() + self.assertFalse(server.connected) + self.assertFalse(server.accepting) + + def test_create_socket(self): + s = asyncore.dispatcher() + s.create_socket(self.family) + self.assertEqual(s.socket.type, socket.SOCK_STREAM) + self.assertEqual(s.socket.family, self.family) + self.assertEqual(s.socket.gettimeout(), 0) + self.assertFalse(s.socket.get_inheritable()) + + def test_bind(self): + if HAS_UNIX_SOCKETS and self.family == socket.AF_UNIX: + self.skipTest("Not applicable to AF_UNIX sockets.") + s1 = asyncore.dispatcher() + s1.create_socket(self.family) + s1.bind(self.addr) + s1.listen(5) + port = s1.socket.getsockname()[1] + + s2 = asyncore.dispatcher() + s2.create_socket(self.family) + # EADDRINUSE indicates the socket was correctly bound + self.assertRaises(OSError, s2.bind, (self.addr[0], port)) + + def test_set_reuse_addr(self): + if HAS_UNIX_SOCKETS and self.family == socket.AF_UNIX: + self.skipTest("Not applicable to AF_UNIX sockets.") + + with socket.socket(self.family) as sock: + try: + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + except OSError: + unittest.skip("SO_REUSEADDR not supported on this platform") + else: + # if SO_REUSEADDR succeeded for sock we expect asyncore + # to do the same + s = asyncore.dispatcher(socket.socket(self.family)) + self.assertFalse(s.socket.getsockopt(socket.SOL_SOCKET, + socket.SO_REUSEADDR)) + s.socket.close() + s.create_socket(self.family) + s.set_reuse_addr() + self.assertTrue(s.socket.getsockopt(socket.SOL_SOCKET, + socket.SO_REUSEADDR)) + + @threading_helper.reap_threads + def test_quick_connect(self): + # see: http://bugs.python.org/issue10340 + if self.family not in (socket.AF_INET, getattr(socket, "AF_INET6", object())): + self.skipTest("test specific to AF_INET and AF_INET6") + + server = BaseServer(self.family, self.addr) + # run the thread 500 ms: the socket should be connected in 200 ms + t = threading.Thread(target=lambda: asyncore.loop(timeout=0.1, + count=5)) + t.start() + try: + with socket.socket(self.family, socket.SOCK_STREAM) as s: + s.settimeout(.2) + s.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, + struct.pack('ii', 1, 0)) + + try: + s.connect(server.address) + except OSError: + pass + finally: + threading_helper.join_thread(t) + +class TestAPI_UseIPv4Sockets(BaseTestAPI): + family = socket.AF_INET + addr = (socket_helper.HOST, 0) + + at unittest.skipUnless(socket_helper.IPV6_ENABLED, 'IPv6 support required') +class TestAPI_UseIPv6Sockets(BaseTestAPI): + family = socket.AF_INET6 + addr = (socket_helper.HOSTv6, 0) + + at unittest.skipUnless(HAS_UNIX_SOCKETS, 'Unix sockets required') +class TestAPI_UseUnixSockets(BaseTestAPI): + if HAS_UNIX_SOCKETS: + family = socket.AF_UNIX + addr = os_helper.TESTFN + + def tearDown(self): + os_helper.unlink(self.addr) + BaseTestAPI.tearDown(self) + +class TestAPI_UseIPv4Select(TestAPI_UseIPv4Sockets, unittest.TestCase): + use_poll = False + + at unittest.skipUnless(hasattr(select, 'poll'), 'select.poll required') +class TestAPI_UseIPv4Poll(TestAPI_UseIPv4Sockets, unittest.TestCase): + use_poll = True + +class TestAPI_UseIPv6Select(TestAPI_UseIPv6Sockets, unittest.TestCase): + use_poll = False + + at unittest.skipUnless(hasattr(select, 'poll'), 'select.poll required') +class TestAPI_UseIPv6Poll(TestAPI_UseIPv6Sockets, unittest.TestCase): + use_poll = True + +class TestAPI_UseUnixSocketsSelect(TestAPI_UseUnixSockets, unittest.TestCase): + use_poll = False + + at unittest.skipUnless(hasattr(select, 'poll'), 'select.poll required') +class TestAPI_UseUnixSocketsPoll(TestAPI_UseUnixSockets, unittest.TestCase): + use_poll = True + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_ftplib.py b/Lib/test/test_ftplib.py index c9edfac96871a..56e3d8ab8528a 100644 --- a/Lib/test/test_ftplib.py +++ b/Lib/test/test_ftplib.py @@ -18,13 +18,17 @@ from unittest import TestCase, skipUnless from test import support -from test.support import _asynchat as asynchat -from test.support import _asyncore as asyncore -from test.support import socket_helper from test.support import threading_helper +from test.support import socket_helper from test.support import warnings_helper from test.support.socket_helper import HOST, HOSTv6 +import warnings +with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + import asyncore + import asynchat + TIMEOUT = support.LOOPBACK_TIMEOUT DEFAULT_ENCODING = 'utf-8' diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index e709ea327fbd3..85b6e5f392111 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -42,8 +42,6 @@ import tempfile from test.support.script_helper import assert_python_ok, assert_python_failure from test import support -from test.support import _asyncore as asyncore -from test.support import _smtpd as smtpd from test.support import os_helper from test.support import socket_helper from test.support import threading_helper @@ -61,6 +59,11 @@ from socketserver import (ThreadingUDPServer, DatagramRequestHandler, ThreadingTCPServer, StreamRequestHandler) +with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + import asyncore + import smtpd + try: import win32evtlog, win32evtlogutil, pywintypes except ImportError: diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 5e15340515674..8da0aa3163fe2 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -30,8 +30,6 @@ import uuid import warnings from test import support -from test.support import _asynchat as asynchat -from test.support import _asyncore as asyncore from test.support import import_helper from test.support import os_helper from test.support import socket_helper @@ -39,6 +37,11 @@ from test.support import warnings_helper from platform import win32_is_iot +with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + import asynchat + import asyncore + try: import resource except ImportError: diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py index 23c6be3a801bf..44cf5231f9d23 100644 --- a/Lib/test/test_poplib.py +++ b/Lib/test/test_poplib.py @@ -12,12 +12,16 @@ import unittest from unittest import TestCase, skipUnless from test import support as test_support -from test.support import _asynchat as asynchat -from test.support import _asyncore as asyncore from test.support import hashlib_helper from test.support import socket_helper from test.support import threading_helper +import warnings +with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + import asynchat + import asyncore + HOST = socket_helper.HOST PORT = 0 diff --git a/Lib/test/test_smtpd.py b/Lib/test/test_smtpd.py new file mode 100644 index 0000000000000..d2e150d535ff6 --- /dev/null +++ b/Lib/test/test_smtpd.py @@ -0,0 +1,1018 @@ +import unittest +import textwrap +from test import support, mock_socket +from test.support import socket_helper +from test.support import warnings_helper +import socket +import io + +import warnings +with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + import smtpd + import asyncore + + +class DummyServer(smtpd.SMTPServer): + def __init__(self, *args, **kwargs): + smtpd.SMTPServer.__init__(self, *args, **kwargs) + self.messages = [] + if self._decode_data: + self.return_status = 'return status' + else: + self.return_status = b'return status' + + def process_message(self, peer, mailfrom, rcpttos, data, **kw): + self.messages.append((peer, mailfrom, rcpttos, data)) + if data == self.return_status: + return '250 Okish' + if 'mail_options' in kw and 'SMTPUTF8' in kw['mail_options']: + return '250 SMTPUTF8 message okish' + + +class DummyDispatcherBroken(Exception): + pass + + +class BrokenDummyServer(DummyServer): + def listen(self, num): + raise DummyDispatcherBroken() + + +class SMTPDServerTest(unittest.TestCase): + def setUp(self): + smtpd.socket = asyncore.socket = mock_socket + + def test_process_message_unimplemented(self): + server = smtpd.SMTPServer((socket_helper.HOST, 0), ('b', 0), + decode_data=True) + conn, addr = server.accept() + channel = smtpd.SMTPChannel(server, conn, addr, decode_data=True) + + def write_line(line): + channel.socket.queue_recv(line) + channel.handle_read() + + write_line(b'HELO example') + write_line(b'MAIL From:eggs at example') + write_line(b'RCPT To:spam at example') + write_line(b'DATA') + self.assertRaises(NotImplementedError, write_line, b'spam\r\n.\r\n') + + def test_decode_data_and_enable_SMTPUTF8_raises(self): + self.assertRaises( + ValueError, + smtpd.SMTPServer, + (socket_helper.HOST, 0), + ('b', 0), + enable_SMTPUTF8=True, + decode_data=True) + + def tearDown(self): + asyncore.close_all() + asyncore.socket = smtpd.socket = socket + + +class DebuggingServerTest(unittest.TestCase): + + def setUp(self): + smtpd.socket = asyncore.socket = mock_socket + + def send_data(self, channel, data, enable_SMTPUTF8=False): + def write_line(line): + channel.socket.queue_recv(line) + channel.handle_read() + write_line(b'EHLO example') + if enable_SMTPUTF8: + write_line(b'MAIL From:eggs at example BODY=8BITMIME SMTPUTF8') + else: + write_line(b'MAIL From:eggs at example') + write_line(b'RCPT To:spam at example') + write_line(b'DATA') + write_line(data) + write_line(b'.') + + def test_process_message_with_decode_data_true(self): + server = smtpd.DebuggingServer((socket_helper.HOST, 0), ('b', 0), + decode_data=True) + conn, addr = server.accept() + channel = smtpd.SMTPChannel(server, conn, addr, decode_data=True) + with support.captured_stdout() as s: + self.send_data(channel, b'From: test\n\nhello\n') + stdout = s.getvalue() + self.assertEqual(stdout, textwrap.dedent("""\ + ---------- MESSAGE FOLLOWS ---------- + From: test + X-Peer: peer-address + + hello + ------------ END MESSAGE ------------ + """)) + + def test_process_message_with_decode_data_false(self): + server = smtpd.DebuggingServer((socket_helper.HOST, 0), ('b', 0)) + conn, addr = server.accept() + channel = smtpd.SMTPChannel(server, conn, addr) + with support.captured_stdout() as s: + self.send_data(channel, b'From: test\n\nh\xc3\xa9llo\xff\n') + stdout = s.getvalue() + self.assertEqual(stdout, textwrap.dedent("""\ + ---------- MESSAGE FOLLOWS ---------- + b'From: test' + b'X-Peer: peer-address' + b'' + b'h\\xc3\\xa9llo\\xff' + ------------ END MESSAGE ------------ + """)) + + def test_process_message_with_enable_SMTPUTF8_true(self): + server = smtpd.DebuggingServer((socket_helper.HOST, 0), ('b', 0), + enable_SMTPUTF8=True) + conn, addr = server.accept() + channel = smtpd.SMTPChannel(server, conn, addr, enable_SMTPUTF8=True) + with support.captured_stdout() as s: + self.send_data(channel, b'From: test\n\nh\xc3\xa9llo\xff\n') + stdout = s.getvalue() + self.assertEqual(stdout, textwrap.dedent("""\ + ---------- MESSAGE FOLLOWS ---------- + b'From: test' + b'X-Peer: peer-address' + b'' + b'h\\xc3\\xa9llo\\xff' + ------------ END MESSAGE ------------ + """)) + + def test_process_SMTPUTF8_message_with_enable_SMTPUTF8_true(self): + server = smtpd.DebuggingServer((socket_helper.HOST, 0), ('b', 0), + enable_SMTPUTF8=True) + conn, addr = server.accept() + channel = smtpd.SMTPChannel(server, conn, addr, enable_SMTPUTF8=True) + with support.captured_stdout() as s: + self.send_data(channel, b'From: test\n\nh\xc3\xa9llo\xff\n', + enable_SMTPUTF8=True) + stdout = s.getvalue() + self.assertEqual(stdout, textwrap.dedent("""\ + ---------- MESSAGE FOLLOWS ---------- + mail options: ['BODY=8BITMIME', 'SMTPUTF8'] + b'From: test' + b'X-Peer: peer-address' + b'' + b'h\\xc3\\xa9llo\\xff' + ------------ END MESSAGE ------------ + """)) + + def tearDown(self): + asyncore.close_all() + asyncore.socket = smtpd.socket = socket + + +class TestFamilyDetection(unittest.TestCase): + def setUp(self): + smtpd.socket = asyncore.socket = mock_socket + + def tearDown(self): + asyncore.close_all() + asyncore.socket = smtpd.socket = socket + + @unittest.skipUnless(socket_helper.IPV6_ENABLED, "IPv6 not enabled") + def test_socket_uses_IPv6(self): + server = smtpd.SMTPServer((socket_helper.HOSTv6, 0), (socket_helper.HOSTv4, 0)) + self.assertEqual(server.socket.family, socket.AF_INET6) + + def test_socket_uses_IPv4(self): + server = smtpd.SMTPServer((socket_helper.HOSTv4, 0), (socket_helper.HOSTv6, 0)) + self.assertEqual(server.socket.family, socket.AF_INET) + + +class TestRcptOptionParsing(unittest.TestCase): + error_response = (b'555 RCPT TO parameters not recognized or not ' + b'implemented\r\n') + + def setUp(self): + smtpd.socket = asyncore.socket = mock_socket + self.old_debugstream = smtpd.DEBUGSTREAM + self.debug = smtpd.DEBUGSTREAM = io.StringIO() + + def tearDown(self): + asyncore.close_all() + asyncore.socket = smtpd.socket = socket + smtpd.DEBUGSTREAM = self.old_debugstream + + def write_line(self, channel, line): + channel.socket.queue_recv(line) + channel.handle_read() + + def test_params_rejected(self): + server = DummyServer((socket_helper.HOST, 0), ('b', 0)) + conn, addr = server.accept() + channel = smtpd.SMTPChannel(server, conn, addr) + self.write_line(channel, b'EHLO example') + self.write_line(channel, b'MAIL from: size=20') + self.write_line(channel, b'RCPT to: foo=bar') + self.assertEqual(channel.socket.last, self.error_response) + + def test_nothing_accepted(self): + server = DummyServer((socket_helper.HOST, 0), ('b', 0)) + conn, addr = server.accept() + channel = smtpd.SMTPChannel(server, conn, addr) + self.write_line(channel, b'EHLO example') + self.write_line(channel, b'MAIL from: size=20') + self.write_line(channel, b'RCPT to: ') + self.assertEqual(channel.socket.last, b'250 OK\r\n') + + +class TestMailOptionParsing(unittest.TestCase): + error_response = (b'555 MAIL FROM parameters not recognized or not ' + b'implemented\r\n') + + def setUp(self): + smtpd.socket = asyncore.socket = mock_socket + self.old_debugstream = smtpd.DEBUGSTREAM + self.debug = smtpd.DEBUGSTREAM = io.StringIO() + + def tearDown(self): + asyncore.close_all() + asyncore.socket = smtpd.socket = socket + smtpd.DEBUGSTREAM = self.old_debugstream + + def write_line(self, channel, line): + channel.socket.queue_recv(line) + channel.handle_read() + + def test_with_decode_data_true(self): + server = DummyServer((socket_helper.HOST, 0), ('b', 0), decode_data=True) + conn, addr = server.accept() + channel = smtpd.SMTPChannel(server, conn, addr, decode_data=True) + self.write_line(channel, b'EHLO example') + for line in [ + b'MAIL from: size=20 SMTPUTF8', + b'MAIL from: size=20 SMTPUTF8 BODY=8BITMIME', + b'MAIL from: size=20 BODY=UNKNOWN', + b'MAIL from: size=20 body=8bitmime', + ]: + self.write_line(channel, line) + self.assertEqual(channel.socket.last, self.error_response) + self.write_line(channel, b'MAIL from: size=20') + self.assertEqual(channel.socket.last, b'250 OK\r\n') + + def test_with_decode_data_false(self): + server = DummyServer((socket_helper.HOST, 0), ('b', 0)) + conn, addr = server.accept() + channel = smtpd.SMTPChannel(server, conn, addr) + self.write_line(channel, b'EHLO example') + for line in [ + b'MAIL from: size=20 SMTPUTF8', + b'MAIL from: size=20 SMTPUTF8 BODY=8BITMIME', + ]: + self.write_line(channel, line) + self.assertEqual(channel.socket.last, self.error_response) + self.write_line( + channel, + b'MAIL from: size=20 SMTPUTF8 BODY=UNKNOWN') + self.assertEqual( + channel.socket.last, + b'501 Error: BODY can only be one of 7BIT, 8BITMIME\r\n') + self.write_line( + channel, b'MAIL from: size=20 body=8bitmime') + self.assertEqual(channel.socket.last, b'250 OK\r\n') + + def test_with_enable_smtputf8_true(self): + server = DummyServer((socket_helper.HOST, 0), ('b', 0), enable_SMTPUTF8=True) + conn, addr = server.accept() + channel = smtpd.SMTPChannel(server, conn, addr, enable_SMTPUTF8=True) + self.write_line(channel, b'EHLO example') + self.write_line( + channel, + b'MAIL from: size=20 body=8bitmime smtputf8') + self.assertEqual(channel.socket.last, b'250 OK\r\n') + + +class SMTPDChannelTest(unittest.TestCase): + def setUp(self): + smtpd.socket = asyncore.socket = mock_socket + self.old_debugstream = smtpd.DEBUGSTREAM + self.debug = smtpd.DEBUGSTREAM = io.StringIO() + self.server = DummyServer((socket_helper.HOST, 0), ('b', 0), + decode_data=True) + conn, addr = self.server.accept() + self.channel = smtpd.SMTPChannel(self.server, conn, addr, + decode_data=True) + + def tearDown(self): + asyncore.close_all() + asyncore.socket = smtpd.socket = socket + smtpd.DEBUGSTREAM = self.old_debugstream + + def write_line(self, line): + self.channel.socket.queue_recv(line) + self.channel.handle_read() + + def test_broken_connect(self): + self.assertRaises( + DummyDispatcherBroken, BrokenDummyServer, + (socket_helper.HOST, 0), ('b', 0), decode_data=True) + + def test_decode_data_and_enable_SMTPUTF8_raises(self): + self.assertRaises( + ValueError, smtpd.SMTPChannel, + self.server, self.channel.conn, self.channel.addr, + enable_SMTPUTF8=True, decode_data=True) + + def test_server_accept(self): + self.server.handle_accept() + + def test_missing_data(self): + self.write_line(b'') + self.assertEqual(self.channel.socket.last, + b'500 Error: bad syntax\r\n') + + def test_EHLO(self): + self.write_line(b'EHLO example') + self.assertEqual(self.channel.socket.last, b'250 HELP\r\n') + + def test_EHLO_bad_syntax(self): + self.write_line(b'EHLO') + self.assertEqual(self.channel.socket.last, + b'501 Syntax: EHLO hostname\r\n') + + def test_EHLO_duplicate(self): + self.write_line(b'EHLO example') + self.write_line(b'EHLO example') + self.assertEqual(self.channel.socket.last, + b'503 Duplicate HELO/EHLO\r\n') + + def test_EHLO_HELO_duplicate(self): + self.write_line(b'EHLO example') + self.write_line(b'HELO example') + self.assertEqual(self.channel.socket.last, + b'503 Duplicate HELO/EHLO\r\n') + + def test_HELO(self): + name = smtpd.socket.getfqdn() + self.write_line(b'HELO example') + self.assertEqual(self.channel.socket.last, + '250 {}\r\n'.format(name).encode('ascii')) + + def test_HELO_EHLO_duplicate(self): + self.write_line(b'HELO example') + self.write_line(b'EHLO example') + self.assertEqual(self.channel.socket.last, + b'503 Duplicate HELO/EHLO\r\n') + + def test_HELP(self): + self.write_line(b'HELP') + self.assertEqual(self.channel.socket.last, + b'250 Supported commands: EHLO HELO MAIL RCPT ' + \ + b'DATA RSET NOOP QUIT VRFY\r\n') + + def test_HELP_command(self): + self.write_line(b'HELP MAIL') + self.assertEqual(self.channel.socket.last, + b'250 Syntax: MAIL FROM:
\r\n') + + def test_HELP_command_unknown(self): + self.write_line(b'HELP SPAM') + self.assertEqual(self.channel.socket.last, + b'501 Supported commands: EHLO HELO MAIL RCPT ' + \ + b'DATA RSET NOOP QUIT VRFY\r\n') + + def test_HELO_bad_syntax(self): + self.write_line(b'HELO') + self.assertEqual(self.channel.socket.last, + b'501 Syntax: HELO hostname\r\n') + + def test_HELO_duplicate(self): + self.write_line(b'HELO example') + self.write_line(b'HELO example') + self.assertEqual(self.channel.socket.last, + b'503 Duplicate HELO/EHLO\r\n') + + def test_HELO_parameter_rejected_when_extensions_not_enabled(self): + self.extended_smtp = False + self.write_line(b'HELO example') + self.write_line(b'MAIL from: SIZE=1234') + self.assertEqual(self.channel.socket.last, + b'501 Syntax: MAIL FROM:
\r\n') + + def test_MAIL_allows_space_after_colon(self): + self.write_line(b'HELO example') + self.write_line(b'MAIL from: ') + self.assertEqual(self.channel.socket.last, + b'250 OK\r\n') + + def test_extended_MAIL_allows_space_after_colon(self): + self.write_line(b'EHLO example') + self.write_line(b'MAIL from: size=20') + self.assertEqual(self.channel.socket.last, + b'250 OK\r\n') + + def test_NOOP(self): + self.write_line(b'NOOP') + self.assertEqual(self.channel.socket.last, b'250 OK\r\n') + + def test_HELO_NOOP(self): + self.write_line(b'HELO example') + self.write_line(b'NOOP') + self.assertEqual(self.channel.socket.last, b'250 OK\r\n') + + def test_NOOP_bad_syntax(self): + self.write_line(b'NOOP hi') + self.assertEqual(self.channel.socket.last, + b'501 Syntax: NOOP\r\n') + + def test_QUIT(self): + self.write_line(b'QUIT') + self.assertEqual(self.channel.socket.last, b'221 Bye\r\n') + + def test_HELO_QUIT(self): + self.write_line(b'HELO example') + self.write_line(b'QUIT') + self.assertEqual(self.channel.socket.last, b'221 Bye\r\n') + + def test_QUIT_arg_ignored(self): + self.write_line(b'QUIT bye bye') + self.assertEqual(self.channel.socket.last, b'221 Bye\r\n') + + def test_bad_state(self): + self.channel.smtp_state = 'BAD STATE' + self.write_line(b'HELO example') + self.assertEqual(self.channel.socket.last, + b'451 Internal confusion\r\n') + + def test_command_too_long(self): + self.write_line(b'HELO example') + self.write_line(b'MAIL from: ' + + b'a' * self.channel.command_size_limit + + b'@example') + self.assertEqual(self.channel.socket.last, + b'500 Error: line too long\r\n') + + def test_MAIL_command_limit_extended_with_SIZE(self): + self.write_line(b'EHLO example') + fill_len = self.channel.command_size_limit - len('MAIL from:<@example>') + self.write_line(b'MAIL from:<' + + b'a' * fill_len + + b'@example> SIZE=1234') + self.assertEqual(self.channel.socket.last, b'250 OK\r\n') + + self.write_line(b'MAIL from:<' + + b'a' * (fill_len + 26) + + b'@example> SIZE=1234') + self.assertEqual(self.channel.socket.last, + b'500 Error: line too long\r\n') + + def test_MAIL_command_rejects_SMTPUTF8_by_default(self): + self.write_line(b'EHLO example') + self.write_line( + b'MAIL from: BODY=8BITMIME SMTPUTF8') + self.assertEqual(self.channel.socket.last[0:1], b'5') + + def test_data_longer_than_default_data_size_limit(self): + # Hack the default so we don't have to generate so much data. + self.channel.data_size_limit = 1048 + self.write_line(b'HELO example') + self.write_line(b'MAIL From:eggs at example') + self.write_line(b'RCPT To:spam at example') + self.write_line(b'DATA') + self.write_line(b'A' * self.channel.data_size_limit + + b'A\r\n.') + self.assertEqual(self.channel.socket.last, + b'552 Error: Too much mail data\r\n') + + def test_MAIL_size_parameter(self): + self.write_line(b'EHLO example') + self.write_line(b'MAIL FROM: SIZE=512') + self.assertEqual(self.channel.socket.last, + b'250 OK\r\n') + + def test_MAIL_invalid_size_parameter(self): + self.write_line(b'EHLO example') + self.write_line(b'MAIL FROM: SIZE=invalid') + self.assertEqual(self.channel.socket.last, + b'501 Syntax: MAIL FROM:
[SP ]\r\n') + + def test_MAIL_RCPT_unknown_parameters(self): + self.write_line(b'EHLO example') + self.write_line(b'MAIL FROM: ham=green') + self.assertEqual(self.channel.socket.last, + b'555 MAIL FROM parameters not recognized or not implemented\r\n') + + self.write_line(b'MAIL FROM:') + self.write_line(b'RCPT TO: ham=green') + self.assertEqual(self.channel.socket.last, + b'555 RCPT TO parameters not recognized or not implemented\r\n') + + def test_MAIL_size_parameter_larger_than_default_data_size_limit(self): + self.channel.data_size_limit = 1048 + self.write_line(b'EHLO example') + self.write_line(b'MAIL FROM: SIZE=2096') + self.assertEqual(self.channel.socket.last, + b'552 Error: message size exceeds fixed maximum message size\r\n') + + def test_need_MAIL(self): + self.write_line(b'HELO example') + self.write_line(b'RCPT to:spam at example') + self.assertEqual(self.channel.socket.last, + b'503 Error: need MAIL command\r\n') + + def test_MAIL_syntax_HELO(self): + self.write_line(b'HELO example') + self.write_line(b'MAIL from eggs at example') + self.assertEqual(self.channel.socket.last, + b'501 Syntax: MAIL FROM:
\r\n') + + def test_MAIL_syntax_EHLO(self): + self.write_line(b'EHLO example') + self.write_line(b'MAIL from eggs at example') + self.assertEqual(self.channel.socket.last, + b'501 Syntax: MAIL FROM:
[SP ]\r\n') + + def test_MAIL_missing_address(self): + self.write_line(b'HELO example') + self.write_line(b'MAIL from:') + self.assertEqual(self.channel.socket.last, + b'501 Syntax: MAIL FROM:
\r\n') + + def test_MAIL_chevrons(self): + self.write_line(b'HELO example') + self.write_line(b'MAIL from:') + self.assertEqual(self.channel.socket.last, b'250 OK\r\n') + + def test_MAIL_empty_chevrons(self): + self.write_line(b'EHLO example') + self.write_line(b'MAIL from:<>') + self.assertEqual(self.channel.socket.last, b'250 OK\r\n') + + def test_MAIL_quoted_localpart(self): + self.write_line(b'EHLO example') + self.write_line(b'MAIL from: <"Fred Blogs"@example.com>') + self.assertEqual(self.channel.socket.last, b'250 OK\r\n') + self.assertEqual(self.channel.mailfrom, '"Fred Blogs"@example.com') + + def test_MAIL_quoted_localpart_no_angles(self): + self.write_line(b'EHLO example') + self.write_line(b'MAIL from: "Fred Blogs"@example.com') + self.assertEqual(self.channel.socket.last, b'250 OK\r\n') + self.assertEqual(self.channel.mailfrom, '"Fred Blogs"@example.com') + + def test_MAIL_quoted_localpart_with_size(self): + self.write_line(b'EHLO example') + self.write_line(b'MAIL from: <"Fred Blogs"@example.com> SIZE=1000') + self.assertEqual(self.channel.socket.last, b'250 OK\r\n') + self.assertEqual(self.channel.mailfrom, '"Fred Blogs"@example.com') + + def test_MAIL_quoted_localpart_with_size_no_angles(self): + self.write_line(b'EHLO example') + self.write_line(b'MAIL from: "Fred Blogs"@example.com SIZE=1000') + self.assertEqual(self.channel.socket.last, b'250 OK\r\n') + self.assertEqual(self.channel.mailfrom, '"Fred Blogs"@example.com') + + def test_nested_MAIL(self): + self.write_line(b'HELO example') + self.write_line(b'MAIL from:eggs at example') + self.write_line(b'MAIL from:spam at example') + self.assertEqual(self.channel.socket.last, + b'503 Error: nested MAIL command\r\n') + + def test_VRFY(self): + self.write_line(b'VRFY eggs at example') + self.assertEqual(self.channel.socket.last, + b'252 Cannot VRFY user, but will accept message and attempt ' + \ + b'delivery\r\n') + + def test_VRFY_syntax(self): + self.write_line(b'VRFY') + self.assertEqual(self.channel.socket.last, + b'501 Syntax: VRFY
\r\n') + + def test_EXPN_not_implemented(self): + self.write_line(b'EXPN') + self.assertEqual(self.channel.socket.last, + b'502 EXPN not implemented\r\n') + + def test_no_HELO_MAIL(self): + self.write_line(b'MAIL from:') + self.assertEqual(self.channel.socket.last, + b'503 Error: send HELO first\r\n') + + def test_need_RCPT(self): + self.write_line(b'HELO example') + self.write_line(b'MAIL From:eggs at example') + self.write_line(b'DATA') + self.assertEqual(self.channel.socket.last, + b'503 Error: need RCPT command\r\n') + + def test_RCPT_syntax_HELO(self): + self.write_line(b'HELO example') + self.write_line(b'MAIL From: eggs at example') + self.write_line(b'RCPT to eggs at example') + self.assertEqual(self.channel.socket.last, + b'501 Syntax: RCPT TO:
\r\n') + + def test_RCPT_syntax_EHLO(self): + self.write_line(b'EHLO example') + self.write_line(b'MAIL From: eggs at example') + self.write_line(b'RCPT to eggs at example') + self.assertEqual(self.channel.socket.last, + b'501 Syntax: RCPT TO:
[SP ]\r\n') + + def test_RCPT_lowercase_to_OK(self): + self.write_line(b'HELO example') + self.write_line(b'MAIL From: eggs at example') + self.write_line(b'RCPT to: ') + self.assertEqual(self.channel.socket.last, b'250 OK\r\n') + + def test_no_HELO_RCPT(self): + self.write_line(b'RCPT to eggs at example') + self.assertEqual(self.channel.socket.last, + b'503 Error: send HELO first\r\n') + + def test_data_dialog(self): + self.write_line(b'HELO example') + self.write_line(b'MAIL From:eggs at example') + self.assertEqual(self.channel.socket.last, b'250 OK\r\n') + self.write_line(b'RCPT To:spam at example') + self.assertEqual(self.channel.socket.last, b'250 OK\r\n') + + self.write_line(b'DATA') + self.assertEqual(self.channel.socket.last, + b'354 End data with .\r\n') + self.write_line(b'data\r\nmore\r\n.') + self.assertEqual(self.channel.socket.last, b'250 OK\r\n') + self.assertEqual(self.server.messages, + [(('peer-address', 'peer-port'), + 'eggs at example', + ['spam at example'], + 'data\nmore')]) + + def test_DATA_syntax(self): + self.write_line(b'HELO example') + self.write_line(b'MAIL From:eggs at example') + self.write_line(b'RCPT To:spam at example') + self.write_line(b'DATA spam') + self.assertEqual(self.channel.socket.last, b'501 Syntax: DATA\r\n') + + def test_no_HELO_DATA(self): + self.write_line(b'DATA spam') + self.assertEqual(self.channel.socket.last, + b'503 Error: send HELO first\r\n') + + def test_data_transparency_section_4_5_2(self): + self.write_line(b'HELO example') + self.write_line(b'MAIL From:eggs at example') + self.write_line(b'RCPT To:spam at example') + self.write_line(b'DATA') + self.write_line(b'..\r\n.\r\n') + self.assertEqual(self.channel.received_data, '.') + + def test_multiple_RCPT(self): + self.write_line(b'HELO example') + self.write_line(b'MAIL From:eggs at example') + self.write_line(b'RCPT To:spam at example') + self.write_line(b'RCPT To:ham at example') + self.write_line(b'DATA') + self.write_line(b'data\r\n.') + self.assertEqual(self.server.messages, + [(('peer-address', 'peer-port'), + 'eggs at example', + ['spam at example','ham at example'], + 'data')]) + + def test_manual_status(self): + # checks that the Channel is able to return a custom status message + self.write_line(b'HELO example') + self.write_line(b'MAIL From:eggs at example') + self.write_line(b'RCPT To:spam at example') + self.write_line(b'DATA') + self.write_line(b'return status\r\n.') + self.assertEqual(self.channel.socket.last, b'250 Okish\r\n') + + def test_RSET(self): + self.write_line(b'HELO example') + self.write_line(b'MAIL From:eggs at example') + self.write_line(b'RCPT To:spam at example') + self.write_line(b'RSET') + self.assertEqual(self.channel.socket.last, b'250 OK\r\n') + self.write_line(b'MAIL From:foo at example') + self.write_line(b'RCPT To:eggs at example') + self.write_line(b'DATA') + self.write_line(b'data\r\n.') + self.assertEqual(self.server.messages, + [(('peer-address', 'peer-port'), + 'foo at example', + ['eggs at example'], + 'data')]) + + def test_HELO_RSET(self): + self.write_line(b'HELO example') + self.write_line(b'RSET') + self.assertEqual(self.channel.socket.last, b'250 OK\r\n') + + def test_RSET_syntax(self): + self.write_line(b'RSET hi') + self.assertEqual(self.channel.socket.last, b'501 Syntax: RSET\r\n') + + def test_unknown_command(self): + self.write_line(b'UNKNOWN_CMD') + self.assertEqual(self.channel.socket.last, + b'500 Error: command "UNKNOWN_CMD" not ' + \ + b'recognized\r\n') + + def test_attribute_deprecations(self): + with warnings_helper.check_warnings(('', DeprecationWarning)): + spam = self.channel._SMTPChannel__server + with warnings_helper.check_warnings(('', DeprecationWarning)): + self.channel._SMTPChannel__server = 'spam' + with warnings_helper.check_warnings(('', DeprecationWarning)): + spam = self.channel._SMTPChannel__line + with warnings_helper.check_warnings(('', DeprecationWarning)): + self.channel._SMTPChannel__line = 'spam' + with warnings_helper.check_warnings(('', DeprecationWarning)): + spam = self.channel._SMTPChannel__state + with warnings_helper.check_warnings(('', DeprecationWarning)): + self.channel._SMTPChannel__state = 'spam' + with warnings_helper.check_warnings(('', DeprecationWarning)): + spam = self.channel._SMTPChannel__greeting + with warnings_helper.check_warnings(('', DeprecationWarning)): + self.channel._SMTPChannel__greeting = 'spam' + with warnings_helper.check_warnings(('', DeprecationWarning)): + spam = self.channel._SMTPChannel__mailfrom + with warnings_helper.check_warnings(('', DeprecationWarning)): + self.channel._SMTPChannel__mailfrom = 'spam' + with warnings_helper.check_warnings(('', DeprecationWarning)): + spam = self.channel._SMTPChannel__rcpttos + with warnings_helper.check_warnings(('', DeprecationWarning)): + self.channel._SMTPChannel__rcpttos = 'spam' + with warnings_helper.check_warnings(('', DeprecationWarning)): + spam = self.channel._SMTPChannel__data + with warnings_helper.check_warnings(('', DeprecationWarning)): + self.channel._SMTPChannel__data = 'spam' + with warnings_helper.check_warnings(('', DeprecationWarning)): + spam = self.channel._SMTPChannel__fqdn + with warnings_helper.check_warnings(('', DeprecationWarning)): + self.channel._SMTPChannel__fqdn = 'spam' + with warnings_helper.check_warnings(('', DeprecationWarning)): + spam = self.channel._SMTPChannel__peer + with warnings_helper.check_warnings(('', DeprecationWarning)): + self.channel._SMTPChannel__peer = 'spam' + with warnings_helper.check_warnings(('', DeprecationWarning)): + spam = self.channel._SMTPChannel__conn + with warnings_helper.check_warnings(('', DeprecationWarning)): + self.channel._SMTPChannel__conn = 'spam' + with warnings_helper.check_warnings(('', DeprecationWarning)): + spam = self.channel._SMTPChannel__addr + with warnings_helper.check_warnings(('', DeprecationWarning)): + self.channel._SMTPChannel__addr = 'spam' + + at unittest.skipUnless(socket_helper.IPV6_ENABLED, "IPv6 not enabled") +class SMTPDChannelIPv6Test(SMTPDChannelTest): + def setUp(self): + smtpd.socket = asyncore.socket = mock_socket + self.old_debugstream = smtpd.DEBUGSTREAM + self.debug = smtpd.DEBUGSTREAM = io.StringIO() + self.server = DummyServer((socket_helper.HOSTv6, 0), ('b', 0), + decode_data=True) + conn, addr = self.server.accept() + self.channel = smtpd.SMTPChannel(self.server, conn, addr, + decode_data=True) + +class SMTPDChannelWithDataSizeLimitTest(unittest.TestCase): + + def setUp(self): + smtpd.socket = asyncore.socket = mock_socket + self.old_debugstream = smtpd.DEBUGSTREAM + self.debug = smtpd.DEBUGSTREAM = io.StringIO() + self.server = DummyServer((socket_helper.HOST, 0), ('b', 0), + decode_data=True) + conn, addr = self.server.accept() + # Set DATA size limit to 32 bytes for easy testing + self.channel = smtpd.SMTPChannel(self.server, conn, addr, 32, + decode_data=True) + + def tearDown(self): + asyncore.close_all() + asyncore.socket = smtpd.socket = socket + smtpd.DEBUGSTREAM = self.old_debugstream + + def write_line(self, line): + self.channel.socket.queue_recv(line) + self.channel.handle_read() + + def test_data_limit_dialog(self): + self.write_line(b'HELO example') + self.write_line(b'MAIL From:eggs at example') + self.assertEqual(self.channel.socket.last, b'250 OK\r\n') + self.write_line(b'RCPT To:spam at example') + self.assertEqual(self.channel.socket.last, b'250 OK\r\n') + + self.write_line(b'DATA') + self.assertEqual(self.channel.socket.last, + b'354 End data with .\r\n') + self.write_line(b'data\r\nmore\r\n.') + self.assertEqual(self.channel.socket.last, b'250 OK\r\n') + self.assertEqual(self.server.messages, + [(('peer-address', 'peer-port'), + 'eggs at example', + ['spam at example'], + 'data\nmore')]) + + def test_data_limit_dialog_too_much_data(self): + self.write_line(b'HELO example') + self.write_line(b'MAIL From:eggs at example') + self.assertEqual(self.channel.socket.last, b'250 OK\r\n') + self.write_line(b'RCPT To:spam at example') + self.assertEqual(self.channel.socket.last, b'250 OK\r\n') + + self.write_line(b'DATA') + self.assertEqual(self.channel.socket.last, + b'354 End data with .\r\n') + self.write_line(b'This message is longer than 32 bytes\r\n.') + self.assertEqual(self.channel.socket.last, + b'552 Error: Too much mail data\r\n') + + +class SMTPDChannelWithDecodeDataFalse(unittest.TestCase): + + def setUp(self): + smtpd.socket = asyncore.socket = mock_socket + self.old_debugstream = smtpd.DEBUGSTREAM + self.debug = smtpd.DEBUGSTREAM = io.StringIO() + self.server = DummyServer((socket_helper.HOST, 0), ('b', 0)) + conn, addr = self.server.accept() + self.channel = smtpd.SMTPChannel(self.server, conn, addr) + + def tearDown(self): + asyncore.close_all() + asyncore.socket = smtpd.socket = socket + smtpd.DEBUGSTREAM = self.old_debugstream + + def write_line(self, line): + self.channel.socket.queue_recv(line) + self.channel.handle_read() + + def test_ascii_data(self): + self.write_line(b'HELO example') + self.write_line(b'MAIL From:eggs at example') + self.write_line(b'RCPT To:spam at example') + self.write_line(b'DATA') + self.write_line(b'plain ascii text') + self.write_line(b'.') + self.assertEqual(self.channel.received_data, b'plain ascii text') + + def test_utf8_data(self): + self.write_line(b'HELO example') + self.write_line(b'MAIL From:eggs at example') + self.write_line(b'RCPT To:spam at example') + self.write_line(b'DATA') + self.write_line(b'utf8 enriched text: \xc5\xbc\xc5\xba\xc4\x87') + self.write_line(b'and some plain ascii') + self.write_line(b'.') + self.assertEqual( + self.channel.received_data, + b'utf8 enriched text: \xc5\xbc\xc5\xba\xc4\x87\n' + b'and some plain ascii') + + +class SMTPDChannelWithDecodeDataTrue(unittest.TestCase): + + def setUp(self): + smtpd.socket = asyncore.socket = mock_socket + self.old_debugstream = smtpd.DEBUGSTREAM + self.debug = smtpd.DEBUGSTREAM = io.StringIO() + self.server = DummyServer((socket_helper.HOST, 0), ('b', 0), + decode_data=True) + conn, addr = self.server.accept() + # Set decode_data to True + self.channel = smtpd.SMTPChannel(self.server, conn, addr, + decode_data=True) + + def tearDown(self): + asyncore.close_all() + asyncore.socket = smtpd.socket = socket + smtpd.DEBUGSTREAM = self.old_debugstream + + def write_line(self, line): + self.channel.socket.queue_recv(line) + self.channel.handle_read() + + def test_ascii_data(self): + self.write_line(b'HELO example') + self.write_line(b'MAIL From:eggs at example') + self.write_line(b'RCPT To:spam at example') + self.write_line(b'DATA') + self.write_line(b'plain ascii text') + self.write_line(b'.') + self.assertEqual(self.channel.received_data, 'plain ascii text') + + def test_utf8_data(self): + self.write_line(b'HELO example') + self.write_line(b'MAIL From:eggs at example') + self.write_line(b'RCPT To:spam at example') + self.write_line(b'DATA') + self.write_line(b'utf8 enriched text: \xc5\xbc\xc5\xba\xc4\x87') + self.write_line(b'and some plain ascii') + self.write_line(b'.') + self.assertEqual( + self.channel.received_data, + 'utf8 enriched text: ???\nand some plain ascii') + + +class SMTPDChannelTestWithEnableSMTPUTF8True(unittest.TestCase): + def setUp(self): + smtpd.socket = asyncore.socket = mock_socket + self.old_debugstream = smtpd.DEBUGSTREAM + self.debug = smtpd.DEBUGSTREAM = io.StringIO() + self.server = DummyServer((socket_helper.HOST, 0), ('b', 0), + enable_SMTPUTF8=True) + conn, addr = self.server.accept() + self.channel = smtpd.SMTPChannel(self.server, conn, addr, + enable_SMTPUTF8=True) + + def tearDown(self): + asyncore.close_all() + asyncore.socket = smtpd.socket = socket + smtpd.DEBUGSTREAM = self.old_debugstream + + def write_line(self, line): + self.channel.socket.queue_recv(line) + self.channel.handle_read() + + def test_MAIL_command_accepts_SMTPUTF8_when_announced(self): + self.write_line(b'EHLO example') + self.write_line( + 'MAIL from: BODY=8BITMIME SMTPUTF8'.encode( + 'utf-8') + ) + self.assertEqual(self.channel.socket.last, b'250 OK\r\n') + + def test_process_smtputf8_message(self): + self.write_line(b'EHLO example') + for mail_parameters in [b'', b'BODY=8BITMIME SMTPUTF8']: + self.write_line(b'MAIL from: ' + mail_parameters) + self.assertEqual(self.channel.socket.last[0:3], b'250') + self.write_line(b'rcpt to:') + self.assertEqual(self.channel.socket.last[0:3], b'250') + self.write_line(b'data') + self.assertEqual(self.channel.socket.last[0:3], b'354') + self.write_line(b'c\r\n.') + if mail_parameters == b'': + self.assertEqual(self.channel.socket.last, b'250 OK\r\n') + else: + self.assertEqual(self.channel.socket.last, + b'250 SMTPUTF8 message okish\r\n') + + def test_utf8_data(self): + self.write_line(b'EHLO example') + self.write_line( + 'MAIL From: nai?ve at exampl? BODY=8BITMIME SMTPUTF8'.encode('utf-8')) + self.assertEqual(self.channel.socket.last[0:3], b'250') + self.write_line('RCPT To:sp?m at exampl?'.encode('utf-8')) + self.assertEqual(self.channel.socket.last[0:3], b'250') + self.write_line(b'DATA') + self.assertEqual(self.channel.socket.last[0:3], b'354') + self.write_line(b'utf8 enriched text: \xc5\xbc\xc5\xba\xc4\x87') + self.write_line(b'.') + self.assertEqual( + self.channel.received_data, + b'utf8 enriched text: \xc5\xbc\xc5\xba\xc4\x87') + + def test_MAIL_command_limit_extended_with_SIZE_and_SMTPUTF8(self): + self.write_line(b'ehlo example') + fill_len = (512 + 26 + 10) - len('mail from:<@example>') + self.write_line(b'MAIL from:<' + + b'a' * (fill_len + 1) + + b'@example>') + self.assertEqual(self.channel.socket.last, + b'500 Error: line too long\r\n') + self.write_line(b'MAIL from:<' + + b'a' * fill_len + + b'@example>') + self.assertEqual(self.channel.socket.last, b'250 OK\r\n') + + def test_multiple_emails_with_extended_command_length(self): + self.write_line(b'ehlo example') + fill_len = (512 + 26 + 10) - len('mail from:<@example>') + for char in [b'a', b'b', b'c']: + self.write_line(b'MAIL from:<' + char * fill_len + b'a at example>') + self.assertEqual(self.channel.socket.last[0:3], b'500') + self.write_line(b'MAIL from:<' + char * fill_len + b'@example>') + self.assertEqual(self.channel.socket.last[0:3], b'250') + self.write_line(b'rcpt to:') + self.assertEqual(self.channel.socket.last[0:3], b'250') + self.write_line(b'data') + self.assertEqual(self.channel.socket.last[0:3], b'354') + self.write_line(b'test\r\n.') + self.assertEqual(self.channel.socket.last[0:3], b'250') + + +class MiscTestCase(unittest.TestCase): + def test__all__(self): + not_exported = { + "program", "Devnull", "DEBUGSTREAM", "NEWLINE", "COMMASPACE", + "DATA_SIZE_DEFAULT", "usage", "Options", "parseargs", + } + support.check__all__(self, smtpd, not_exported=not_exported) + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py index bdce3e37095e4..9761a37251731 100644 --- a/Lib/test/test_smtplib.py +++ b/Lib/test/test_smtplib.py @@ -18,13 +18,17 @@ import unittest from test import support, mock_socket -from test.support import _asyncore as asyncore -from test.support import _smtpd as smtpd from test.support import hashlib_helper from test.support import socket_helper from test.support import threading_helper from unittest.mock import Mock +import warnings +with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + import asyncore + import smtpd + HOST = socket_helper.HOST if sys.platform == 'darwin': diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 88eeb07afa036..981e2fe82ee46 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -4,7 +4,6 @@ import unittest import unittest.mock from test import support -from test.support import _asyncore as asyncore from test.support import import_helper from test.support import os_helper from test.support import socket_helper @@ -31,6 +30,10 @@ except ImportError: ctypes = None +import warnings +with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + import asyncore ssl = import_helper.import_module("ssl") import _ssl diff --git a/Misc/NEWS.d/next/Library/2021-11-11-12-59-10.bpo-28533.68mMZa.rst b/Misc/NEWS.d/next/Library/2021-11-11-12-59-10.bpo-28533.68mMZa.rst deleted file mode 100644 index 49243815e31f2..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-11-11-12-59-10.bpo-28533.68mMZa.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove the ``asyncore`` and ``asynchat`` modules, deprecated in Python 3.6: -use the :mod:`asyncio` module instead. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2021-11-11-12-59-49.bpo-28533.LvIFCQ.rst b/Misc/NEWS.d/next/Library/2021-11-11-12-59-49.bpo-28533.LvIFCQ.rst deleted file mode 100644 index 67fb3686b1d86..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-11-11-12-59-49.bpo-28533.LvIFCQ.rst +++ /dev/null @@ -1,3 +0,0 @@ -Remove the ``smtpd`` module, deprecated in Python 3.6: the `aiosmtpd -`__ module can be used instead, it is based -on asyncio. Patch by Victor Stinner. diff --git a/PCbuild/lib.pyproj b/PCbuild/lib.pyproj index 7dd40ad64a7e3..43c570f1dab37 100644 --- a/PCbuild/lib.pyproj +++ b/PCbuild/lib.pyproj @@ -24,6 +24,7 @@ + @@ -49,6 +50,7 @@ + @@ -720,6 +722,7 @@ + @@ -857,6 +860,7 @@ + @@ -878,6 +882,7 @@ + @@ -1258,6 +1263,7 @@ + diff --git a/Python/stdlib_module_names.h b/Python/stdlib_module_names.h index 7d421081b2ab8..754fa94e35eba 100644 --- a/Python/stdlib_module_names.h +++ b/Python/stdlib_module_names.h @@ -96,7 +96,9 @@ static const char* _Py_stdlib_module_names[] = { "argparse", "array", "ast", +"asynchat", "asyncio", +"asyncore", "atexit", "audioop", "base64", @@ -240,6 +242,7 @@ static const char* _Py_stdlib_module_names[] = { "shutil", "signal", "site", +"smtpd", "smtplib", "sndhdr", "socket", From webhook-mailer at python.org Tue Dec 7 06:45:22 2021 From: webhook-mailer at python.org (vsajip) Date: Tue, 07 Dec 2021 11:45:22 -0000 Subject: [Python-checkins] [3.10] bpo-35821: Add an example to Logger.propagate documentation. (GH-29841) (GH-29957) Message-ID: https://github.com/python/cpython/commit/f78c229b4ec8621a9b15c6396b6c91518e8975d6 commit: f78c229b4ec8621a9b15c6396b6c91518e8975d6 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: vsajip date: 2021-12-07T11:45:13Z summary: [3.10] bpo-35821: Add an example to Logger.propagate documentation. (GH-29841) (GH-29957) files: M Doc/library/logging.rst diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index bb1bbf0e3708c..ade4a3c6b261e 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -80,6 +80,15 @@ is the module's name in the Python package namespace. If this evaluates to false, logging messages are not passed to the handlers of ancestor loggers. + Spelling it out with an example: If the propagate attribute of the logger named + `A.B.C` evaluates to true, any event logged to `A.B.C` via a method call such as + `logging.getLogger('A.B.C').error(...)` will [subject to passing that logger's + level and filter settings] be passed in turn to any handlers attached to loggers + named `A.B`, `A` and the root logger, after first being passed to any handlers + attached to `A.B.C`. If any logger in the chain `A.B.C`, `A.B`, `A` has its + `propagate` attribute set to false, then that is the last logger whose handlers + are offered the event to handle, and propagation stops at that point. + The constructor sets this attribute to ``True``. .. note:: If you attach a handler to a logger *and* one or more of its From webhook-mailer at python.org Tue Dec 7 06:45:53 2021 From: webhook-mailer at python.org (vsajip) Date: Tue, 07 Dec 2021 11:45:53 -0000 Subject: [Python-checkins] [3.9] bpo-35821: Add an example to Logger.propagate documentation. (GH-29841) (GH-29958) Message-ID: https://github.com/python/cpython/commit/e688568cdfe758a2316ecaf0c8df868d5dde0d83 commit: e688568cdfe758a2316ecaf0c8df868d5dde0d83 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: vsajip date: 2021-12-07T11:45:49Z summary: [3.9] bpo-35821: Add an example to Logger.propagate documentation. (GH-29841) (GH-29958) files: M Doc/library/logging.rst diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index e72a898a11363..705b31d604500 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -80,6 +80,15 @@ is the module's name in the Python package namespace. If this evaluates to false, logging messages are not passed to the handlers of ancestor loggers. + Spelling it out with an example: If the propagate attribute of the logger named + `A.B.C` evaluates to true, any event logged to `A.B.C` via a method call such as + `logging.getLogger('A.B.C').error(...)` will [subject to passing that logger's + level and filter settings] be passed in turn to any handlers attached to loggers + named `A.B`, `A` and the root logger, after first being passed to any handlers + attached to `A.B.C`. If any logger in the chain `A.B.C`, `A.B`, `A` has its + `propagate` attribute set to false, then that is the last logger whose handlers + are offered the event to handle, and propagation stops at that point. + The constructor sets this attribute to ``True``. .. note:: If you attach a handler to a logger *and* one or more of its From webhook-mailer at python.org Tue Dec 7 07:00:11 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Tue, 07 Dec 2021 12:00:11 -0000 Subject: [Python-checkins] bpo-45664: Fix resolve_bases() and new_class() for GenericAlias instance as a base (GH-29298) (GH-29928) Message-ID: https://github.com/python/cpython/commit/bffce2cbb5543bc63a67e33ad599328a12f2b00a commit: bffce2cbb5543bc63a67e33ad599328a12f2b00a branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: serhiy-storchaka date: 2021-12-07T14:00:06+02:00 summary: bpo-45664: Fix resolve_bases() and new_class() for GenericAlias instance as a base (GH-29298) (GH-29928) (cherry picked from commit 2b318ce1c988b7b6e3caf293d55f289e066b6e0f) Co-authored-by: Serhiy Storchaka files: A Misc/NEWS.d/next/Library/2021-10-28-23-40-54.bpo-45664.7dqtxQ.rst M Lib/test/test_types.py M Lib/types.py diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index 49dc5bf40e3ed..fe432a4deb803 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -7,6 +7,7 @@ import locale import sys import types +import typing import unittest.mock import weakref @@ -888,6 +889,17 @@ def __mro_entries__(self, bases): self.assertEqual(D.__orig_bases__, (c,)) self.assertEqual(D.__mro__, (D, A, object)) + def test_new_class_with_mro_entry_genericalias(self): + L1 = types.new_class('L1', (typing.List[int],), {}) + self.assertEqual(L1.__bases__, (list, typing.Generic)) + self.assertEqual(L1.__orig_bases__, (typing.List[int],)) + self.assertEqual(L1.__mro__, (L1, list, typing.Generic, object)) + + L2 = types.new_class('L2', (list[int],), {}) + self.assertEqual(L2.__bases__, (list,)) + self.assertEqual(L2.__orig_bases__, (list[int],)) + self.assertEqual(L2.__mro__, (L2, list, object)) + def test_new_class_with_mro_entry_none(self): class A: pass class B: pass @@ -1003,6 +1015,11 @@ def __mro_entries__(self, bases): for bases in [x, y, z, t]: self.assertIs(types.resolve_bases(bases), bases) + def test_resolve_bases_with_mro_entry(self): + self.assertEqual(types.resolve_bases((typing.List[int],)), + (list, typing.Generic)) + self.assertEqual(types.resolve_bases((list[int],)), (list,)) + def test_metaclass_derivation(self): # issue1294232: correct metaclass calculation new_calls = [] # to check the order of __new__ calls diff --git a/Lib/types.py b/Lib/types.py index ad2020ec69b63..f15fda5933a3f 100644 --- a/Lib/types.py +++ b/Lib/types.py @@ -82,7 +82,7 @@ def resolve_bases(bases): updated = False shift = 0 for i, base in enumerate(bases): - if isinstance(base, type): + if isinstance(base, type) and not isinstance(base, GenericAlias): continue if not hasattr(base, "__mro_entries__"): continue diff --git a/Misc/NEWS.d/next/Library/2021-10-28-23-40-54.bpo-45664.7dqtxQ.rst b/Misc/NEWS.d/next/Library/2021-10-28-23-40-54.bpo-45664.7dqtxQ.rst new file mode 100644 index 0000000000000..573a569845a87 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-10-28-23-40-54.bpo-45664.7dqtxQ.rst @@ -0,0 +1,2 @@ +Fix :func:`types.resolve_bases` and :func:`types.new_class` for +:class:`types.GenericAlias` instance as a base. From webhook-mailer at python.org Tue Dec 7 08:02:34 2021 From: webhook-mailer at python.org (pablogsal) Date: Tue, 07 Dec 2021 13:02:34 -0000 Subject: [Python-checkins] bpo-46004: Fix error location for loops with invalid targets (GH-29959) Message-ID: https://github.com/python/cpython/commit/1c7a1c3be08ee911d347fffd2716f3911ba751f9 commit: 1c7a1c3be08ee911d347fffd2716f3911ba751f9 branch: main author: Pablo Galindo Salgado committer: pablogsal date: 2021-12-07T13:02:15Z summary: bpo-46004: Fix error location for loops with invalid targets (GH-29959) files: A Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-24-24.bpo-46004.TTEU1p.rst M Lib/test/test_exceptions.py M Parser/pegen.h diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index e4b7b8f0a6406..a954ecb8f7c25 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -234,6 +234,7 @@ def testSyntaxErrorOffset(self): check("ages = {'Alice'=22, 'Bob'=23}", 1, 16) check('match ...:\n case {**rest, "key": value}:\n ...', 2, 19) check("[a b c d e f]", 1, 2) + check("for x yfff:", 1, 7) # Errors thrown by compile.c check('class foo:return 1', 1, 11) diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-24-24.bpo-46004.TTEU1p.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-24-24.bpo-46004.TTEU1p.rst new file mode 100644 index 0000000000000..199bccf8166f0 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-24-24.bpo-46004.TTEU1p.rst @@ -0,0 +1,2 @@ +Fix the :exc:`SyntaxError` location for errors involving for loops with +invalid targets. Patch by Pablo Galindo diff --git a/Parser/pegen.h b/Parser/pegen.h index 78e75d7060cf1..caba34e535b6a 100644 --- a/Parser/pegen.h +++ b/Parser/pegen.h @@ -227,8 +227,9 @@ _RAISE_SYNTAX_ERROR_INVALID_TARGET(Parser *p, TARGETS_TYPE type, void *e) msg, _PyPegen_get_expr_name(invalid_target) ); + return RAISE_SYNTAX_ERROR_KNOWN_LOCATION(invalid_target, "invalid syntax"); } - return RAISE_SYNTAX_ERROR("invalid syntax"); + return NULL; } // Action utility functions From webhook-mailer at python.org Tue Dec 7 10:23:42 2021 From: webhook-mailer at python.org (pablogsal) Date: Tue, 07 Dec 2021 15:23:42 -0000 Subject: [Python-checkins] [3.10] bpo-46004: Fix error location for loops with invalid targets (GH-29959). (GH-29961) Message-ID: https://github.com/python/cpython/commit/c52141200364898818956a73b955f7c04f634dc8 commit: c52141200364898818956a73b955f7c04f634dc8 branch: 3.10 author: Pablo Galindo Salgado committer: pablogsal date: 2021-12-07T15:23:33Z summary: [3.10] bpo-46004: Fix error location for loops with invalid targets (GH-29959). (GH-29961) (cherry picked from commit 1c7a1c3be08ee911d347fffd2716f3911ba751f9) Co-authored-by: Pablo Galindo Salgado files: A Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-24-24.bpo-46004.TTEU1p.rst M Lib/test/test_exceptions.py M Parser/pegen.h diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index ad2864bc41637..bc5f83a5d2dc8 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -234,6 +234,7 @@ def testSyntaxErrorOffset(self): check("ages = {'Alice'=22, 'Bob'=23}", 1, 16) check('match ...:\n case {**rest, "key": value}:\n ...', 2, 19) check("[a b c d e f]", 1, 2) + check("for x yfff:", 1, 7) # Errors thrown by compile.c check('class foo:return 1', 1, 11) diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-24-24.bpo-46004.TTEU1p.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-24-24.bpo-46004.TTEU1p.rst new file mode 100644 index 0000000000000..199bccf8166f0 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-24-24.bpo-46004.TTEU1p.rst @@ -0,0 +1,2 @@ +Fix the :exc:`SyntaxError` location for errors involving for loops with +invalid targets. Patch by Pablo Galindo diff --git a/Parser/pegen.h b/Parser/pegen.h index 04c7b9d19bb8a..29d48052e4bc9 100644 --- a/Parser/pegen.h +++ b/Parser/pegen.h @@ -321,8 +321,9 @@ _RAISE_SYNTAX_ERROR_INVALID_TARGET(Parser *p, TARGETS_TYPE type, void *e) msg, _PyPegen_get_expr_name(invalid_target) ); + return RAISE_SYNTAX_ERROR_KNOWN_LOCATION(invalid_target, "invalid syntax"); } - return RAISE_SYNTAX_ERROR("invalid syntax"); + return NULL; } void *_PyPegen_arguments_parsing_error(Parser *, expr_ty); From webhook-mailer at python.org Tue Dec 7 10:25:23 2021 From: webhook-mailer at python.org (Fidget-Spinner) Date: Tue, 07 Dec 2021 15:25:23 -0000 Subject: [Python-checkins] bpo-35821: Fix restructuredtext code formatting in logging.rst (GH-29963) Message-ID: https://github.com/python/cpython/commit/c7e7a4b969b5728d4b4f3c59bf98e1e830d5c6d6 commit: c7e7a4b969b5728d4b4f3c59bf98e1e830d5c6d6 branch: main author: Ken Jin <28750310+Fidget-Spinner at users.noreply.github.com> committer: Fidget-Spinner <28750310+Fidget-Spinner at users.noreply.github.com> date: 2021-12-07T23:25:13+08:00 summary: bpo-35821: Fix restructuredtext code formatting in logging.rst (GH-29963) files: M Doc/library/logging.rst diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index e7c64e5ba4036..ea6494f219ae7 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -81,12 +81,12 @@ is the module's name in the Python package namespace. of ancestor loggers. Spelling it out with an example: If the propagate attribute of the logger named - `A.B.C` evaluates to true, any event logged to `A.B.C` via a method call such as - `logging.getLogger('A.B.C').error(...)` will [subject to passing that logger's + ``A.B.C`` evaluates to true, any event logged to ``A.B.C`` via a method call such as + ``logging.getLogger('A.B.C').error(...)`` will [subject to passing that logger's level and filter settings] be passed in turn to any handlers attached to loggers - named `A.B`, `A` and the root logger, after first being passed to any handlers - attached to `A.B.C`. If any logger in the chain `A.B.C`, `A.B`, `A` has its - `propagate` attribute set to false, then that is the last logger whose handlers + named ``A.B``, ``A`` and the root logger, after first being passed to any handlers + attached to ``A.B.C``. If any logger in the chain ``A.B.C``, ``A.B``, ``A`` has its + ``propagate`` attribute set to false, then that is the last logger whose handlers are offered the event to handle, and propagation stops at that point. The constructor sets this attribute to ``True``. From webhook-mailer at python.org Tue Dec 7 10:47:43 2021 From: webhook-mailer at python.org (miss-islington) Date: Tue, 07 Dec 2021 15:47:43 -0000 Subject: [Python-checkins] [3.10] bpo-35821: Fix restructuredtext code formatting in logging.rst (GH-29963) (GH-29965) Message-ID: https://github.com/python/cpython/commit/14f03ce6e8a33cc8b45f11c4d428193fc7c4a145 commit: 14f03ce6e8a33cc8b45f11c4d428193fc7c4a145 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-07T07:47:31-08:00 summary: [3.10] bpo-35821: Fix restructuredtext code formatting in logging.rst (GH-29963) (GH-29965) (cherry picked from commit c7e7a4b969b5728d4b4f3c59bf98e1e830d5c6d6) Co-authored-by: Ken Jin <28750310+Fidget-Spinner at users.noreply.github.com> Automerge-Triggered-By: GH:Fidget-Spinner files: M Doc/library/logging.rst diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index ade4a3c6b261e..74b1f69caec5c 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -81,12 +81,12 @@ is the module's name in the Python package namespace. of ancestor loggers. Spelling it out with an example: If the propagate attribute of the logger named - `A.B.C` evaluates to true, any event logged to `A.B.C` via a method call such as - `logging.getLogger('A.B.C').error(...)` will [subject to passing that logger's + ``A.B.C`` evaluates to true, any event logged to ``A.B.C`` via a method call such as + ``logging.getLogger('A.B.C').error(...)`` will [subject to passing that logger's level and filter settings] be passed in turn to any handlers attached to loggers - named `A.B`, `A` and the root logger, after first being passed to any handlers - attached to `A.B.C`. If any logger in the chain `A.B.C`, `A.B`, `A` has its - `propagate` attribute set to false, then that is the last logger whose handlers + named ``A.B``, ``A`` and the root logger, after first being passed to any handlers + attached to ``A.B.C``. If any logger in the chain ``A.B.C``, ``A.B``, ``A`` has its + ``propagate`` attribute set to false, then that is the last logger whose handlers are offered the event to handle, and propagation stops at that point. The constructor sets this attribute to ``True``. From webhook-mailer at python.org Tue Dec 7 10:48:42 2021 From: webhook-mailer at python.org (miss-islington) Date: Tue, 07 Dec 2021 15:48:42 -0000 Subject: [Python-checkins] bpo-35821: Fix restructuredtext code formatting in logging.rst (GH-29963) Message-ID: https://github.com/python/cpython/commit/db42809d299d1bc3a07b29fabe8f74fa02a7e59e commit: db42809d299d1bc3a07b29fabe8f74fa02a7e59e branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-07T07:48:32-08:00 summary: bpo-35821: Fix restructuredtext code formatting in logging.rst (GH-29963) (cherry picked from commit c7e7a4b969b5728d4b4f3c59bf98e1e830d5c6d6) Co-authored-by: Ken Jin <28750310+Fidget-Spinner at users.noreply.github.com> files: M Doc/library/logging.rst diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index 705b31d604500..9d6167cca5294 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -81,12 +81,12 @@ is the module's name in the Python package namespace. of ancestor loggers. Spelling it out with an example: If the propagate attribute of the logger named - `A.B.C` evaluates to true, any event logged to `A.B.C` via a method call such as - `logging.getLogger('A.B.C').error(...)` will [subject to passing that logger's + ``A.B.C`` evaluates to true, any event logged to ``A.B.C`` via a method call such as + ``logging.getLogger('A.B.C').error(...)`` will [subject to passing that logger's level and filter settings] be passed in turn to any handlers attached to loggers - named `A.B`, `A` and the root logger, after first being passed to any handlers - attached to `A.B.C`. If any logger in the chain `A.B.C`, `A.B`, `A` has its - `propagate` attribute set to false, then that is the last logger whose handlers + named ``A.B``, ``A`` and the root logger, after first being passed to any handlers + attached to ``A.B.C``. If any logger in the chain ``A.B.C``, ``A.B``, ``A`` has its + ``propagate`` attribute set to false, then that is the last logger whose handlers are offered the event to handle, and propagation stops at that point. The constructor sets this attribute to ``True``. From webhook-mailer at python.org Tue Dec 7 11:03:04 2021 From: webhook-mailer at python.org (markshannon) Date: Tue, 07 Dec 2021 16:03:04 -0000 Subject: [Python-checkins] bpo-45947: Place dict and values pointer at fixed (negative) offset just before GC header. (GH-29879) Message-ID: https://github.com/python/cpython/commit/8319114feedd2a5b77378bba24eb9fb2689c5033 commit: 8319114feedd2a5b77378bba24eb9fb2689c5033 branch: main author: Mark Shannon committer: markshannon date: 2021-12-07T16:02:53Z summary: bpo-45947: Place dict and values pointer at fixed (negative) offset just before GC header. (GH-29879) * Place __dict__ immediately before GC header for plain Python objects. * Fix up lazy dict creation logic to use managed dict pointers. * Manage values pointer, placing them directly before managed dict pointers. * Convert hint-based load/store attr specialization target managed dict classes. * Specialize LOAD_METHOD for managed dict objects. * Remove unsafe _PyObject_GC_Calloc function. * Remove unsafe _PyObject_GC_Malloc() function. * Add comment explaning use of Py_TPFLAGS_MANAGED_DICT. files: A Misc/NEWS.d/next/Core and Builtins/2021-12-01-14-06-36.bpo-45947.1XPPm_.rst M Include/cpython/object.h M Include/cpython/objimpl.h M Include/internal/pycore_object.h M Include/object.h M Lib/test/test_stable_abi_ctypes.py M Lib/test/test_sys.py M Misc/stable_abi.txt M Modules/_testcapimodule.c M Modules/gcmodule.c M Objects/dictobject.c M Objects/exceptions.c M Objects/object.c M Objects/typeobject.c M PC/python3dll.c M Python/ceval.c M Python/specialize.c M Python/sysmodule.c M Tools/gdb/libpython.py diff --git a/Include/cpython/object.h b/Include/cpython/object.h index 3a8a256e3b9ae..0c3957aff4b5d 100644 --- a/Include/cpython/object.h +++ b/Include/cpython/object.h @@ -270,7 +270,6 @@ struct _typeobject { destructor tp_finalize; vectorcallfunc tp_vectorcall; - Py_ssize_t tp_inline_values_offset; }; /* The *real* layout of a type object when allocated on the heap */ diff --git a/Include/cpython/objimpl.h b/Include/cpython/objimpl.h index d83700e2a4647..4a905c25cc845 100644 --- a/Include/cpython/objimpl.h +++ b/Include/cpython/objimpl.h @@ -90,9 +90,6 @@ PyAPI_FUNC(int) PyObject_IS_GC(PyObject *obj); # define _PyGC_FINALIZED(o) PyObject_GC_IsFinalized(o) #endif -PyAPI_FUNC(PyObject *) _PyObject_GC_Malloc(size_t size); -PyAPI_FUNC(PyObject *) _PyObject_GC_Calloc(size_t size); - /* Test if a type supports weak references */ #define PyType_SUPPORTS_WEAKREFS(t) ((t)->tp_weaklistoffset > 0) diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h index 3c126aaef1187..9041a4dc8a3ce 100644 --- a/Include/internal/pycore_object.h +++ b/Include/internal/pycore_object.h @@ -168,6 +168,15 @@ _PyObject_IS_GC(PyObject *obj) // Fast inlined version of PyType_IS_GC() #define _PyType_IS_GC(t) _PyType_HasFeature((t), Py_TPFLAGS_HAVE_GC) +static inline size_t +_PyType_PreHeaderSize(PyTypeObject *tp) +{ + return _PyType_IS_GC(tp) * sizeof(PyGC_Head) + + _PyType_HasFeature(tp, Py_TPFLAGS_MANAGED_DICT) * 2 * sizeof(PyObject *); +} + +void _PyObject_GC_Link(PyObject *op); + // Usage: assert(_Py_CheckSlotResult(obj, "__getitem__", result != NULL)); extern int _Py_CheckSlotResult( PyObject *obj, @@ -185,7 +194,19 @@ extern int _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values, PyObject *name, PyObject *value); PyObject * _PyObject_GetInstanceAttribute(PyObject *obj, PyDictValues *values, PyObject *name); -PyDictValues ** _PyObject_ValuesPointer(PyObject *); + +static inline PyDictValues **_PyObject_ValuesPointer(PyObject *obj) +{ + assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT); + return ((PyDictValues **)obj)-4; +} + +static inline PyObject **_PyObject_ManagedDictPointer(PyObject *obj) +{ + assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT); + return ((PyObject **)obj)-3; +} + PyObject ** _PyObject_DictPointer(PyObject *); int _PyObject_VisitInstanceAttributes(PyObject *self, visitproc visit, void *arg); void _PyObject_ClearInstanceAttributes(PyObject *self); diff --git a/Include/object.h b/Include/object.h index 33df303a44eb7..e5544e8b588ed 100644 --- a/Include/object.h +++ b/Include/object.h @@ -334,6 +334,12 @@ given type object has a specified feature. #ifndef Py_LIMITED_API +/* Placement of dict (and values) pointers are managed by the VM, not by the type. + * The VM will automatically set tp_dictoffset. Should not be used for variable sized + * classes, such as classes that extend tuple. + */ +#define Py_TPFLAGS_MANAGED_DICT (1 << 4) + /* Set if instances of the type object are treated as sequences for pattern matching */ #define Py_TPFLAGS_SEQUENCE (1 << 5) /* Set if instances of the type object are treated as mappings for pattern matching */ diff --git a/Lib/test/test_stable_abi_ctypes.py b/Lib/test/test_stable_abi_ctypes.py index 1e27bcaf889a2..d0cd5c20dd5f4 100644 --- a/Lib/test/test_stable_abi_ctypes.py +++ b/Lib/test/test_stable_abi_ctypes.py @@ -817,7 +817,6 @@ def test_available_symbols(self): "_PyErr_BadInternalCall", "_PyObject_CallFunction_SizeT", "_PyObject_CallMethod_SizeT", - "_PyObject_GC_Malloc", "_PyObject_GC_New", "_PyObject_GC_NewVar", "_PyObject_GC_Resize", diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 81802893a8ee5..41ac03b920e64 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1421,8 +1421,8 @@ def delx(self): del self.__x check((1,2,3), vsize('') + 3*self.P) # type # static type: PyTypeObject - fmt = 'P2nPI13Pl4Pn9Pn12PIPP' - s = vsize(fmt) + fmt = 'P2nPI13Pl4Pn9Pn12PIP' + s = vsize('2P' + fmt) check(int, s) # class s = vsize(fmt + # PyTypeObject diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-01-14-06-36.bpo-45947.1XPPm_.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-01-14-06-36.bpo-45947.1XPPm_.rst new file mode 100644 index 0000000000000..5156bd35369e1 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-01-14-06-36.bpo-45947.1XPPm_.rst @@ -0,0 +1,3 @@ +Place pointers to dict and values immediately before GC header. This reduces +number of dependent memory loads to access either dict or values from 3 to +1. diff --git a/Misc/stable_abi.txt b/Misc/stable_abi.txt index 9f5a85bdec40f..de6caa8c80746 100644 --- a/Misc/stable_abi.txt +++ b/Misc/stable_abi.txt @@ -1577,9 +1577,6 @@ function _PyObject_CallFunction_SizeT function _PyObject_CallMethod_SizeT added 3.2 abi_only -function _PyObject_GC_Malloc - added 3.2 - abi_only function _PyObject_GC_New added 3.2 abi_only diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 0216c985415ce..56d394985eb7c 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -5861,6 +5861,7 @@ test_tstate_capi(PyObject *self, PyObject *Py_UNUSED(args)) } +static PyObject *negative_dictoffset(PyObject *, PyObject *); static PyObject *test_buildvalue_issue38913(PyObject *, PyObject *); static PyObject *getargs_s_hash_int(PyObject *, PyObject *, PyObject*); @@ -5929,14 +5930,15 @@ static PyMethodDef TestMethods[] = { #if (defined(__linux__) || defined(__FreeBSD__)) && defined(__GNUC__) {"test_pep3118_obsolete_write_locks", (PyCFunction)test_pep3118_obsolete_write_locks, METH_NOARGS}, #endif - {"getbuffer_with_null_view", getbuffer_with_null_view, METH_O}, - {"PyBuffer_SizeFromFormat", test_PyBuffer_SizeFromFormat, METH_VARARGS}, - {"test_buildvalue_N", test_buildvalue_N, METH_NOARGS}, + {"getbuffer_with_null_view", getbuffer_with_null_view, METH_O}, + {"PyBuffer_SizeFromFormat", test_PyBuffer_SizeFromFormat, METH_VARARGS}, + {"test_buildvalue_N", test_buildvalue_N, METH_NOARGS}, + {"negative_dictoffset", negative_dictoffset, METH_NOARGS}, {"test_buildvalue_issue38913", test_buildvalue_issue38913, METH_NOARGS}, - {"get_args", get_args, METH_VARARGS}, + {"get_args", get_args, METH_VARARGS}, {"test_get_statictype_slots", test_get_statictype_slots, METH_NOARGS}, {"test_get_type_name", test_get_type_name, METH_NOARGS}, - {"test_get_type_qualname", test_get_type_qualname, METH_NOARGS}, + {"test_get_type_qualname", test_get_type_qualname, METH_NOARGS}, {"test_type_from_ephemeral_spec", test_type_from_ephemeral_spec, METH_NOARGS}, {"get_kwargs", (PyCFunction)(void(*)(void))get_kwargs, METH_VARARGS|METH_KEYWORDS}, @@ -7629,6 +7631,11 @@ PyInit__testcapi(void) return m; } +static PyObject * +negative_dictoffset(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return PyType_FromSpec(&HeapCTypeWithNegativeDict_spec); +} /* Test the C API exposed when PY_SSIZE_T_CLEAN is not defined */ diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index b505676636d38..1808057a650e9 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -69,10 +69,10 @@ module gc #define NEXT_MASK_UNREACHABLE (1) /* Get an object's GC head */ -#define AS_GC(o) ((PyGC_Head *)(o)-1) +#define AS_GC(o) ((PyGC_Head *)(((char *)(o))-sizeof(PyGC_Head))) /* Get the object given the GC head */ -#define FROM_GC(g) ((PyObject *)(((PyGC_Head *)g)+1)) +#define FROM_GC(g) ((PyObject *)(((char *)(g))+sizeof(PyGC_Head))) static inline int gc_is_collecting(PyGC_Head *g) @@ -2231,28 +2231,14 @@ PyObject_IS_GC(PyObject *obj) return _PyObject_IS_GC(obj); } -static PyObject * -_PyObject_GC_Alloc(int use_calloc, size_t basicsize) +void +_PyObject_GC_Link(PyObject *op) { + PyGC_Head *g = AS_GC(op); + assert(((uintptr_t)g & (sizeof(uintptr_t)-1)) == 0); // g must be correctly aligned + PyThreadState *tstate = _PyThreadState_GET(); GCState *gcstate = &tstate->interp->gc; - if (basicsize > PY_SSIZE_T_MAX - sizeof(PyGC_Head)) { - return _PyErr_NoMemory(tstate); - } - size_t size = sizeof(PyGC_Head) + basicsize; - - PyGC_Head *g; - if (use_calloc) { - g = (PyGC_Head *)PyObject_Calloc(1, size); - } - else { - g = (PyGC_Head *)PyObject_Malloc(size); - } - if (g == NULL) { - return _PyErr_NoMemory(tstate); - } - assert(((uintptr_t)g & 3) == 0); // g must be aligned 4bytes boundary - g->_gc_next = 0; g->_gc_prev = 0; gcstate->generations[0].count++; /* number of allocated GC objects */ @@ -2266,26 +2252,32 @@ _PyObject_GC_Alloc(int use_calloc, size_t basicsize) gc_collect_generations(tstate); gcstate->collecting = 0; } - PyObject *op = FROM_GC(g); - return op; } -PyObject * -_PyObject_GC_Malloc(size_t basicsize) -{ - return _PyObject_GC_Alloc(0, basicsize); -} - -PyObject * -_PyObject_GC_Calloc(size_t basicsize) +static PyObject * +gc_alloc(size_t basicsize, size_t presize) { - return _PyObject_GC_Alloc(1, basicsize); + PyThreadState *tstate = _PyThreadState_GET(); + if (basicsize > PY_SSIZE_T_MAX - presize) { + return _PyErr_NoMemory(tstate); + } + size_t size = presize + basicsize; + char *mem = PyObject_Malloc(size); + if (mem == NULL) { + return _PyErr_NoMemory(tstate); + } + ((PyObject **)mem)[0] = NULL; + ((PyObject **)mem)[1] = NULL; + PyObject *op = (PyObject *)(mem + presize); + _PyObject_GC_Link(op); + return op; } PyObject * _PyObject_GC_New(PyTypeObject *tp) { - PyObject *op = _PyObject_GC_Malloc(_PyObject_SIZE(tp)); + size_t presize = _PyType_PreHeaderSize(tp); + PyObject *op = gc_alloc(_PyObject_SIZE(tp), presize); if (op == NULL) { return NULL; } @@ -2303,8 +2295,9 @@ _PyObject_GC_NewVar(PyTypeObject *tp, Py_ssize_t nitems) PyErr_BadInternalCall(); return NULL; } + size_t presize = _PyType_PreHeaderSize(tp); size = _PyObject_VAR_SIZE(tp, nitems); - op = (PyVarObject *) _PyObject_GC_Malloc(size); + op = (PyVarObject *)gc_alloc(size, presize); if (op == NULL) { return NULL; } @@ -2333,6 +2326,7 @@ _PyObject_GC_Resize(PyVarObject *op, Py_ssize_t nitems) void PyObject_GC_Del(void *op) { + size_t presize = _PyType_PreHeaderSize(((PyObject *)op)->ob_type); PyGC_Head *g = AS_GC(op); if (_PyObject_GC_IS_TRACKED(op)) { gc_list_remove(g); @@ -2341,7 +2335,7 @@ PyObject_GC_Del(void *op) if (gcstate->generations[0].count > 0) { gcstate->generations[0].count--; } - PyObject_Free(g); + PyObject_Free(((char *)op)-presize); } int diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 475d92d329828..7ce4b9069f77e 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -4961,8 +4961,8 @@ static int init_inline_values(PyObject *obj, PyTypeObject *tp) { assert(tp->tp_flags & Py_TPFLAGS_HEAPTYPE); - assert(tp->tp_dictoffset > 0); - assert(tp->tp_inline_values_offset > 0); + // assert(type->tp_dictoffset > 0); -- TO DO Update this assert. + assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT); PyDictKeysObject *keys = CACHED_KEYS(tp); assert(keys != NULL); if (keys->dk_usable > 1) { @@ -4979,7 +4979,7 @@ init_inline_values(PyObject *obj, PyTypeObject *tp) for (int i = 0; i < size; i++) { values->values[i] = NULL; } - *((PyDictValues **)((char *)obj + tp->tp_inline_values_offset)) = values; + *_PyObject_ValuesPointer(obj) = values; return 0; } @@ -4990,7 +4990,7 @@ _PyObject_InitializeDict(PyObject *obj) if (tp->tp_dictoffset == 0) { return 0; } - if (tp->tp_inline_values_offset) { + if (tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) { return init_inline_values(obj, tp); } PyObject *dict; @@ -5032,7 +5032,7 @@ make_dict_from_instance_attributes(PyDictKeysObject *keys, PyDictValues *values) PyObject * _PyObject_MakeDictFromInstanceAttributes(PyObject *obj, PyDictValues *values) { - assert(Py_TYPE(obj)->tp_inline_values_offset != 0); + assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT); PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj)); return make_dict_from_instance_attributes(keys, values); } @@ -5042,10 +5042,10 @@ _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values, PyObject *name, PyObject *value) { assert(PyUnicode_CheckExact(name)); - PyTypeObject *tp = Py_TYPE(obj); PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj)); assert(keys != NULL); assert(values != NULL); + assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT); int ix = insert_into_dictkeys(keys, name); if (ix == DKIX_EMPTY) { if (value == NULL) { @@ -5056,8 +5056,8 @@ _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values, if (dict == NULL) { return -1; } - *((PyDictValues **)((char *)obj + tp->tp_inline_values_offset)) = NULL; - *((PyObject **) ((char *)obj + tp->tp_dictoffset)) = dict; + *_PyObject_ValuesPointer(obj) = NULL; + *_PyObject_ManagedDictPointer(obj) = dict; return PyDict_SetItem(dict, name, value); } PyObject *old_value = values->values[ix]; @@ -5102,17 +5102,23 @@ _PyObject_IsInstanceDictEmpty(PyObject *obj) if (tp->tp_dictoffset == 0) { return 1; } - PyDictValues **values_ptr = _PyObject_ValuesPointer(obj); - if (values_ptr && *values_ptr) { - PyDictKeysObject *keys = CACHED_KEYS(tp); - for (Py_ssize_t i = 0; i < keys->dk_nentries; i++) { - if ((*values_ptr)->values[i] != NULL) { - return 0; + PyObject **dictptr; + if (tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) { + PyDictValues *values = *_PyObject_ValuesPointer(obj); + if (values) { + PyDictKeysObject *keys = CACHED_KEYS(tp); + for (Py_ssize_t i = 0; i < keys->dk_nentries; i++) { + if (values->values[i] != NULL) { + return 0; + } } + return 1; } - return 1; + dictptr = _PyObject_ManagedDictPointer(obj); + } + else { + dictptr = _PyObject_DictPointer(obj); } - PyObject **dictptr = _PyObject_DictPointer(obj); PyObject *dict = *dictptr; if (dict == NULL) { return 1; @@ -5125,7 +5131,7 @@ int _PyObject_VisitInstanceAttributes(PyObject *self, visitproc visit, void *arg) { PyTypeObject *tp = Py_TYPE(self); - assert(tp->tp_inline_values_offset); + assert(Py_TYPE(self)->tp_flags & Py_TPFLAGS_MANAGED_DICT); PyDictValues **values_ptr = _PyObject_ValuesPointer(self); if (*values_ptr == NULL) { return 0; @@ -5141,7 +5147,7 @@ void _PyObject_ClearInstanceAttributes(PyObject *self) { PyTypeObject *tp = Py_TYPE(self); - assert(tp->tp_inline_values_offset); + assert(Py_TYPE(self)->tp_flags & Py_TPFLAGS_MANAGED_DICT); PyDictValues **values_ptr = _PyObject_ValuesPointer(self); if (*values_ptr == NULL) { return; @@ -5156,7 +5162,7 @@ void _PyObject_FreeInstanceAttributes(PyObject *self) { PyTypeObject *tp = Py_TYPE(self); - assert(tp->tp_inline_values_offset); + assert(Py_TYPE(self)->tp_flags & Py_TPFLAGS_MANAGED_DICT); PyDictValues **values_ptr = _PyObject_ValuesPointer(self); if (*values_ptr == NULL) { return; @@ -5171,28 +5177,42 @@ _PyObject_FreeInstanceAttributes(PyObject *self) PyObject * PyObject_GenericGetDict(PyObject *obj, void *context) { - PyObject **dictptr = _PyObject_DictPointer(obj); - if (dictptr == NULL) { - PyErr_SetString(PyExc_AttributeError, - "This object has no __dict__"); - return NULL; - } - PyObject *dict = *dictptr; - if (dict == NULL) { - PyTypeObject *tp = Py_TYPE(obj); + PyObject *dict; + PyTypeObject *tp = Py_TYPE(obj); + if (_PyType_HasFeature(tp, Py_TPFLAGS_MANAGED_DICT)) { PyDictValues **values_ptr = _PyObject_ValuesPointer(obj); - if (values_ptr && *values_ptr) { + PyObject **dictptr = _PyObject_ManagedDictPointer(obj); + if (*values_ptr) { + assert(*dictptr == NULL); *dictptr = dict = make_dict_from_instance_attributes(CACHED_KEYS(tp), *values_ptr); if (dict != NULL) { *values_ptr = NULL; } } - else if (_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE) && CACHED_KEYS(tp)) { - dictkeys_incref(CACHED_KEYS(tp)); - *dictptr = dict = new_dict_with_shared_keys(CACHED_KEYS(tp)); + else if (*dictptr == NULL) { + *dictptr = dict = PyDict_New(); } else { - *dictptr = dict = PyDict_New(); + dict = *dictptr; + } + } + else { + PyObject **dictptr = _PyObject_DictPointer(obj); + if (dictptr == NULL) { + PyErr_SetString(PyExc_AttributeError, + "This object has no __dict__"); + return NULL; + } + dict = *dictptr; + if (dict == NULL) { + PyTypeObject *tp = Py_TYPE(obj); + if (_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE) && CACHED_KEYS(tp)) { + dictkeys_incref(CACHED_KEYS(tp)); + *dictptr = dict = new_dict_with_shared_keys(CACHED_KEYS(tp)); + } + else { + *dictptr = dict = PyDict_New(); + } } } Py_XINCREF(dict); diff --git a/Objects/exceptions.c b/Objects/exceptions.c index c99f17a30f169..e1a8c1363ef62 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -3484,7 +3484,6 @@ _PyErr_TrySetFromCause(const char *format, ...) PyObject* msg_prefix; PyObject *exc, *val, *tb; PyTypeObject *caught_type; - PyObject **dictptr; PyObject *instance_args; Py_ssize_t num_args, caught_type_size, base_exc_size; PyObject *new_exc, *new_val, *new_tb; @@ -3530,9 +3529,7 @@ _PyErr_TrySetFromCause(const char *format, ...) } /* Ensure the instance dict is also empty */ - dictptr = _PyObject_GetDictPtr(val); - if (dictptr != NULL && *dictptr != NULL && - PyDict_GET_SIZE(*dictptr) > 0) { + if (!_PyObject_IsInstanceDictEmpty(val)) { /* While we could potentially copy a non-empty instance dictionary * to the replacement exception, for now we take the more * conservative path of leaving exceptions with attributes set diff --git a/Objects/object.c b/Objects/object.c index 25f5a2133d574..a1c2e16b6fa2c 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1073,6 +1073,9 @@ _PyObject_DictPointer(PyObject *obj) Py_ssize_t dictoffset; PyTypeObject *tp = Py_TYPE(obj); + if (tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) { + return _PyObject_ManagedDictPointer(obj); + } dictoffset = tp->tp_dictoffset; if (dictoffset == 0) return NULL; @@ -1096,24 +1099,20 @@ _PyObject_DictPointer(PyObject *obj) PyObject ** _PyObject_GetDictPtr(PyObject *obj) { - PyObject **dict_ptr = _PyObject_DictPointer(obj); - if (dict_ptr == NULL) { - return NULL; - } - if (*dict_ptr != NULL) { - return dict_ptr; + if ((Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) { + return _PyObject_DictPointer(obj); } + PyObject **dict_ptr = _PyObject_ManagedDictPointer(obj); PyDictValues **values_ptr = _PyObject_ValuesPointer(obj); - if (values_ptr == NULL || *values_ptr == NULL) { + if (*values_ptr == NULL) { return dict_ptr; } + assert(*dict_ptr == NULL); PyObject *dict = _PyObject_MakeDictFromInstanceAttributes(obj, *values_ptr); if (dict == NULL) { PyErr_Clear(); return NULL; } - assert(*dict_ptr == NULL); - assert(*values_ptr != NULL); *values_ptr = NULL; *dict_ptr = dict; return dict_ptr; @@ -1185,10 +1184,12 @@ _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) } } } - PyDictValues **values_ptr = _PyObject_ValuesPointer(obj); - if (values_ptr && *values_ptr) { + PyDictValues *values; + if ((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) && + (values = *_PyObject_ValuesPointer(obj))) + { assert(*_PyObject_DictPointer(obj) == NULL); - PyObject *attr = _PyObject_GetInstanceAttribute(obj, *values_ptr, name); + PyObject *attr = _PyObject_GetInstanceAttribute(obj, values, name); if (attr != NULL) { *method = attr; Py_XDECREF(descr); @@ -1240,17 +1241,6 @@ _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) return 0; } -PyDictValues ** -_PyObject_ValuesPointer(PyObject *obj) -{ - PyTypeObject *tp = Py_TYPE(obj); - Py_ssize_t offset = tp->tp_inline_values_offset; - if (offset == 0) { - return NULL; - } - return (PyDictValues **) ((char *)obj + offset); -} - /* Generic GetAttr functions - put these in your tp_[gs]etattro slot. */ PyObject * @@ -1267,7 +1257,6 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *descr = NULL; PyObject *res = NULL; descrgetfunc f; - Py_ssize_t dictoffset; PyObject **dictptr; if (!PyUnicode_Check(name)){ @@ -1299,8 +1288,10 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, } } if (dict == NULL) { - PyDictValues **values_ptr = _PyObject_ValuesPointer(obj); - if (values_ptr && *values_ptr) { + if ((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) && + *_PyObject_ValuesPointer(obj)) + { + PyDictValues **values_ptr = _PyObject_ValuesPointer(obj); if (PyUnicode_CheckExact(name)) { assert(*_PyObject_DictPointer(obj) == NULL); res = _PyObject_GetInstanceAttribute(obj, *values_ptr, name); @@ -1320,22 +1311,8 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, } } else { - /* Inline _PyObject_DictPointer */ - dictoffset = tp->tp_dictoffset; - if (dictoffset != 0) { - if (dictoffset < 0) { - Py_ssize_t tsize = Py_SIZE(obj); - if (tsize < 0) { - tsize = -tsize; - } - size_t size = _PyObject_VAR_SIZE(tp, tsize); - _PyObject_ASSERT(obj, size <= PY_SSIZE_T_MAX); - - dictoffset += (Py_ssize_t)size; - _PyObject_ASSERT(obj, dictoffset > 0); - _PyObject_ASSERT(obj, dictoffset % SIZEOF_VOID_P == 0); - } - dictptr = (PyObject **) ((char *)obj + dictoffset); + dictptr = _PyObject_DictPointer(obj); + if (dictptr) { dict = *dictptr; } } @@ -1426,9 +1403,8 @@ _PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name, } if (dict == NULL) { - PyDictValues **values_ptr = _PyObject_ValuesPointer(obj); - if (values_ptr && *values_ptr) { - res = _PyObject_StoreInstanceAttribute(obj, *values_ptr, name, value); + if ((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) && *_PyObject_ValuesPointer(obj)) { + res = _PyObject_StoreInstanceAttribute(obj, *_PyObject_ValuesPointer(obj), name, value); } else { PyObject **dictptr = _PyObject_DictPointer(obj); @@ -1478,8 +1454,9 @@ PyObject_GenericSetDict(PyObject *obj, PyObject *value, void *context) { PyObject **dictptr = _PyObject_GetDictPtr(obj); if (dictptr == NULL) { - PyDictValues** values_ptr = _PyObject_ValuesPointer(obj); - if (values_ptr != NULL && *values_ptr != NULL) { + if (_PyType_HasFeature(Py_TYPE(obj), Py_TPFLAGS_MANAGED_DICT) && + *_PyObject_ValuesPointer(obj) != NULL) + { /* Was unable to convert to dict */ PyErr_NoMemory(); } diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 22e509be26fff..2fd93b61c0b2b 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1146,17 +1146,17 @@ _PyType_AllocNoTrack(PyTypeObject *type, Py_ssize_t nitems) const size_t size = _PyObject_VAR_SIZE(type, nitems+1); /* note that we need to add one, for the sentinel */ - if (_PyType_IS_GC(type)) { - obj = _PyObject_GC_Malloc(size); - } - else { - obj = (PyObject *)PyObject_Malloc(size); - } - - if (obj == NULL) { + const size_t presize = _PyType_PreHeaderSize(type); + char *alloc = PyObject_Malloc(size + presize); + if (alloc == NULL) { return PyErr_NoMemory(); } - + obj = (PyObject *)(alloc + presize); + if (presize) { + ((PyObject **)alloc)[0] = NULL; + ((PyObject **)alloc)[1] = NULL; + _PyObject_GC_Link(obj); + } memset(obj, '\0', size); if (type->tp_itemsize == 0) { @@ -1232,7 +1232,7 @@ subtype_traverse(PyObject *self, visitproc visit, void *arg) assert(base); } - if (type->tp_inline_values_offset) { + if (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) { assert(type->tp_dictoffset); int err = _PyObject_VisitInstanceAttributes(self, visit, arg); if (err) { @@ -1301,7 +1301,7 @@ subtype_clear(PyObject *self) /* Clear the instance dict (if any), to break cycles involving only __dict__ slots (as in the case 'self.__dict__ is self'). */ - if (type->tp_inline_values_offset) { + if (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) { _PyObject_ClearInstanceAttributes(self); } if (type->tp_dictoffset != base->tp_dictoffset) { @@ -1360,6 +1360,8 @@ subtype_dealloc(PyObject *self) int type_needs_decref = (type->tp_flags & Py_TPFLAGS_HEAPTYPE && !(base->tp_flags & Py_TPFLAGS_HEAPTYPE)); + assert((type->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0); + /* Call the base tp_dealloc() */ assert(basedealloc); basedealloc(self); @@ -1445,10 +1447,18 @@ subtype_dealloc(PyObject *self) } /* If we added a dict, DECREF it, or free inline values. */ - if (type->tp_inline_values_offset) { - _PyObject_FreeInstanceAttributes(self); + if (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) { + PyObject **dictptr = _PyObject_ManagedDictPointer(self); + if (*dictptr != NULL) { + assert(*_PyObject_ValuesPointer(self) == NULL); + Py_DECREF(*dictptr); + *dictptr = NULL; + } + else { + _PyObject_FreeInstanceAttributes(self); + } } - if (type->tp_dictoffset && !base->tp_dictoffset) { + else if (type->tp_dictoffset && !base->tp_dictoffset) { PyObject **dictptr = _PyObject_DictPointer(self); if (dictptr != NULL) { PyObject *dict = *dictptr; @@ -2243,18 +2253,10 @@ extra_ivars(PyTypeObject *type, PyTypeObject *base) return t_size != b_size || type->tp_itemsize != base->tp_itemsize; } - if (type->tp_inline_values_offset && base->tp_inline_values_offset == 0 && - type->tp_inline_values_offset + sizeof(PyDictValues *) == t_size && - type->tp_flags & Py_TPFLAGS_HEAPTYPE) - t_size -= sizeof(PyDictValues *); if (type->tp_weaklistoffset && base->tp_weaklistoffset == 0 && type->tp_weaklistoffset + sizeof(PyObject *) == t_size && type->tp_flags & Py_TPFLAGS_HEAPTYPE) t_size -= sizeof(PyObject *); - if (type->tp_dictoffset && base->tp_dictoffset == 0 && - type->tp_dictoffset + sizeof(PyObject *) == t_size && - type->tp_flags & Py_TPFLAGS_HEAPTYPE) - t_size -= sizeof(PyObject *); return t_size != b_size; } @@ -2982,13 +2984,8 @@ type_new_descriptors(const type_new_ctx *ctx, PyTypeObject *type) } } - if (ctx->add_dict) { - if (ctx->base->tp_itemsize) { - type->tp_dictoffset = -(long)sizeof(PyObject *); - } - else { - type->tp_dictoffset = slotoffset; - } + if (ctx->add_dict && ctx->base->tp_itemsize) { + type->tp_dictoffset = -(long)sizeof(PyObject *); slotoffset += sizeof(PyObject *); } @@ -2997,12 +2994,10 @@ type_new_descriptors(const type_new_ctx *ctx, PyTypeObject *type) type->tp_weaklistoffset = slotoffset; slotoffset += sizeof(PyObject *); } - if (type->tp_dictoffset > 0) { - type->tp_inline_values_offset = slotoffset; - slotoffset += sizeof(PyDictValues *); - } - else { - type->tp_inline_values_offset = 0; + if (ctx->add_dict && ctx->base->tp_itemsize == 0) { + assert((type->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0); + type->tp_flags |= Py_TPFLAGS_MANAGED_DICT; + type->tp_dictoffset = -slotoffset - sizeof(PyObject *)*3; } type->tp_basicsize = slotoffset; @@ -3206,8 +3201,7 @@ type_new_impl(type_new_ctx *ctx) // Put the proper slots in place fixup_slot_dispatchers(type); - if (type->tp_inline_values_offset) { - assert(type->tp_dictoffset > 0); + if (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) { PyHeapTypeObject *et = (PyHeapTypeObject*)type; et->ht_cached_keys = _PyDict_NewKeysForClass(); } @@ -3594,8 +3588,7 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases) if (PyType_Ready(type) < 0) goto fail; - if (type->tp_inline_values_offset) { - assert(type->tp_dictoffset > 0); + if (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) { res->ht_cached_keys = _PyDict_NewKeysForClass(); } @@ -4658,7 +4651,6 @@ compatible_with_tp_base(PyTypeObject *child) child->tp_itemsize == parent->tp_itemsize && child->tp_dictoffset == parent->tp_dictoffset && child->tp_weaklistoffset == parent->tp_weaklistoffset && - child->tp_inline_values_offset == parent->tp_inline_values_offset && ((child->tp_flags & Py_TPFLAGS_HAVE_GC) == (parent->tp_flags & Py_TPFLAGS_HAVE_GC)) && (child->tp_dealloc == subtype_dealloc || @@ -4678,8 +4670,6 @@ same_slots_added(PyTypeObject *a, PyTypeObject *b) size += sizeof(PyObject *); if (a->tp_weaklistoffset == size && b->tp_weaklistoffset == size) size += sizeof(PyObject *); - if (a->tp_inline_values_offset == size && b->tp_inline_values_offset == size) - size += sizeof(PyObject *); /* Check slots compliance */ if (!(a->tp_flags & Py_TPFLAGS_HEAPTYPE) || @@ -4729,16 +4719,22 @@ compatible_for_assignment(PyTypeObject* oldto, PyTypeObject* newto, const char* if (newbase != oldbase && (newbase->tp_base != oldbase->tp_base || !same_slots_added(newbase, oldbase))) { - PyErr_Format(PyExc_TypeError, - "%s assignment: " - "'%s' object layout differs from '%s'", - attr, - newto->tp_name, - oldto->tp_name); - return 0; + goto differs; } - - return 1; + /* The above does not check for managed __dicts__ */ + if ((oldto->tp_flags & Py_TPFLAGS_MANAGED_DICT) == + ((newto->tp_flags & Py_TPFLAGS_MANAGED_DICT))) + { + return 1; + } +differs: + PyErr_Format(PyExc_TypeError, + "%s assignment: " + "'%s' object layout differs from '%s'", + attr, + newto->tp_name, + oldto->tp_name); + return 0; } static int @@ -4826,15 +4822,13 @@ object_set_class(PyObject *self, PyObject *value, void *closure) if (compatible_for_assignment(oldto, newto, "__class__")) { /* Changing the class will change the implicit dict keys, * so we must materialize the dictionary first. */ - assert(oldto->tp_inline_values_offset == newto->tp_inline_values_offset); + assert((oldto->tp_flags & Py_TPFLAGS_MANAGED_DICT) == (newto->tp_flags & Py_TPFLAGS_MANAGED_DICT)); _PyObject_GetDictPtr(self); - PyDictValues** values_ptr = _PyObject_ValuesPointer(self); - if (values_ptr != NULL && *values_ptr != NULL) { + if (oldto->tp_flags & Py_TPFLAGS_MANAGED_DICT && *_PyObject_ValuesPointer(self)) { /* Was unable to convert to dict */ PyErr_NoMemory(); return -1; } - assert(_PyObject_ValuesPointer(self) == NULL || *_PyObject_ValuesPointer(self) == NULL); if (newto->tp_flags & Py_TPFLAGS_HEAPTYPE) { Py_INCREF(newto); } @@ -4980,15 +4974,14 @@ _PyObject_GetState(PyObject *obj, int required) assert(slotnames == Py_None || PyList_Check(slotnames)); if (required) { Py_ssize_t basicsize = PyBaseObject_Type.tp_basicsize; - if (Py_TYPE(obj)->tp_dictoffset) { + if (Py_TYPE(obj)->tp_dictoffset && + (Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) + { basicsize += sizeof(PyObject *); } if (Py_TYPE(obj)->tp_weaklistoffset) { basicsize += sizeof(PyObject *); } - if (Py_TYPE(obj)->tp_inline_values_offset) { - basicsize += sizeof(PyDictValues *); - } if (slotnames != Py_None) { basicsize += sizeof(PyObject *) * PyList_GET_SIZE(slotnames); } @@ -5749,6 +5742,7 @@ inherit_special(PyTypeObject *type, PyTypeObject *base) if (type->tp_clear == NULL) type->tp_clear = base->tp_clear; } + type->tp_flags |= (base->tp_flags & Py_TPFLAGS_MANAGED_DICT); if (type->tp_basicsize == 0) type->tp_basicsize = base->tp_basicsize; @@ -5761,7 +5755,6 @@ inherit_special(PyTypeObject *type, PyTypeObject *base) COPYVAL(tp_itemsize); COPYVAL(tp_weaklistoffset); COPYVAL(tp_dictoffset); - COPYVAL(tp_inline_values_offset); #undef COPYVAL /* Setup fast subclass flags */ diff --git a/PC/python3dll.c b/PC/python3dll.c index d2a87070de5cc..6e469357ede50 100755 --- a/PC/python3dll.c +++ b/PC/python3dll.c @@ -28,7 +28,6 @@ EXPORT_FUNC(_PyArg_VaParseTupleAndKeywords_SizeT) EXPORT_FUNC(_PyErr_BadInternalCall) EXPORT_FUNC(_PyObject_CallFunction_SizeT) EXPORT_FUNC(_PyObject_CallMethod_SizeT) -EXPORT_FUNC(_PyObject_GC_Malloc) EXPORT_FUNC(_PyObject_GC_New) EXPORT_FUNC(_PyObject_GC_NewVar) EXPORT_FUNC(_PyObject_GC_Resize) diff --git a/Python/ceval.c b/Python/ceval.c index a8bbad33552e4..446772dd4f7c0 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3599,9 +3599,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr _PyAttrCache *cache1 = &caches[-1].attr; assert(cache1->tp_version != 0); DEOPT_IF(tp->tp_version_tag != cache1->tp_version, LOAD_ATTR); - assert(tp->tp_dictoffset > 0); - assert(tp->tp_inline_values_offset > 0); - PyDictValues *values = *(PyDictValues **)(((char *)owner) + tp->tp_inline_values_offset); + assert(tp->tp_dictoffset < 0); + assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT); + PyDictValues *values = *_PyObject_ValuesPointer(owner); DEOPT_IF(values == NULL, LOAD_ATTR); res = values->values[cache0->index]; DEOPT_IF(res == NULL, LOAD_ATTR); @@ -3633,8 +3633,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr _PyAttrCache *cache1 = &caches[-1].attr; assert(cache1->tp_version != 0); DEOPT_IF(tp->tp_version_tag != cache1->tp_version, LOAD_ATTR); - assert(tp->tp_dictoffset > 0); - PyDictObject *dict = *(PyDictObject **)(((char *)owner) + tp->tp_dictoffset); + assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT); + PyDictObject *dict = *(PyDictObject **)_PyObject_ManagedDictPointer(owner); DEOPT_IF(dict == NULL, LOAD_ATTR); assert(PyDict_CheckExact((PyObject *)dict)); PyObject *name = GETITEM(names, cache0->original_oparg); @@ -3701,9 +3701,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr _PyAttrCache *cache1 = &caches[-1].attr; assert(cache1->tp_version != 0); DEOPT_IF(tp->tp_version_tag != cache1->tp_version, STORE_ATTR); - assert(tp->tp_dictoffset > 0); - assert(tp->tp_inline_values_offset > 0); - PyDictValues *values = *(PyDictValues **)(((char *)owner) + tp->tp_inline_values_offset); + assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT); + PyDictValues *values = *_PyObject_ValuesPointer(owner); DEOPT_IF(values == NULL, STORE_ATTR); STAT_INC(STORE_ATTR, hit); int index = cache0->index; @@ -3731,8 +3730,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr _PyAttrCache *cache1 = &caches[-1].attr; assert(cache1->tp_version != 0); DEOPT_IF(tp->tp_version_tag != cache1->tp_version, STORE_ATTR); - assert(tp->tp_dictoffset > 0); - PyDictObject *dict = *(PyDictObject **)(((char *)owner) + tp->tp_dictoffset); + assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT); + PyDictObject *dict = *(PyDictObject **)_PyObject_ManagedDictPointer(owner); DEOPT_IF(dict == NULL, STORE_ATTR); assert(PyDict_CheckExact((PyObject *)dict)); PyObject *name = GETITEM(names, cache0->original_oparg); @@ -4506,9 +4505,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr _PyObjectCache *cache2 = &caches[-2].obj; DEOPT_IF(self_cls->tp_version_tag != cache1->tp_version, LOAD_METHOD); - assert(self_cls->tp_dictoffset > 0); - assert(self_cls->tp_inline_values_offset > 0); - PyDictObject *dict = *(PyDictObject **)(((char *)self) + self_cls->tp_dictoffset); + assert(self_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT); + PyDictObject *dict = *(PyDictObject**)_PyObject_ManagedDictPointer(self); DEOPT_IF(dict != NULL, LOAD_METHOD); DEOPT_IF(((PyHeapTypeObject *)self_cls)->ht_cached_keys->dk_version != cache1->dk_version_or_hint, LOAD_METHOD); STAT_INC(LOAD_METHOD, hit); diff --git a/Python/specialize.c b/Python/specialize.c index b384675560be7..cdc535396fa76 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -451,6 +451,7 @@ initial_counter_value(void) { #define SPEC_FAIL_NON_OBJECT_SLOT 14 #define SPEC_FAIL_READ_ONLY 15 #define SPEC_FAIL_AUDITED_SLOT 16 +#define SPEC_FAIL_NOT_MANAGED_DICT 17 /* Methods */ @@ -506,7 +507,7 @@ specialize_module_load_attr( PyObject *value = NULL; PyObject *getattr; _Py_IDENTIFIER(__getattr__); - assert(owner->ob_type->tp_inline_values_offset == 0); + assert((owner->ob_type->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0); PyDictObject *dict = (PyDictObject *)m->md_dict; if (dict == NULL) { SPECIALIZATION_FAIL(opcode, SPEC_FAIL_NO_DICT); @@ -634,66 +635,44 @@ specialize_dict_access( assert(kind == NON_OVERRIDING || kind == NON_DESCRIPTOR || kind == ABSENT || kind == BUILTIN_CLASSMETHOD || kind == PYTHON_CLASSMETHOD); // No descriptor, or non overriding. - if (type->tp_dictoffset < 0) { - SPECIALIZATION_FAIL(base_op, SPEC_FAIL_OUT_OF_RANGE); + if ((type->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) { + SPECIALIZATION_FAIL(base_op, SPEC_FAIL_NOT_MANAGED_DICT); return 0; } - if (type->tp_dictoffset > 0) { - PyObject **dictptr = (PyObject **) ((char *)owner + type->tp_dictoffset); - PyDictObject *dict = (PyDictObject *)*dictptr; - if (type->tp_inline_values_offset && dict == NULL) { - // Virtual dictionary - PyDictKeysObject *keys = ((PyHeapTypeObject *)type)->ht_cached_keys; - assert(type->tp_inline_values_offset > 0); - assert(PyUnicode_CheckExact(name)); - Py_ssize_t index = _PyDictKeys_StringLookup(keys, name); - assert (index != DKIX_ERROR); - if (index != (uint16_t)index) { - SPECIALIZATION_FAIL(base_op, SPEC_FAIL_OUT_OF_RANGE); - return 0; - } - cache1->tp_version = type->tp_version_tag; - cache0->index = (uint16_t)index; - *instr = _Py_MAKECODEUNIT(values_op, _Py_OPARG(*instr)); + PyObject **dictptr = _PyObject_ManagedDictPointer(owner); + PyDictObject *dict = (PyDictObject *)*dictptr; + if (dict == NULL) { + // Virtual dictionary + PyDictKeysObject *keys = ((PyHeapTypeObject *)type)->ht_cached_keys; + assert(PyUnicode_CheckExact(name)); + Py_ssize_t index = _PyDictKeys_StringLookup(keys, name); + assert (index != DKIX_ERROR); + if (index != (uint16_t)index) { + SPECIALIZATION_FAIL(base_op, SPEC_FAIL_OUT_OF_RANGE); return 0; } - else { - if (dict == NULL || !PyDict_CheckExact(dict)) { - SPECIALIZATION_FAIL(base_op, SPEC_FAIL_NO_DICT); - return 0; - } - // We found an instance with a __dict__. - PyObject *value = NULL; - Py_ssize_t hint = - _PyDict_GetItemHint(dict, name, -1, &value); - if (hint != (uint32_t)hint) { - SPECIALIZATION_FAIL(base_op, SPEC_FAIL_OUT_OF_RANGE); - return 0; - } - cache1->dk_version_or_hint = (uint32_t)hint; - cache1->tp_version = type->tp_version_tag; - *instr = _Py_MAKECODEUNIT(hint_op, _Py_OPARG(*instr)); - return 1; - } + cache1->tp_version = type->tp_version_tag; + cache0->index = (uint16_t)index; + *instr = _Py_MAKECODEUNIT(values_op, _Py_OPARG(*instr)); } - assert(type->tp_dictoffset == 0); - /* No attribute in instance dictionary */ - switch(kind) { - case NON_OVERRIDING: - case BUILTIN_CLASSMETHOD: - case PYTHON_CLASSMETHOD: - SPECIALIZATION_FAIL(base_op, SPEC_FAIL_NON_OVERRIDING_DESCRIPTOR); - return 0; - case NON_DESCRIPTOR: - /* To do -- Optimize this case */ - SPECIALIZATION_FAIL(base_op, SPEC_FAIL_NOT_DESCRIPTOR); + else { + if (!PyDict_CheckExact(dict)) { + SPECIALIZATION_FAIL(base_op, SPEC_FAIL_NO_DICT); return 0; - case ABSENT: - SPECIALIZATION_FAIL(base_op, SPEC_FAIL_EXPECTED_ERROR); + } + // We found an instance with a __dict__. + PyObject *value = NULL; + Py_ssize_t hint = + _PyDict_GetItemHint(dict, name, -1, &value); + if (hint != (uint32_t)hint) { + SPECIALIZATION_FAIL(base_op, SPEC_FAIL_OUT_OF_RANGE); return 0; - default: - Py_UNREACHABLE(); + } + cache1->dk_version_or_hint = (uint32_t)hint; + cache1->tp_version = type->tp_version_tag; + *instr = _Py_MAKECODEUNIT(hint_op, _Py_OPARG(*instr)); } + return 1; } int @@ -965,12 +944,6 @@ _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name, } goto success; } - // Technically this is fine for bound method calls, but it's uncommon and - // slightly slower at runtime to get dict. - if (owner_cls->tp_dictoffset < 0) { - SPECIALIZATION_FAIL(LOAD_METHOD, SPEC_FAIL_OUT_OF_RANGE); - goto fail; - } PyObject *descr = NULL; DesciptorClassification kind = 0; @@ -980,9 +953,8 @@ _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name, SPECIALIZATION_FAIL(LOAD_METHOD, load_method_fail_kind(kind)); goto fail; } - if (owner_cls->tp_inline_values_offset) { - PyObject **owner_dictptr = _PyObject_DictPointer(owner); - assert(owner_dictptr); + if (owner_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT) { + PyObject **owner_dictptr = _PyObject_ManagedDictPointer(owner); if (*owner_dictptr) { SPECIALIZATION_FAIL(LOAD_METHOD, SPEC_FAIL_IS_ATTR); goto fail; diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 13fae797b29c2..af4f926f0e408 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1681,10 +1681,7 @@ _PySys_GetSizeOf(PyObject *o) return (size_t)-1; } - /* add gc_head size */ - if (_PyObject_IS_GC(o)) - return ((size_t)size) + sizeof(PyGC_Head); - return (size_t)size; + return (size_t)size + _PyType_PreHeaderSize(Py_TYPE(o)); } static PyObject * diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py index a105e58b4af90..a0a95e3fc63cb 100755 --- a/Tools/gdb/libpython.py +++ b/Tools/gdb/libpython.py @@ -83,7 +83,8 @@ def _sizeof_void_p(): # value computed later, see PyUnicodeObjectPtr.proxy() _is_pep393 = None -Py_TPFLAGS_HEAPTYPE = (1 << 9) +Py_TPFLAGS_MANAGED_DICT = (1 << 4) +Py_TPFLAGS_HEAPTYPE = (1 << 9) Py_TPFLAGS_LONG_SUBCLASS = (1 << 24) Py_TPFLAGS_LIST_SUBCLASS = (1 << 25) Py_TPFLAGS_TUPLE_SUBCLASS = (1 << 26) @@ -507,7 +508,6 @@ def get_attr_dict(self): tsize = -tsize size = _PyObject_VAR_SIZE(typeobj, tsize) dictoffset += size - assert dictoffset > 0 assert dictoffset % _sizeof_void_p() == 0 dictptr = self._gdbval.cast(_type_char_ptr()) + dictoffset @@ -523,12 +523,11 @@ def get_attr_dict(self): def get_keys_values(self): typeobj = self.type() - values_offset = int_from_int(typeobj.field('tp_inline_values_offset')) - if values_offset == 0: + has_values = int_from_int(typeobj.field('tp_flags')) & Py_TPFLAGS_MANAGED_DICT + if not has_values: return None - charptr = self._gdbval.cast(_type_char_ptr()) + values_offset PyDictValuesPtrPtr = gdb.lookup_type("PyDictValues").pointer().pointer() - valuesptr = charptr.cast(PyDictValuesPtrPtr) + valuesptr = self._gdbval.cast(PyDictValuesPtrPtr) - 4 values = valuesptr.dereference() if long(values) == 0: return None From webhook-mailer at python.org Tue Dec 7 11:17:30 2021 From: webhook-mailer at python.org (iritkatriel) Date: Tue, 07 Dec 2021 16:17:30 -0000 Subject: [Python-checkins] bpo-45635: standardize error handling in traceback.c (GH-29905) Message-ID: https://github.com/python/cpython/commit/d596acbd3b4f6716ed98895eb0b48e9830e0b320 commit: d596acbd3b4f6716ed98895eb0b48e9830e0b320 branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-12-07T16:17:22Z summary: bpo-45635: standardize error handling in traceback.c (GH-29905) Co-authored-by: Erlend Egeberg Aasland files: M Python/traceback.c diff --git a/Python/traceback.c b/Python/traceback.c index 8aef3d810d316..b0ff5e9a6b075 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -385,16 +385,14 @@ _Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject * int _Py_WriteIndent(int indent, PyObject *f) { - int err = 0; char buf[11] = " "; assert(strlen(buf) == 10); while (indent > 0) { if (indent < 10) { buf[indent] = '\0'; } - err = PyFile_WriteString(buf, f); - if (err != 0) { - return err; + if (PyFile_WriteString(buf, f) < 0) { + return -1; } indent -= 10; } @@ -407,11 +405,15 @@ _Py_WriteIndent(int indent, PyObject *f) int _Py_WriteIndentedMargin(int indent, const char *margin, PyObject *f) { - int err = _Py_WriteIndent(indent, f); - if (err == 0 && margin) { - err = PyFile_WriteString(margin, f); + if (_Py_WriteIndent(indent, f) < 0) { + return -1; } - return err; + if (margin) { + if (PyFile_WriteString(margin, f) < 0) { + return -1; + } + } + return 0; } static int @@ -419,7 +421,6 @@ display_source_line_with_margin(PyObject *f, PyObject *filename, int lineno, int int margin_indent, const char *margin, int *truncation, PyObject **line) { - int err = 0; int fd; int i; char *found_encoding; @@ -502,19 +503,20 @@ display_source_line_with_margin(PyObject *f, PyObject *filename, int lineno, int lineobj = PyFile_GetLine(fob, -1); if (!lineobj) { PyErr_Clear(); - err = -1; break; } } res = _PyObject_CallMethodIdNoArgs(fob, &PyId_close); - if (res) + if (res) { Py_DECREF(res); - else + } + else { PyErr_Clear(); + } Py_DECREF(fob); if (!lineobj || !PyUnicode_Check(lineobj)) { Py_XDECREF(lineobj); - return err; + return -1; } if (line) { @@ -545,23 +547,29 @@ display_source_line_with_margin(PyObject *f, PyObject *filename, int lineno, int *truncation = i - indent; } - if (err == 0) { - err = _Py_WriteIndentedMargin(margin_indent, margin, f); + if (_Py_WriteIndentedMargin(margin_indent, margin, f) < 0) { + goto error; } + /* Write some spaces before the line */ - if (err == 0) { - err = _Py_WriteIndent(indent, f); + if (_Py_WriteIndent(indent, f) < 0) { + goto error; } /* finally display the line */ - if (err == 0) { - err = PyFile_WriteObject(lineobj, f, Py_PRINT_RAW); + if (PyFile_WriteObject(lineobj, f, Py_PRINT_RAW) < 0) { + goto error; } - Py_DECREF(lineobj); - if (err == 0) { - err = PyFile_WriteString("\n", f); + + if (PyFile_WriteString("\n", f) < 0) { + goto error; } - return err; + + Py_DECREF(lineobj); + return 0; +error: + Py_DECREF(lineobj); + return -1; } int @@ -723,41 +731,51 @@ static inline int print_error_location_carets(PyObject *f, int offset, Py_ssize_t start_offset, Py_ssize_t end_offset, Py_ssize_t right_start_offset, Py_ssize_t left_end_offset, const char *primary, const char *secondary) { - int err = 0; int special_chars = (left_end_offset != -1 || right_start_offset != -1); + const char *str; while (++offset <= end_offset) { if (offset <= start_offset || offset > end_offset) { - err = PyFile_WriteString(" ", f); + str = " "; } else if (special_chars && left_end_offset < offset && offset <= right_start_offset) { - err = PyFile_WriteString(secondary, f); + str = secondary; } else { - err = PyFile_WriteString(primary, f); + str = primary; + } + if (PyFile_WriteString(str, f) < 0) { + return -1; } } - err = PyFile_WriteString("\n", f); - return err; + if (PyFile_WriteString("\n", f) < 0) { + return -1; + } + return 0; } static int tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int lineno, PyFrameObject *frame, PyObject *name, int margin_indent, const char *margin) { - int err; - PyObject *line; + if (filename == NULL || name == NULL) { + return -1; + } - if (filename == NULL || name == NULL) + if (_Py_WriteIndentedMargin(margin_indent, margin, f) < 0) { return -1; - line = PyUnicode_FromFormat(" File \"%U\", line %d, in %U\n", - filename, lineno, name); - if (line == NULL) + } + + PyObject *line = PyUnicode_FromFormat(" File \"%U\", line %d, in %U\n", + filename, lineno, name); + if (line == NULL) { return -1; - err = _Py_WriteIndentedMargin(margin_indent, margin, f); - if (err == 0) { - err = PyFile_WriteObject(line, f, Py_PRINT_RAW); } + + int res = PyFile_WriteObject(line, f, Py_PRINT_RAW); Py_DECREF(line); - if (err != 0) - return err; + if (res < 0) { + return -1; + } + + int err = 0; int truncation = _TRACEBACK_SOURCE_LINE_INDENT; PyObject* source_line = NULL; @@ -849,11 +867,16 @@ tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int linen end_offset = i + 1; } - err = _Py_WriteIndentedMargin(margin_indent, margin, f); - if (err == 0) { - err = print_error_location_carets(f, truncation, start_offset, end_offset, - right_start_offset, left_end_offset, - primary_error_char, secondary_error_char); + if (_Py_WriteIndentedMargin(margin_indent, margin, f) < 0) { + err = -1; + goto done; + } + + if (print_error_location_carets(f, truncation, start_offset, end_offset, + right_start_offset, left_end_offset, + primary_error_char, secondary_error_char) < 0) { + err = -1; + goto done; } done: @@ -884,7 +907,7 @@ static int tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit, int indent, const char *margin) { - int err = 0; + PyCodeObject *code = NULL; Py_ssize_t depth = 0; PyObject *last_file = NULL; int last_line = -1; @@ -899,14 +922,16 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit, depth--; tb = tb->tb_next; } - while (tb != NULL && err == 0) { - PyCodeObject *code = PyFrame_GetCode(tb->tb_frame); + while (tb != NULL) { + code = PyFrame_GetCode(tb->tb_frame); if (last_file == NULL || code->co_filename != last_file || last_line == -1 || tb->tb_lineno != last_line || last_name == NULL || code->co_name != last_name) { if (cnt > TB_RECURSIVE_CUTOFF) { - err = tb_print_line_repeated(f, cnt); + if (tb_print_line_repeated(f, cnt) < 0) { + goto error; + } } last_file = code->co_filename; last_line = tb->tb_lineno; @@ -914,20 +939,28 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit, cnt = 0; } cnt++; - if (err == 0 && cnt <= TB_RECURSIVE_CUTOFF) { - err = tb_displayline(tb, f, code->co_filename, tb->tb_lineno, - tb->tb_frame, code->co_name, indent, margin); - if (err == 0) { - err = PyErr_CheckSignals(); + if (cnt <= TB_RECURSIVE_CUTOFF) { + if (tb_displayline(tb, f, code->co_filename, tb->tb_lineno, + tb->tb_frame, code->co_name, indent, margin) < 0) { + goto error; + } + + if (PyErr_CheckSignals() < 0) { + goto error; } } - Py_DECREF(code); + Py_CLEAR(code); tb = tb->tb_next; } - if (err == 0 && cnt > TB_RECURSIVE_CUTOFF) { - err = tb_print_line_repeated(f, cnt); + if (cnt > TB_RECURSIVE_CUTOFF) { + if (tb_print_line_repeated(f, cnt) < 0) { + goto error; + } } - return err; + return 0; +error: + Py_XDECREF(code); + return -1; } #define PyTraceBack_LIMIT 1000 @@ -936,12 +969,12 @@ int _PyTraceBack_Print_Indented(PyObject *v, int indent, const char *margin, const char *header_margin, const char *header, PyObject *f) { - int err; PyObject *limitv; long limit = PyTraceBack_LIMIT; - if (v == NULL) + if (v == NULL) { return 0; + } if (!PyTraceBack_Check(v)) { PyErr_BadInternalCall(); return -1; @@ -957,14 +990,19 @@ _PyTraceBack_Print_Indented(PyObject *v, int indent, const char *margin, return 0; } } - err = _Py_WriteIndentedMargin(indent, header_margin, f); - if (err == 0) { - err = PyFile_WriteString(header, f); + if (_Py_WriteIndentedMargin(indent, header_margin, f) < 0) { + return -1; + } + + if (PyFile_WriteString(header, f) < 0) { + return -1; } - if (err == 0) { - err = tb_printinternal((PyTracebackObject *)v, f, limit, indent, margin); + + if (tb_printinternal((PyTracebackObject *)v, f, limit, indent, margin) < 0) { + return -1; } - return err; + + return 0; } int From webhook-mailer at python.org Tue Dec 7 13:05:58 2021 From: webhook-mailer at python.org (pablogsal) Date: Tue, 07 Dec 2021 18:05:58 -0000 Subject: [Python-checkins] Fix leak when an exception is raised during generator creation. (GH-29960) Message-ID: https://github.com/python/cpython/commit/064e53d19aea6d6906fa8f7706a2556a2c293ccd commit: 064e53d19aea6d6906fa8f7706a2556a2c293ccd branch: main author: Mark Shannon committer: pablogsal date: 2021-12-07T18:05:48Z summary: Fix leak when an exception is raised during generator creation. (GH-29960) files: M Python/ceval.c diff --git a/Python/ceval.c b/Python/ceval.c index 446772dd4f7c0..c22af02330b92 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -5852,24 +5852,6 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func, return -1; } -static int -initialize_coro_frame(InterpreterFrame *frame, PyThreadState *tstate, - PyFunctionObject *func, PyObject *locals, - PyObject *const *args, Py_ssize_t argcount, - PyObject *kwnames) -{ - assert(is_tstate_valid(tstate)); - assert(func->func_defaults == NULL || PyTuple_CheckExact(func->func_defaults)); - PyCodeObject *code = (PyCodeObject *)func->func_code; - _PyFrame_InitializeSpecials(frame, func, locals, code->co_nlocalsplus); - for (int i = 0; i < code->co_nlocalsplus; i++) { - frame->localsplus[i] = NULL; - } - assert(frame->frame_obj == NULL); - return initialize_locals(tstate, func, frame->localsplus, args, argcount, kwnames); -} - - /* Consumes all the references to the args */ static PyObject * make_coro(PyThreadState *tstate, PyFunctionObject *func, @@ -5883,12 +5865,17 @@ make_coro(PyThreadState *tstate, PyFunctionObject *func, return NULL; } InterpreterFrame *frame = (InterpreterFrame *)((PyGenObject *)gen)->gi_iframe; - if (initialize_coro_frame(frame, tstate, func, locals, args, argcount, kwnames)) { + PyCodeObject *code = (PyCodeObject *)func->func_code; + _PyFrame_InitializeSpecials(frame, func, locals, code->co_nlocalsplus); + for (int i = 0; i < code->co_nlocalsplus; i++) { + frame->localsplus[i] = NULL; + } + ((PyGenObject *)gen)->gi_frame_valid = 1; + if (initialize_locals(tstate, func, frame->localsplus, args, argcount, kwnames)) { Py_DECREF(gen); return NULL; } frame->generator = gen; - ((PyGenObject *)gen)->gi_frame_valid = 1; return gen; } From webhook-mailer at python.org Tue Dec 7 13:10:06 2021 From: webhook-mailer at python.org (ambv) Date: Tue, 07 Dec 2021 18:10:06 -0000 Subject: [Python-checkins] bpo-45582: Fix framework path and bootstrap build (GH-29954) Message-ID: https://github.com/python/cpython/commit/06c4ae8b1380eec1c5f3cd8faa21102d1c940bab commit: 06c4ae8b1380eec1c5f3cd8faa21102d1c940bab branch: main author: Christian Heimes committer: ambv date: 2021-12-07T19:09:53+01:00 summary: bpo-45582: Fix framework path and bootstrap build (GH-29954) * Check NS API return values for NULL to prevent segfault in ``_bootstrap_python``. * Set modPathInitialized to 1 so the ``decode_to_dict`` path is used. Signed-off-by: Christian Heimes files: M Makefile.pre.in M Modules/getpath.c diff --git a/Makefile.pre.in b/Makefile.pre.in index 94fc5c37209ef..8e6e553554de1 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -954,9 +954,9 @@ BOOTSTRAP_HEADERS = \ Programs/_bootstrap_python.o: Programs/_bootstrap_python.c $(BOOTSTRAP_HEADERS) $(PYTHON_HEADERS) -_bootstrap_python: $(LIBRARY_OBJS_OMIT_FROZEN) Programs/_bootstrap_python.o Modules/getpath_bootstrap.o Modules/Setup.local +_bootstrap_python: $(LIBRARY_OBJS_OMIT_FROZEN) Programs/_bootstrap_python.o Modules/getpath.o Modules/Setup.local $(LINKCC) $(PY_LDFLAGS_NOLTO) -o $@ $(LIBRARY_OBJS_OMIT_FROZEN) \ - Programs/_bootstrap_python.o Modules/getpath_bootstrap.o $(LIBS) $(MODLIBS) $(SYSLIBS) + Programs/_bootstrap_python.o Modules/getpath.o $(LIBS) $(MODLIBS) $(SYSLIBS) ############################################################################ # Deepfreeze targets @@ -1205,18 +1205,6 @@ Modules/getpath.o: $(srcdir)/Modules/getpath.c Python/frozen_modules/getpath.h M -DPLATLIBDIR='"$(PLATLIBDIR)"' \ -o $@ $(srcdir)/Modules/getpath.c -# like getpath.o with additional -DPY_BOOTSTRAP_PYTHON=1 -Modules/getpath_bootstrap.o: $(srcdir)/Modules/getpath.c Python/frozen_modules/getpath.h Makefile $(PYTHON_HEADERS) - $(CC) -c $(PY_CORE_CFLAGS) -DPYTHONPATH='"$(PYTHONPATH)"' \ - -DPREFIX='"$(prefix)"' \ - -DEXEC_PREFIX='"$(exec_prefix)"' \ - -DVERSION='"$(VERSION)"' \ - -DVPATH='"$(VPATH)"' \ - -DPLATLIBDIR='"$(PLATLIBDIR)"' \ - -DPY_BOOTSTRAP_PYTHON=1 \ - -o $@ $(srcdir)/Modules/getpath.c - - Programs/python.o: $(srcdir)/Programs/python.c $(MAINCC) -c $(PY_CORE_CFLAGS) -o $@ $(srcdir)/Programs/python.c diff --git a/Modules/getpath.c b/Modules/getpath.c index 9ce7260f77826..0b982f10e418b 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -754,12 +754,10 @@ library_to_dict(PyObject *dict, const char *key) if (PyWin_DLLhModule) { return winmodule_to_dict(dict, key, PyWin_DLLhModule); } -#elif defined(WITH_NEXT_FRAMEWORK) && !defined(PY_BOOTSTRAP_PYTHON) - // _bootstrap_python does not use framework and crashes +#elif defined(WITH_NEXT_FRAMEWORK) static char modPath[MAXPATHLEN + 1]; static int modPathInitialized = -1; if (modPathInitialized < 0) { - NSModule pythonModule; modPathInitialized = 0; /* On Mac OS X we have a special case if we're running from a framework. @@ -767,12 +765,17 @@ library_to_dict(PyObject *dict, const char *key) which is in the framework, not relative to the executable, which may be outside of the framework. Except when we're in the build directory... */ - pythonModule = NSModuleForSymbol(NSLookupAndBindSymbol("_Py_Initialize")); - - /* Use dylib functions to find out where the framework was loaded from */ - const char *path = NSLibraryNameForModule(pythonModule); - if (path) { - strncpy(modPath, path, MAXPATHLEN); + NSSymbol symbol = NSLookupAndBindSymbol("_Py_Initialize"); + if (symbol != NULL) { + NSModule pythonModule = NSModuleForSymbol(symbol); + if (pythonModule != NULL) { + /* Use dylib functions to find out where the framework was loaded from */ + const char *path = NSLibraryNameForModule(pythonModule); + if (path) { + strncpy(modPath, path, MAXPATHLEN); + modPathInitialized = 1; + } + } } } if (modPathInitialized > 0) { From webhook-mailer at python.org Tue Dec 7 14:56:56 2021 From: webhook-mailer at python.org (tiran) Date: Tue, 07 Dec 2021 19:56:56 -0000 Subject: [Python-checkins] bpo-45847: Revert Port _ctypes partly to PY_STDLIB_MOD (GH-29747) (GH-29969) Message-ID: https://github.com/python/cpython/commit/91b59a3fcdcb93d74bb89cce536f11d2990f655d commit: 91b59a3fcdcb93d74bb89cce536f11d2990f655d branch: main author: Christian Heimes committer: tiran date: 2021-12-07T20:56:41+01:00 summary: bpo-45847: Revert Port _ctypes partly to PY_STDLIB_MOD (GH-29747) (GH-29969) files: M Modules/Setup.stdlib.in M configure M configure.ac M pyconfig.h.in M setup.py diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index eaf624d8bc579..5788b446201e5 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -136,7 +136,7 @@ # # needs -lffi and -ldl - at MODULE__CTYPES_TRUE@_ctypes _ctypes/_ctypes.c _ctypes/callbacks.c _ctypes/callproc.c _ctypes/stgdict.c _ctypes/cfield.c +#@MODULE__CTYPES_TRUE at _ctypes _ctypes/_ctypes.c _ctypes/callbacks.c _ctypes/callproc.c _ctypes/stgdict.c _ctypes/cfield.c # needs -lncurses, -lncursesw or -lcurses, sometimes -ltermcap #@MODULE__CURSES_TRUE at _curses _cursesmodule.c diff --git a/configure b/configure index 608055d91fac3..8ba76bf8c63f7 100755 --- a/configure +++ b/configure @@ -664,8 +664,6 @@ MODULE__GDBM_FALSE MODULE__GDBM_TRUE MODULE__DECIMAL_FALSE MODULE__DECIMAL_TRUE -MODULE__CTYPES_FALSE -MODULE__CTYPES_TRUE MODULE__CRYPT_FALSE MODULE__CRYPT_TRUE MODULE__BLAKE2_FALSE @@ -830,8 +828,6 @@ LIBMPDEC_INTERNAL LIBMPDEC_LDFLAGS LIBMPDEC_CFLAGS LIBFFI_INCLUDEDIR -LIBFFI_LIBS -LIBFFI_CFLAGS LIBEXPAT_INTERNAL LIBEXPAT_LDFLAGS LIBEXPAT_CFLAGS @@ -1064,8 +1060,6 @@ CPP PROFILE_TASK LIBUUID_CFLAGS LIBUUID_LIBS -LIBFFI_CFLAGS -LIBFFI_LIBS LIBNSL_CFLAGS LIBNSL_LIBS LIBSQLITE3_CFLAGS @@ -1863,9 +1857,6 @@ Some influential environment variables: C compiler flags for LIBUUID, overriding pkg-config LIBUUID_LIBS linker flags for LIBUUID, overriding pkg-config - LIBFFI_CFLAGS - C compiler flags for LIBFFI, overriding pkg-config - LIBFFI_LIBS linker flags for LIBFFI, overriding pkg-config LIBNSL_CFLAGS C compiler flags for LIBNSL, overriding pkg-config LIBNSL_LIBS linker flags for LIBNSL, overriding pkg-config @@ -11410,335 +11401,6 @@ $as_echo "$as_me: WARNING: --with(out)-system-ffi is ignored on this platform" > with_system_ffi="yes" fi -have_libffi=missing -if test "x$with_system_ffi" = xyes; then : - - -pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBFFI" >&5 -$as_echo_n "checking for LIBFFI... " >&6; } - -if test -n "$LIBFFI_CFLAGS"; then - pkg_cv_LIBFFI_CFLAGS="$LIBFFI_CFLAGS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libffi\""; } >&5 - ($PKG_CONFIG --exists --print-errors "libffi") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_LIBFFI_CFLAGS=`$PKG_CONFIG --cflags "libffi" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi -if test -n "$LIBFFI_LIBS"; then - pkg_cv_LIBFFI_LIBS="$LIBFFI_LIBS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libffi\""; } >&5 - ($PKG_CONFIG --exists --print-errors "libffi") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_LIBFFI_LIBS=`$PKG_CONFIG --libs "libffi" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi - - - -if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - -if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then - _pkg_short_errors_supported=yes -else - _pkg_short_errors_supported=no -fi - if test $_pkg_short_errors_supported = yes; then - LIBFFI_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libffi" 2>&1` - else - LIBFFI_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libffi" 2>&1` - fi - # Put the nasty error message in config.log where it belongs - echo "$LIBFFI_PKG_ERRORS" >&5 - - - ac_fn_c_check_header_mongrel "$LINENO" "ffi.h" "ac_cv_header_ffi_h" "$ac_includes_default" -if test "x$ac_cv_header_ffi_h" = xyes; then : - - save_CFLAGS=$CFLAGS -save_CPPFLAGS=$CPPFLAGS -save_LDFLAGS=$LDFLAGS -save_LIBS=$LIBS - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ffi_call in -lffi" >&5 -$as_echo_n "checking for ffi_call in -lffi... " >&6; } -if ${ac_cv_lib_ffi_ffi_call+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lffi $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char ffi_call (); -int -main () -{ -return ffi_call (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_ffi_ffi_call=yes -else - ac_cv_lib_ffi_ffi_call=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ffi_ffi_call" >&5 -$as_echo "$ac_cv_lib_ffi_ffi_call" >&6; } -if test "x$ac_cv_lib_ffi_ffi_call" = xyes; then : - have_libffi=yes -else - have_libffi=no -fi - - -CFLAGS=$save_CFLAGS -CPPFLAGS=$save_CPPFLAGS -LDFLAGS=$save_LDFLAGS -LIBS=$save_LIBS - - - -fi - - - -elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - - ac_fn_c_check_header_mongrel "$LINENO" "ffi.h" "ac_cv_header_ffi_h" "$ac_includes_default" -if test "x$ac_cv_header_ffi_h" = xyes; then : - - save_CFLAGS=$CFLAGS -save_CPPFLAGS=$CPPFLAGS -save_LDFLAGS=$LDFLAGS -save_LIBS=$LIBS - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ffi_call in -lffi" >&5 -$as_echo_n "checking for ffi_call in -lffi... " >&6; } -if ${ac_cv_lib_ffi_ffi_call+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lffi $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char ffi_call (); -int -main () -{ -return ffi_call (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_ffi_ffi_call=yes -else - ac_cv_lib_ffi_ffi_call=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ffi_ffi_call" >&5 -$as_echo "$ac_cv_lib_ffi_ffi_call" >&6; } -if test "x$ac_cv_lib_ffi_ffi_call" = xyes; then : - have_libffi=yes -else - have_libffi=no -fi - - -CFLAGS=$save_CFLAGS -CPPFLAGS=$save_CPPFLAGS -LDFLAGS=$save_LDFLAGS -LIBS=$save_LIBS - - - -fi - - - -else - LIBFFI_CFLAGS=$pkg_cv_LIBFFI_CFLAGS - LIBFFI_LIBS=$pkg_cv_LIBFFI_LIBS - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - have_libffi=yes -fi - -else - - have_libffi=yes - LIBFFI_CFLAGS="-I\$(srcdir)/Modules/_ctypes/darwin -DUSING_MALLOC_CLOSURE_DOT_C=1 -DMACOSX" - LIBFFI_LIBS= - -fi - -case $LIBS in #( - *-ldl*) : - LIBFFI_LIBS="$LIBFFI_LIBS -ldl" - ;; #( - *) : - ;; -esac - -if test "$with_system_ffi" = yes -a "$have_libffi" = yes; then - save_CFLAGS=$CFLAGS -save_CPPFLAGS=$CPPFLAGS -save_LDFLAGS=$LDFLAGS -save_LIBS=$LIBS - - - CFLAGS="$LIBFFI_CFLAGS $CFLAGS" - LIBS="$LIBFFI_LIBS $LIBS" - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ffi_prep_cif_var in ffi.h" >&5 -$as_echo_n "checking for ffi_prep_cif_var in ffi.h... " >&6; } -if ${ac_cv_ffi_prep_cif_var+:} false; then : - $as_echo_n "(cached) " >&6 -else - - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "ffi_prep_cif_var" >/dev/null 2>&1; then : - ac_cv_ffi_prep_cif_var=yes -else - ac_cv_ffi_prep_cif_var=no -fi -rm -f conftest* - - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_ffi_prep_cif_var" >&5 -$as_echo "$ac_cv_ffi_prep_cif_var" >&6; } - if test "x$ac_cv_ffi_prep_cif_var" = xyes; then : - - -$as_echo "#define HAVE_FFI_PREP_CIF_VAR 1" >>confdefs.h - - -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ffi_prep_closure_loc in ffi.h" >&5 -$as_echo_n "checking for ffi_prep_closure_loc in ffi.h... " >&6; } -if ${ac_cv_ffi_prep_closure_loc+:} false; then : - $as_echo_n "(cached) " >&6 -else - - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "ffi_prep_closure_loc" >/dev/null 2>&1; then : - ac_cv_ffi_prep_closure_loc=yes -else - ac_cv_ffi_prep_closure_loc=no -fi -rm -f conftest* - - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_ffi_prep_closure_loc" >&5 -$as_echo "$ac_cv_ffi_prep_closure_loc" >&6; } - if test "x$ac_cv_ffi_prep_closure_loc" = xyes; then : - - -$as_echo "#define HAVE_FFI_PREP_CLOSURE_LOC 1" >>confdefs.h - - -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ffi_closure_alloc in ffi.h" >&5 -$as_echo_n "checking for ffi_closure_alloc in ffi.h... " >&6; } -if ${ac_cv_ffi_closure_alloc+:} false; then : - $as_echo_n "(cached) " >&6 -else - - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "ffi_closure_alloc" >/dev/null 2>&1; then : - ac_cv_ffi_closure_alloc=yes -else - ac_cv_ffi_closure_alloc=no -fi -rm -f conftest* - - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_ffi_closure_alloc" >&5 -$as_echo "$ac_cv_ffi_closure_alloc" >&6; } - if test "x$ac_cv_ffi_closure_alloc" = xyes; then : - - -$as_echo "#define HAVE_FFI_CLOSURE_ALLOC 1" >>confdefs.h - - -fi - -CFLAGS=$save_CFLAGS -CPPFLAGS=$save_CPPFLAGS -LDFLAGS=$save_LDFLAGS -LIBS=$save_LIBS - - -fi - - if test "$with_system_ffi" = "yes" && test -n "$PKG_CONFIG"; then LIBFFI_INCLUDEDIR="`"$PKG_CONFIG" libffi --cflags-only-I 2>/dev/null | sed -e 's/^-I//;s/ *$//'`" else @@ -23078,42 +22740,6 @@ fi $as_echo "$py_cv_module__crypt" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _ctypes" >&5 -$as_echo_n "checking for stdlib extension module _ctypes... " >&6; } - case $py_stdlib_not_available in #( - *_ctypes*) : - py_cv_module__ctypes=n/a ;; #( - *) : - if true; then : - if test "$have_libffi" = yes; then : - py_cv_module__ctypes=yes -else - py_cv_module__ctypes=missing -fi -else - py_cv_module__ctypes=disabled -fi - ;; -esac - as_fn_append MODULE_BLOCK "MODULE__CTYPES=$py_cv_module__ctypes$as_nl" - if test "x$py_cv_module__ctypes" = xyes; then : - - as_fn_append MODULE_BLOCK "MODULE__CTYPES_CFLAGS=$LIBFFI_CFLAGS$as_nl" - as_fn_append MODULE_BLOCK "MODULE__CTYPES_LDFLAGS=$LIBFFI_LIBS$as_nl" - -fi - if test "$py_cv_module__ctypes" = yes; then - MODULE__CTYPES_TRUE= - MODULE__CTYPES_FALSE='#' -else - MODULE__CTYPES_TRUE='#' - MODULE__CTYPES_FALSE= -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__ctypes" >&5 -$as_echo "$py_cv_module__ctypes" >&6; } - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _decimal" >&5 $as_echo_n "checking for stdlib extension module _decimal... " >&6; } case $py_stdlib_not_available in #( @@ -23724,7 +23350,7 @@ $as_echo_n "checking for stdlib extension module _ctypes_test... " >&6; } py_cv_module__ctypes_test=n/a ;; #( *) : if test "$TEST_MODULES" = yes; then : - if test "$have_libffi" = yes; then : + if true; then : py_cv_module__ctypes_test=yes else py_cv_module__ctypes_test=missing @@ -23738,7 +23364,7 @@ esac if test "x$py_cv_module__ctypes_test" = xyes; then : - as_fn_append MODULE_BLOCK "MODULE__CTYPES_TEST_LDFLAGS=$LIBM$as_nl" + as_fn_append MODULE_BLOCK "MODULE__CTYPES_TEST_LDFLAGS=-lm$as_nl" fi if test "$py_cv_module__ctypes_test" = yes; then @@ -24162,10 +23788,6 @@ if test -z "${MODULE__CRYPT_TRUE}" && test -z "${MODULE__CRYPT_FALSE}"; then as_fn_error $? "conditional \"MODULE__CRYPT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${MODULE__CTYPES_TRUE}" && test -z "${MODULE__CTYPES_FALSE}"; then - as_fn_error $? "conditional \"MODULE__CTYPES\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi if test -z "${MODULE__DECIMAL_TRUE}" && test -z "${MODULE__DECIMAL_FALSE}"; then as_fn_error $? "conditional \"MODULE__DECIMAL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index 7cc6c0c2f592a..0905014d25b66 100644 --- a/configure.ac +++ b/configure.ac @@ -3187,60 +3187,6 @@ else with_system_ffi="yes" fi -dnl detect libffi -have_libffi=missing -AS_VAR_IF([with_system_ffi], [yes], [ - PKG_CHECK_MODULES([LIBFFI], [libffi], [have_libffi=yes], [ - AC_CHECK_HEADER([ffi.h], [ - WITH_SAVE_ENV([ - AC_CHECK_LIB([ffi], [ffi_call], [have_libffi=yes], [have_libffi=no]) - ]) - ]) - ]) -], [ - dnl private ffi copy - have_libffi=yes - LIBFFI_CFLAGS="-I\$(srcdir)/Modules/_ctypes/darwin -DUSING_MALLOC_CLOSURE_DOT_C=1 -DMACOSX" - LIBFFI_LIBS= -]) - -dnl _ctypes needs -ldl for dlopen -AS_CASE([$LIBS], - [*-ldl*], [LIBFFI_LIBS="$LIBFFI_LIBS -ldl"] -) - -if test "$with_system_ffi" = yes -a "$have_libffi" = yes; then - WITH_SAVE_ENV([ - CFLAGS="$LIBFFI_CFLAGS $CFLAGS" - LIBS="$LIBFFI_LIBS $LIBS" - - AC_CACHE_CHECK([for ffi_prep_cif_var in ffi.h], [ac_cv_ffi_prep_cif_var], [ - AC_EGREP_HEADER([ffi_prep_cif_var], [ffi.h], [ac_cv_ffi_prep_cif_var=yes], [ac_cv_ffi_prep_cif_var=no]) - ]) - AS_VAR_IF([ac_cv_ffi_prep_cif_var], [yes], [ - AC_DEFINE([HAVE_FFI_PREP_CIF_VAR], [1], - [Define to 1 if you have the ffi_prep_cif_var function in header file.]) - ]) - - AC_CACHE_CHECK([for ffi_prep_closure_loc in ffi.h], [ac_cv_ffi_prep_closure_loc], [ - AC_EGREP_HEADER([ffi_prep_closure_loc], [ffi.h], [ac_cv_ffi_prep_closure_loc=yes], [ac_cv_ffi_prep_closure_loc=no]) - ]) - AS_VAR_IF([ac_cv_ffi_prep_closure_loc], [yes], [ - AC_DEFINE([HAVE_FFI_PREP_CLOSURE_LOC], [1], - [Define to 1 if you have the ffi_prep_closure_loc function in header file.]) - ]) - - AC_CACHE_CHECK([for ffi_closure_alloc in ffi.h], [ac_cv_ffi_closure_alloc], [ - AC_EGREP_HEADER([ffi_closure_alloc], [ffi.h], [ac_cv_ffi_closure_alloc=yes], [ac_cv_ffi_closure_alloc=no]) - ]) - AS_VAR_IF([ac_cv_ffi_closure_alloc], [yes], [ - AC_DEFINE([HAVE_FFI_CLOSURE_ALLOC], [1], - [Define to 1 if you have the ffi_closure_alloc function in header file.]) - ]) - ]) -fi - - if test "$with_system_ffi" = "yes" && test -n "$PKG_CONFIG"; then LIBFFI_INCLUDEDIR="`"$PKG_CONFIG" libffi --cflags-only-I 2>/dev/null | sed -e 's/^-I//;s/ *$//'`" else @@ -6484,9 +6430,7 @@ PY_STDLIB_MOD([_blake2], [test "$with_builtin_blake2" = yes]) PY_STDLIB_MOD([_crypt], [], [test "$ac_cv_crypt_crypt" = yes], [$LIBCRYPT_CFLAGS], [$LIBCRYPT_LIBS]) -PY_STDLIB_MOD([_ctypes], - [], [test "$have_libffi" = yes], - [$LIBFFI_CFLAGS], [$LIBFFI_LIBS]) +dnl PY_STDLIB_MOD([_ctypes], [], [], [], []) dnl PY_STDLIB_MOD([_curses], [], [], [], []) dnl PY_STDLIB_MOD([_curses_panel], [], [], [], []) PY_STDLIB_MOD([_decimal], [], [], [$LIBMPDEC_CFLAGS], [$LIBMPDEC_LDFLAGS]) @@ -6530,9 +6474,7 @@ PY_STDLIB_MOD([_testbuffer], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_testimportmultiple], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_testmultiphase], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_xxtestfuzz], [test "$TEST_MODULES" = yes]) -PY_STDLIB_MOD([_ctypes_test], - [test "$TEST_MODULES" = yes], [test "$have_libffi" = yes], - [], [$LIBM]) +PY_STDLIB_MOD([_ctypes_test], [test "$TEST_MODULES" = yes], [], [], [-lm]) dnl Limited API template modules. dnl The limited C API is not compatible with the Py_TRACE_REFS macro. diff --git a/pyconfig.h.in b/pyconfig.h.in index c6cc1fd377762..efad243d0af8a 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -356,18 +356,6 @@ /* Define to 1 if you have the `fexecve' function. */ #undef HAVE_FEXECVE -/* Define to 1 if you have the ffi_closure_alloc function in header - file. */ -#undef HAVE_FFI_CLOSURE_ALLOC - -/* Define to 1 if you have the ffi_prep_cif_var function in header - file. */ -#undef HAVE_FFI_PREP_CIF_VAR - -/* Define to 1 if you have the ffi_prep_closure_loc function in header - file. */ -#undef HAVE_FFI_PREP_CLOSURE_LOC - /* Define to 1 if you have the `flock' function. */ #undef HAVE_FLOCK diff --git a/setup.py b/setup.py index ca5d0774e001a..572f2ac1783b8 100644 --- a/setup.py +++ b/setup.py @@ -669,6 +669,12 @@ def print_three_column(lst): raise RuntimeError("Failed to build some stdlib modules") def build_extension(self, ext): + + if ext.name == '_ctypes': + if not self.configure_ctypes(ext): + self.failed.append(ext.name) + return + try: build_ext.build_extension(self, ext) except (CCompilerError, DistutilsError) as why: @@ -1732,26 +1738,10 @@ def detect_tkinter(self): library_dirs=added_lib_dirs)) return True - def detect_ctypes(self): - ext = Extension( - '_ctypes', - [ - '_ctypes/_ctypes.c', - '_ctypes/callbacks.c', - '_ctypes/callproc.c', - '_ctypes/stgdict.c', - '_ctypes/cfield.c', - ] - ) - if MACOS: - self._build_ctypes_macos(ext) - else: - self.use_system_libffi = True - self.addext(ext) - - self.addext(Extension('_ctypes_test', ['_ctypes/_ctypes_test.c'])) + def configure_ctypes(self, ext): + return True - def _build_ctypes_macos(self, ext): + def detect_ctypes(self): # Thomas Heller's _ctypes module if (not sysconfig.get_config_var("LIBFFI_INCLUDEDIR") and MACOS): @@ -1759,11 +1749,20 @@ def _build_ctypes_macos(self, ext): else: self.use_system_libffi = '--with-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS") + include_dirs = [] + extra_compile_args = [] + extra_link_args = [] + sources = ['_ctypes/_ctypes.c', + '_ctypes/callbacks.c', + '_ctypes/callproc.c', + '_ctypes/stgdict.c', + '_ctypes/cfield.c'] + if MACOS: - ext.sources.append('_ctypes/malloc_closure.c') - ext.extra_compile_args.append('-DUSING_MALLOC_CLOSURE_DOT_C=1') - ext.extra_compile_args.append('-DMACOSX') - ext.include_dirs.append('_ctypes/darwin') + sources.append('_ctypes/malloc_closure.c') + extra_compile_args.append('-DUSING_MALLOC_CLOSURE_DOT_C=1') + extra_compile_args.append('-DMACOSX') + include_dirs.append('_ctypes/darwin') elif HOST_PLATFORM == 'sunos5': # XXX This shouldn't be necessary; it appears that some @@ -1774,12 +1773,20 @@ def _build_ctypes_macos(self, ext): # this option. If you want to compile ctypes with the Sun # compiler, please research a proper solution, instead of # finding some -z option for the Sun compiler. - ext.extra_link_args.append('-mimpure-text') + extra_link_args.append('-mimpure-text') elif HOST_PLATFORM.startswith('hp-ux'): - ext.extra_link_args.append('-fPIC') - + extra_link_args.append('-fPIC') + + ext = Extension('_ctypes', + include_dirs=include_dirs, + extra_compile_args=extra_compile_args, + extra_link_args=extra_link_args, + libraries=[], + sources=sources) self.add(ext) + # function my_sqrt() needs libm for sqrt() + self.addext(Extension('_ctypes_test', ['_ctypes/_ctypes_test.c'])) ffi_inc = sysconfig.get_config_var("LIBFFI_INCLUDEDIR") ffi_lib = None From webhook-mailer at python.org Tue Dec 7 16:02:36 2021 From: webhook-mailer at python.org (ericsnowcurrently) Date: Tue, 07 Dec 2021 21:02:36 -0000 Subject: [Python-checkins] bpo-46008: Return void from _PyEval_InitState(). (gh-29970) Message-ID: https://github.com/python/cpython/commit/8262c96bcc1841188866c1b022d9087e89639d98 commit: 8262c96bcc1841188866c1b022d9087e89639d98 branch: main author: Eric Snow committer: ericsnowcurrently date: 2021-12-07T14:02:17-07:00 summary: bpo-46008: Return void from _PyEval_InitState(). (gh-29970) This falls into the category of keep-allocation-and-initialization separate. It also allows us to use _PyEval_InitState() safely in functions that return void. https://bugs.python.org/issue46008 files: M Include/internal/pycore_ceval.h M Python/ceval.c M Python/pystate.c diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index 26d5677b12837..20508d4a68747 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -17,7 +17,7 @@ struct _ceval_runtime_state; extern void _Py_FinishPendingCalls(PyThreadState *tstate); extern void _PyEval_InitRuntimeState(struct _ceval_runtime_state *); -extern int _PyEval_InitState(struct _ceval_state *ceval); +extern void _PyEval_InitState(struct _ceval_state *, PyThread_type_lock); extern void _PyEval_FiniState(struct _ceval_state *ceval); PyAPI_FUNC(void) _PyEval_SignalReceived(PyInterpreterState *interp); PyAPI_FUNC(int) _PyEval_AddPendingCall( diff --git a/Python/ceval.c b/Python/ceval.c index c22af02330b92..36d1360015ceb 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -747,24 +747,19 @@ _PyEval_InitRuntimeState(struct _ceval_runtime_state *ceval) #endif } -int -_PyEval_InitState(struct _ceval_state *ceval) +void +_PyEval_InitState(struct _ceval_state *ceval, PyThread_type_lock pending_lock) { ceval->recursion_limit = Py_DEFAULT_RECURSION_LIMIT; struct _pending_calls *pending = &ceval->pending; assert(pending->lock == NULL); - pending->lock = PyThread_allocate_lock(); - if (pending->lock == NULL) { - return -1; - } + pending->lock = pending_lock; #ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS _gil_initialize(&ceval->gil); #endif - - return 0; } void diff --git a/Python/pystate.c b/Python/pystate.c index ba14c9d8af9fb..a0bd05077ee15 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -225,10 +225,12 @@ PyInterpreterState_New(void) _PyRuntimeState *runtime = &_PyRuntime; interp->runtime = runtime; - if (_PyEval_InitState(&interp->ceval) < 0) { + PyThread_type_lock pending_lock = PyThread_allocate_lock(); + if (pending_lock == NULL) { goto out_of_memory; } + _PyEval_InitState(&interp->ceval, pending_lock); _PyGC_InitState(&interp->gc); PyConfig_InitPythonConfig(&interp->config); _PyType_InitCache(interp); From webhook-mailer at python.org Tue Dec 7 16:03:59 2021 From: webhook-mailer at python.org (ericsnowcurrently) Date: Tue, 07 Dec 2021 21:03:59 -0000 Subject: [Python-checkins] bpo-46008: Move thread-related interpreter state into a sub-struct. (gh-29971) Message-ID: https://github.com/python/cpython/commit/313f92a57bc3887026ec16adb536bb2b7580ce47 commit: 313f92a57bc3887026ec16adb536bb2b7580ce47 branch: main author: Eric Snow committer: ericsnowcurrently date: 2021-12-07T14:03:47-07:00 summary: bpo-46008: Move thread-related interpreter state into a sub-struct. (gh-29971) This parallels _PyRuntimeState.interpreters. Doing this helps make it more clear what part of PyInterpreterState relates to its threads. https://bugs.python.org/issue46008 files: M Include/internal/pycore_interp.h M Modules/_threadmodule.c M Python/ceval.c M Python/pylifecycle.c M Python/pystate.c M Python/thread.c M Python/thread_nt.h M Python/thread_pthread.h diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index f52ee594106f9..53938e3d7bc09 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -238,7 +238,19 @@ struct type_cache { struct _is { struct _is *next; - struct _ts *tstate_head; + + struct pythreads { + int _preallocated_used; + uint64_t next_unique_id; + struct _ts *head; + /* Used in Modules/_threadmodule.c. */ + long count; + /* Support for runtime thread stack size tuning. + A value of 0 means using the platform's default stack size + or the size specified by the THREAD_STACK_SIZE macro. */ + /* Used in Python/thread.c. */ + size_t stacksize; + } threads; /* Reference to the _PyRuntime global variable. This field exists to not have to pass runtime in addition to tstate to a function. @@ -268,14 +280,6 @@ struct _is { // (-1: "off", 1: "on", 0: no override) int override_frozen_modules; - /* Used in Modules/_threadmodule.c. */ - long num_threads; - /* Support for runtime thread stack size tuning. - A value of 0 means using the platform's default stack size - or the size specified by the THREAD_STACK_SIZE macro. */ - /* Used in Python/thread.c. */ - size_t pythread_stacksize; - PyObject *codec_search_path; PyObject *codec_search_cache; PyObject *codec_error_registry; @@ -302,8 +306,6 @@ struct _is { PyObject *after_forkers_child; #endif - uint64_t tstate_next_unique_id; - struct _warnings_runtime_state warnings; struct atexit_state atexit; diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index 39b116afcaa3e..2ba081d92b9af 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -3,7 +3,7 @@ /* Interface to Sjoerd's portable C thread library */ #include "Python.h" -#include "pycore_interp.h" // _PyInterpreterState.num_threads +#include "pycore_interp.h" // _PyInterpreterState.threads.count #include "pycore_moduleobject.h" // _PyModule_GetState() #include "pycore_pylifecycle.h" #include "pycore_pystate.h" // _PyThreadState_Init() @@ -1089,7 +1089,7 @@ thread_run(void *boot_raw) #endif _PyThreadState_Init(tstate); PyEval_AcquireThread(tstate); - tstate->interp->num_threads++; + tstate->interp->threads.count++; PyObject *res = PyObject_Call(boot->func, boot->args, boot->kwargs); if (res == NULL) { @@ -1105,7 +1105,7 @@ thread_run(void *boot_raw) } thread_bootstate_free(boot); - tstate->interp->num_threads--; + tstate->interp->threads.count--; PyThreadState_Clear(tstate); _PyThreadState_DeleteCurrent(tstate); @@ -1279,7 +1279,7 @@ static PyObject * thread__count(PyObject *self, PyObject *Py_UNUSED(ignored)) { PyInterpreterState *interp = _PyInterpreterState_GET(); - return PyLong_FromLong(interp->num_threads); + return PyLong_FromLong(interp->threads.count); } PyDoc_STRVAR(_count_doc, diff --git a/Python/ceval.c b/Python/ceval.c index 36d1360015ceb..2e40c0f5b391a 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -784,7 +784,7 @@ Py_SetRecursionLimit(int new_limit) { PyInterpreterState *interp = _PyInterpreterState_GET(); interp->ceval.recursion_limit = new_limit; - for (PyThreadState *p = interp->tstate_head; p != NULL; p = p->next) { + for (PyThreadState *p = interp->threads.head; p != NULL; p = p->next) { int depth = p->recursion_limit - p->recursion_remaining; p->recursion_limit = new_limit; p->recursion_remaining = new_limit - depth; diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 84b76ea3275a7..f648ddab0388f 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -2043,7 +2043,7 @@ Py_EndInterpreter(PyThreadState *tstate) _PyAtExit_Call(tstate->interp); - if (tstate != interp->tstate_head || tstate->next != NULL) { + if (tstate != interp->threads.head || tstate->next != NULL) { Py_FatalError("not the last thread"); } diff --git a/Python/pystate.c b/Python/pystate.c index a0bd05077ee15..4dd4cab249725 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -271,7 +271,7 @@ PyInterpreterState_New(void) return NULL; } - interp->tstate_next_unique_id = 0; + interp->threads.next_unique_id = 0; interp->audit_hooks = NULL; @@ -297,7 +297,7 @@ interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate) } HEAD_LOCK(runtime); - for (PyThreadState *p = interp->tstate_head; p != NULL; p = p->next) { + for (PyThreadState *p = interp->threads.head; p != NULL; p = p->next) { PyThreadState_Clear(p); } HEAD_UNLOCK(runtime); @@ -371,7 +371,7 @@ zapthreads(PyInterpreterState *interp, int check_current) PyThreadState *tstate; /* No need to lock the mutex here because this should only happen when the threads are all really dead (XXX famous last words). */ - while ((tstate = interp->tstate_head) != NULL) { + while ((tstate = interp->threads.head) != NULL) { _PyThreadState_Delete(tstate, check_current); } } @@ -399,7 +399,7 @@ PyInterpreterState_Delete(PyInterpreterState *interp) break; } } - if (interp->tstate_head != NULL) { + if (interp->threads.head != NULL) { Py_FatalError("remaining threads"); } *p = interp->next; @@ -702,12 +702,12 @@ new_threadstate(PyInterpreterState *interp, int init) } HEAD_LOCK(runtime); - tstate->id = ++interp->tstate_next_unique_id; + tstate->id = ++interp->threads.next_unique_id; tstate->prev = NULL; - tstate->next = interp->tstate_head; + tstate->next = interp->threads.head; if (tstate->next) tstate->next->prev = tstate; - interp->tstate_head = tstate; + interp->threads.head = tstate; HEAD_UNLOCK(runtime); return tstate; @@ -930,7 +930,7 @@ tstate_delete_common(PyThreadState *tstate, tstate->prev->next = tstate->next; } else { - interp->tstate_head = tstate->next; + interp->threads.head = tstate->next; } if (tstate->next) { tstate->next->prev = tstate->prev; @@ -1008,7 +1008,7 @@ _PyThreadState_DeleteExcept(_PyRuntimeState *runtime, PyThreadState *tstate) /* Remove all thread states, except tstate, from the linked list of thread states. This will allow calling PyThreadState_Clear() without holding the lock. */ - PyThreadState *list = interp->tstate_head; + PyThreadState *list = interp->threads.head; if (list == tstate) { list = tstate->next; } @@ -1019,7 +1019,7 @@ _PyThreadState_DeleteExcept(_PyRuntimeState *runtime, PyThreadState *tstate) tstate->next->prev = tstate->prev; } tstate->prev = tstate->next = NULL; - interp->tstate_head = tstate; + interp->threads.head = tstate; HEAD_UNLOCK(runtime); /* Clear and deallocate all stale thread states. Even if this @@ -1180,7 +1180,7 @@ PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc) * head_mutex for the duration. */ HEAD_LOCK(runtime); - for (PyThreadState *tstate = interp->tstate_head; tstate != NULL; tstate = tstate->next) { + for (PyThreadState *tstate = interp->threads.head; tstate != NULL; tstate = tstate->next) { if (tstate->thread_id != id) { continue; } @@ -1244,7 +1244,7 @@ PyInterpreterState_Next(PyInterpreterState *interp) { PyThreadState * PyInterpreterState_ThreadHead(PyInterpreterState *interp) { - return interp->tstate_head; + return interp->threads.head; } PyThreadState * @@ -1281,7 +1281,7 @@ _PyThread_CurrentFrames(void) PyInterpreterState *i; for (i = runtime->interpreters.head; i != NULL; i = i->next) { PyThreadState *t; - for (t = i->tstate_head; t != NULL; t = t->next) { + for (t = i->threads.head; t != NULL; t = t->next) { InterpreterFrame *frame = t->cframe->current_frame; if (frame == NULL) { continue; @@ -1334,7 +1334,7 @@ _PyThread_CurrentExceptions(void) PyInterpreterState *i; for (i = runtime->interpreters.head; i != NULL; i = i->next) { PyThreadState *t; - for (t = i->tstate_head; t != NULL; t = t->next) { + for (t = i->threads.head; t != NULL; t = t->next) { _PyErr_StackItem *err_info = _PyErr_GetTopmostException(t); if (err_info == NULL) { continue; diff --git a/Python/thread.c b/Python/thread.c index dfe28b6bdb680..b1c0cfe84f28d 100644 --- a/Python/thread.c +++ b/Python/thread.c @@ -109,7 +109,7 @@ _PyThread_debug_deprecation(void) size_t PyThread_get_stacksize(void) { - return _PyInterpreterState_GET()->pythread_stacksize; + return _PyInterpreterState_GET()->threads.stacksize; } /* Only platforms defining a THREAD_SET_STACKSIZE() macro diff --git a/Python/thread_nt.h b/Python/thread_nt.h index 0dde1a0409738..084bd58731487 100644 --- a/Python/thread_nt.h +++ b/Python/thread_nt.h @@ -1,4 +1,4 @@ -#include "pycore_interp.h" // _PyInterpreterState.pythread_stacksize +#include "pycore_interp.h" // _PyInterpreterState.threads.stacksize /* This code implemented by Dag.Gruneau at elsa.preseco.comm.se */ /* Fast NonRecursiveMutex support by Yakov Markovitch, markovitch at iso.ru */ @@ -199,7 +199,7 @@ PyThread_start_new_thread(void (*func)(void *), void *arg) obj->func = func; obj->arg = arg; PyThreadState *tstate = _PyThreadState_GET(); - size_t stacksize = tstate ? tstate->interp->pythread_stacksize : 0; + size_t stacksize = tstate ? tstate->interp->threads.stacksize : 0; hThread = (HANDLE)_beginthreadex(0, Py_SAFE_DOWNCAST(stacksize, Py_ssize_t, unsigned int), bootstrap, obj, @@ -376,13 +376,13 @@ _pythread_nt_set_stacksize(size_t size) { /* set to default */ if (size == 0) { - _PyInterpreterState_GET()->pythread_stacksize = 0; + _PyInterpreterState_GET()->threads.stacksize = 0; return 0; } /* valid range? */ if (size >= THREAD_MIN_STACKSIZE && size < THREAD_MAX_STACKSIZE) { - _PyInterpreterState_GET()->pythread_stacksize = size; + _PyInterpreterState_GET()->threads.stacksize = size; return 0; } diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index 12dad7e9e4427..c90ab25d4841d 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -1,4 +1,4 @@ -#include "pycore_interp.h" // _PyInterpreterState.pythread_stacksize +#include "pycore_interp.h" // _PyInterpreterState.threads.stacksize /* Posix threads interface */ @@ -262,7 +262,7 @@ PyThread_start_new_thread(void (*func)(void *), void *arg) #endif #if defined(THREAD_STACK_SIZE) PyThreadState *tstate = _PyThreadState_GET(); - size_t stacksize = tstate ? tstate->interp->pythread_stacksize : 0; + size_t stacksize = tstate ? tstate->interp->threads.stacksize : 0; tss = (stacksize != 0) ? stacksize : THREAD_STACK_SIZE; if (tss != 0) { if (pthread_attr_setstacksize(&attrs, tss) != 0) { @@ -764,7 +764,7 @@ _pythread_pthread_set_stacksize(size_t size) /* set to default */ if (size == 0) { - _PyInterpreterState_GET()->pythread_stacksize = 0; + _PyInterpreterState_GET()->threads.stacksize = 0; return 0; } @@ -781,7 +781,7 @@ _pythread_pthread_set_stacksize(size_t size) rc = pthread_attr_setstacksize(&attrs, size); pthread_attr_destroy(&attrs); if (rc == 0) { - _PyInterpreterState_GET()->pythread_stacksize = size; + _PyInterpreterState_GET()->threads.stacksize = size; return 0; } } From webhook-mailer at python.org Tue Dec 7 16:38:02 2021 From: webhook-mailer at python.org (miss-islington) Date: Tue, 07 Dec 2021 21:38:02 -0000 Subject: [Python-checkins] bpo-46008: Use PyMem_RawCalloc() to allocate PyThreadState. (GH-29972) Message-ID: https://github.com/python/cpython/commit/9b577cd01f66512b503115c0fdbf0734edfd5f8a commit: 9b577cd01f66512b503115c0fdbf0734edfd5f8a branch: main author: Eric Snow committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-07T13:37:51-08:00 summary: bpo-46008: Use PyMem_RawCalloc() to allocate PyThreadState. (GH-29972) Doing so allows us to stop assigning various fields to `NULL` and 0. It also more closely matches the behavior of a static initializer. Automerge-Triggered-By: GH:ericsnowcurrently files: M Python/pystate.c diff --git a/Python/pystate.c b/Python/pystate.c index 4dd4cab249725..49acd560b386e 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -634,7 +634,7 @@ static PyThreadState * new_threadstate(PyInterpreterState *interp, int init) { _PyRuntimeState *runtime = interp->runtime; - PyThreadState *tstate = (PyThreadState *)PyMem_RawMalloc(sizeof(PyThreadState)); + PyThreadState *tstate = (PyThreadState *)PyMem_RawCalloc(1, sizeof(PyThreadState)); if (tstate == NULL) { return NULL; } @@ -643,49 +643,16 @@ new_threadstate(PyInterpreterState *interp, int init) tstate->recursion_limit = interp->ceval.recursion_limit; tstate->recursion_remaining = interp->ceval.recursion_limit; - tstate->recursion_headroom = 0; - tstate->tracing = 0; - tstate->root_cframe.use_tracing = 0; - tstate->root_cframe.current_frame = NULL; tstate->cframe = &tstate->root_cframe; - tstate->gilstate_counter = 0; - tstate->async_exc = NULL; tstate->thread_id = PyThread_get_thread_ident(); #ifdef PY_HAVE_THREAD_NATIVE_ID tstate->native_thread_id = PyThread_get_thread_native_id(); -#else - tstate->native_thread_id = 0; #endif - tstate->dict = NULL; - - tstate->curexc_type = NULL; - tstate->curexc_value = NULL; - tstate->curexc_traceback = NULL; - - tstate->exc_state.exc_type = NULL; - tstate->exc_state.exc_value = NULL; - tstate->exc_state.exc_traceback = NULL; - tstate->exc_state.previous_item = NULL; tstate->exc_info = &tstate->exc_state; - tstate->c_profilefunc = NULL; - tstate->c_tracefunc = NULL; - tstate->c_profileobj = NULL; - tstate->c_traceobj = NULL; - - tstate->trash_delete_nesting = 0; - tstate->trash_delete_later = NULL; - tstate->on_delete = NULL; - tstate->on_delete_data = NULL; - - tstate->coroutine_origin_tracking_depth = 0; - - tstate->async_gen_firstiter = NULL; - tstate->async_gen_finalizer = NULL; - - tstate->context = NULL; tstate->context_ver = 1; + tstate->datastack_chunk = allocate_chunk(DATA_STACK_CHUNK_SIZE, NULL); if (tstate->datastack_chunk == NULL) { PyMem_RawFree(tstate); @@ -694,8 +661,6 @@ new_threadstate(PyInterpreterState *interp, int init) /* If top points to entry 0, then _PyThreadState_PopFrame will try to pop this chunk */ tstate->datastack_top = &tstate->datastack_chunk->data[1]; tstate->datastack_limit = (PyObject **)(((char *)tstate->datastack_chunk) + DATA_STACK_CHUNK_SIZE); - /* Mark trace_info as uninitialized */ - tstate->trace_info.code = NULL; if (init) { _PyThreadState_Init(tstate); @@ -703,7 +668,6 @@ new_threadstate(PyInterpreterState *interp, int init) HEAD_LOCK(runtime); tstate->id = ++interp->threads.next_unique_id; - tstate->prev = NULL; tstate->next = interp->threads.head; if (tstate->next) tstate->next->prev = tstate; From webhook-mailer at python.org Tue Dec 7 19:26:39 2021 From: webhook-mailer at python.org (ericsnowcurrently) Date: Wed, 08 Dec 2021 00:26:39 -0000 Subject: [Python-checkins] bpo-46008: Stop calling _PyThreadState_Init() in new_threadstate(). (gh-29973) Message-ID: https://github.com/python/cpython/commit/1f384e318481532323bb9076f4447bc02da07209 commit: 1f384e318481532323bb9076f4447bc02da07209 branch: main author: Eric Snow committer: ericsnowcurrently date: 2021-12-07T17:26:29-07:00 summary: bpo-46008: Stop calling _PyThreadState_Init() in new_threadstate(). (gh-29973) This simplifies new_threadstate(). We also rename _PyThreadState_Init() to _PyThreadState_SetCurrent() to reflect what it actually does. https://bugs.python.org/issue46008 files: M Include/internal/pycore_pystate.h M Modules/_threadmodule.c M Python/pystate.c diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h index 9a570b08bc583..f139fa96f5dd9 100644 --- a/Include/internal/pycore_pystate.h +++ b/Include/internal/pycore_pystate.h @@ -127,6 +127,8 @@ static inline PyInterpreterState* _PyInterpreterState_GET(void) { // PyThreadState functions +PyAPI_FUNC(void) _PyThreadState_SetCurrent(PyThreadState *tstate); +// We keep this around exclusively for stable ABI compatibility. PyAPI_FUNC(void) _PyThreadState_Init( PyThreadState *tstate); PyAPI_FUNC(void) _PyThreadState_DeleteExcept( diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index 2ba081d92b9af..cde2e0b6be7e4 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -6,7 +6,7 @@ #include "pycore_interp.h" // _PyInterpreterState.threads.count #include "pycore_moduleobject.h" // _PyModule_GetState() #include "pycore_pylifecycle.h" -#include "pycore_pystate.h" // _PyThreadState_Init() +#include "pycore_pystate.h" // _PyThreadState_SetCurrent() #include // offsetof() #include "structmember.h" // PyMemberDef @@ -1087,7 +1087,7 @@ thread_run(void *boot_raw) #else tstate->native_thread_id = 0; #endif - _PyThreadState_Init(tstate); + _PyThreadState_SetCurrent(tstate); PyEval_AcquireThread(tstate); tstate->interp->threads.count++; diff --git a/Python/pystate.c b/Python/pystate.c index 49acd560b386e..f94019d029441 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -631,7 +631,7 @@ allocate_chunk(int size_in_bytes, _PyStackChunk* previous) } static PyThreadState * -new_threadstate(PyInterpreterState *interp, int init) +new_threadstate(PyInterpreterState *interp) { _PyRuntimeState *runtime = interp->runtime; PyThreadState *tstate = (PyThreadState *)PyMem_RawCalloc(1, sizeof(PyThreadState)); @@ -662,10 +662,6 @@ new_threadstate(PyInterpreterState *interp, int init) tstate->datastack_top = &tstate->datastack_chunk->data[1]; tstate->datastack_limit = (PyObject **)(((char *)tstate->datastack_chunk) + DATA_STACK_CHUNK_SIZE); - if (init) { - _PyThreadState_Init(tstate); - } - HEAD_LOCK(runtime); tstate->id = ++interp->threads.next_unique_id; tstate->next = interp->threads.head; @@ -680,17 +676,27 @@ new_threadstate(PyInterpreterState *interp, int init) PyThreadState * PyThreadState_New(PyInterpreterState *interp) { - return new_threadstate(interp, 1); + PyThreadState *tstate = new_threadstate(interp); + _PyThreadState_SetCurrent(tstate); + return tstate; } PyThreadState * _PyThreadState_Prealloc(PyInterpreterState *interp) { - return new_threadstate(interp, 0); + return new_threadstate(interp); } +// We keep this around for (accidental) stable ABI compatibility. +// Realisically, no extensions are using it. void _PyThreadState_Init(PyThreadState *tstate) +{ + Py_FatalError("_PyThreadState_Init() is for internal use only"); +} + +void +_PyThreadState_SetCurrent(PyThreadState *tstate) { _PyGILState_NoteThreadState(&tstate->interp->runtime->gilstate, tstate); } From webhook-mailer at python.org Tue Dec 7 20:56:15 2021 From: webhook-mailer at python.org (ericsnowcurrently) Date: Wed, 08 Dec 2021 01:56:15 -0000 Subject: [Python-checkins] bpo-46008: Add _PyInterpreterState_Main(). (gh-29978) Message-ID: https://github.com/python/cpython/commit/758b74e71eb22e1e83a9eb937d1c015e461745a1 commit: 758b74e71eb22e1e83a9eb937d1c015e461745a1 branch: main author: Eric Snow committer: ericsnowcurrently date: 2021-12-07T18:56:06-07:00 summary: bpo-46008: Add _PyInterpreterState_Main(). (gh-29978) PyInterpreterState_Main() is a plain function exposed in the public C-API. For internal usage we can take the more efficient approach in this PR. https://bugs.python.org/issue46008 files: M Include/internal/pycore_pystate.h M Modules/posixmodule.c M Python/pylifecycle.c M Python/pystate.c diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h index f139fa96f5dd9..06f58fb5100f0 100644 --- a/Include/internal/pycore_pystate.h +++ b/Include/internal/pycore_pystate.h @@ -21,19 +21,23 @@ _Py_IsMainThread(void) } +static inline PyInterpreterState * +_PyInterpreterState_Main(void) +{ + return _PyRuntime.interpreters.main; +} + static inline int _Py_IsMainInterpreter(PyInterpreterState *interp) { - /* Use directly _PyRuntime rather than tstate->interp->runtime, since - this function is used in performance critical code path (ceval) */ - return (interp == _PyRuntime.interpreters.main); + return (interp == _PyInterpreterState_Main()); } static inline const PyConfig * _Py_GetMainConfig(void) { - PyInterpreterState *interp = _PyRuntime.interpreters.main; + PyInterpreterState *interp = _PyInterpreterState_Main(); if (interp == NULL) { return NULL; } @@ -45,7 +49,7 @@ _Py_GetMainConfig(void) static inline int _Py_ThreadCanHandleSignals(PyInterpreterState *interp) { - return (_Py_IsMainThread() && interp == _PyRuntime.interpreters.main); + return (_Py_IsMainThread() && _Py_IsMainInterpreter(interp)); } diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index b1c2914fb0f1f..2d95efebb1033 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -6696,7 +6696,7 @@ os_fork1_impl(PyObject *module) { pid_t pid; - if (_PyInterpreterState_GET() != PyInterpreterState_Main()) { + if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) { PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters"); return NULL; } @@ -7348,7 +7348,7 @@ os_forkpty_impl(PyObject *module) int master_fd = -1; pid_t pid; - if (_PyInterpreterState_GET() != PyInterpreterState_Main()) { + if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) { PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters"); return NULL; } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index f648ddab0388f..2b386a11f9f6e 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1953,7 +1953,7 @@ new_interpreter(PyThreadState **tstate_p, int isolated_subinterpreter) #endif { /* No current thread state, copy from the main interpreter */ - PyInterpreterState *main_interp = PyInterpreterState_Main(); + PyInterpreterState *main_interp = _PyInterpreterState_Main(); config = _PyInterpreterState_GetConfig(main_interp); } diff --git a/Python/pystate.c b/Python/pystate.c index f94019d029441..f21673e9c3ec6 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1204,7 +1204,7 @@ PyInterpreterState_Head(void) PyInterpreterState * PyInterpreterState_Main(void) { - return _PyRuntime.interpreters.main; + return _PyInterpreterState_Main(); } PyInterpreterState * From webhook-mailer at python.org Tue Dec 7 20:59:56 2021 From: webhook-mailer at python.org (ericsnowcurrently) Date: Wed, 08 Dec 2021 01:59:56 -0000 Subject: [Python-checkins] bpo-46008: Move Py*State init into distinct functions. (gh-29977) Message-ID: https://github.com/python/cpython/commit/32a67246b0d1e08cd50fc3bfa58052cfeb515b2e commit: 32a67246b0d1e08cd50fc3bfa58052cfeb515b2e branch: main author: Eric Snow committer: ericsnowcurrently date: 2021-12-07T18:59:49-07:00 summary: bpo-46008: Move Py*State init into distinct functions. (gh-29977) Previously, basic initialization of PyInterprterState happened in PyInterpreterState_New() (along with allocation and adding the new interpreter to the runtime state). This prevented us from initializing interpreter states that were allocated separately (e.g. statically or in a free list). We've addressed that here by factoring out a separate function just for initialization. We've done the same for PyThreadState. _PyRuntimeState was sorted out when we added it since _PyRuntime is statically allocated. However, here we update the existing init code to line up with the functions for PyInterpreterState and PyThreadState. https://bugs.python.org/issue46008 files: M Include/cpython/pystate.h M Include/internal/pycore_interp.h M Include/internal/pycore_runtime.h M Python/pystate.c diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index 5adbf3b495316..aa518281c80f5 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -77,6 +77,12 @@ struct _ts { struct _ts *next; PyInterpreterState *interp; + /* Has been initialized to a safe state. + + In order to be effective, this must be set to 0 during or right + after allocation. */ + int _initialized; + int recursion_remaining; int recursion_limit; int recursion_headroom; /* Allow 50 more calls to handle any errors. */ diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index 53938e3d7bc09..e421aa4bc4d7b 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -240,7 +240,6 @@ struct _is { struct _is *next; struct pythreads { - int _preallocated_used; uint64_t next_unique_id; struct _ts *head; /* Used in Modules/_threadmodule.c. */ @@ -262,6 +261,11 @@ struct _is { int requires_idref; PyThread_type_lock id_mutex; + /* Has been initialized to a safe state. + + In order to be effective, this must be set to 0 during or right + after allocation. */ + int _initialized; int finalizing; struct _ceval_state ceval; diff --git a/Include/internal/pycore_runtime.h b/Include/internal/pycore_runtime.h index 9df833c270193..39e30b785a3cd 100644 --- a/Include/internal/pycore_runtime.h +++ b/Include/internal/pycore_runtime.h @@ -67,6 +67,12 @@ struct _Py_unicode_runtime_ids { /* Full Python runtime state */ typedef struct pyruntimestate { + /* Has been initialized to a safe state. + + In order to be effective, this must be set to 0 during or right + after allocation. */ + int _initialized; + /* Is running Py_PreInitialize()? */ int preinitializing; @@ -136,9 +142,18 @@ typedef struct pyruntimestate { } _PyRuntimeState; #define _PyRuntimeState_INIT \ - {.preinitialized = 0, .core_initialized = 0, .initialized = 0} + { \ + ._initialized = 0, \ + } /* Note: _PyRuntimeState_INIT sets other fields to 0/NULL */ +static inline void +_PyRuntimeState_reset(_PyRuntimeState *runtime) +{ + /* Make it match _PyRuntimeState_INIT. */ + memset(runtime, 0, sizeof(*runtime)); +} + PyAPI_DATA(_PyRuntimeState) _PyRuntime; diff --git a/Python/pystate.c b/Python/pystate.c index f21673e9c3ec6..463b248f22336 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -46,20 +46,54 @@ static PyThreadState *_PyGILState_GetThisThreadState(struct _gilstate_runtime_st static void _PyThreadState_Delete(PyThreadState *tstate, int check_current); -static PyStatus -_PyRuntimeState_Init_impl(_PyRuntimeState *runtime) +static int +alloc_for_runtime(PyThread_type_lock *plock1, PyThread_type_lock *plock2, + PyThread_type_lock *plock3) { - /* We preserve the hook across init, because there is - currently no public API to set it between runtime - initialization and interpreter initialization. */ - void *open_code_hook = runtime->open_code_hook; - void *open_code_userdata = runtime->open_code_userdata; - _Py_AuditHookEntry *audit_hook_head = runtime->audit_hook_head; - // bpo-42882: Preserve next_index value if Py_Initialize()/Py_Finalize() - // is called multiple times. - Py_ssize_t unicode_next_index = runtime->unicode_ids.next_index; + /* Force default allocator, since _PyRuntimeState_Fini() must + use the same allocator than this function. */ + PyMemAllocatorEx old_alloc; + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - memset(runtime, 0, sizeof(*runtime)); + PyThread_type_lock lock1 = PyThread_allocate_lock(); + if (lock1 == NULL) { + return -1; + } + + PyThread_type_lock lock2 = PyThread_allocate_lock(); + if (lock2 == NULL) { + PyThread_free_lock(lock1); + return -1; + } + + PyThread_type_lock lock3 = PyThread_allocate_lock(); + if (lock3 == NULL) { + PyThread_free_lock(lock1); + PyThread_free_lock(lock2); + return -1; + } + + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + *plock1 = lock1; + *plock2 = lock2; + *plock3 = lock3; + return 0; +} + +static void +init_runtime(_PyRuntimeState *runtime, + void *open_code_hook, void *open_code_userdata, + _Py_AuditHookEntry *audit_hook_head, + Py_ssize_t unicode_next_index, + PyThread_type_lock unicode_ids_mutex, + PyThread_type_lock interpreters_mutex, + PyThread_type_lock xidregistry_mutex) +{ + if (runtime->_initialized) { + _PyRuntimeState_reset(runtime); + assert(!runtime->initialized); + } runtime->open_code_hook = open_code_hook; runtime->open_code_userdata = open_code_userdata; @@ -76,41 +110,44 @@ _PyRuntimeState_Init_impl(_PyRuntimeState *runtime) Py_tss_t initial = Py_tss_NEEDS_INIT; runtime->gilstate.autoTSSkey = initial; - runtime->interpreters.mutex = PyThread_allocate_lock(); - if (runtime->interpreters.mutex == NULL) { - return _PyStatus_NO_MEMORY(); - } + runtime->interpreters.mutex = interpreters_mutex; + // This prevents interpreters from getting created + // until _PyInterpreterState_Enable() is called. runtime->interpreters.next_id = -1; - runtime->xidregistry.mutex = PyThread_allocate_lock(); - if (runtime->xidregistry.mutex == NULL) { - return _PyStatus_NO_MEMORY(); - } + runtime->xidregistry.mutex = xidregistry_mutex; // Set it to the ID of the main thread of the main interpreter. runtime->main_thread = PyThread_get_thread_ident(); - runtime->unicode_ids.lock = PyThread_allocate_lock(); - if (runtime->unicode_ids.lock == NULL) { - return _PyStatus_NO_MEMORY(); - } runtime->unicode_ids.next_index = unicode_next_index; + runtime->unicode_ids.lock = unicode_ids_mutex; - return _PyStatus_OK(); + runtime->_initialized = 1; } PyStatus _PyRuntimeState_Init(_PyRuntimeState *runtime) { - /* Force default allocator, since _PyRuntimeState_Fini() must - use the same allocator than this function. */ - PyMemAllocatorEx old_alloc; - _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + /* We preserve the hook across init, because there is + currently no public API to set it between runtime + initialization and interpreter initialization. */ + void *open_code_hook = runtime->open_code_hook; + void *open_code_userdata = runtime->open_code_userdata; + _Py_AuditHookEntry *audit_hook_head = runtime->audit_hook_head; + // bpo-42882: Preserve next_index value if Py_Initialize()/Py_Finalize() + // is called multiple times. + Py_ssize_t unicode_next_index = runtime->unicode_ids.next_index; - PyStatus status = _PyRuntimeState_Init_impl(runtime); + PyThread_type_lock lock1, lock2, lock3; + if (alloc_for_runtime(&lock1, &lock2, &lock3) != 0) { + return _PyStatus_NO_MEMORY(); + } - PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - return status; + init_runtime(runtime, open_code_hook, open_code_userdata, audit_hook_head, + unicode_next_index, lock1, lock2, lock3); + + return _PyStatus_OK(); } void @@ -204,37 +241,51 @@ _PyInterpreterState_Enable(_PyRuntimeState *runtime) return _PyStatus_OK(); } -PyInterpreterState * -PyInterpreterState_New(void) +static PyInterpreterState * +alloc_interpreter(void) { - PyThreadState *tstate = _PyThreadState_GET(); - /* tstate is NULL when Py_InitializeFromConfig() calls - PyInterpreterState_New() to create the main interpreter. */ - if (_PySys_Audit(tstate, "cpython.PyInterpreterState_New", NULL) < 0) { - return NULL; - } + return PyMem_RawCalloc(1, sizeof(PyInterpreterState)); +} - PyInterpreterState *interp = PyMem_RawCalloc(1, sizeof(PyInterpreterState)); - if (interp == NULL) { - return NULL; - } +static void +free_interpreter(PyInterpreterState *interp) +{ + PyMem_RawFree(interp); +} - interp->id_refcount = -1; +/* Get the interpreter state to a minimal consistent state. + Further init happens in pylifecycle.c before it can be used. + All fields not initialized here are expected to be zeroed out, + e.g. by PyMem_RawCalloc() or memset(). + The runtime state is not manipulated. Instead it is assumed that + the interpreter is getting added to the runtime. + */ - /* Don't get runtime from tstate since tstate can be NULL */ - _PyRuntimeState *runtime = &_PyRuntime; +static void +init_interpreter(PyInterpreterState *interp, + _PyRuntimeState *runtime, int64_t id, + PyInterpreterState *next, + PyThread_type_lock pending_lock) +{ + if (interp->_initialized) { + Py_FatalError("interpreter already initialized"); + } + + assert(runtime != NULL); interp->runtime = runtime; - PyThread_type_lock pending_lock = PyThread_allocate_lock(); - if (pending_lock == NULL) { - goto out_of_memory; - } + assert(id > 0 || (id == 0 && interp == runtime->interpreters.main)); + interp->id = id; + interp->id_refcount = -1; + + assert(runtime->interpreters.head == interp); + assert(next != NULL || (interp == runtime->interpreters.main)); + interp->next = next; _PyEval_InitState(&interp->ceval, pending_lock); _PyGC_InitState(&interp->gc); PyConfig_InitPythonConfig(&interp->config); _PyType_InitCache(interp); - interp->eval_frame = NULL; #ifdef HAVE_DLOPEN #if HAVE_DECL_RTLD_NOW @@ -244,45 +295,90 @@ PyInterpreterState_New(void) #endif #endif + interp->_initialized = 1; +} + +PyInterpreterState * +PyInterpreterState_New(void) +{ + PyInterpreterState *interp; + PyThreadState *tstate = _PyThreadState_GET(); + + /* tstate is NULL when Py_InitializeFromConfig() calls + PyInterpreterState_New() to create the main interpreter. */ + if (_PySys_Audit(tstate, "cpython.PyInterpreterState_New", NULL) < 0) { + return NULL; + } + + PyThread_type_lock pending_lock = PyThread_allocate_lock(); + if (pending_lock == NULL) { + if (tstate != NULL) { + _PyErr_NoMemory(tstate); + } + return NULL; + } + + /* Don't get runtime from tstate since tstate can be NULL. */ + _PyRuntimeState *runtime = &_PyRuntime; struct pyinterpreters *interpreters = &runtime->interpreters; + /* We completely serialize creation of multiple interpreters, since + it simplifies things here and blocking concurrent calls isn't a problem. + Regardless, we must fully block subinterpreter creation until + after the main interpreter is created. */ HEAD_LOCK(runtime); - if (interpreters->next_id < 0) { - /* overflow or Py_Initialize() not called! */ - if (tstate != NULL) { - _PyErr_SetString(tstate, PyExc_RuntimeError, - "failed to get an interpreter ID"); + + int64_t id = interpreters->next_id; + interpreters->next_id += 1; + + // Allocate the interpreter and add it to the runtime state. + PyInterpreterState *old_head = interpreters->head; + if (old_head == NULL) { + // We are creating the main interpreter. + assert(interpreters->main == NULL); + assert(id == 0); + + interp = alloc_interpreter(); + if (interp == NULL) { + goto error; } - PyMem_RawFree(interp); - interp = NULL; + assert(interp->id == 0); + assert(interp->next == NULL); + + interpreters->main = interp; } else { - interp->id = interpreters->next_id; - interpreters->next_id += 1; - interp->next = interpreters->head; - if (interpreters->main == NULL) { - interpreters->main = interp; + assert(id != 0); + assert(interpreters->main != NULL); + + interp = alloc_interpreter(); + if (interp == NULL) { + goto error; } - interpreters->head = interp; - } - HEAD_UNLOCK(runtime); - if (interp == NULL) { - return NULL; + if (id < 0) { + /* overflow or Py_Initialize() not called yet! */ + if (tstate != NULL) { + _PyErr_SetString(tstate, PyExc_RuntimeError, + "failed to get an interpreter ID"); + } + goto error; + } } + interpreters->head = interp; - interp->threads.next_unique_id = 0; - - interp->audit_hooks = NULL; + init_interpreter(interp, runtime, id, old_head, pending_lock); + HEAD_UNLOCK(runtime); return interp; -out_of_memory: - if (tstate != NULL) { - _PyErr_NoMemory(tstate); - } +error: + HEAD_UNLOCK(runtime); - PyMem_RawFree(interp); + PyThread_free_lock(pending_lock); + if (interp != NULL) { + free_interpreter(interp); + } return NULL; } @@ -415,7 +511,7 @@ PyInterpreterState_Delete(PyInterpreterState *interp) if (interp->id_mutex != NULL) { PyThread_free_lock(interp->id_mutex); } - PyMem_RawFree(interp); + free_interpreter(interp); } @@ -453,7 +549,7 @@ _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime) } PyInterpreterState *prev_interp = interp; interp = interp->next; - PyMem_RawFree(prev_interp); + free_interpreter(prev_interp); } HEAD_UNLOCK(runtime); @@ -631,46 +727,121 @@ allocate_chunk(int size_in_bytes, _PyStackChunk* previous) } static PyThreadState * -new_threadstate(PyInterpreterState *interp) +alloc_threadstate(void) { - _PyRuntimeState *runtime = interp->runtime; - PyThreadState *tstate = (PyThreadState *)PyMem_RawCalloc(1, sizeof(PyThreadState)); - if (tstate == NULL) { - return NULL; + return PyMem_RawCalloc(1, sizeof(PyThreadState)); +} + +static void +free_threadstate(PyThreadState *tstate) +{ + PyMem_RawFree(tstate); +} + +/* Get the thread state to a minimal consistent state. + Further init happens in pylifecycle.c before it can be used. + All fields not initialized here are expected to be zeroed out, + e.g. by PyMem_RawCalloc() or memset(). + The interpreter state is not manipulated. Instead it is assumed that + the thread is getting added to the interpreter. + */ + +static void +init_threadstate(PyThreadState *tstate, + PyInterpreterState *interp, uint64_t id, + PyThreadState *next, + _PyStackChunk *datastack_chunk) +{ + if (tstate->_initialized) { + Py_FatalError("thread state already initialized"); } + assert(interp != NULL); tstate->interp = interp; - tstate->recursion_limit = interp->ceval.recursion_limit; - tstate->recursion_remaining = interp->ceval.recursion_limit; - tstate->cframe = &tstate->root_cframe; + assert(id > 0); + tstate->id = id; + + assert(interp->threads.head == tstate); + assert((next != NULL && id != 1) || (next == NULL && id == 1)); + if (next != NULL) { + assert(next->prev == NULL || next->prev == tstate); + next->prev = tstate; + } + tstate->next = next; + tstate->prev = NULL; + tstate->thread_id = PyThread_get_thread_ident(); #ifdef PY_HAVE_THREAD_NATIVE_ID tstate->native_thread_id = PyThread_get_thread_native_id(); #endif - tstate->exc_info = &tstate->exc_state; - tstate->context_ver = 1; - tstate->datastack_chunk = allocate_chunk(DATA_STACK_CHUNK_SIZE, NULL); - if (tstate->datastack_chunk == NULL) { - PyMem_RawFree(tstate); - return NULL; - } + tstate->recursion_limit = interp->ceval.recursion_limit, + tstate->recursion_remaining = interp->ceval.recursion_limit, + + tstate->exc_info = &tstate->exc_state; + + tstate->cframe = &tstate->root_cframe; + assert(datastack_chunk != NULL); + tstate->datastack_chunk = datastack_chunk; /* If top points to entry 0, then _PyThreadState_PopFrame will try to pop this chunk */ tstate->datastack_top = &tstate->datastack_chunk->data[1]; tstate->datastack_limit = (PyObject **)(((char *)tstate->datastack_chunk) + DATA_STACK_CHUNK_SIZE); + tstate->_initialized = 1; +} + +static PyThreadState * +new_threadstate(PyInterpreterState *interp) +{ + PyThreadState *tstate; + _PyRuntimeState *runtime = interp->runtime; + + _PyStackChunk *datastack_chunk = allocate_chunk(DATA_STACK_CHUNK_SIZE, NULL); + if (datastack_chunk == NULL) { + return NULL; + } + + /* We serialize concurrent creation to protect global state. */ HEAD_LOCK(runtime); - tstate->id = ++interp->threads.next_unique_id; - tstate->next = interp->threads.head; - if (tstate->next) - tstate->next->prev = tstate; + + interp->threads.next_unique_id += 1; + uint64_t id = interp->threads.next_unique_id; + + // Allocate the thread state and add it to the interpreter. + PyThreadState *old_head = interp->threads.head; + if (old_head == NULL) { + // It's the interpreter's initial thread state. + assert(id == 1); + + tstate = alloc_threadstate(); + if (tstate == NULL) { + goto error; + } + } + else { + // Every valid interpreter must have at least one thread. + assert(id > 1); + assert(old_head->prev == NULL); + + tstate = alloc_threadstate(); + if (tstate == NULL) { + goto error; + } + } interp->threads.head = tstate; - HEAD_UNLOCK(runtime); + init_threadstate(tstate, interp, id, old_head, datastack_chunk); + + HEAD_UNLOCK(runtime); return tstate; + +error: + HEAD_UNLOCK(runtime); + _PyObject_VirtualFree(datastack_chunk, datastack_chunk->size); + return NULL; } PyThreadState * @@ -931,7 +1102,7 @@ _PyThreadState_Delete(PyThreadState *tstate, int check_current) } } tstate_delete_common(tstate, gilstate); - PyMem_RawFree(tstate); + free_threadstate(tstate); } @@ -950,7 +1121,7 @@ _PyThreadState_DeleteCurrent(PyThreadState *tstate) tstate_delete_common(tstate, gilstate); _PyRuntimeGILState_SetThreadState(gilstate, NULL); _PyEval_ReleaseLock(tstate); - PyMem_RawFree(tstate); + free_threadstate(tstate); } void From webhook-mailer at python.org Tue Dec 7 21:18:31 2021 From: webhook-mailer at python.org (zooba) Date: Wed, 08 Dec 2021 02:18:31 -0000 Subject: [Python-checkins] bpo-45582: Write empty pybuilddir.txt on Windows to allow relocatable build directories (GH-29979) Message-ID: https://github.com/python/cpython/commit/b0b30862796e97b3f0ee358bcc61d21f0cc98441 commit: b0b30862796e97b3f0ee358bcc61d21f0cc98441 branch: main author: Steve Dower committer: zooba date: 2021-12-08T02:18:21Z summary: bpo-45582: Write empty pybuilddir.txt on Windows to allow relocatable build directories (GH-29979) files: M Modules/getpath.py M PCbuild/pyproject.props M PCbuild/python.vcxproj diff --git a/Modules/getpath.py b/Modules/getpath.py index 4ef49a8847dd2..6a13e232ec3e8 100644 --- a/Modules/getpath.py +++ b/Modules/getpath.py @@ -449,6 +449,10 @@ def search_up(prefix, *landmarks, test=isfile): readlines(joinpath(real_executable_dir, BUILDDIR_TXT))[0], ) build_prefix = joinpath(real_executable_dir, VPATH) + except IndexError: + # File exists but is empty + platstdlib_dir = real_executable_dir + build_prefix = joinpath(real_executable_dir, VPATH) except FileNotFoundError: if isfile(joinpath(real_executable_dir, BUILD_LANDMARK)): build_prefix = joinpath(real_executable_dir, VPATH) diff --git a/PCbuild/pyproject.props b/PCbuild/pyproject.props index 0eaeb6b1229a2..bbcabb5cdb405 100644 --- a/PCbuild/pyproject.props +++ b/PCbuild/pyproject.props @@ -73,7 +73,7 @@ PGInstrument PGUpdate advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;%(AdditionalDependencies) - /OPT:REF,NOICF /CGTHREADS:1 /PDBTHREADS:1 %(AdditionalOptions) + /OPT:REF,NOICF %(AdditionalOptions) true diff --git a/PCbuild/python.vcxproj b/PCbuild/python.vcxproj index 0b4329dd07636..f44513702879e 100644 --- a/PCbuild/python.vcxproj +++ b/PCbuild/python.vcxproj @@ -148,10 +148,6 @@ $(_PGOPath) - - <_Content>$(OutDir) - <_ExistingContent Condition="Exists('$(OutDir)pybuilddir.txt')">$([System.IO.File]::ReadAllText('$(OutDir)pybuilddir.txt')) - - + From webhook-mailer at python.org Tue Dec 7 22:38:39 2021 From: webhook-mailer at python.org (rhettinger) Date: Wed, 08 Dec 2021 03:38:39 -0000 Subject: [Python-checkins] bpo-20751: Match variable name to the example. (GH-29980) Message-ID: https://github.com/python/cpython/commit/4ccccb1cfc1f30327e76a2d845cc274be56b34b1 commit: 4ccccb1cfc1f30327e76a2d845cc274be56b34b1 branch: main author: Raymond Hettinger committer: rhettinger date: 2021-12-07T21:38:21-06:00 summary: bpo-20751: Match variable name to the example. (GH-29980) files: M Doc/reference/datamodel.rst diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 597c8ec9f176b..81dad77fab97a 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1823,7 +1823,7 @@ Class Binding Super Binding A dotted lookup such as ``super(A, a).x`` searches - ``obj.__class__.__mro__`` for a base class ``B`` following ``A`` and then + ``a.__class__.__mro__`` for a base class ``B`` following ``A`` and then returns ``B.__dict__['x'].__get__(a, A)``. If not a descriptor, ``x`` is returned unchanged. @@ -1843,15 +1843,19 @@ Super Binding x = 999 def m(self): - 'Demonstrate these two calls are equivalent' - result1 = super(A, a).x - result2 = B.__dict__['x'].__get__(a, A) + 'Demonstrate these two descriptor invocations are equivalent' + result1 = super(A, self).x + result2 = B.__dict__['x'].__get__(self, A) return result1 == result2 .. doctest:: :hide: >>> a = A() + >>> a.__class__.__mro__.index(B) > a.__class__.__mro__.index(A) + True + >>> super(A, a).x == B.__dict__['x'].__get__(a, A) + True >>> a.m() True From webhook-mailer at python.org Wed Dec 8 04:41:46 2021 From: webhook-mailer at python.org (iritkatriel) Date: Wed, 08 Dec 2021 09:41:46 -0000 Subject: [Python-checkins] bpo-40222: update doc entry with respect to the change in WITH_EXCEPT_START (GH-29975) Message-ID: https://github.com/python/cpython/commit/7989e9dff68fd681657aa9f93ac6e8fa12c534e4 commit: 7989e9dff68fd681657aa9f93ac6e8fa12c534e4 branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-12-08T09:41:28Z summary: bpo-40222: update doc entry with respect to the change in WITH_EXCEPT_START (GH-29975) files: M Doc/library/dis.rst diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 6fe64be9f0fb3..62d2150e304fa 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -584,12 +584,14 @@ iterations of the loop. .. opcode:: WITH_EXCEPT_START - Calls the function in position 7 on the stack with the top three + Calls the function in position 8 on the stack with the top three items on the stack as arguments. Used to implement the call ``context_manager.__exit__(*exc_info())`` when an exception has occurred in a :keyword:`with` statement. .. versionadded:: 3.9 + .. versionchanged:: 3.11 + The ``__exit__`` function is in position 8 of the stack rather than 7. .. opcode:: POP_EXCEPT_AND_RERAISE From webhook-mailer at python.org Wed Dec 8 05:42:14 2021 From: webhook-mailer at python.org (asvetlov) Date: Wed, 08 Dec 2021 10:42:14 -0000 Subject: [Python-checkins] Fix double-space in exception message (GH-29955) Message-ID: https://github.com/python/cpython/commit/c602c1be439e295fed9ebab47e895ef1d9df28be commit: c602c1be439e295fed9ebab47e895ef1d9df28be branch: main author: Ned Batchelder committer: asvetlov date: 2021-12-08T12:42:02+02:00 summary: Fix double-space in exception message (GH-29955) files: M Lib/statistics.py diff --git a/Lib/statistics.py b/Lib/statistics.py index ff19ce9672d33..c104571d39053 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -463,7 +463,7 @@ def geometric_mean(data): return exp(fmean(map(log, data))) except ValueError: raise StatisticsError('geometric mean requires a non-empty dataset ' - ' containing positive numbers') from None + 'containing positive numbers') from None def harmonic_mean(data, weights=None): From webhook-mailer at python.org Wed Dec 8 05:52:30 2021 From: webhook-mailer at python.org (tiran) Date: Wed, 08 Dec 2021 10:52:30 -0000 Subject: [Python-checkins] bpo-45847: Don't override user overrides for CFLAGS/LIBS (GH-29967) Message-ID: https://github.com/python/cpython/commit/0461c68cdff1392a5299ebd8c37ddce0b60dd6cc commit: 0461c68cdff1392a5299ebd8c37ddce0b60dd6cc branch: main author: Christian Heimes committer: tiran date: 2021-12-08T11:52:08+01:00 summary: bpo-45847: Don't override user overrides for CFLAGS/LIBS (GH-29967) files: M configure M configure.ac M setup.py diff --git a/configure b/configure index 8ba76bf8c63f7..444dd675a2dda 100755 --- a/configure +++ b/configure @@ -10538,8 +10538,8 @@ if eval test \"x\$"$as_ac_var"\" = x"yes"; then : _ACEOF have_uuid=yes - LIBUUID_CFLAGS= - LIBUUID_LIBS= + LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""} + LIBUUID_LIBS=${LIBUUID_LIBS-""} fi done @@ -10612,8 +10612,6 @@ fi echo "$LIBUUID_PKG_ERRORS" >&5 - LIBUUID_LIBS="-luuid" - LIBUUID_CFLAGS= for ac_header in uuid/uuid.h do : ac_fn_c_check_header_mongrel "$LINENO" "uuid/uuid.h" "ac_cv_header_uuid_uuid_h" "$ac_includes_default" @@ -10731,6 +10729,12 @@ LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS + if test "x$have_uuid" = xyes; then : + + LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""} + LIBUUID_LIBS=${LIBUUID_LIBS-"-luuid"} + +fi fi @@ -10742,8 +10746,6 @@ elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - LIBUUID_LIBS="-luuid" - LIBUUID_CFLAGS= for ac_header in uuid/uuid.h do : ac_fn_c_check_header_mongrel "$LINENO" "uuid/uuid.h" "ac_cv_header_uuid_uuid_h" "$ac_includes_default" @@ -10861,6 +10863,12 @@ LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS + if test "x$have_uuid" = xyes; then : + + LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""} + LIBUUID_LIBS=${LIBUUID_LIBS-"-luuid"} + +fi fi @@ -10898,8 +10906,8 @@ _ACEOF if test "x$ac_cv_func_uuid_generate_time" = xyes; then : have_uuid=yes - LIBUUID_CFLAGS= - LIBUUID_LIBS= + LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""} + LIBUUID_LIBS=${LIBUUID_LIBS-""} fi @@ -11350,8 +11358,8 @@ $as_echo "$with_system_expat" >&6; } if test "x$with_system_expat" = xyes; then : - LIBEXPAT_CFLAGS="" - LIBEXPAT_LDFLAGS="-lexpat" + LIBEXPAT_CFLAGS=${LIBEXPAT_CFLAGS-""} + LIBEXPAT_LDFLAGS=${LIBEXPAT_LDFLAGS-"-lexpat"} LIBEXPAT_INTERNAL= else @@ -11424,8 +11432,8 @@ $as_echo "$with_system_libmpdec" >&6; } if test "x$with_system_libmpdec" = xyes; then : - LIBMPDEC_CFLAGS="" - LIBMPDEC_LDFLAGS="-lmpdec" + LIBMPDEC_CFLAGS=${LIBMPDEC_CFLAGS-""} + LIBMPDEC_LDFLAGS=${LIBMPDEC_LDFLAGS-"-lmpdec"} LIBMPDEC_INTERNAL= else @@ -11600,7 +11608,7 @@ fi echo "$LIBNSL_PKG_ERRORS" >&5 - LIBNSL_CFLAGS= + LIBNSL_CFLAGS=${LIBNSL_CFLAGS-""} save_CFLAGS=$CFLAGS save_CPPFLAGS=$CPPFLAGS save_LDFLAGS=$LDFLAGS @@ -11674,19 +11682,20 @@ LIBS=$save_LIBS case $ac_cv_search_yp_match in #( no) : - LIBNSL_LIBS= ;; #( + libnsl="" ;; #( "none required") : - LIBNSL_LIBS= ;; #( + libnsl="" ;; #( *) : - LIBNSL_LIBS=$ac_cv_search_yp_match + libnsl="$ac_cv_search_yp_match" ;; esac + LIBNSL_LIBS=${LIBNSL_LIBS-$libnsl} elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - LIBNSL_CFLAGS= + LIBNSL_CFLAGS=${LIBNSL_CFLAGS-""} save_CFLAGS=$CFLAGS save_CPPFLAGS=$CPPFLAGS save_LDFLAGS=$LDFLAGS @@ -11760,13 +11769,14 @@ LIBS=$save_LIBS case $ac_cv_search_yp_match in #( no) : - LIBNSL_LIBS= ;; #( + libnsl="" ;; #( "none required") : - LIBNSL_LIBS= ;; #( + libnsl="" ;; #( *) : - LIBNSL_LIBS=$ac_cv_search_yp_match + libnsl="$ac_cv_search_yp_match" ;; esac + LIBNSL_LIBS=${LIBNSL_LIBS-$libnsl} else LIBNSL_CFLAGS=$pkg_cv_LIBNSL_CFLAGS @@ -11867,16 +11877,16 @@ fi echo "$LIBSQLITE3_PKG_ERRORS" >&5 - LIBSQLITE3_LIBS="-lsqlite3" - LIBSQLITE3_CFLAGS= + LIBSQLITE3_CFLAGS=${LIBSQLITE3_CFLAGS-""} + LIBSQLITE3_LIBS=${LIBSQLITE3_LIBS-"-lsqlite3"} elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - LIBSQLITE3_LIBS="-lsqlite3" - LIBSQLITE3_CFLAGS= + LIBSQLITE3_CFLAGS=${LIBSQLITE3_CFLAGS-""} + LIBSQLITE3_LIBS=${LIBSQLITE3_LIBS-"-lsqlite3"} else @@ -12147,7 +12157,7 @@ $as_echo "$ac_cv_lib_gdbm_gdbm_open" >&6; } if test "x$ac_cv_lib_gdbm_gdbm_open" = xyes; then : have_gdbm=yes - GDBM_LIBS="$GDBM_LIBS -lgdbm" + GDBM_LIBS=${GDBM_LIBS-"-lgdbm"} else have_gdbm=no @@ -14619,8 +14629,8 @@ $as_echo "$ac_cv_lib_z_gzread" >&6; } if test "x$ac_cv_lib_z_gzread" = xyes; then : have_zlib=yes - ZLIB_CFLAGS= - ZLIB_LIBS=-lz + ZLIB_CFLAGS=${ZLIB_CFLAGS-""} + ZLIB_LIBS=${ZLIB_LIBS-"-lz"} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inflateCopy in -lz" >&5 $as_echo_n "checking for inflateCopy in -lz... " >&6; } if ${ac_cv_lib_z_inflateCopy+:} false; then : @@ -14741,8 +14751,8 @@ $as_echo "$ac_cv_lib_z_gzread" >&6; } if test "x$ac_cv_lib_z_gzread" = xyes; then : have_zlib=yes - ZLIB_CFLAGS= - ZLIB_LIBS=-lz + ZLIB_CFLAGS=${ZLIB_CFLAGS-""} + ZLIB_LIBS=${ZLIB_LIBS-"-lz"} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inflateCopy in -lz" >&5 $as_echo_n "checking for inflateCopy in -lz... " >&6; } if ${ac_cv_lib_z_inflateCopy+:} false; then : @@ -14938,8 +14948,8 @@ $as_echo "$ac_cv_lib_bz2_BZ2_bzCompress" >&6; } if test "x$ac_cv_lib_bz2_BZ2_bzCompress" = xyes; then : have_bzip2=yes - BZIP2_CFLAGS= - BZIP2_LIBS=-lbz2 + BZIP2_CFLAGS=${BZIP2_CFLAGS-""} + BZIP2_LIBS=${BZIP2_LIBS-"-lbz2"} else have_bzip2=no @@ -15017,8 +15027,8 @@ $as_echo "$ac_cv_lib_bz2_BZ2_bzCompress" >&6; } if test "x$ac_cv_lib_bz2_BZ2_bzCompress" = xyes; then : have_bzip2=yes - BZIP2_CFLAGS= - BZIP2_LIBS=-lbz2 + BZIP2_CFLAGS=${BZIP2_CFLAGS-""} + BZIP2_LIBS=${BZIP2_LIBS-"-lbz2"} else have_bzip2=no @@ -15160,8 +15170,8 @@ $as_echo "$ac_cv_lib_lzma_lzma_easy_encoder" >&6; } if test "x$ac_cv_lib_lzma_lzma_easy_encoder" = xyes; then : have_liblzma=yes - LIBLZMA_CFLAGS= - LIBLZMA_LIBS=-llzma + LIBLZMA_CFLAGS=${LIBLZMA_CFLAGS-""} + LIBLZMA_LIBS=${LIBLZMA_LIBS-"-llzma"} else have_liblzma=no @@ -15239,8 +15249,8 @@ $as_echo "$ac_cv_lib_lzma_lzma_easy_encoder" >&6; } if test "x$ac_cv_lib_lzma_lzma_easy_encoder" = xyes; then : have_liblzma=yes - LIBLZMA_CFLAGS= - LIBLZMA_LIBS=-llzma + LIBLZMA_CFLAGS=${LIBLZMA_CFLAGS-""} + LIBLZMA_LIBS=${LIBLZMA_LIBS-"-llzma"} else have_liblzma=no @@ -15840,10 +15850,11 @@ if test "$ac_res" != no; then : $as_echo "#define HAVE_CRYPT_R 1" >>confdefs.h if test "$ac_cv_search_crypt_r" = "none required"; then - LIBCRYPT_LIBS= + libcrypt= else - LIBCRYPT_LIBS="$ac_cv_search_crypt_r" + libcrypt="$ac_cv_search_crypt_r" fi + LIBCRYPT_LIBS=${LIBCRYPT_LIBS-$libcrypt} fi @@ -15922,10 +15933,11 @@ if test "$ac_res" != no; then : $as_echo "#define HAVE_CRYPT_R 1" >>confdefs.h if test "$ac_cv_search_crypt_r" = "none required"; then - LIBCRYPT_LIBS= + libcrypt= else - LIBCRYPT_LIBS="$ac_cv_search_crypt_r" + libcrypt="$ac_cv_search_crypt_r" fi + LIBCRYPT_LIBS=${LIBCRYPT_LIBS-$libcrypt} fi diff --git a/configure.ac b/configure.ac index 0905014d25b66..31544dde03fb0 100644 --- a/configure.ac +++ b/configure.ac @@ -2947,8 +2947,8 @@ dnl stream in big-endian byte-order AC_CHECK_HEADERS([uuid.h], [ AC_CHECK_FUNCS([uuid_create uuid_enc_be], [ have_uuid=yes - LIBUUID_CFLAGS= - LIBUUID_LIBS= + LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""} + LIBUUID_LIBS=${LIBUUID_LIBS-""} ]) ]) @@ -2961,8 +2961,6 @@ AS_VAR_IF([have_uuid], [missing], [ AC_DEFINE([HAVE_UUID_H], [1]) AC_DEFINE([HAVE_UUID_GENERATE_TIME_SAFE], [1]) ], [ - LIBUUID_LIBS="-luuid" - LIBUUID_CFLAGS= AC_CHECK_HEADERS([uuid/uuid.h], [ WITH_SAVE_ENV( [AC_CHECK_LIB([uuid], [uuid_generate_time], [have_uuid=yes]) @@ -2973,6 +2971,10 @@ AS_VAR_IF([have_uuid], [missing], [ AC_DEFINE([HAVE_UUID_GENERATE_TIME_SAFE], [1]) ]) ]) + AS_VAR_IF([have_uuid], [yes], [ + LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""} + LIBUUID_LIBS=${LIBUUID_LIBS-"-luuid"} + ]) ]) ] ) @@ -2983,8 +2985,8 @@ AS_VAR_IF([have_uuid], [missing], [ AC_CHECK_HEADERS([uuid/uuid.h], [ AC_CHECK_FUNC([uuid_generate_time], [ have_uuid=yes - LIBUUID_CFLAGS= - LIBUUID_LIBS= + LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""} + LIBUUID_LIBS=${LIBUUID_LIBS-""} ]) ]) ]) @@ -3147,8 +3149,8 @@ AC_ARG_WITH(system_expat, AC_MSG_RESULT($with_system_expat) AS_VAR_IF([with_system_expat], [yes], [ - LIBEXPAT_CFLAGS="" - LIBEXPAT_LDFLAGS="-lexpat" + LIBEXPAT_CFLAGS=${LIBEXPAT_CFLAGS-""} + LIBEXPAT_LDFLAGS=${LIBEXPAT_LDFLAGS-"-lexpat"} LIBEXPAT_INTERNAL= ], [ LIBEXPAT_CFLAGS="-I\$(srcdir)/Modules/expat" @@ -3203,8 +3205,8 @@ AC_ARG_WITH(system_libmpdec, AC_MSG_RESULT($with_system_libmpdec) AS_VAR_IF([with_system_libmpdec], [yes], [ - LIBMPDEC_CFLAGS="" - LIBMPDEC_LDFLAGS="-lmpdec" + LIBMPDEC_CFLAGS=${LIBMPDEC_CFLAGS-""} + LIBMPDEC_LDFLAGS=${LIBMPDEC_LDFLAGS-"-lmpdec"} LIBMPDEC_INTERNAL= ], [ LIBMPDEC_CFLAGS="-I\$(srcdir)/Modules/_decimal/libmpdec" @@ -3293,15 +3295,16 @@ fi dnl check for NIS / libnsl dependencies dnl libnsl dependencies include tirpc includes and lib PKG_CHECK_MODULES([LIBNSL], [libnsl], [have_nis=yes], [ - LIBNSL_CFLAGS= + LIBNSL_CFLAGS=${LIBNSL_CFLAGS-""} WITH_SAVE_ENV([ AC_SEARCH_LIBS([yp_match], [nsl], [have_nis=yes], [have_nis=no]) ]) AS_CASE([$ac_cv_search_yp_match], - [no], [LIBNSL_LIBS=], - ["none required"], [LIBNSL_LIBS=], - [LIBNSL_LIBS=$ac_cv_search_yp_match] + [no], [libnsl=""], + ["none required"], [libnsl=""], + [libnsl="$ac_cv_search_yp_match"] ) + LIBNSL_LIBS=${LIBNSL_LIBS-$libnsl} ]) AS_VAR_IF([have_nis], [yes], [ @@ -3314,8 +3317,8 @@ AS_VAR_IF([have_nis], [yes], [ dnl Check for SQLite library. Use pkg-config if available. PKG_CHECK_MODULES( [LIBSQLITE3], [sqlite3 >= 3.7.15], [], [ - LIBSQLITE3_LIBS="-lsqlite3" - LIBSQLITE3_CFLAGS= + LIBSQLITE3_CFLAGS=${LIBSQLITE3_CFLAGS-""} + LIBSQLITE3_LIBS=${LIBSQLITE3_LIBS-"-lsqlite3"} ] ) AS_VAR_APPEND([LIBSQLITE3_CFLAGS], [' -I$(srcdir)/Modules/_sqlite']) @@ -3402,7 +3405,7 @@ WITH_SAVE_ENV([ AC_CHECK_HEADERS([gdbm.h], [ AC_CHECK_LIB([gdbm], [gdbm_open], [ have_gdbm=yes - GDBM_LIBS="$GDBM_LIBS -lgdbm" + GDBM_LIBS=${GDBM_LIBS-"-lgdbm"} ], [have_gdbm=no]) ], [have_gdbm=no]) ]) @@ -4196,8 +4199,8 @@ PKG_CHECK_MODULES([ZLIB], [zlib >= 1.2.0], [ WITH_SAVE_ENV([ AC_CHECK_LIB([z], [gzread], [ have_zlib=yes - ZLIB_CFLAGS= - ZLIB_LIBS=-lz + ZLIB_CFLAGS=${ZLIB_CFLAGS-""} + ZLIB_LIBS=${ZLIB_LIBS-"-lz"} AC_CHECK_LIB([z], [inflateCopy], [AC_DEFINE([HAVE_ZLIB_COPY], [1])]) ], [ have_zlib=no @@ -4217,8 +4220,8 @@ PKG_CHECK_MODULES([BZIP2], [bzip2], [have_bzip2=yes], [ WITH_SAVE_ENV([ AC_CHECK_LIB([bz2], [BZ2_bzCompress], [ have_bzip2=yes - BZIP2_CFLAGS= - BZIP2_LIBS=-lbz2 + BZIP2_CFLAGS=${BZIP2_CFLAGS-""} + BZIP2_LIBS=${BZIP2_LIBS-"-lbz2"} ], [have_bzip2=no]) ]) ], [have_bzip2=no]) @@ -4229,8 +4232,8 @@ PKG_CHECK_MODULES([LIBLZMA], [liblzma], [have_liblzma=yes], [ WITH_SAVE_ENV([ AC_CHECK_LIB([lzma], [lzma_easy_encoder], [ have_liblzma=yes - LIBLZMA_CFLAGS= - LIBLZMA_LIBS=-llzma + LIBLZMA_CFLAGS=${LIBLZMA_CFLAGS-""} + LIBLZMA_LIBS=${LIBLZMA_LIBS-"-llzma"} ], [have_liblzma=no]) ]) ], [have_liblzma=no]) @@ -4303,10 +4306,11 @@ PKG_CHECK_MODULES([LIBCRYPT], [libxcrypt >= 3.1.1], [ AC_SEARCH_LIBS([crypt_r], [crypt], [ AC_DEFINE([HAVE_CRYPT_R], [1]) if test "$ac_cv_search_crypt_r" = "none required"; then - LIBCRYPT_LIBS= + libcrypt= else - LIBCRYPT_LIBS="$ac_cv_search_crypt_r" + libcrypt="$ac_cv_search_crypt_r" fi + LIBCRYPT_LIBS=${LIBCRYPT_LIBS-$libcrypt} ]) ]) ]) diff --git a/setup.py b/setup.py index 572f2ac1783b8..e30674f31cdb8 100644 --- a/setup.py +++ b/setup.py @@ -665,7 +665,9 @@ def print_three_column(lst): print("Custom linker flags may require --with-openssl-rpath=auto") print() - if os.environ.get("PYTHONSTRICTEXTENSIONBUILD") and (self.failed or self.failed_on_import): + if os.environ.get("PYTHONSTRICTEXTENSIONBUILD") and ( + self.failed or self.failed_on_import or self.missing + ): raise RuntimeError("Failed to build some stdlib modules") def build_extension(self, ext): From webhook-mailer at python.org Wed Dec 8 05:55:45 2021 From: webhook-mailer at python.org (asvetlov) Date: Wed, 08 Dec 2021 10:55:45 -0000 Subject: [Python-checkins] doc: Add link issue 44010 (GH-29454) Message-ID: https://github.com/python/cpython/commit/3e0f13b9e48eec8c54a185e4180bfca4e5e685f6 commit: 3e0f13b9e48eec8c54a185e4180bfca4e5e685f6 branch: main author: Rafael Fontenelle committer: asvetlov date: 2021-12-08T12:55:39+02:00 summary: doc: Add link issue 44010 (GH-29454) files: M Doc/whatsnew/3.10.rst diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index a30fd2d0c0c05..118563965091f 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -1173,7 +1173,7 @@ Highlight the new :ref:`soft keywords ` :keyword:`match`, :keyword:`case `, and :keyword:`_ ` in pattern-matching statements. However, this highlighting is not perfect and will be incorrect in some rare cases, including some ``_``-s in -``case`` patterns. (Contributed by Tal Einat in bpo-44010.) +``case`` patterns. (Contributed by Tal Einat in :issue:`44010`.) importlib.metadata ------------------ From webhook-mailer at python.org Wed Dec 8 06:07:32 2021 From: webhook-mailer at python.org (miss-islington) Date: Wed, 08 Dec 2021 11:07:32 -0000 Subject: [Python-checkins] Fix double-space in exception message (GH-29955) Message-ID: https://github.com/python/cpython/commit/fbdbbdb67bb9378be56c17f8c204a9bb85791ebf commit: fbdbbdb67bb9378be56c17f8c204a9bb85791ebf branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-08T03:07:27-08:00 summary: Fix double-space in exception message (GH-29955) (cherry picked from commit c602c1be439e295fed9ebab47e895ef1d9df28be) Co-authored-by: Ned Batchelder files: M Lib/statistics.py diff --git a/Lib/statistics.py b/Lib/statistics.py index cfcc456fd786e..f66245380abb1 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -374,7 +374,7 @@ def geometric_mean(data): return exp(fmean(map(log, data))) except ValueError: raise StatisticsError('geometric mean requires a non-empty dataset ' - ' containing positive numbers') from None + 'containing positive numbers') from None def harmonic_mean(data, weights=None): From webhook-mailer at python.org Wed Dec 8 06:18:39 2021 From: webhook-mailer at python.org (miss-islington) Date: Wed, 08 Dec 2021 11:18:39 -0000 Subject: [Python-checkins] doc: Add link issue 44010 (GH-29454) Message-ID: https://github.com/python/cpython/commit/cca3004f64d49c9e170396ac787712fe03bffb29 commit: cca3004f64d49c9e170396ac787712fe03bffb29 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-08T03:18:33-08:00 summary: doc: Add link issue 44010 (GH-29454) (cherry picked from commit 3e0f13b9e48eec8c54a185e4180bfca4e5e685f6) Co-authored-by: Rafael Fontenelle files: M Doc/whatsnew/3.10.rst diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index 4ee193f158fde..c74e9f0ae5cb6 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -1162,7 +1162,7 @@ Highlight the new :ref:`soft keywords ` :keyword:`match`, :keyword:`case `, and :keyword:`_ ` in pattern-matching statements. However, this highlighting is not perfect and will be incorrect in some rare cases, including some ``_``-s in -``case`` patterns. (Contributed by Tal Einat in bpo-44010.) +``case`` patterns. (Contributed by Tal Einat in :issue:`44010`.) importlib.metadata ------------------ From webhook-mailer at python.org Wed Dec 8 06:42:10 2021 From: webhook-mailer at python.org (asvetlov) Date: Wed, 08 Dec 2021 11:42:10 -0000 Subject: [Python-checkins] Fix double-space in exception message (GH-29955) (GH-29983) Message-ID: https://github.com/python/cpython/commit/25254d484248f5a555d30209f455b8d8ee2e72df commit: 25254d484248f5a555d30209f455b8d8ee2e72df branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: asvetlov date: 2021-12-08T13:41:50+02:00 summary: Fix double-space in exception message (GH-29955) (GH-29983) (cherry picked from commit c602c1be439e295fed9ebab47e895ef1d9df28be) Co-authored-by: Ned Batchelder Co-authored-by: Ned Batchelder files: M Lib/statistics.py diff --git a/Lib/statistics.py b/Lib/statistics.py index f9d3802ec5f83..463ac9e92c6a1 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -361,7 +361,7 @@ def geometric_mean(data): return exp(fmean(map(log, data))) except ValueError: raise StatisticsError('geometric mean requires a non-empty dataset ' - ' containing positive numbers') from None + 'containing positive numbers') from None def harmonic_mean(data): From webhook-mailer at python.org Wed Dec 8 07:09:46 2021 From: webhook-mailer at python.org (markshannon) Date: Wed, 08 Dec 2021 12:09:46 -0000 Subject: [Python-checkins] bpo-46009: Do not exhaust generator when send() method raises (GH-29986) Message-ID: https://github.com/python/cpython/commit/69806b9516dbe092381f3ef884c7c64bb9b8414a commit: 69806b9516dbe092381f3ef884c7c64bb9b8414a branch: main author: Mark Shannon committer: markshannon date: 2021-12-08T12:09:26Z summary: bpo-46009: Do not exhaust generator when send() method raises (GH-29986) files: A Misc/NEWS.d/next/Core and Builtins/2021-12-08-11-06-53.bpo-46009.cL8pH0.rst M Doc/library/dis.rst M Lib/test/test_generators.py M Objects/genobject.c M Python/ceval.c diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 62d2150e304fa..9665e8dbf6cfc 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -1170,9 +1170,8 @@ All of the following opcodes use their arguments. .. opcode:: GEN_START (kind) - Pops TOS. If TOS was not ``None``, raises an exception. The ``kind`` - operand corresponds to the type of generator or coroutine and determines - the error message. The legal kinds are 0 for generator, 1 for coroutine, + Pops TOS. The ``kind`` operand corresponds to the type of generator or + coroutine. The legal kinds are 0 for generator, 1 for coroutine, and 2 for async generator. .. versionadded:: 3.10 diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py index 433204b09fee6..4f4fd9c5aa76e 100644 --- a/Lib/test/test_generators.py +++ b/Lib/test/test_generators.py @@ -162,6 +162,14 @@ def f(): with self.assertRaises((TypeError, pickle.PicklingError)): pickle.dumps(g, proto) + def test_send_non_none_to_new_gen(self): + def f(): + yield 1 + g = f() + with self.assertRaises(TypeError): + g.send(0) + self.assertEqual(next(g), 1) + class ExceptionTest(unittest.TestCase): # Tests for the issue #23353: check that the currently handled exception diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-08-11-06-53.bpo-46009.cL8pH0.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-08-11-06-53.bpo-46009.cL8pH0.rst new file mode 100644 index 0000000000000..a80e66b7c6451 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-08-11-06-53.bpo-46009.cL8pH0.rst @@ -0,0 +1,5 @@ +Restore behavior from 3.9 and earlier when sending non-None to newly started +generator. In 3.9 this did not affect the state of the generator. In 3.10.0 +and 3.10.1 ``gen_func().send(0)`` is equivalent to +``gen_func().throw(TypeError(...)`` which exhausts the generator. In 3.10.2 +onward, the behavior has been reverted to that of 3.9. diff --git a/Objects/genobject.c b/Objects/genobject.c index c4ba660530cae..147194c38a0a1 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -157,6 +157,19 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, PyObject *result; *presult = NULL; + if (frame->f_lasti < 0 && arg && arg != Py_None) { + const char *msg = "can't send non-None value to a " + "just-started generator"; + if (PyCoro_CheckExact(gen)) { + msg = NON_INIT_CORO_MSG; + } + else if (PyAsyncGen_CheckExact(gen)) { + msg = "can't send non-None value to a " + "just-started async generator"; + } + PyErr_SetString(PyExc_TypeError, msg); + return PYGEN_ERROR; + } if (gen->gi_frame_valid && _PyFrame_IsExecuting(frame)) { const char *msg = "generator already executing"; if (PyCoro_CheckExact(gen)) { diff --git a/Python/ceval.c b/Python/ceval.c index 2e40c0f5b391a..4f5ccf51e9cfe 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2714,25 +2714,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr TARGET(GEN_START) { PyObject *none = POP(); + assert(none == Py_None); + assert(oparg < 3); Py_DECREF(none); - if (!Py_IsNone(none)) { - if (oparg > 2) { - _PyErr_SetString(tstate, PyExc_SystemError, - "Illegal kind for GEN_START"); - } - else { - static const char *gen_kind[3] = { - "generator", - "coroutine", - "async generator" - }; - _PyErr_Format(tstate, PyExc_TypeError, - "can't send non-None value to a " - "just-started %s", - gen_kind[oparg]); - } - goto error; - } DISPATCH(); } From webhook-mailer at python.org Wed Dec 8 09:46:41 2021 From: webhook-mailer at python.org (pablogsal) Date: Wed, 08 Dec 2021 14:46:41 -0000 Subject: [Python-checkins] [3.10] bpo-46009: Do not exhaust generator when send() method raises (GH-29986). (GH-29988) Message-ID: https://github.com/python/cpython/commit/99c72326d245fb604609a87a51ef1ad0845467b7 commit: 99c72326d245fb604609a87a51ef1ad0845467b7 branch: 3.10 author: Mark Shannon committer: pablogsal date: 2021-12-08T14:46:32Z summary: [3.10] bpo-46009: Do not exhaust generator when send() method raises (GH-29986). (GH-29988) * [3.10] bpo-46009: Do not exhaust generator when send() method raises (GH-29986). (cherry picked from commit 69806b9516dbe092381f3ef884c7c64bb9b8414a) Co-authored-by: Mark Shannon * Rename variable after cherry-pick. * Add NULL check. files: A Misc/NEWS.d/next/Core and Builtins/2021-12-08-11-06-53.bpo-46009.cL8pH0.rst M Doc/library/dis.rst M Lib/test/test_generators.py M Objects/genobject.c M Python/ceval.c diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index e7e67daae5254..74820f9bdb578 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -1252,9 +1252,8 @@ All of the following opcodes use their arguments. .. opcode:: GEN_START (kind) - Pops TOS. If TOS was not ``None``, raises an exception. The ``kind`` - operand corresponds to the type of generator or coroutine and determines - the error message. The legal kinds are 0 for generator, 1 for coroutine, + Pops TOS. The ``kind`` operand corresponds to the type of generator or + coroutine. The legal kinds are 0 for generator, 1 for coroutine, and 2 for async generator. .. versionadded:: 3.10 diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py index d14c757c7b6e4..3bf5f3b7438e7 100644 --- a/Lib/test/test_generators.py +++ b/Lib/test/test_generators.py @@ -161,6 +161,14 @@ def f(): with self.assertRaises((TypeError, pickle.PicklingError)): pickle.dumps(g, proto) + def test_send_non_none_to_new_gen(self): + def f(): + yield 1 + g = f() + with self.assertRaises(TypeError): + g.send(0) + self.assertEqual(next(g), 1) + class ExceptionTest(unittest.TestCase): # Tests for the issue #23353: check that the currently handled exception diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-08-11-06-53.bpo-46009.cL8pH0.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-08-11-06-53.bpo-46009.cL8pH0.rst new file mode 100644 index 0000000000000..a80e66b7c6451 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-08-11-06-53.bpo-46009.cL8pH0.rst @@ -0,0 +1,5 @@ +Restore behavior from 3.9 and earlier when sending non-None to newly started +generator. In 3.9 this did not affect the state of the generator. In 3.10.0 +and 3.10.1 ``gen_func().send(0)`` is equivalent to +``gen_func().throw(TypeError(...)`` which exhausts the generator. In 3.10.2 +onward, the behavior has been reverted to that of 3.9. diff --git a/Objects/genobject.c b/Objects/genobject.c index 3ac38de0c311b..33fc4a592492a 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -145,6 +145,19 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, PyObject *result; *presult = NULL; + if (f != NULL && f->f_lasti < 0 && arg && arg != Py_None) { + const char *msg = "can't send non-None value to a " + "just-started generator"; + if (PyCoro_CheckExact(gen)) { + msg = NON_INIT_CORO_MSG; + } + else if (PyAsyncGen_CheckExact(gen)) { + msg = "can't send non-None value to a " + "just-started async generator"; + } + PyErr_SetString(PyExc_TypeError, msg); + return PYGEN_ERROR; + } if (f != NULL && _PyFrame_IsExecuting(f)) { const char *msg = "generator already executing"; if (PyCoro_CheckExact(gen)) { diff --git a/Python/ceval.c b/Python/ceval.c index 624baf537518f..8ad1713b78c01 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2649,25 +2649,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag) case TARGET(GEN_START): { PyObject *none = POP(); + assert(none == Py_None); + assert(oparg < 3); Py_DECREF(none); - if (!Py_IsNone(none)) { - if (oparg > 2) { - _PyErr_SetString(tstate, PyExc_SystemError, - "Illegal kind for GEN_START"); - } - else { - static const char *gen_kind[3] = { - "generator", - "coroutine", - "async generator" - }; - _PyErr_Format(tstate, PyExc_TypeError, - "can't send non-None value to a " - "just-started %s", - gen_kind[oparg]); - } - goto error; - } DISPATCH(); } From webhook-mailer at python.org Wed Dec 8 11:05:13 2021 From: webhook-mailer at python.org (markshannon) Date: Wed, 08 Dec 2021 16:05:13 -0000 Subject: [Python-checkins] bpo-45813: Drop redundant assertion from frame.clear() (GH-29990) Message-ID: https://github.com/python/cpython/commit/d4363d214097b3fca8b7910c2e0e91c8b0873fb2 commit: d4363d214097b3fca8b7910c2e0e91c8b0873fb2 branch: main author: Andrew Svetlov committer: markshannon date: 2021-12-08T16:05:00Z summary: bpo-45813: Drop redundant assertion from frame.clear() (GH-29990) * bpo-45813: Drop redundant assertion from frame.clear() * Move assertion to frame_dealloc() files: M Lib/test/test_coroutines.py M Objects/frameobject.c diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py index fc8b8bc9541eb..3081853303b37 100644 --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -2191,13 +2191,22 @@ async def run_gen(): return 'end' self.assertEqual(run_async(run_gen()), ([], 'end')) - def test_bpo_45813(self): + def test_bpo_45813_1(self): 'This would crash the interpreter in 3.11a2' async def f(): pass - frame = f().cr_frame + with self.assertWarns(RuntimeWarning): + frame = f().cr_frame frame.clear() + def test_bpo_45813_2(self): + 'This would crash the interpreter in 3.11a2' + async def f(): + pass + gen = f() + with self.assertWarns(RuntimeWarning): + gen.cr_frame.clear() + class CoroAsyncIOCompatTest(unittest.TestCase): diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 926a32a5100bd..2197e07bc0610 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -613,6 +613,10 @@ static PyGetSetDef frame_getsetlist[] = { static void frame_dealloc(PyFrameObject *f) { + /* It is the responsibility of the owning generator/coroutine + * to have cleared the generator pointer */ + assert(f->f_frame->generator == NULL); + if (_PyObject_GC_IS_TRACKED(f)) { _PyObject_GC_UNTRACK(f); } @@ -686,7 +690,6 @@ frame_clear(PyFrameObject *f, PyObject *Py_UNUSED(ignored)) } if (f->f_frame->generator) { _PyGen_Finalize(f->f_frame->generator); - assert(f->f_frame->generator == NULL); } (void)frame_tp_clear(f); Py_RETURN_NONE; From webhook-mailer at python.org Wed Dec 8 13:47:36 2021 From: webhook-mailer at python.org (iritkatriel) Date: Wed, 08 Dec 2021 18:47:36 -0000 Subject: [Python-checkins] bpo-45635: refactor print_exception() into smaller functions (GH-29981) Message-ID: https://github.com/python/cpython/commit/f893bb2e01307c92ca19597f44874ecaffe7f06f commit: f893bb2e01307c92ca19597f44874ecaffe7f06f branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-12-08T18:47:27Z summary: bpo-45635: refactor print_exception() into smaller functions (GH-29981) Co-authored-by: Erlend Egeberg Aasland files: M Python/pythonrun.c diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 5a118b4821ec0..cfc39361d5fcb 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -908,38 +908,35 @@ write_indented_margin(struct exception_print_context *ctx, PyObject *f) return _Py_WriteIndentedMargin(EXC_INDENT(ctx), EXC_MARGIN(ctx), f); } -static void -print_exception(struct exception_print_context *ctx, PyObject *value) +static int +print_exception_invalid_type(struct exception_print_context *ctx, + PyObject *value) { - int err = 0; - PyObject *type, *tb, *tmp; PyObject *f = ctx->file; - - _Py_IDENTIFIER(print_file_and_line); - - if (!PyExceptionInstance_Check(value)) { - if (err == 0) { - err = _Py_WriteIndent(EXC_INDENT(ctx), f); - } - if (err == 0) { - err = PyFile_WriteString("TypeError: print_exception(): Exception expected for value, ", f); - } - if (err == 0) { - err = PyFile_WriteString(Py_TYPE(value)->tp_name, f); - } - if (err == 0) { - err = PyFile_WriteString(" found\n", f); - } - if (err != 0) { - PyErr_Clear(); - } - return; + if (_Py_WriteIndent(EXC_INDENT(ctx), f) < 0) { + return -1; + } + const char *const msg = "TypeError: print_exception(): Exception expected " + "for value, "; + if (PyFile_WriteString(msg, f) < 0) { + return -1; + } + if (PyFile_WriteString(Py_TYPE(value)->tp_name, f) < 0) { + return -1; + } + if (PyFile_WriteString(" found\n", f) < 0) { + return -1; } + return 0; +} - Py_INCREF(value); - fflush(stdout); - type = (PyObject *) Py_TYPE(value); - tb = PyException_GetTraceback(value); +static int +print_exception_traceback(struct exception_print_context *ctx, PyObject *value) +{ + PyObject *f = ctx->file; + int err = 0; + + PyObject *tb = PyException_GetTraceback(value); if (tb && tb != Py_None) { const char *header = EXCEPTION_TB_HEADER; const char *header_margin = EXC_MARGIN(ctx); @@ -952,6 +949,117 @@ print_exception(struct exception_print_context *ctx, PyObject *value) err = _PyTraceBack_Print_Indented( tb, EXC_INDENT(ctx), EXC_MARGIN(ctx), header_margin, header, f); } + Py_XDECREF(tb); + return err; +} + +/* Prints the message line: module.qualname[: str(exc)] */ +static int +print_exception_message(struct exception_print_context *ctx, PyObject *type, + PyObject *value) +{ + PyObject *f = ctx->file; + + _Py_IDENTIFIER(__module__); + + assert(PyExceptionClass_Check(type)); + + if (write_indented_margin(ctx, f) < 0) { + return -1; + } + PyObject *modulename = _PyObject_GetAttrId(type, &PyId___module__); + if (modulename == NULL || !PyUnicode_Check(modulename)) { + Py_XDECREF(modulename); + PyErr_Clear(); + if (PyFile_WriteString(".", f) < 0) { + return -1; + } + } + else { + if (!_PyUnicode_EqualToASCIIId(modulename, &PyId_builtins) && + !_PyUnicode_EqualToASCIIId(modulename, &PyId___main__)) + { + int res = PyFile_WriteObject(modulename, f, Py_PRINT_RAW); + Py_DECREF(modulename); + if (res < 0) { + return -1; + } + if (PyFile_WriteString(".", f) < 0) { + return -1; + } + } + else { + Py_DECREF(modulename); + } + } + + PyObject *qualname = PyType_GetQualName((PyTypeObject *)type); + if (qualname == NULL || !PyUnicode_Check(qualname)) { + Py_XDECREF(qualname); + PyErr_Clear(); + if (PyFile_WriteString("", f) < 0) { + return -1; + } + } + else { + int res = PyFile_WriteObject(qualname, f, Py_PRINT_RAW); + Py_DECREF(qualname); + if (res < 0) { + return -1; + } + } + + if (Py_IsNone(value)) { + return 0; + } + + PyObject *s = PyObject_Str(value); + if (s == NULL) { + PyErr_Clear(); + if (PyFile_WriteString(": ", f) < 0) { + return -1; + } + } + else { + /* only print colon if the str() of the + object is not the empty string + */ + if (!PyUnicode_Check(s) || PyUnicode_GetLength(s) != 0) { + if (PyFile_WriteString(": ", f) < 0) { + Py_DECREF(s); + return -1; + } + } + int res = PyFile_WriteObject(s, f, Py_PRINT_RAW); + Py_DECREF(s); + if (res < 0) { + return -1; + } + } + + return 0; +} + +static void +print_exception(struct exception_print_context *ctx, PyObject *value) +{ + int err = 0; + PyObject *tmp; + PyObject *f = ctx->file; + + _Py_IDENTIFIER(print_file_and_line); + + if (!PyExceptionInstance_Check(value)) { + if (print_exception_invalid_type(ctx, value) < 0) { + PyErr_Clear(); /* TODO: change to return -1 */ + } + return; + } + + Py_INCREF(value); + fflush(stdout); + PyObject *type = (PyObject *) Py_TYPE(value); + err = print_exception_traceback(ctx, value); if (err == 0 && (err = _PyObject_LookupAttrId(value, &PyId_print_file_and_line, &tmp)) > 0) { @@ -1006,66 +1114,11 @@ print_exception(struct exception_print_context *ctx, PyObject *value) err = -1; } } - if (err != 0) { - /* Don't do anything else */ - } - else { - PyObject* modulename; - _Py_IDENTIFIER(__module__); - assert(PyExceptionClass_Check(type)); - - err = write_indented_margin(ctx, f); - if (err == 0) { - modulename = _PyObject_GetAttrId(type, &PyId___module__); - if (modulename == NULL || !PyUnicode_Check(modulename)) - { - Py_XDECREF(modulename); - PyErr_Clear(); - err = PyFile_WriteString(".", f); - } - else { - if (!_PyUnicode_EqualToASCIIId(modulename, &PyId_builtins) && - !_PyUnicode_EqualToASCIIId(modulename, &PyId___main__)) - { - err = PyFile_WriteObject(modulename, f, Py_PRINT_RAW); - if (err == 0) { - err = PyFile_WriteString(".", f); - } - } - Py_DECREF(modulename); - } - } - if (err == 0) { - PyObject* qualname = PyType_GetQualName((PyTypeObject *)type); - if (qualname == NULL || !PyUnicode_Check(qualname)) { - Py_XDECREF(qualname); - PyErr_Clear(); - err = PyFile_WriteString("", f); - } - else { - err = PyFile_WriteObject(qualname, f, Py_PRINT_RAW); - Py_DECREF(qualname); - } - } - } - if (err == 0 && (value != Py_None)) { - PyObject *s = PyObject_Str(value); - /* only print colon if the str() of the - object is not the empty string - */ - if (s == NULL) { - PyErr_Clear(); - err = -1; - PyFile_WriteString(": ", f); - } - else if (!PyUnicode_Check(s) || - PyUnicode_GetLength(s) != 0) - err = PyFile_WriteString(": ", f); - if (err == 0) - err = PyFile_WriteObject(s, f, Py_PRINT_RAW); - Py_XDECREF(s); + if (err == 0) { + err = print_exception_message(ctx, type, value); } + /* try to write a newline in any case */ if (err < 0) { PyErr_Clear(); @@ -1118,7 +1171,6 @@ print_exception(struct exception_print_context *ctx, PyObject *value) } Py_XDECREF(note); } - Py_XDECREF(tb); Py_DECREF(value); /* If an error happened here, don't show it. XXX This is wrong, but too many callers rely on this behavior. */ From webhook-mailer at python.org Wed Dec 8 13:53:09 2021 From: webhook-mailer at python.org (asvetlov) Date: Wed, 08 Dec 2021 18:53:09 -0000 Subject: [Python-checkins] bpo-45359: Support TopologicalSorter type subscript (GH-28714) Message-ID: https://github.com/python/cpython/commit/3cb9731b7e59b0df9a7a9ab6b7746a669958b693 commit: 3cb9731b7e59b0df9a7a9ab6b7746a669958b693 branch: main author: Jacob Hayes committer: asvetlov date: 2021-12-08T20:52:57+02:00 summary: bpo-45359: Support TopologicalSorter type subscript (GH-28714) * Support TopologicalSorter type subscript * ?? Added by blurb_it. * Add TopologicalSorter to GenericAlias tests * Update Misc/NEWS.d/next/Library/2021-10-03-22-27-35.bpo-45359.LX_uxe.rst Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> Co-authored-by: Batuhan Taskaya files: A Misc/NEWS.d/next/Library/2021-10-03-22-27-35.bpo-45359.LX_uxe.rst M Lib/graphlib.py M Lib/test/test_genericalias.py diff --git a/Lib/graphlib.py b/Lib/graphlib.py index 1c5d9a413c944..636545648e12d 100644 --- a/Lib/graphlib.py +++ b/Lib/graphlib.py @@ -1,3 +1,5 @@ +from types import GenericAlias + __all__ = ["TopologicalSorter", "CycleError"] _NODE_OUT = -1 @@ -244,3 +246,5 @@ def static_order(self): node_group = self.get_ready() yield from node_group self.done(*node_group) + + __class_getitem__ = classmethod(GenericAlias) diff --git a/Lib/test/test_genericalias.py b/Lib/test/test_genericalias.py index 0daaff099a868..706cc5ea1af2f 100644 --- a/Lib/test/test_genericalias.py +++ b/Lib/test/test_genericalias.py @@ -13,6 +13,7 @@ from contextvars import ContextVar, Token from dataclasses import Field from functools import partial, partialmethod, cached_property +from graphlib import TopologicalSorter from mailbox import Mailbox, _PartialFile try: import ctypes @@ -56,6 +57,7 @@ class BaseTest(unittest.TestCase): OrderedDict, Counter, UserDict, UserList, Pattern, Match, partial, partialmethod, cached_property, + TopologicalSorter, AbstractContextManager, AbstractAsyncContextManager, Awaitable, Coroutine, AsyncIterable, AsyncIterator, diff --git a/Misc/NEWS.d/next/Library/2021-10-03-22-27-35.bpo-45359.LX_uxe.rst b/Misc/NEWS.d/next/Library/2021-10-03-22-27-35.bpo-45359.LX_uxe.rst new file mode 100644 index 0000000000000..6f5c97fde82a0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-10-03-22-27-35.bpo-45359.LX_uxe.rst @@ -0,0 +1 @@ +Implement :pep:`585` for :class:`graphlib.TopologicalSorter`. \ No newline at end of file From webhook-mailer at python.org Wed Dec 8 14:26:08 2021 From: webhook-mailer at python.org (zooba) Date: Wed, 08 Dec 2021 19:26:08 -0000 Subject: [Python-checkins] bpo-46015: Fixes calculation of sys.path in a venv on Windows (GH-29992) Message-ID: https://github.com/python/cpython/commit/7778116c2f573edf320bd55301137a968e4339d8 commit: 7778116c2f573edf320bd55301137a968e4339d8 branch: main author: Steve Dower committer: zooba date: 2021-12-08T19:25:58Z summary: bpo-46015: Fixes calculation of sys.path in a venv on Windows (GH-29992) Also ensures that pybuilddir.txt is written early enough in the build to be picked up by later steps. files: A Misc/NEWS.d/next/Windows/2021-12-08-16-36-20.bpo-46105.t1mJ6Q.rst M Lib/test/test_embed.py M Lib/test/test_getpath.py M Modules/getpath.c M Modules/getpath.py M PCbuild/python.vcxproj diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index 94161b651ff86..8012d80bf3e55 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -1362,6 +1362,8 @@ def test_init_pyvenv_cfg(self): if not MS_WINDOWS: paths[-1] = lib_dynload else: + # Include DLLs directory as well + paths.insert(1, '.\\DLLs') for index, path in enumerate(paths): if index == 0: # Because we copy the DLLs into tmpdir as well, the zip file diff --git a/Lib/test/test_getpath.py b/Lib/test/test_getpath.py index 9dd167b9975c0..3fb1b280031c8 100644 --- a/Lib/test/test_getpath.py +++ b/Lib/test/test_getpath.py @@ -100,6 +100,7 @@ def test_venv_win32(self): module_search_paths_set=1, module_search_paths=[ r"C:\Python\python98.zip", + r"C:\Python\DLLs", r"C:\Python\Lib", r"C:\Python", ], diff --git a/Misc/NEWS.d/next/Windows/2021-12-08-16-36-20.bpo-46105.t1mJ6Q.rst b/Misc/NEWS.d/next/Windows/2021-12-08-16-36-20.bpo-46105.t1mJ6Q.rst new file mode 100644 index 0000000000000..bfb6d31f7b6e3 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2021-12-08-16-36-20.bpo-46105.t1mJ6Q.rst @@ -0,0 +1 @@ +Fixed calculation of :data:`sys.path` in a venv on Windows. diff --git a/Modules/getpath.c b/Modules/getpath.c index 0b982f10e418b..fedb41cdb3788 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -390,7 +390,7 @@ getpath_readlines(PyObject *Py_UNUSED(self), PyObject *args) while (cb && (p1[cb] == L'\n' || p1[cb] == L'\r')) { --cb; } - PyObject *u = PyUnicode_FromWideChar(p1, cb + 1); + PyObject *u = PyUnicode_FromWideChar(p1, cb ? cb + 1 : 0); if (!u || PyList_Append(r, u) < 0) { Py_XDECREF(u); Py_CLEAR(r); diff --git a/Modules/getpath.py b/Modules/getpath.py index 6a13e232ec3e8..84c9760b11248 100644 --- a/Modules/getpath.py +++ b/Modules/getpath.py @@ -668,14 +668,17 @@ def search_up(prefix, *landmarks, test=isfile): pythonpath.append(joinpath(prefix, p)) # Then add stdlib_dir and platstdlib_dir - if stdlib_dir: - pythonpath.append(stdlib_dir) - if platstdlib_dir: - if os_name == 'nt' and venv_prefix: - # QUIRK: Windows appends executable_dir instead of platstdlib_dir - # when in a venv - pythonpath.append(executable_dir) - else: + if os_name == 'nt' and venv_prefix: + # QUIRK: Windows generates paths differently in a venv + if platstdlib_dir: + pythonpath.append(platstdlib_dir) + if stdlib_dir: + pythonpath.append(stdlib_dir) + pythonpath.append(executable_dir) + else: + if stdlib_dir: + pythonpath.append(stdlib_dir) + if platstdlib_dir: pythonpath.append(platstdlib_dir) config['module_search_paths'] = pythonpath diff --git a/PCbuild/python.vcxproj b/PCbuild/python.vcxproj index f44513702879e..77bccde69e3ba 100644 --- a/PCbuild/python.vcxproj +++ b/PCbuild/python.vcxproj @@ -117,6 +117,10 @@ + + + + ucrtbase @@ -147,7 +151,4 @@ $(_PGOPath) - - - From webhook-mailer at python.org Wed Dec 8 15:08:12 2021 From: webhook-mailer at python.org (iritkatriel) Date: Wed, 08 Dec 2021 20:08:12 -0000 Subject: [Python-checkins] bpo-45711: Remove unnecessary normalization of exc_info (GH-29922) Message-ID: https://github.com/python/cpython/commit/2109f7880b65755329a877da3a7f8a362de07350 commit: 2109f7880b65755329a877da3a7f8a362de07350 branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-12-08T20:08:06Z summary: bpo-45711: Remove unnecessary normalization of exc_info (GH-29922) files: A Misc/NEWS.d/next/Core and Builtins/2021-12-05-17-36-08.bpo-45711.3TmTSw.rst M Python/errors.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-05-17-36-08.bpo-45711.3TmTSw.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-05-17-36-08.bpo-45711.3TmTSw.rst new file mode 100644 index 0000000000000..4e1f27a077b50 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-05-17-36-08.bpo-45711.3TmTSw.rst @@ -0,0 +1 @@ +:c:func:`_PyErr_ChainStackItem` no longer normalizes ``exc_info`` (including setting the traceback on the exception instance) because ``exc_info`` is always normalized. \ No newline at end of file diff --git a/Python/errors.c b/Python/errors.c index 0a8b5a257fb2c..44d2773acdb5c 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -647,26 +647,6 @@ _PyErr_ChainStackItem(_PyErr_StackItem *exc_info) PyObject *typ, *val, *tb; _PyErr_Fetch(tstate, &typ, &val, &tb); - PyObject *typ2, *val2, *tb2; - typ2 = exc_info->exc_type; - val2 = exc_info->exc_value; - tb2 = exc_info->exc_traceback; -#ifdef Py_DEBUG - PyObject *typ2_before = typ2; - PyObject *val2_before = val2; - PyObject *tb2_before = tb2; -#endif - _PyErr_NormalizeException(tstate, &typ2, &val2, &tb2); -#ifdef Py_DEBUG - /* exc_info should already be normalized */ - assert(typ2 == typ2_before); - assert(val2 == val2_before); - assert(tb2 == tb2_before); -#endif - if (tb2 != NULL) { - PyException_SetTraceback(val2, tb2); - } - /* _PyErr_SetObject sets the context from PyThreadState. */ _PyErr_SetObject(tstate, typ, val); Py_DECREF(typ); // since _PyErr_Occurred was true From webhook-mailer at python.org Wed Dec 8 17:28:56 2021 From: webhook-mailer at python.org (vstinner) Date: Wed, 08 Dec 2021 22:28:56 -0000 Subject: [Python-checkins] bpo-46016: fcntl module add FreeBSD's F_DUP2FD_CLOEXEC flag support (GH-29993) Message-ID: https://github.com/python/cpython/commit/267539bff700c2493778c07eeb1642b9584c4826 commit: 267539bff700c2493778c07eeb1642b9584c4826 branch: main author: David CARLIER committer: vstinner date: 2021-12-08T23:28:51+01:00 summary: bpo-46016: fcntl module add FreeBSD's F_DUP2FD_CLOEXEC flag support (GH-29993) files: A Misc/NEWS.d/next/Library/2021-12-08-19-15-03.bpo-46016.s9PuyF.rst M Doc/library/fcntl.rst M Doc/whatsnew/3.11.rst M Modules/fcntlmodule.c diff --git a/Doc/library/fcntl.rst b/Doc/library/fcntl.rst index 9d8021150c42f..846c8d7ba96da 100644 --- a/Doc/library/fcntl.rst +++ b/Doc/library/fcntl.rst @@ -44,6 +44,11 @@ descriptor. ``F_SETPIPE_SZ`` constants, which allow to check and modify a pipe's size respectively. +.. versionchanged:: 3.11 + On FreeBSD, the fcntl module exposes the ``F_DUP2FD`` and ``F_DUP2FD_CLOEXEC`` + constants, which allow to duplicate a file descriptor, the latter setting + ``FD_CLOEXEC`` flag in addition. + The module defines the following functions: diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index a570864743d47..264a801da7899 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -329,6 +329,14 @@ unicodedata * The Unicode database has been updated to version 14.0.0. (:issue:`45190`). +fcntl +----- + +* On FreeBSD, the `F_DUP2FD` and `F_DUP2FD_CLOEXEC` flags respectively + are supported, the former equals to ``dup2`` usage while the latter set + the ``FD_CLOEXEC`` flag in addition. + + Optimizations ============= diff --git a/Misc/NEWS.d/next/Library/2021-12-08-19-15-03.bpo-46016.s9PuyF.rst b/Misc/NEWS.d/next/Library/2021-12-08-19-15-03.bpo-46016.s9PuyF.rst new file mode 100644 index 0000000000000..7308c542aacf5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-08-19-15-03.bpo-46016.s9PuyF.rst @@ -0,0 +1 @@ +Adding `F_DUP2FD` and `F_DUP2FD_CLOEXEC` constants from FreeBSD into the fcntl module. diff --git a/Modules/fcntlmodule.c b/Modules/fcntlmodule.c index cdf0f9bf3790e..ea9b2bc14a9f2 100644 --- a/Modules/fcntlmodule.c +++ b/Modules/fcntlmodule.c @@ -581,6 +581,14 @@ all_ins(PyObject* m) if (PyModule_AddIntMacro(m, F_NOCACHE)) return -1; #endif +/* FreeBSD specifics */ +#ifdef F_DUP2FD + if (PyModule_AddIntMacro(m, F_DUP2FD)) return -1; +#endif +#ifdef F_DUP2FD_CLOEXEC + if (PyModule_AddIntMacro(m, F_DUP2FD_CLOEXEC)) return -1; +#endif + /* For F_{GET|SET}FL */ #ifdef FD_CLOEXEC if (PyModule_AddIntMacro(m, FD_CLOEXEC)) return -1; From webhook-mailer at python.org Wed Dec 8 18:42:12 2021 From: webhook-mailer at python.org (pablogsal) Date: Wed, 08 Dec 2021 23:42:12 -0000 Subject: [Python-checkins] Fix some false positives of documentation syntax problems Message-ID: https://github.com/python/cpython/commit/3ea574f35b69235e17b7eb603bc5f1b026cf7d31 commit: 3ea574f35b69235e17b7eb603bc5f1b026cf7d31 branch: main author: Pablo Galindo committer: pablogsal date: 2021-12-08T22:22:55Z summary: Fix some false positives of documentation syntax problems files: M Doc/reference/datamodel.rst M Doc/tools/susp-ignored.csv M Doc/using/configure.rst diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 81dad77fab97a..aa0d91ad1c97d 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -2331,7 +2331,7 @@ called:: from inspect import isclass def subscribe(obj, x): - """Return the result of the expression `obj[x]`""" + """Return the result of the expression 'obj[x]'""" class_of_obj = type(obj) diff --git a/Doc/tools/susp-ignored.csv b/Doc/tools/susp-ignored.csv index 280e9a63cdcc3..cbc3ac0bbab34 100644 --- a/Doc/tools/susp-ignored.csv +++ b/Doc/tools/susp-ignored.csv @@ -369,7 +369,6 @@ whatsnew/changelog,,::,default::DeprecationWarning library/importlib.metadata,,:main,"EntryPoint(name='wheel', value='wheel.cli:main', group='console_scripts')" library/importlib.metadata,,`,loading the metadata for packages for the indicated ``context``. library/re,,`,"`" -using/configure,84,:db2,=db1:db2:... library/typing,,`,# Type of ``val`` is narrowed to ``str`` library/typing,,`,"# Else, type of ``val`` is narrowed to ``float``." library/typing,,`,# Type of ``val`` is narrowed to ``list[str]``. @@ -380,4 +379,5 @@ library/tkinter,,::,"grid [ttk::button .frm.btn -text ""Quit"" -command ""destro library/tkinter,,::,ttk::frame library/tkinter,,::,ttk::button library/tkinter,,::,ttk::widget -reference/datamodel,2285,`,"""""""Return the result of the expression `obj[x]`""""""" +whatsnew/changelog,305,::,Lib/email/mime/nonmultipart.py::MIMENonMultipart +whatsnew/changelog,308,::,Lib/ctypes/test/test_functions.py::test_mro diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index 5720f015eca06..7802a7c810b29 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -80,7 +80,7 @@ General Options .. versionadded:: 3.9 -.. cmdoption:: --with-dbmliborder=db1:db2:... +.. cmdoption:: --with-dbmliborder= Override order to check db backends for the :mod:`dbm` module From webhook-mailer at python.org Wed Dec 8 20:17:24 2021 From: webhook-mailer at python.org (corona10) Date: Thu, 09 Dec 2021 01:17:24 -0000 Subject: [Python-checkins] bpo-45510: Check both types when specializing subtraction (GH-29995) Message-ID: https://github.com/python/cpython/commit/5de39f4b412ed5b0f3ed0140c83b2c1f8c707603 commit: 5de39f4b412ed5b0f3ed0140c83b2c1f8c707603 branch: main author: Brandt Bucher committer: corona10 date: 2021-12-09T10:17:16+09:00 summary: bpo-45510: Check both types when specializing subtraction (GH-29995) files: M Python/specialize.c diff --git a/Python/specialize.c b/Python/specialize.c index cdc535396fa76..5121845008100 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -1490,6 +1490,10 @@ _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, break; case NB_SUBTRACT: case NB_INPLACE_SUBTRACT: + if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) { + SPECIALIZATION_FAIL(BINARY_OP, SPEC_FAIL_DIFFERENT_TYPES); + goto failure; + } if (PyLong_CheckExact(lhs)) { *instr = _Py_MAKECODEUNIT(BINARY_OP_SUBTRACT_INT, _Py_OPARG(*instr)); From webhook-mailer at python.org Thu Dec 9 03:58:22 2021 From: webhook-mailer at python.org (miss-islington) Date: Thu, 09 Dec 2021 08:58:22 -0000 Subject: [Python-checkins] bpo-46007: Exclude PyUnicode_CHECK_INTERNED() from limited C API (GH-29987) Message-ID: https://github.com/python/cpython/commit/73325bbe774b16891f999fb557177206470676b1 commit: 73325bbe774b16891f999fb557177206470676b1 branch: main author: Victor Stinner committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-09T00:58:09-08:00 summary: bpo-46007: Exclude PyUnicode_CHECK_INTERNED() from limited C API (GH-29987) Exclude the PyUnicode_CHECK_INTERNED() macro from the limited C API, because it uses the PyASCIIObject structure which is excluded from the limited C API. Automerge-Triggered-By: GH:encukou files: A Misc/NEWS.d/next/C API/2021-12-08-12-41-51.bpo-46007.sMgDLz.rst M Doc/whatsnew/3.11.rst M Include/cpython/unicodeobject.h M Include/unicodeobject.h diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 264a801da7899..4a113cdb8905c 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -723,6 +723,12 @@ Porting to Python 3.11 been included directly, consider including ``Python.h`` instead. (Contributed by Victor Stinner in :issue:`35134`.) +* The :c:func:`PyUnicode_CHECK_INTERNED` macro has been excluded from the + limited C API. It was never usable there, because it used internal structures + which are not available in the limited C API. + (Contributed by Victor Stinner in :issue:`46007`.) + + Deprecated ---------- diff --git a/Include/cpython/unicodeobject.h b/Include/cpython/unicodeobject.h index e02137c7cad7d..be5647c7d263c 100644 --- a/Include/cpython/unicodeobject.h +++ b/Include/cpython/unicodeobject.h @@ -279,6 +279,10 @@ PyAPI_FUNC(int) _PyUnicode_CheckConsistency( #define SSTATE_INTERNED_MORTAL 1 #define SSTATE_INTERNED_IMMORTAL 2 +/* Use only if you know it's a string */ +#define PyUnicode_CHECK_INTERNED(op) \ + (((PyASCIIObject *)(op))->state.interned) + /* Return true if the string contains only ASCII characters, or 0 if not. The string may be compact (PyUnicode_IS_COMPACT_ASCII) or not, but must be ready. */ diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h index abce967caff78..6426c5d06b445 100644 --- a/Include/unicodeobject.h +++ b/Include/unicodeobject.h @@ -269,10 +269,6 @@ PyAPI_FUNC(PyObject *) PyUnicode_InternFromString( // and will be removed in Python 3.12. Use PyUnicode_InternInPlace() instead. Py_DEPRECATED(3.10) PyAPI_FUNC(void) PyUnicode_InternImmortal(PyObject **); -/* Use only if you know it's a string */ -#define PyUnicode_CHECK_INTERNED(op) \ - (((PyASCIIObject *)(op))->state.interned) - /* --- wchar_t support for platforms which support it --------------------- */ #ifdef HAVE_WCHAR_H diff --git a/Misc/NEWS.d/next/C API/2021-12-08-12-41-51.bpo-46007.sMgDLz.rst b/Misc/NEWS.d/next/C API/2021-12-08-12-41-51.bpo-46007.sMgDLz.rst new file mode 100644 index 0000000000000..6ed871b9950af --- /dev/null +++ b/Misc/NEWS.d/next/C API/2021-12-08-12-41-51.bpo-46007.sMgDLz.rst @@ -0,0 +1,3 @@ +The :c:func:`PyUnicode_CHECK_INTERNED` macro has been excluded from the limited +C API. It was never usable there, because it used internal structures which are +not available in the limited C API. Patch by Victor Stinner. From webhook-mailer at python.org Thu Dec 9 07:56:25 2021 From: webhook-mailer at python.org (Fidget-Spinner) Date: Thu, 09 Dec 2021 12:56:25 -0000 Subject: [Python-checkins] bpo-45391: mark UnionType as a class in documentation (GH-28757) Message-ID: https://github.com/python/cpython/commit/e2cfc89e099b8fad5d8d5bd7f59dadffb6078778 commit: e2cfc89e099b8fad5d8d5bd7f59dadffb6078778 branch: main author: Bern?t G?bor committer: Fidget-Spinner <28750310+Fidget-Spinner at users.noreply.github.com> date: 2021-12-09T20:56:14+08:00 summary: bpo-45391: mark UnionType as a class in documentation (GH-28757) Signed-off-by: Bern?t G?bor files: M Doc/library/types.rst diff --git a/Doc/library/types.rst b/Doc/library/types.rst index 2314b02c7449c..5cd42f1fc2928 100644 --- a/Doc/library/types.rst +++ b/Doc/library/types.rst @@ -312,7 +312,7 @@ Standard names are defined for the following types: This type can now be subclassed. -.. data:: UnionType +.. class:: UnionType The type of :ref:`union type expressions`. From webhook-mailer at python.org Thu Dec 9 08:16:50 2021 From: webhook-mailer at python.org (pablogsal) Date: Thu, 09 Dec 2021 13:16:50 -0000 Subject: [Python-checkins] bpo-25066: Added repr for multiprocessing.Event (GH-29749) Message-ID: https://github.com/python/cpython/commit/af6b4068859a5d0c8afd696f3c0c0155660211a4 commit: af6b4068859a5d0c8afd696f3c0c0155660211a4 branch: main author: Kumar Aditya committer: pablogsal date: 2021-12-09T13:16:45Z summary: bpo-25066: Added repr for multiprocessing.Event (GH-29749) Co-authored-by: Pablo Galindo Salgado files: A Misc/NEWS.d/next/Library/2021-11-24-12-25-42.bpo-25066.YIcIkn.rst M Lib/multiprocessing/synchronize.py M Lib/test/_test_multiprocessing.py diff --git a/Lib/multiprocessing/synchronize.py b/Lib/multiprocessing/synchronize.py index d0be48f1fd7a8..42624b543601a 100644 --- a/Lib/multiprocessing/synchronize.py +++ b/Lib/multiprocessing/synchronize.py @@ -353,6 +353,9 @@ def wait(self, timeout=None): return True return False + def __repr__(self) -> str: + set_status = 'set' if self.is_set() else 'unset' + return f"<{type(self).__qualname__} at {id(self):#x} {set_status}>" # # Barrier # diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index 3bc5b8f3d79b0..b2d656ab42897 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -1645,7 +1645,20 @@ def test_event(self): self.assertEqual(wait(), True) p.join() -# + def test_repr(self) -> None: + event = self.Event() + if self.TYPE == 'processes': + self.assertRegex(repr(event), r"") + event.set() + self.assertRegex(repr(event), r"") + event.clear() + self.assertRegex(repr(event), r"") + elif self.TYPE == 'manager': + self.assertRegex(repr(event), r" https://github.com/python/cpython/commit/2c2ee83c4db4dbd54017dc364bbefc70fa75ea5d commit: 2c2ee83c4db4dbd54017dc364bbefc70fa75ea5d branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-09T05:17:36-08:00 summary: bpo-45391: mark UnionType as a class in documentation (GH-28757) Signed-off-by: Bern?t G?bor (cherry picked from commit e2cfc89e099b8fad5d8d5bd7f59dadffb6078778) Co-authored-by: Bern?t G?bor files: M Doc/library/types.rst diff --git a/Doc/library/types.rst b/Doc/library/types.rst index 2314b02c7449c..5cd42f1fc2928 100644 --- a/Doc/library/types.rst +++ b/Doc/library/types.rst @@ -312,7 +312,7 @@ Standard names are defined for the following types: This type can now be subclassed. -.. data:: UnionType +.. class:: UnionType The type of :ref:`union type expressions`. From webhook-mailer at python.org Thu Dec 9 08:53:55 2021 From: webhook-mailer at python.org (pablogsal) Date: Thu, 09 Dec 2021 13:53:55 -0000 Subject: [Python-checkins] bpo-46025: Fix a crash in the atexit module for auto-unregistering functions (GH-30002) Message-ID: https://github.com/python/cpython/commit/f0d290d25cad66e615ada68ba190b8a23ac1deaa commit: f0d290d25cad66e615ada68ba190b8a23ac1deaa branch: main author: Pablo Galindo Salgado committer: pablogsal date: 2021-12-09T13:53:44Z summary: bpo-46025: Fix a crash in the atexit module for auto-unregistering functions (GH-30002) files: A Misc/NEWS.d/next/Core and Builtins/2021-12-09-11-41-35.bpo-46025.pkEvW9.rst M Lib/test/_test_atexit.py M Modules/atexitmodule.c diff --git a/Lib/test/_test_atexit.py b/Lib/test/_test_atexit.py index a31658531113b..55d2808334917 100644 --- a/Lib/test/_test_atexit.py +++ b/Lib/test/_test_atexit.py @@ -116,6 +116,21 @@ def test_bound_methods(self): atexit._run_exitfuncs() self.assertEqual(l, [5]) + def test_atexit_with_unregistered_function(self): + # See bpo-46025 for more info + def func(): + atexit.unregister(func) + 1/0 + atexit.register(func) + try: + with support.catch_unraisable_exception() as cm: + atexit._run_exitfuncs() + self.assertEqual(cm.unraisable.object, func) + self.assertEqual(cm.unraisable.exc_type, ZeroDivisionError) + self.assertEqual(type(cm.unraisable.exc_value), ZeroDivisionError) + finally: + atexit.unregister(func) + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-09-11-41-35.bpo-46025.pkEvW9.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-09-11-41-35.bpo-46025.pkEvW9.rst new file mode 100644 index 0000000000000..dd2f1ff4731e7 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-09-11-41-35.bpo-46025.pkEvW9.rst @@ -0,0 +1,2 @@ +Fix a crash in the :mod:`atexit` module involving functions that unregister +themselves before raising exceptions. Patch by Pablo Galindo. diff --git a/Modules/atexitmodule.c b/Modules/atexitmodule.c index e536b4abe295f..95c653cf4782a 100644 --- a/Modules/atexitmodule.c +++ b/Modules/atexitmodule.c @@ -93,13 +93,16 @@ atexit_callfuncs(struct atexit_state *state) continue; } + // bpo-46025: Increment the refcount of cb->func as the call itself may unregister it + PyObject* the_func = Py_NewRef(cb->func); PyObject *res = PyObject_Call(cb->func, cb->args, cb->kwargs); if (res == NULL) { - _PyErr_WriteUnraisableMsg("in atexit callback", cb->func); + _PyErr_WriteUnraisableMsg("in atexit callback", the_func); } else { Py_DECREF(res); } + Py_DECREF(the_func); } atexit_cleanup(state); From webhook-mailer at python.org Thu Dec 9 09:24:43 2021 From: webhook-mailer at python.org (tiran) Date: Thu, 09 Dec 2021 14:24:43 -0000 Subject: [Python-checkins] bpo-46016: Fix rest syntax of GH-29993 (GH-30006) Message-ID: https://github.com/python/cpython/commit/b123ad8030a4ad15c8dbb7cb3638caf625943878 commit: b123ad8030a4ad15c8dbb7cb3638caf625943878 branch: main author: Kumar Aditya committer: tiran date: 2021-12-09T15:24:32+01:00 summary: bpo-46016: Fix rest syntax of GH-29993 (GH-30006) files: M Doc/whatsnew/3.11.rst M Misc/NEWS.d/next/Library/2021-12-08-19-15-03.bpo-46016.s9PuyF.rst diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 4a113cdb8905c..7a828663e7f34 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -332,7 +332,7 @@ unicodedata fcntl ----- -* On FreeBSD, the `F_DUP2FD` and `F_DUP2FD_CLOEXEC` flags respectively +* On FreeBSD, the :attr:`F_DUP2FD` and :attr:`F_DUP2FD_CLOEXEC` flags respectively are supported, the former equals to ``dup2`` usage while the latter set the ``FD_CLOEXEC`` flag in addition. diff --git a/Misc/NEWS.d/next/Library/2021-12-08-19-15-03.bpo-46016.s9PuyF.rst b/Misc/NEWS.d/next/Library/2021-12-08-19-15-03.bpo-46016.s9PuyF.rst index 7308c542aacf5..485bd86f3145e 100644 --- a/Misc/NEWS.d/next/Library/2021-12-08-19-15-03.bpo-46016.s9PuyF.rst +++ b/Misc/NEWS.d/next/Library/2021-12-08-19-15-03.bpo-46016.s9PuyF.rst @@ -1 +1 @@ -Adding `F_DUP2FD` and `F_DUP2FD_CLOEXEC` constants from FreeBSD into the fcntl module. +Adding :attr:`F_DUP2FD` and :attr:`F_DUP2FD_CLOEXEC` constants from FreeBSD into the fcntl module. From webhook-mailer at python.org Thu Dec 9 09:38:11 2021 From: webhook-mailer at python.org (iritkatriel) Date: Thu, 09 Dec 2021 14:38:11 -0000 Subject: [Python-checkins] bpo-45635: continue refactor of print_exception() to standardize error handling (GH-29996) Message-ID: https://github.com/python/cpython/commit/dc4a212bd305831cb4b187a2e0cc82666fcb15ca commit: dc4a212bd305831cb4b187a2e0cc82666fcb15ca branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-12-09T14:38:00Z summary: bpo-45635: continue refactor of print_exception() to standardize error handling (GH-29996) Co-authored-by: Erlend Egeberg Aasland files: M Python/pythonrun.c diff --git a/Python/pythonrun.c b/Python/pythonrun.c index cfc39361d5fcb..74b497c8f0627 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1040,6 +1040,78 @@ print_exception_message(struct exception_print_context *ctx, PyObject *type, return 0; } +static int +print_exception_suggestions(struct exception_print_context *ctx, + PyObject *value) +{ + PyObject *f = ctx->file; + PyObject *suggestions = _Py_Offer_Suggestions(value); + if (suggestions) { + // Add a trailer ". Did you mean: (...)?" + if (PyFile_WriteString(". Did you mean: '", f) < 0) { + goto error; + } + if (PyFile_WriteObject(suggestions, f, Py_PRINT_RAW) < 0) { + goto error; + } + if (PyFile_WriteString("'?", f) < 0) { + goto error; + } + Py_DECREF(suggestions); + } + else if (PyErr_Occurred()) { + PyErr_Clear(); + } + return 0; +error: + Py_XDECREF(suggestions); + return -1; +} + +static int +print_exception_note(struct exception_print_context *ctx, PyObject *value) +{ + PyObject *f = ctx->file; + _Py_IDENTIFIER(__note__); + + PyObject *note = _PyObject_GetAttrId(value, &PyId___note__); + if (note == NULL) { + return -1; + } + if (!PyUnicode_Check(note)) { + Py_DECREF(note); + return 0; + } + + PyObject *lines = PyUnicode_Splitlines(note, 1); + Py_DECREF(note); + + if (lines == NULL) { + return -1; + } + + Py_ssize_t n = PyList_GET_SIZE(lines); + for (Py_ssize_t i = 0; i < n; i++) { + PyObject *line = PyList_GET_ITEM(lines, i); + assert(PyUnicode_Check(line)); + if (write_indented_margin(ctx, f) < 0) { + goto error; + } + if (PyFile_WriteObject(line, f, Py_PRINT_RAW) < 0) { + goto error; + } + } + if (PyFile_WriteString("\n", f) < 0) { + goto error; + } + + Py_DECREF(lines); + return 0; +error: + Py_DECREF(lines); + return -1; +} + static void print_exception(struct exception_print_context *ctx, PyObject *value) { @@ -1073,13 +1145,12 @@ print_exception(struct exception_print_context *ctx, PyObject *value) PyErr_Clear(); } else { - PyObject *line; Py_DECREF(value); value = message; - line = PyUnicode_FromFormat(" File \"%S\", line %zd\n", - filename, lineno); + PyObject *line = PyUnicode_FromFormat(" File \"%S\", line %zd\n", + filename, lineno); Py_DECREF(filename); if (line != NULL) { err = write_indented_margin(ctx, f); @@ -1118,59 +1189,16 @@ print_exception(struct exception_print_context *ctx, PyObject *value) if (err == 0) { err = print_exception_message(ctx, type, value); } - - /* try to write a newline in any case */ - if (err < 0) { - PyErr_Clear(); + if (err == 0) { + err = print_exception_suggestions(ctx, value); } - PyObject* suggestions = _Py_Offer_Suggestions(value); - if (suggestions) { - // Add a trailer ". Did you mean: (...)?" - err = PyFile_WriteString(". Did you mean: '", f); - if (err == 0) { - err = PyFile_WriteObject(suggestions, f, Py_PRINT_RAW); - err += PyFile_WriteString("'?", f); - } - Py_DECREF(suggestions); - } else if (PyErr_Occurred()) { - PyErr_Clear(); + if (err == 0) { + err = PyFile_WriteString("\n", f); } - err += PyFile_WriteString("\n", f); - if (err == 0 && PyExceptionInstance_Check(value)) { - _Py_IDENTIFIER(__note__); - - PyObject *note = _PyObject_GetAttrId(value, &PyId___note__); - if (note == NULL) { - err = -1; - } - if (err == 0 && PyUnicode_Check(note)) { - _Py_static_string(PyId_newline, "\n"); - PyObject *lines = PyUnicode_Split( - note, _PyUnicode_FromId(&PyId_newline), -1); - if (lines == NULL) { - err = -1; - } - else { - Py_ssize_t n = PyList_GET_SIZE(lines); - for (Py_ssize_t i = 0; i < n; i++) { - if (err == 0) { - PyObject *line = PyList_GET_ITEM(lines, i); - assert(PyUnicode_Check(line)); - err = write_indented_margin(ctx, f); - if (err == 0) { - err = PyFile_WriteObject(line, f, Py_PRINT_RAW); - } - if (err == 0) { - err = PyFile_WriteString("\n", f); - } - } - } - } - Py_DECREF(lines); - } - Py_XDECREF(note); + err = print_exception_note(ctx, value); } + Py_DECREF(value); /* If an error happened here, don't show it. XXX This is wrong, but too many callers rely on this behavior. */ @@ -1194,36 +1222,35 @@ print_chained(struct exception_print_context* ctx, PyObject *value, const char * message, const char *tag) { PyObject *f = ctx->file; - bool need_close = ctx->need_close; - - int err = Py_EnterRecursiveCall(" in print_chained"); - if (err == 0) { - print_exception_recursive(ctx, value); - Py_LeaveRecursiveCall(); - if (err == 0) { - err = write_indented_margin(ctx, f); - } - if (err == 0) { - err = PyFile_WriteString("\n", f); - } - if (err == 0) { - err = write_indented_margin(ctx, f); - } - if (err == 0) { - err = PyFile_WriteString(message, f); - } - if (err == 0) { - err = write_indented_margin(ctx, f); - } - if (err == 0) { - err = PyFile_WriteString("\n", f); - } + if (Py_EnterRecursiveCall(" in print_chained") < 0) { + return -1; } - + bool need_close = ctx->need_close; + print_exception_recursive(ctx, value); ctx->need_close = need_close; - return err; + Py_LeaveRecursiveCall(); + + if (write_indented_margin(ctx, f) < 0) { + return -1; + } + if (PyFile_WriteString("\n", f) < 0) { + return -1; + } + if (write_indented_margin(ctx, f) < 0) { + return -1; + } + if (PyFile_WriteString(message, f) < 0) { + return -1; + } + if (write_indented_margin(ctx, f) < 0) { + return -1; + } + if (PyFile_WriteString("\n", f) < 0) { + return -1; + } + return 0; } static void From webhook-mailer at python.org Thu Dec 9 10:16:20 2021 From: webhook-mailer at python.org (pablogsal) Date: Thu, 09 Dec 2021 15:16:20 -0000 Subject: [Python-checkins] bpo-46025: Fix a crash in the atexit module for auto-unregistering functions (GH-30002) (GH-30005) Message-ID: https://github.com/python/cpython/commit/934a24c641da5bc4bdb724e901adc20f9a5dff40 commit: 934a24c641da5bc4bdb724e901adc20f9a5dff40 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: pablogsal date: 2021-12-09T15:16:09Z summary: bpo-46025: Fix a crash in the atexit module for auto-unregistering functions (GH-30002) (GH-30005) (cherry picked from commit f0d290d25cad66e615ada68ba190b8a23ac1deaa) Co-authored-by: Pablo Galindo Salgado Co-authored-by: Pablo Galindo Salgado files: A Misc/NEWS.d/next/Core and Builtins/2021-12-09-11-41-35.bpo-46025.pkEvW9.rst M Lib/test/_test_atexit.py M Modules/atexitmodule.c diff --git a/Lib/test/_test_atexit.py b/Lib/test/_test_atexit.py index a31658531113b..55d2808334917 100644 --- a/Lib/test/_test_atexit.py +++ b/Lib/test/_test_atexit.py @@ -116,6 +116,21 @@ def test_bound_methods(self): atexit._run_exitfuncs() self.assertEqual(l, [5]) + def test_atexit_with_unregistered_function(self): + # See bpo-46025 for more info + def func(): + atexit.unregister(func) + 1/0 + atexit.register(func) + try: + with support.catch_unraisable_exception() as cm: + atexit._run_exitfuncs() + self.assertEqual(cm.unraisable.object, func) + self.assertEqual(cm.unraisable.exc_type, ZeroDivisionError) + self.assertEqual(type(cm.unraisable.exc_value), ZeroDivisionError) + finally: + atexit.unregister(func) + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-09-11-41-35.bpo-46025.pkEvW9.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-09-11-41-35.bpo-46025.pkEvW9.rst new file mode 100644 index 0000000000000..dd2f1ff4731e7 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-09-11-41-35.bpo-46025.pkEvW9.rst @@ -0,0 +1,2 @@ +Fix a crash in the :mod:`atexit` module involving functions that unregister +themselves before raising exceptions. Patch by Pablo Galindo. diff --git a/Modules/atexitmodule.c b/Modules/atexitmodule.c index e536b4abe295f..95c653cf4782a 100644 --- a/Modules/atexitmodule.c +++ b/Modules/atexitmodule.c @@ -93,13 +93,16 @@ atexit_callfuncs(struct atexit_state *state) continue; } + // bpo-46025: Increment the refcount of cb->func as the call itself may unregister it + PyObject* the_func = Py_NewRef(cb->func); PyObject *res = PyObject_Call(cb->func, cb->args, cb->kwargs); if (res == NULL) { - _PyErr_WriteUnraisableMsg("in atexit callback", cb->func); + _PyErr_WriteUnraisableMsg("in atexit callback", the_func); } else { Py_DECREF(res); } + Py_DECREF(the_func); } atexit_cleanup(state); From webhook-mailer at python.org Thu Dec 9 11:51:17 2021 From: webhook-mailer at python.org (gvanrossum) Date: Thu, 09 Dec 2021 16:51:17 -0000 Subject: [Python-checkins] bpo-45654: Freeze the runpy module and stuff it imports (GH-29903) Message-ID: https://github.com/python/cpython/commit/44b0e76f2a80c9a78242b7542b8b1218d244af07 commit: 44b0e76f2a80c9a78242b7542b8b1218d244af07 branch: main author: Kumar Aditya committer: gvanrossum date: 2021-12-09T08:51:09-08:00 summary: bpo-45654: Freeze the runpy module and stuff it imports (GH-29903) files: A Misc/NEWS.d/next/Core and Builtins/2021-12-09-11-57-43.bpo-45654.MZc7ei.rst M Makefile.pre.in M PCbuild/_freeze_module.vcxproj M PCbuild/_freeze_module.vcxproj.filters M PCbuild/pythoncore.vcxproj M Python/frozen.c M Tools/scripts/freeze_modules.py diff --git a/Makefile.pre.in b/Makefile.pre.in index 8e6e553554de1..f6801353cfeb4 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -490,6 +490,10 @@ DEEPFREEZE_OBJS = \ Python/deepfreeze/os.o \ Python/deepfreeze/site.o \ Python/deepfreeze/stat.o \ + Python/deepfreeze/types.o \ + Python/deepfreeze/importlib.util.o \ + Python/deepfreeze/importlib.machinery.o \ + Python/deepfreeze/runpy.o \ Python/deepfreeze/__hello__.o \ Python/deepfreeze/__phello__.o \ Python/deepfreeze/__phello__.ham.o \ @@ -1010,6 +1014,18 @@ Python/deepfreeze/site.c: Python/frozen_modules/site.h $(DEEPFREEZE_DEPS) Python/deepfreeze/stat.c: Python/frozen_modules/stat.h $(DEEPFREEZE_DEPS) $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/stat.h -m stat -o Python/deepfreeze/stat.c +Python/deepfreeze/types.c: Python/frozen_modules/types.h $(DEEPFREEZE_DEPS) + $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/types.h -m types -o Python/deepfreeze/types.c + +Python/deepfreeze/importlib.util.c: Python/frozen_modules/importlib.util.h $(DEEPFREEZE_DEPS) + $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/importlib.util.h -m importlib.util -o Python/deepfreeze/importlib.util.c + +Python/deepfreeze/importlib.machinery.c: Python/frozen_modules/importlib.machinery.h $(DEEPFREEZE_DEPS) + $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/importlib.machinery.h -m importlib.machinery -o Python/deepfreeze/importlib.machinery.c + +Python/deepfreeze/runpy.c: Python/frozen_modules/runpy.h $(DEEPFREEZE_DEPS) + $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/runpy.h -m runpy -o Python/deepfreeze/runpy.c + Python/deepfreeze/__hello__.c: Python/frozen_modules/__hello__.h $(DEEPFREEZE_DEPS) $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/__hello__.h -m __hello__ -o Python/deepfreeze/__hello__.c @@ -1049,6 +1065,10 @@ FROZEN_FILES_IN = \ Lib/os.py \ Lib/site.py \ Lib/stat.py \ + Lib/types.py \ + Lib/importlib/util.py \ + Lib/importlib/machinery.py \ + Lib/runpy.py \ Lib/__hello__.py \ Lib/__phello__/__init__.py \ Lib/__phello__/ham/__init__.py \ @@ -1071,6 +1091,10 @@ FROZEN_FILES_OUT = \ Python/frozen_modules/os.h \ Python/frozen_modules/site.h \ Python/frozen_modules/stat.h \ + Python/frozen_modules/types.h \ + Python/frozen_modules/importlib.util.h \ + Python/frozen_modules/importlib.machinery.h \ + Python/frozen_modules/runpy.h \ Python/frozen_modules/__hello__.h \ Python/frozen_modules/__phello__.h \ Python/frozen_modules/__phello__.ham.h \ @@ -1130,6 +1154,18 @@ Python/frozen_modules/site.h: $(FREEZE_MODULE) Lib/site.py Python/frozen_modules/stat.h: $(FREEZE_MODULE) Lib/stat.py $(FREEZE_MODULE) stat $(srcdir)/Lib/stat.py Python/frozen_modules/stat.h +Python/frozen_modules/types.h: $(FREEZE_MODULE) Lib/types.py + $(FREEZE_MODULE) types $(srcdir)/Lib/types.py Python/frozen_modules/types.h + +Python/frozen_modules/importlib.util.h: $(FREEZE_MODULE) Lib/importlib/util.py + $(FREEZE_MODULE) importlib.util $(srcdir)/Lib/importlib/util.py Python/frozen_modules/importlib.util.h + +Python/frozen_modules/importlib.machinery.h: $(FREEZE_MODULE) Lib/importlib/machinery.py + $(FREEZE_MODULE) importlib.machinery $(srcdir)/Lib/importlib/machinery.py Python/frozen_modules/importlib.machinery.h + +Python/frozen_modules/runpy.h: $(FREEZE_MODULE) Lib/runpy.py + $(FREEZE_MODULE) runpy $(srcdir)/Lib/runpy.py Python/frozen_modules/runpy.h + Python/frozen_modules/__hello__.h: $(FREEZE_MODULE) Lib/__hello__.py $(FREEZE_MODULE) __hello__ $(srcdir)/Lib/__hello__.py Python/frozen_modules/__hello__.h diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-09-11-57-43.bpo-45654.MZc7ei.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-09-11-57-43.bpo-45654.MZc7ei.rst new file mode 100644 index 0000000000000..9072558a30e9a --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-09-11-57-43.bpo-45654.MZc7ei.rst @@ -0,0 +1 @@ +Deepfreeze :mod:`runpy`, patch by Kumar Aditya. \ No newline at end of file diff --git a/PCbuild/_freeze_module.vcxproj b/PCbuild/_freeze_module.vcxproj index 07a6bfdde7402..2c06a8956ae45 100644 --- a/PCbuild/_freeze_module.vcxproj +++ b/PCbuild/_freeze_module.vcxproj @@ -330,6 +330,34 @@ $(IntDir)stat.g.c $(PySourcePath)Python\deepfreeze\df.stat.c + + types + $(IntDir)types.g.h + $(PySourcePath)Python\frozen_modules\types.h + $(IntDir)types.g.c + $(PySourcePath)Python\deepfreeze\df.types.c + + + importlib.util + $(IntDir)importlib.util.g.h + $(PySourcePath)Python\frozen_modules\importlib.util.h + $(IntDir)importlib.util.g.c + $(PySourcePath)Python\deepfreeze\df.importlib.util.c + + + importlib.machinery + $(IntDir)importlib.machinery.g.h + $(PySourcePath)Python\frozen_modules\importlib.machinery.h + $(IntDir)importlib.machinery.g.c + $(PySourcePath)Python\deepfreeze\df.importlib.machinery.c + + + runpy + $(IntDir)runpy.g.h + $(PySourcePath)Python\frozen_modules\runpy.h + $(IntDir)runpy.g.c + $(PySourcePath)Python\deepfreeze\df.runpy.c + __hello__ $(IntDir)__hello__.g.h diff --git a/PCbuild/_freeze_module.vcxproj.filters b/PCbuild/_freeze_module.vcxproj.filters index 1c8f1b0dcf449..7690e5ee58890 100644 --- a/PCbuild/_freeze_module.vcxproj.filters +++ b/PCbuild/_freeze_module.vcxproj.filters @@ -447,6 +447,18 @@ Python Files + + Python Files + + + Python Files + + + Python Files + + + Python Files + Python Files diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 119650a1eec51..a2ee95e0ae9fc 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -532,6 +532,10 @@ + + + + diff --git a/Python/frozen.c b/Python/frozen.c index 9f43db70886f7..377c32249a83e 100644 --- a/Python/frozen.c +++ b/Python/frozen.c @@ -53,6 +53,10 @@ #include "frozen_modules/os.h" #include "frozen_modules/site.h" #include "frozen_modules/stat.h" +#include "frozen_modules/types.h" +#include "frozen_modules/importlib.util.h" +#include "frozen_modules/importlib.machinery.h" +#include "frozen_modules/runpy.h" #include "frozen_modules/__hello__.h" #include "frozen_modules/__phello__.h" #include "frozen_modules/__phello__.ham.h" @@ -79,6 +83,10 @@ extern PyObject *_Py_get_posixpath_toplevel(void); extern PyObject *_Py_get_os_toplevel(void); extern PyObject *_Py_get_site_toplevel(void); extern PyObject *_Py_get_stat_toplevel(void); +extern PyObject *_Py_get_types_toplevel(void); +extern PyObject *_Py_get_importlib_util_toplevel(void); +extern PyObject *_Py_get_importlib_machinery_toplevel(void); +extern PyObject *_Py_get_runpy_toplevel(void); extern PyObject *_Py_get___hello___toplevel(void); extern PyObject *_Py_get___hello___toplevel(void); extern PyObject *_Py_get___hello___toplevel(void); @@ -116,6 +124,12 @@ static const struct _frozen stdlib_modules[] = { {"os", _Py_M__os, (int)sizeof(_Py_M__os), GET_CODE(os)}, {"site", _Py_M__site, (int)sizeof(_Py_M__site), GET_CODE(site)}, {"stat", _Py_M__stat, (int)sizeof(_Py_M__stat), GET_CODE(stat)}, + + /* runpy - run module with -m */ + {"types", _Py_M__types, (int)sizeof(_Py_M__types), GET_CODE(types)}, + {"importlib.util", _Py_M__importlib_util, (int)sizeof(_Py_M__importlib_util), GET_CODE(importlib_util)}, + {"importlib.machinery", _Py_M__importlib_machinery, (int)sizeof(_Py_M__importlib_machinery), GET_CODE(importlib_machinery)}, + {"runpy", _Py_M__runpy, (int)sizeof(_Py_M__runpy), GET_CODE(runpy)}, {0, 0, 0} /* stdlib sentinel */ }; static const struct _frozen test_modules[] = { diff --git a/Tools/scripts/freeze_modules.py b/Tools/scripts/freeze_modules.py index 363a2e66bef52..b0c953159dc34 100644 --- a/Tools/scripts/freeze_modules.py +++ b/Tools/scripts/freeze_modules.py @@ -68,6 +68,12 @@ 'site', 'stat', ]), + ('runpy - run module with -m', [ + "types", + "importlib.util", + "importlib.machinery", + "runpy" + ]), (TESTS_SECTION, [ '__hello__', '__hello__ : __hello_alias__', From webhook-mailer at python.org Thu Dec 9 13:32:04 2021 From: webhook-mailer at python.org (zooba) Date: Thu, 09 Dec 2021 18:32:04 -0000 Subject: [Python-checkins] bpo-46018: Ensure that math.expm1 does not raise on underflow (GH-29997) Message-ID: https://github.com/python/cpython/commit/3363e1cb05d0d19ed172ea63606d8cb6268747fc commit: 3363e1cb05d0d19ed172ea63606d8cb6268747fc branch: main author: Steve Dower committer: zooba date: 2021-12-09T18:31:54Z summary: bpo-46018: Ensure that math.expm1 does not raise on underflow (GH-29997) files: A Misc/NEWS.d/next/Library/2021-12-09-00-44-42.bpo-46018.hkTI7v.rst M Modules/mathmodule.c diff --git a/Misc/NEWS.d/next/Library/2021-12-09-00-44-42.bpo-46018.hkTI7v.rst b/Misc/NEWS.d/next/Library/2021-12-09-00-44-42.bpo-46018.hkTI7v.rst new file mode 100644 index 0000000000000..6ff76f58779d2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-09-00-44-42.bpo-46018.hkTI7v.rst @@ -0,0 +1 @@ +Ensure that :func:`math.expm1` does not raise on underflow. diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 84b5b954b1051..011ce0afd3aec 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -985,9 +985,13 @@ is_error(double x) * On some platforms (Ubuntu/ia64) it seems that errno can be * set to ERANGE for subnormal results that do *not* underflow * to zero. So to be safe, we'll ignore ERANGE whenever the - * function result is less than one in absolute value. + * function result is less than 1.5 in absolute value. + * + * bpo-46018: Changed to 1.5 to ensure underflows in expm1() + * are correctly detected, since the function may underflow + * toward -1.0 rather than 0.0. */ - if (fabs(x) < 1.0) + if (fabs(x) < 1.5) result = 0; else PyErr_SetString(PyExc_OverflowError, From webhook-mailer at python.org Thu Dec 9 13:44:47 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Thu, 09 Dec 2021 18:44:47 -0000 Subject: [Python-checkins] Remove an outdated comment. (GH-30010) Message-ID: https://github.com/python/cpython/commit/d8a464ef0380692975d73a3a1513d901b6af8e65 commit: d8a464ef0380692975d73a3a1513d901b6af8e65 branch: main author: Serhiy Storchaka committer: serhiy-storchaka date: 2021-12-09T20:44:36+02:00 summary: Remove an outdated comment. (GH-30010) files: M Tools/clinic/clinic.py diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index f20fab61c4de8..4b4ebb8313adc 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -2820,8 +2820,6 @@ def converter_init(self, *, accept={object}): def parse_arg(self, argname, displayname): if self.format_unit == 'i': - # XXX PyFloat_Check can be removed after the end of the - # deprecation in _PyLong_FromNbIndexOrNbInt. return """ {paramname} = _PyLong_AsInt({argname}); if ({paramname} == -1 && PyErr_Occurred()) {{{{ From webhook-mailer at python.org Thu Dec 9 13:56:04 2021 From: webhook-mailer at python.org (miss-islington) Date: Thu, 09 Dec 2021 18:56:04 -0000 Subject: [Python-checkins] bpo-46018: Ensure that math.expm1 does not raise on underflow (GH-29997) Message-ID: https://github.com/python/cpython/commit/5ae4265b8c8042c496e569b6dbf9ef107e1d5b31 commit: 5ae4265b8c8042c496e569b6dbf9ef107e1d5b31 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-09T10:55:53-08:00 summary: bpo-46018: Ensure that math.expm1 does not raise on underflow (GH-29997) (cherry picked from commit 3363e1cb05d0d19ed172ea63606d8cb6268747fc) Co-authored-by: Steve Dower files: A Misc/NEWS.d/next/Library/2021-12-09-00-44-42.bpo-46018.hkTI7v.rst M Modules/mathmodule.c diff --git a/Misc/NEWS.d/next/Library/2021-12-09-00-44-42.bpo-46018.hkTI7v.rst b/Misc/NEWS.d/next/Library/2021-12-09-00-44-42.bpo-46018.hkTI7v.rst new file mode 100644 index 0000000000000..6ff76f58779d2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-09-00-44-42.bpo-46018.hkTI7v.rst @@ -0,0 +1 @@ +Ensure that :func:`math.expm1` does not raise on underflow. diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index c974601b95e37..1f16849a3e6f6 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -971,9 +971,13 @@ is_error(double x) * On some platforms (Ubuntu/ia64) it seems that errno can be * set to ERANGE for subnormal results that do *not* underflow * to zero. So to be safe, we'll ignore ERANGE whenever the - * function result is less than one in absolute value. + * function result is less than 1.5 in absolute value. + * + * bpo-46018: Changed to 1.5 to ensure underflows in expm1() + * are correctly detected, since the function may underflow + * toward -1.0 rather than 0.0. */ - if (fabs(x) < 1.0) + if (fabs(x) < 1.5) result = 0; else PyErr_SetString(PyExc_OverflowError, From webhook-mailer at python.org Thu Dec 9 14:37:19 2021 From: webhook-mailer at python.org (miss-islington) Date: Thu, 09 Dec 2021 19:37:19 -0000 Subject: [Python-checkins] bpo-46018: Ensure that math.expm1 does not raise on underflow (GH-29997) Message-ID: https://github.com/python/cpython/commit/ca08655b808aed2e3abeb64cb67d98a79a661dda commit: ca08655b808aed2e3abeb64cb67d98a79a661dda branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-09T11:37:06-08:00 summary: bpo-46018: Ensure that math.expm1 does not raise on underflow (GH-29997) (cherry picked from commit 3363e1cb05d0d19ed172ea63606d8cb6268747fc) Co-authored-by: Steve Dower files: A Misc/NEWS.d/next/Library/2021-12-09-00-44-42.bpo-46018.hkTI7v.rst M Modules/mathmodule.c diff --git a/Misc/NEWS.d/next/Library/2021-12-09-00-44-42.bpo-46018.hkTI7v.rst b/Misc/NEWS.d/next/Library/2021-12-09-00-44-42.bpo-46018.hkTI7v.rst new file mode 100644 index 0000000000000..6ff76f58779d2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-09-00-44-42.bpo-46018.hkTI7v.rst @@ -0,0 +1 @@ +Ensure that :func:`math.expm1` does not raise on underflow. diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 16da00817b505..4534176adce14 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -977,9 +977,13 @@ is_error(double x) * On some platforms (Ubuntu/ia64) it seems that errno can be * set to ERANGE for subnormal results that do *not* underflow * to zero. So to be safe, we'll ignore ERANGE whenever the - * function result is less than one in absolute value. + * function result is less than 1.5 in absolute value. + * + * bpo-46018: Changed to 1.5 to ensure underflows in expm1() + * are correctly detected, since the function may underflow + * toward -1.0 rather than 0.0. */ - if (fabs(x) < 1.0) + if (fabs(x) < 1.5) result = 0; else PyErr_SetString(PyExc_OverflowError, From webhook-mailer at python.org Thu Dec 9 14:59:38 2021 From: webhook-mailer at python.org (ericsnowcurrently) Date: Thu, 09 Dec 2021 19:59:38 -0000 Subject: [Python-checkins] bpo-46008: Make runtime-global object/type lifecycle functions and state consistent. (gh-29998) Message-ID: https://github.com/python/cpython/commit/c8749b578324ad4089c8d014d9136bc42b065343 commit: c8749b578324ad4089c8d014d9136bc42b065343 branch: main author: Eric Snow committer: ericsnowcurrently date: 2021-12-09T12:59:26-07:00 summary: bpo-46008: Make runtime-global object/type lifecycle functions and state consistent. (gh-29998) This change is strictly renames and moving code around. It helps in the following ways: * ensures type-related init functions focus strictly on one of the three aspects (state, objects, types) * passes in PyInterpreterState * to all those functions, simplifying work on moving types/objects/state to the interpreter * consistent naming conventions help make what's going on more clear * keeping API related to a type in the corresponding header file makes it more obvious where to look for it https://bugs.python.org/issue46008 files: A Include/internal/pycore_bytesobject.h A Include/internal/pycore_exceptions.h A Include/internal/pycore_genobject.h A Include/internal/pycore_long_state.h A Include/internal/pycore_sliceobject.h A Include/internal/pycore_typeobject.h A Include/internal/pycore_unicodeobject.h M Include/internal/pycore_context.h M Include/internal/pycore_dict.h M Include/internal/pycore_floatobject.h M Include/internal/pycore_frame.h M Include/internal/pycore_hamt.h M Include/internal/pycore_interp.h M Include/internal/pycore_list.h M Include/internal/pycore_long.h M Include/internal/pycore_pyerrors.h M Include/internal/pycore_pylifecycle.h M Include/internal/pycore_runtime.h M Include/internal/pycore_structseq.h M Include/internal/pycore_tuple.h M Makefile.pre.in M Objects/bytesobject.c M Objects/exceptions.c M Objects/floatobject.c M Objects/genobject.c M Objects/listobject.c M Objects/longobject.c M Objects/object.c M Objects/structseq.c M Objects/tupleobject.c M Objects/typeobject.c M Objects/unicodeobject.c M PCbuild/pythoncore.vcxproj M PCbuild/pythoncore.vcxproj.filters M Python/context.c M Python/errors.c M Python/hamt.c M Python/pylifecycle.c diff --git a/Include/internal/pycore_bytesobject.h b/Include/internal/pycore_bytesobject.h new file mode 100644 index 0000000000000..b00ed9784ef34 --- /dev/null +++ b/Include/internal/pycore_bytesobject.h @@ -0,0 +1,30 @@ +#ifndef Py_INTERNAL_BYTESOBJECT_H +#define Py_INTERNAL_BYTESOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + + +/* runtime lifecycle */ + +extern PyStatus _PyBytes_InitGlobalObjects(PyInterpreterState *); +extern PyStatus _PyBytes_InitTypes(PyInterpreterState *); +extern void _PyBytes_Fini(PyInterpreterState *); + + +/* other API */ + +struct _Py_bytes_state { + PyObject *empty_string; + PyBytesObject *characters[256]; +}; + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_BYTESOBJECT_H */ diff --git a/Include/internal/pycore_context.h b/Include/internal/pycore_context.h index a482dd4212287..31ca0a43fae29 100644 --- a/Include/internal/pycore_context.h +++ b/Include/internal/pycore_context.h @@ -7,6 +7,32 @@ #include "pycore_hamt.h" /* PyHamtObject */ + +/* runtime lifecycle */ + +PyStatus _PyContext_InitTypes(PyInterpreterState *); +void _PyContext_Fini(PyInterpreterState *); + + +/* other API */ + +#ifndef WITH_FREELISTS +// without freelists +# define PyContext_MAXFREELIST 0 +#endif + +#ifndef PyContext_MAXFREELIST +# define PyContext_MAXFREELIST 255 +#endif + +struct _Py_context_state { +#if PyContext_MAXFREELIST > 0 + // List of free PyContext objects + PyContext *freelist; + int numfree; +#endif +}; + struct _pycontextobject { PyObject_HEAD PyContext *ctx_prev; @@ -36,7 +62,4 @@ struct _pycontexttokenobject { }; -int _PyContext_Init(void); -void _PyContext_Fini(PyInterpreterState *interp); - #endif /* !Py_INTERNAL_CONTEXT_H */ diff --git a/Include/internal/pycore_dict.h b/Include/internal/pycore_dict.h index 2f0536801ec6e..faa8bb49bb7a4 100644 --- a/Include/internal/pycore_dict.h +++ b/Include/internal/pycore_dict.h @@ -10,6 +10,32 @@ extern "C" { #endif +/* runtime lifecycle */ + +extern void _PyDict_Fini(PyInterpreterState *interp); + + +/* other API */ + +#ifndef WITH_FREELISTS +// without freelists +# define PyDict_MAXFREELIST 0 +#endif + +#ifndef PyDict_MAXFREELIST +# define PyDict_MAXFREELIST 80 +#endif + +struct _Py_dict_state { +#if PyDict_MAXFREELIST > 0 + /* Dictionary reuse scheme to save calls to malloc and free */ + PyDictObject *free_list[PyDict_MAXFREELIST]; + int numfree; + PyDictKeysObject *keys_free_list[PyDict_MAXFREELIST]; + int keys_numfree; +#endif +}; + typedef struct { /* Cached hash code of me_key. */ Py_hash_t me_hash; diff --git a/Include/internal/pycore_exceptions.h b/Include/internal/pycore_exceptions.h new file mode 100644 index 0000000000000..1651966dad936 --- /dev/null +++ b/Include/internal/pycore_exceptions.h @@ -0,0 +1,37 @@ +#ifndef Py_INTERNAL_EXCEPTIONS_H +#define Py_INTERNAL_EXCEPTIONS_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + + +/* runtime lifecycle */ + +extern PyStatus _PyExc_InitState(PyInterpreterState *); +extern PyStatus _PyExc_InitGlobalObjects(PyInterpreterState *); +extern PyStatus _PyExc_InitTypes(PyInterpreterState *); +extern void _PyExc_Fini(PyInterpreterState *); + + +/* other API */ + +struct _Py_exc_state { + // The dict mapping from errno codes to OSError subclasses + PyObject *errnomap; + PyBaseExceptionObject *memerrors_freelist; + int memerrors_numfree; + // The ExceptionGroup type + PyObject *PyExc_ExceptionGroup; +}; + +extern void _PyExc_ClearExceptionGroupType(PyInterpreterState *); + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_EXCEPTIONS_H */ diff --git a/Include/internal/pycore_floatobject.h b/Include/internal/pycore_floatobject.h index 18227c9e36925..be6045587de1c 100644 --- a/Include/internal/pycore_floatobject.h +++ b/Include/internal/pycore_floatobject.h @@ -8,6 +8,35 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif + +/* runtime lifecycle */ + +extern void _PyFloat_InitState(PyInterpreterState *); +extern PyStatus _PyFloat_InitTypes(PyInterpreterState *); +extern void _PyFloat_Fini(PyInterpreterState *); + + +/* other API */ + +#ifndef WITH_FREELISTS +// without freelists +# define PyFloat_MAXFREELIST 0 +#endif + +#ifndef PyFloat_MAXFREELIST +# define PyFloat_MAXFREELIST 100 +#endif + +struct _Py_float_state { +#if PyFloat_MAXFREELIST > 0 + /* Special free list + free_list is a singly-linked list of available PyFloatObjects, + linked via abuse of their ob_type members. */ + int numfree; + PyFloatObject *free_list; +#endif +}; + /* _PyFloat_{Pack,Unpack}{4,8} * * The struct and pickle (at least) modules need an efficient platform- diff --git a/Include/internal/pycore_frame.h b/Include/internal/pycore_frame.h index f4f7ab942c1ac..a55877b55fb8a 100644 --- a/Include/internal/pycore_frame.h +++ b/Include/internal/pycore_frame.h @@ -4,6 +4,14 @@ extern "C" { #endif + +/* runtime lifecycle */ + +extern void _PyFrame_Fini(PyInterpreterState *interp); + + +/* other API */ + /* These values are chosen so that the inline functions below all * compare f_state to zero. */ diff --git a/Include/internal/pycore_genobject.h b/Include/internal/pycore_genobject.h new file mode 100644 index 0000000000000..74a676df4ad53 --- /dev/null +++ b/Include/internal/pycore_genobject.h @@ -0,0 +1,46 @@ +#ifndef Py_INTERNAL_GENOBJECT_H +#define Py_INTERNAL_GENOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + + +/* runtime lifecycle */ + +extern void _PyAsyncGen_Fini(PyInterpreterState *); + + +/* other API */ + +#ifndef WITH_FREELISTS +// without freelists +# define _PyAsyncGen_MAXFREELIST 0 +#endif + +#ifndef _PyAsyncGen_MAXFREELIST +# define _PyAsyncGen_MAXFREELIST 80 +#endif + +struct _Py_async_gen_state { +#if _PyAsyncGen_MAXFREELIST > 0 + /* Freelists boost performance 6-10%; they also reduce memory + fragmentation, as _PyAsyncGenWrappedValue and PyAsyncGenASend + are short-living objects that are instantiated for every + __anext__() call. */ + struct _PyAsyncGenWrappedValue* value_freelist[_PyAsyncGen_MAXFREELIST]; + int value_numfree; + + struct PyAsyncGenASend* asend_freelist[_PyAsyncGen_MAXFREELIST]; + int asend_numfree; +#endif +}; + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_GENOBJECT_H */ diff --git a/Include/internal/pycore_hamt.h b/Include/internal/pycore_hamt.h index aaf655909551a..cf9c19e022d8a 100644 --- a/Include/internal/pycore_hamt.h +++ b/Include/internal/pycore_hamt.h @@ -8,6 +8,14 @@ #define _Py_HAMT_MAX_TREE_DEPTH 7 +/* runtime lifecycle */ + +PyStatus _PyHamt_InitTypes(PyInterpreterState *); +void _PyHamt_Fini(PyInterpreterState *); + + +/* other API */ + #define PyHamt_Check(o) Py_IS_TYPE(o, &_PyHamt_Type) @@ -110,7 +118,4 @@ PyObject * _PyHamt_NewIterValues(PyHamtObject *o); /* Return a Items iterator over "o". */ PyObject * _PyHamt_NewIterItems(PyHamtObject *o); -int _PyHamt_Init(void); -void _PyHamt_Fini(void); - #endif /* !Py_INTERNAL_HAMT_H */ diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index e421aa4bc4d7b..e4d7b1b8752ea 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -10,8 +10,18 @@ extern "C" { #include "pycore_atomic.h" // _Py_atomic_address #include "pycore_ast_state.h" // struct ast_state +#include "pycore_bytesobject.h" // struct _Py_bytes_state +#include "pycore_context.h" // struct _Py_context_state +#include "pycore_dict.h" // struct _Py_dict_state +#include "pycore_exceptions.h" // struct _Py_exc_state +#include "pycore_floatobject.h" // struct _Py_float_state +#include "pycore_genobject.h" // struct _Py_async_gen_state #include "pycore_gil.h" // struct _gil_runtime_state #include "pycore_gc.h" // struct _gc_runtime_state +#include "pycore_list.h" // struct _Py_list_state +#include "pycore_tuple.h" // struct _Py_tuple_state +#include "pycore_typeobject.h" // struct type_cache +#include "pycore_unicodeobject.h" // struct _Py_unicode_state #include "pycore_warnings.h" // struct _warnings_runtime_state struct _pending_calls { @@ -44,158 +54,6 @@ struct _ceval_state { #endif }; -/* fs_codec.encoding is initialized to NULL. - Later, it is set to a non-NULL string by _PyUnicode_InitEncodings(). */ -struct _Py_unicode_fs_codec { - char *encoding; // Filesystem encoding (encoded to UTF-8) - int utf8; // encoding=="utf-8"? - char *errors; // Filesystem errors (encoded to UTF-8) - _Py_error_handler error_handler; -}; - -struct _Py_bytes_state { - PyObject *empty_string; - PyBytesObject *characters[256]; -}; - -struct _Py_unicode_ids { - Py_ssize_t size; - PyObject **array; -}; - -struct _Py_unicode_state { - // The empty Unicode object is a singleton to improve performance. - PyObject *empty_string; - /* Single character Unicode strings in the Latin-1 range are being - shared as well. */ - PyObject *latin1[256]; - struct _Py_unicode_fs_codec fs_codec; - - /* This dictionary holds all interned unicode strings. Note that references - to strings in this dictionary are *not* counted in the string's ob_refcnt. - When the interned string reaches a refcnt of 0 the string deallocation - function will delete the reference from this dictionary. - - Another way to look at this is that to say that the actual reference - count of a string is: s->ob_refcnt + (s->state ? 2 : 0) - */ - PyObject *interned; - - // Unicode identifiers (_Py_Identifier): see _PyUnicode_FromId() - struct _Py_unicode_ids ids; -}; - -#ifndef WITH_FREELISTS -// without freelists -# define PyFloat_MAXFREELIST 0 -// for tuples only store empty tuple singleton -# define PyTuple_MAXSAVESIZE 1 -# define PyTuple_MAXFREELIST 1 -# define PyList_MAXFREELIST 0 -# define PyDict_MAXFREELIST 0 -# define _PyAsyncGen_MAXFREELIST 0 -# define PyContext_MAXFREELIST 0 -#endif - -#ifndef PyFloat_MAXFREELIST -# define PyFloat_MAXFREELIST 100 -#endif - -struct _Py_float_state { -#if PyFloat_MAXFREELIST > 0 - /* Special free list - free_list is a singly-linked list of available PyFloatObjects, - linked via abuse of their ob_type members. */ - int numfree; - PyFloatObject *free_list; -#endif -}; - -/* Speed optimization to avoid frequent malloc/free of small tuples */ -#ifndef PyTuple_MAXSAVESIZE - // Largest tuple to save on free list -# define PyTuple_MAXSAVESIZE 20 -#endif -#ifndef PyTuple_MAXFREELIST - // Maximum number of tuples of each size to save -# define PyTuple_MAXFREELIST 2000 -#endif - -struct _Py_tuple_state { -#if PyTuple_MAXSAVESIZE > 0 - /* Entries 1 up to PyTuple_MAXSAVESIZE are free lists, - entry 0 is the empty tuple () of which at most one instance - will be allocated. */ - PyTupleObject *free_list[PyTuple_MAXSAVESIZE]; - int numfree[PyTuple_MAXSAVESIZE]; -#endif -}; - -/* Empty list reuse scheme to save calls to malloc and free */ -#ifndef PyList_MAXFREELIST -# define PyList_MAXFREELIST 80 -#endif - -struct _Py_list_state { -#if PyList_MAXFREELIST > 0 - PyListObject *free_list[PyList_MAXFREELIST]; - int numfree; -#endif -}; - -#ifndef PyDict_MAXFREELIST -# define PyDict_MAXFREELIST 80 -#endif - -struct _Py_dict_state { -#if PyDict_MAXFREELIST > 0 - /* Dictionary reuse scheme to save calls to malloc and free */ - PyDictObject *free_list[PyDict_MAXFREELIST]; - int numfree; - PyDictKeysObject *keys_free_list[PyDict_MAXFREELIST]; - int keys_numfree; -#endif -}; - -#ifndef _PyAsyncGen_MAXFREELIST -# define _PyAsyncGen_MAXFREELIST 80 -#endif - -struct _Py_async_gen_state { -#if _PyAsyncGen_MAXFREELIST > 0 - /* Freelists boost performance 6-10%; they also reduce memory - fragmentation, as _PyAsyncGenWrappedValue and PyAsyncGenASend - are short-living objects that are instantiated for every - __anext__() call. */ - struct _PyAsyncGenWrappedValue* value_freelist[_PyAsyncGen_MAXFREELIST]; - int value_numfree; - - struct PyAsyncGenASend* asend_freelist[_PyAsyncGen_MAXFREELIST]; - int asend_numfree; -#endif -}; - -#ifndef PyContext_MAXFREELIST -# define PyContext_MAXFREELIST 255 -#endif - -struct _Py_context_state { -#if PyContext_MAXFREELIST > 0 - // List of free PyContext objects - PyContext *freelist; - int numfree; -#endif -}; - -struct _Py_exc_state { - // The dict mapping from errno codes to OSError subclasses - PyObject *errnomap; - PyBaseExceptionObject *memerrors_freelist; - int memerrors_numfree; - // The ExceptionGroup type - PyObject *PyExc_ExceptionGroup; -}; - // atexit state typedef struct { @@ -211,27 +69,6 @@ struct atexit_state { }; -// Type attribute lookup cache: speed up attribute and method lookups, -// see _PyType_Lookup(). -struct type_cache_entry { - unsigned int version; // initialized from type->tp_version_tag - PyObject *name; // reference to exactly a str or None - PyObject *value; // borrowed reference or NULL -}; - -#define MCACHE_SIZE_EXP 12 -#define MCACHE_STATS 0 - -struct type_cache { - struct type_cache_entry hashtable[1 << MCACHE_SIZE_EXP]; -#if MCACHE_STATS - size_t hits; - size_t misses; - size_t collisions; -#endif -}; - - /* interpreter state */ // The PyInterpreterState typedef is in Include/pystate.h. diff --git a/Include/internal/pycore_list.h b/Include/internal/pycore_list.h index f18fb052c49c7..0717a1f9563a2 100644 --- a/Include/internal/pycore_list.h +++ b/Include/internal/pycore_list.h @@ -11,6 +11,30 @@ extern "C" { #include "listobject.h" // _PyList_CAST() +/* runtime lifecycle */ + +extern void _PyList_Fini(PyInterpreterState *); + + +/* other API */ + +#ifndef WITH_FREELISTS +// without freelists +# define PyList_MAXFREELIST 0 +#endif + +/* Empty list reuse scheme to save calls to malloc and free */ +#ifndef PyList_MAXFREELIST +# define PyList_MAXFREELIST 80 +#endif + +struct _Py_list_state { +#if PyList_MAXFREELIST > 0 + PyListObject *free_list[PyList_MAXFREELIST]; + int numfree; +#endif +}; + #define _PyList_ITEMS(op) (_PyList_CAST(op)->ob_item) diff --git a/Include/internal/pycore_long.h b/Include/internal/pycore_long.h index b9f926996d810..a5639ceb6924a 100644 --- a/Include/internal/pycore_long.h +++ b/Include/internal/pycore_long.h @@ -8,18 +8,28 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#include "pycore_interp.h" // PyInterpreterState.small_ints +#include "pycore_long_state.h" // _PyLong_SMALL_INTS #include "pycore_pystate.h" // _PyThreadState_GET() +#include "pycore_runtime.h" // _PyRuntime + + +/* runtime lifecycle */ + +extern void _PyLong_InitGlobalObjects(PyInterpreterState *); +extern PyStatus _PyLong_InitTypes(PyInterpreterState *); + + +/* other API */ // Return a borrowed reference to the zero singleton. // The function cannot return NULL. static inline PyObject* _PyLong_GetZero(void) -{ return (PyObject *)&_PyRuntime.small_ints[_PY_NSMALLNEGINTS]; } +{ return (PyObject *)&_PyLong_SMALL_INTS[_PY_NSMALLNEGINTS]; } // Return a borrowed reference to the one singleton. // The function cannot return NULL. static inline PyObject* _PyLong_GetOne(void) -{ return (PyObject *)&_PyRuntime.small_ints[_PY_NSMALLNEGINTS+1]; } +{ return (PyObject *)&_PyLong_SMALL_INTS[_PY_NSMALLNEGINTS+1]; } PyObject *_PyLong_Add(PyLongObject *left, PyLongObject *right); PyObject *_PyLong_Multiply(PyLongObject *left, PyLongObject *right); diff --git a/Include/internal/pycore_long_state.h b/Include/internal/pycore_long_state.h new file mode 100644 index 0000000000000..5fe8e623a9eff --- /dev/null +++ b/Include/internal/pycore_long_state.h @@ -0,0 +1,33 @@ +#ifndef Py_INTERNAL_LONG_STATE_H +#define Py_INTERNAL_LONG_STATE_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +#define _PY_NSMALLPOSINTS 257 +#define _PY_NSMALLNEGINTS 5 + +// _PyLong_GetZero() and _PyLong_GetOne() must always be available +#if _PY_NSMALLPOSINTS < 2 +# error "_PY_NSMALLPOSINTS must be greater than 1" +#endif + +struct _Py_long_state { + /* Small integers are preallocated in this array so that they + * can be shared. + * The integers that are preallocated are those in the range + *-_PY_NSMALLNEGINTS (inclusive) to _PY_NSMALLPOSINTS (not inclusive). + */ + PyLongObject small_ints[_PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS]; +}; + +#define _PyLong_SMALL_INTS _PyRuntime.int_state.small_ints + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_LONG_STATE_H */ diff --git a/Include/internal/pycore_pyerrors.h b/Include/internal/pycore_pyerrors.h index 14ea182f4f47a..3134afeb86490 100644 --- a/Include/internal/pycore_pyerrors.h +++ b/Include/internal/pycore_pyerrors.h @@ -8,6 +8,14 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif + +/* runtime lifecycle */ + +extern PyStatus _PyErr_InitTypes(PyInterpreterState *); + + +/* other API */ + static inline PyObject* _PyErr_Occurred(PyThreadState *tstate) { assert(tstate != NULL); diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index 5e0f36ab2ae49..766e889f237b9 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -49,13 +49,6 @@ PyAPI_FUNC(int) _Py_IsLocaleCoercionTarget(const char *ctype_loc); /* Various one-time initializers */ -extern PyStatus _PyUnicode_Init(PyInterpreterState *interp); -extern PyStatus _PyUnicode_InitTypes(void); -extern PyStatus _PyBytes_Init(PyInterpreterState *interp); -extern int _PyStructSequence_Init(void); -extern void _PyLong_Init(PyInterpreterState *interp); -extern int _PyLong_InitTypes(void); -extern PyStatus _PyTuple_Init(PyInterpreterState *interp); extern PyStatus _PyFaulthandler_Init(int enable); extern int _PyTraceMalloc_Init(int enable); extern PyObject * _PyBuiltin_Init(PyInterpreterState *interp); @@ -65,15 +58,9 @@ extern PyStatus _PySys_Create( extern PyStatus _PySys_ReadPreinitWarnOptions(PyWideStringList *options); extern PyStatus _PySys_ReadPreinitXOptions(PyConfig *config); extern int _PySys_UpdateConfig(PyThreadState *tstate); -extern PyStatus _PyExc_Init(PyInterpreterState *interp); -extern PyStatus _PyErr_InitTypes(void); extern PyStatus _PyBuiltins_AddExceptions(PyObject * bltinmod); -extern void _PyFloat_Init(void); -extern int _PyFloat_InitTypes(void); extern PyStatus _Py_HashRandomization_Init(const PyConfig *); -extern PyStatus _PyTypes_Init(void); -extern PyStatus _PyTypes_InitSlotDefs(void); extern PyStatus _PyImportZip_Init(PyThreadState *tstate); extern PyStatus _PyGC_Init(PyInterpreterState *interp); extern PyStatus _PyAtExit_Init(PyInterpreterState *interp); @@ -81,28 +68,13 @@ extern PyStatus _PyAtExit_Init(PyInterpreterState *interp); /* Various internal finalizers */ -extern void _PyFrame_Fini(PyInterpreterState *interp); -extern void _PyDict_Fini(PyInterpreterState *interp); -extern void _PyTuple_Fini(PyInterpreterState *interp); -extern void _PyList_Fini(PyInterpreterState *interp); -extern void _PyBytes_Fini(PyInterpreterState *interp); -extern void _PyFloat_Fini(PyInterpreterState *interp); -extern void _PySlice_Fini(PyInterpreterState *interp); -extern void _PyAsyncGen_Fini(PyInterpreterState *interp); - extern int _PySignal_Init(int install_signal_handlers); extern void _PySignal_Fini(void); -extern void _PyExc_ClearExceptionGroupType(PyInterpreterState *interp); -extern void _PyExc_Fini(PyInterpreterState *interp); extern void _PyImport_Fini(void); extern void _PyImport_Fini2(void); extern void _PyGC_Fini(PyInterpreterState *interp); -extern void _PyType_Fini(PyInterpreterState *interp); extern void _Py_HashRandomization_Fini(void); -extern void _PyUnicode_Fini(PyInterpreterState *interp); -extern void _PyUnicode_ClearInterned(PyInterpreterState *interp); -extern void _PyLong_Fini(PyInterpreterState *interp); extern void _PyFaulthandler_Fini(void); extern void _PyHash_Fini(void); extern void _PyTraceMalloc_Fini(void); diff --git a/Include/internal/pycore_runtime.h b/Include/internal/pycore_runtime.h index 39e30b785a3cd..bd88510d1f056 100644 --- a/Include/internal/pycore_runtime.h +++ b/Include/internal/pycore_runtime.h @@ -10,14 +10,8 @@ extern "C" { #include "pycore_atomic.h" /* _Py_atomic_address */ #include "pycore_gil.h" // struct _gil_runtime_state - -#define _PY_NSMALLPOSINTS 257 -#define _PY_NSMALLNEGINTS 5 - -// _PyLong_GetZero() and _PyLong_GetOne() must always be available -#if _PY_NSMALLPOSINTS < 2 -# error "_PY_NSMALLPOSINTS must be greater than 1" -#endif +#include "pycore_long_state.h" // struct _Py_long_state +#include "pycore_unicodeobject.h" // struct _Py_unicode_runtime_ids /* ceval state */ @@ -57,13 +51,6 @@ typedef struct _Py_AuditHookEntry { void *userData; } _Py_AuditHookEntry; -struct _Py_unicode_runtime_ids { - PyThread_type_lock lock; - // next_index value must be preserved when Py_Initialize()/Py_Finalize() - // is called multiple times: see _PyUnicode_FromId() implementation. - Py_ssize_t next_index; -}; - /* Full Python runtime state */ typedef struct pyruntimestate { @@ -114,12 +101,7 @@ typedef struct pyruntimestate { unsigned long main_thread; - /* Small integers are preallocated in this array so that they - * can be shared. - * The integers that are preallocated are those in the range - *-_PY_NSMALLNEGINTS (inclusive) to _PY_NSMALLPOSINTS (not inclusive). - */ - PyLongObject small_ints[_PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS]; + struct _Py_long_state int_state; #define NEXITFUNCS 32 void (*exitfuncs[NEXITFUNCS])(void); diff --git a/Include/internal/pycore_sliceobject.h b/Include/internal/pycore_sliceobject.h new file mode 100644 index 0000000000000..e81834c041e41 --- /dev/null +++ b/Include/internal/pycore_sliceobject.h @@ -0,0 +1,20 @@ +#ifndef Py_INTERNAL_SLICEOBJECT_H +#define Py_INTERNAL_SLICEOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + + +/* runtime lifecycle */ + +extern void _PySlice_Fini(PyInterpreterState *); + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_SLICEOBJECT_H */ diff --git a/Include/internal/pycore_structseq.h b/Include/internal/pycore_structseq.h index 84c8d477e0dac..3a61cb9a12608 100644 --- a/Include/internal/pycore_structseq.h +++ b/Include/internal/pycore_structseq.h @@ -9,6 +9,13 @@ extern "C" { #endif +/* runtime lifecycle */ + +extern PyStatus _PyStructSequence_InitState(PyInterpreterState *); + + +/* other API */ + PyAPI_FUNC(int) _PyStructSequence_InitType( PyTypeObject *type, PyStructSequence_Desc *desc, diff --git a/Include/internal/pycore_tuple.h b/Include/internal/pycore_tuple.h index 79c827fe8800a..624c21caec1cc 100644 --- a/Include/internal/pycore_tuple.h +++ b/Include/internal/pycore_tuple.h @@ -10,6 +10,43 @@ extern "C" { #include "tupleobject.h" /* _PyTuple_CAST() */ + +/* runtime lifecycle */ + +extern PyStatus _PyTuple_InitGlobalObjects(PyInterpreterState *); +extern PyStatus _PyTuple_InitTypes(PyInterpreterState *); +extern void _PyTuple_Fini(PyInterpreterState *); + + +/* other API */ + +#ifndef WITH_FREELISTS +// without freelists +// for tuples only store empty tuple singleton +# define PyTuple_MAXSAVESIZE 1 +# define PyTuple_MAXFREELIST 1 +#endif + +/* Speed optimization to avoid frequent malloc/free of small tuples */ +#ifndef PyTuple_MAXSAVESIZE + // Largest tuple to save on free list +# define PyTuple_MAXSAVESIZE 20 +#endif +#ifndef PyTuple_MAXFREELIST + // Maximum number of tuples of each size to save +# define PyTuple_MAXFREELIST 2000 +#endif + +struct _Py_tuple_state { +#if PyTuple_MAXSAVESIZE > 0 + /* Entries 1 up to PyTuple_MAXSAVESIZE are free lists, + entry 0 is the empty tuple () of which at most one instance + will be allocated. */ + PyTupleObject *free_list[PyTuple_MAXSAVESIZE]; + int numfree[PyTuple_MAXSAVESIZE]; +#endif +}; + #define _PyTuple_ITEMS(op) (_PyTuple_CAST(op)->ob_item) extern PyObject *_PyTuple_FromArray(PyObject *const *, Py_ssize_t); diff --git a/Include/internal/pycore_typeobject.h b/Include/internal/pycore_typeobject.h new file mode 100644 index 0000000000000..7fd8a1f35092f --- /dev/null +++ b/Include/internal/pycore_typeobject.h @@ -0,0 +1,47 @@ +#ifndef Py_INTERNAL_TYPEOBJECT_H +#define Py_INTERNAL_TYPEOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + + +/* runtime lifecycle */ + +extern PyStatus _PyTypes_InitState(PyInterpreterState *); +extern PyStatus _PyTypes_InitTypes(PyInterpreterState *); +extern void _PyTypes_Fini(PyInterpreterState *); + + +/* other API */ + +// Type attribute lookup cache: speed up attribute and method lookups, +// see _PyType_Lookup(). +struct type_cache_entry { + unsigned int version; // initialized from type->tp_version_tag + PyObject *name; // reference to exactly a str or None + PyObject *value; // borrowed reference or NULL +}; + +#define MCACHE_SIZE_EXP 12 +#define MCACHE_STATS 0 + +struct type_cache { + struct type_cache_entry hashtable[1 << MCACHE_SIZE_EXP]; +#if MCACHE_STATS + size_t hits; + size_t misses; + size_t collisions; +#endif +}; + +extern PyStatus _PyTypes_InitSlotDefs(void); + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_TYPEOBJECT_H */ diff --git a/Include/internal/pycore_unicodeobject.h b/Include/internal/pycore_unicodeobject.h new file mode 100644 index 0000000000000..c50c42011a934 --- /dev/null +++ b/Include/internal/pycore_unicodeobject.h @@ -0,0 +1,71 @@ +#ifndef Py_INTERNAL_UNICODEOBJECT_H +#define Py_INTERNAL_UNICODEOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + + +/* runtime lifecycle */ + +extern void _PyUnicode_InitState(PyInterpreterState *); +extern PyStatus _PyUnicode_InitGlobalObjects(PyInterpreterState *); +extern PyStatus _PyUnicode_InitTypes(PyInterpreterState *); +extern void _PyUnicode_Fini(PyInterpreterState *); + + +/* other API */ + +struct _Py_unicode_runtime_ids { + PyThread_type_lock lock; + // next_index value must be preserved when Py_Initialize()/Py_Finalize() + // is called multiple times: see _PyUnicode_FromId() implementation. + Py_ssize_t next_index; +}; + +/* fs_codec.encoding is initialized to NULL. + Later, it is set to a non-NULL string by _PyUnicode_InitEncodings(). */ +struct _Py_unicode_fs_codec { + char *encoding; // Filesystem encoding (encoded to UTF-8) + int utf8; // encoding=="utf-8"? + char *errors; // Filesystem errors (encoded to UTF-8) + _Py_error_handler error_handler; +}; + +struct _Py_unicode_ids { + Py_ssize_t size; + PyObject **array; +}; + +struct _Py_unicode_state { + // The empty Unicode object is a singleton to improve performance. + PyObject *empty_string; + /* Single character Unicode strings in the Latin-1 range are being + shared as well. */ + PyObject *latin1[256]; + struct _Py_unicode_fs_codec fs_codec; + + /* This dictionary holds all interned unicode strings. Note that references + to strings in this dictionary are *not* counted in the string's ob_refcnt. + When the interned string reaches a refcnt of 0 the string deallocation + function will delete the reference from this dictionary. + + Another way to look at this is that to say that the actual reference + count of a string is: s->ob_refcnt + (s->state ? 2 : 0) + */ + PyObject *interned; + + // Unicode identifiers (_Py_Identifier): see _PyUnicode_FromId() + struct _Py_unicode_ids ids; +}; + +extern void _PyUnicode_ClearInterned(PyInterpreterState *); + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_UNICODEOBJECT_H */ diff --git a/Makefile.pre.in b/Makefile.pre.in index f6801353cfeb4..57928eead4384 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1576,6 +1576,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/internal/pycore_atomic_funcs.h \ $(srcdir)/Include/internal/pycore_bitutils.h \ $(srcdir)/Include/internal/pycore_bytes_methods.h \ + $(srcdir)/Include/internal/pycore_bytesobject.h \ $(srcdir)/Include/internal/pycore_call.h \ $(srcdir)/Include/internal/pycore_ceval.h \ $(srcdir)/Include/internal/pycore_code.h \ @@ -1584,10 +1585,12 @@ PYTHON_HEADERS= \ $(srcdir)/Include/internal/pycore_context.h \ $(srcdir)/Include/internal/pycore_dict.h \ $(srcdir)/Include/internal/pycore_dtoa.h \ + $(srcdir)/Include/internal/pycore_exceptions.h \ $(srcdir)/Include/internal/pycore_fileutils.h \ $(srcdir)/Include/internal/pycore_floatobject.h \ $(srcdir)/Include/internal/pycore_format.h \ $(srcdir)/Include/internal/pycore_function.h \ + $(srcdir)/Include/internal/pycore_genobject.h \ $(srcdir)/Include/internal/pycore_getopt.h \ $(srcdir)/Include/internal/pycore_gil.h \ $(srcdir)/Include/internal/pycore_hamt.h \ @@ -1598,6 +1601,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/internal/pycore_interpreteridobject.h \ $(srcdir)/Include/internal/pycore_list.h \ $(srcdir)/Include/internal/pycore_long.h \ + $(srcdir)/Include/internal/pycore_long_state.h \ $(srcdir)/Include/internal/pycore_moduleobject.h \ $(srcdir)/Include/internal/pycore_namespace.h \ $(srcdir)/Include/internal/pycore_object.h \ @@ -1609,14 +1613,17 @@ PYTHON_HEADERS= \ $(srcdir)/Include/internal/pycore_pymem.h \ $(srcdir)/Include/internal/pycore_pystate.h \ $(srcdir)/Include/internal/pycore_runtime.h \ + $(srcdir)/Include/internal/pycore_sliceobject.h \ $(srcdir)/Include/internal/pycore_strhex.h \ $(srcdir)/Include/internal/pycore_structseq.h \ $(srcdir)/Include/internal/pycore_symtable.h \ $(srcdir)/Include/internal/pycore_sysmodule.h \ $(srcdir)/Include/internal/pycore_traceback.h \ $(srcdir)/Include/internal/pycore_tuple.h \ + $(srcdir)/Include/internal/pycore_typeobject.h \ $(srcdir)/Include/internal/pycore_ucnhash.h \ $(srcdir)/Include/internal/pycore_unionobject.h \ + $(srcdir)/Include/internal/pycore_unicodeobject.h \ $(srcdir)/Include/internal/pycore_warnings.h \ $(DTRACE_HEADERS) \ \ diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 66fd2ecc3c41d..2f7e0a6dde6fe 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -5,6 +5,7 @@ #include "Python.h" #include "pycore_abstract.h" // _PyIndex_Check() #include "pycore_bytes_methods.h" // _Py_bytes_startswith() +#include "pycore_bytesobject.h" // struct _Py_bytes_state #include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_format.h" // F_LJUST #include "pycore_initconfig.h" // _PyStatus_OK() @@ -3086,7 +3087,7 @@ _PyBytes_Resize(PyObject **pv, Py_ssize_t newsize) PyStatus -_PyBytes_Init(PyInterpreterState *interp) +_PyBytes_InitGlobalObjects(PyInterpreterState *interp) { struct _Py_bytes_state *state = &interp->bytes; if (bytes_create_empty_string_singleton(state) < 0) { @@ -3096,6 +3097,25 @@ _PyBytes_Init(PyInterpreterState *interp) } +PyStatus +_PyBytes_InitTypes(PyInterpreterState *interp) +{ + if (!_Py_IsMainInterpreter(interp)) { + return _PyStatus_OK(); + } + + if (PyType_Ready(&PyBytes_Type) < 0) { + return _PyStatus_ERR("Can't initialize bytes type"); + } + + if (PyType_Ready(&PyBytesIter_Type) < 0) { + return _PyStatus_ERR("Can't initialize bytes iterator type"); + } + + return _PyStatus_OK(); +} + + void _PyBytes_Fini(PyInterpreterState *interp) { diff --git a/Objects/exceptions.c b/Objects/exceptions.c index e1a8c1363ef62..134015752560d 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -7,6 +7,7 @@ #define PY_SSIZE_T_CLEAN #include #include +#include "pycore_exceptions.h" // struct _Py_exc_state #include "pycore_initconfig.h" #include "pycore_object.h" #include "structmember.h" // PyMemberDef @@ -3189,10 +3190,8 @@ SimpleExtendsException(PyExc_Warning, ResourceWarning, #endif /* MS_WINDOWS */ PyStatus -_PyExc_Init(PyInterpreterState *interp) +_PyExc_InitTypes(PyInterpreterState *interp) { - struct _Py_exc_state *state = &interp->exc_state; - #define PRE_INIT(TYPE) \ if (!(_PyExc_ ## TYPE.tp_flags & Py_TPFLAGS_READY)) { \ if (PyType_Ready(&_PyExc_ ## TYPE) < 0) { \ @@ -3201,17 +3200,6 @@ _PyExc_Init(PyInterpreterState *interp) Py_INCREF(PyExc_ ## TYPE); \ } -#define ADD_ERRNO(TYPE, CODE) \ - do { \ - PyObject *_code = PyLong_FromLong(CODE); \ - assert(_PyObject_RealIsSubclass(PyExc_ ## TYPE, PyExc_OSError)); \ - if (!_code || PyDict_SetItem(state->errnomap, _code, PyExc_ ## TYPE)) { \ - Py_XDECREF(_code); \ - return _PyStatus_ERR("errmap insertion problem."); \ - } \ - Py_DECREF(_code); \ - } while (0) - PRE_INIT(BaseException); PRE_INIT(BaseExceptionGroup); PRE_INIT(Exception); @@ -3282,10 +3270,37 @@ _PyExc_Init(PyInterpreterState *interp) PRE_INIT(ProcessLookupError); PRE_INIT(TimeoutError); + return _PyStatus_OK(); + +#undef PRE_INIT +} + +PyStatus +_PyExc_InitGlobalObjects(PyInterpreterState *interp) +{ if (preallocate_memerrors() < 0) { return _PyStatus_NO_MEMORY(); } + return _PyStatus_OK(); +} + +PyStatus +_PyExc_InitState(PyInterpreterState *interp) +{ + struct _Py_exc_state *state = &interp->exc_state; + +#define ADD_ERRNO(TYPE, CODE) \ + do { \ + PyObject *_code = PyLong_FromLong(CODE); \ + assert(_PyObject_RealIsSubclass(PyExc_ ## TYPE, PyExc_OSError)); \ + if (!_code || PyDict_SetItem(state->errnomap, _code, PyExc_ ## TYPE)) { \ + Py_XDECREF(_code); \ + return _PyStatus_ERR("errmap insertion problem."); \ + } \ + Py_DECREF(_code); \ + } while (0) + /* Add exceptions to errnomap */ assert(state->errnomap == NULL); state->errnomap = PyDict_New(); @@ -3317,7 +3332,6 @@ _PyExc_Init(PyInterpreterState *interp) return _PyStatus_OK(); -#undef PRE_INIT #undef ADD_ERRNO } diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 7fc192e720117..f8620d6f8ef0b 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -6,6 +6,7 @@ #include "Python.h" #include "pycore_dtoa.h" // _Py_dg_dtoa() #include "pycore_floatobject.h" // _PyFloat_FormatAdvancedWriter() +#include "pycore_initconfig.h" // _PyStatus_OK() #include "pycore_interp.h" // _PyInterpreterState.float_state #include "pycore_long.h" // _PyLong_GetOne() #include "pycore_object.h" // _PyObject_Init() @@ -1981,8 +1982,12 @@ PyTypeObject PyFloat_Type = { }; void -_PyFloat_Init(void) +_PyFloat_InitState(PyInterpreterState *interp) { + if (!_Py_IsMainInterpreter(interp)) { + return; + } + /* We attempt to determine if this machine is using IEEE floating point formats by peering at the bits of some carefully chosen values. If it looks like we are on an @@ -2030,16 +2035,25 @@ _PyFloat_Init(void) float_format = detected_float_format; } -int -_PyFloat_InitTypes(void) +PyStatus +_PyFloat_InitTypes(PyInterpreterState *interp) { + if (!_Py_IsMainInterpreter(interp)) { + return _PyStatus_OK(); + } + + if (PyType_Ready(&PyFloat_Type) < 0) { + return _PyStatus_ERR("Can't initialize float type"); + } + /* Init float info */ if (FloatInfoType.tp_name == NULL) { if (PyStructSequence_InitType2(&FloatInfoType, &floatinfo_desc) < 0) { - return -1; + return _PyStatus_ERR("can't init float info type"); } } - return 0; + + return _PyStatus_OK(); } void diff --git a/Objects/genobject.c b/Objects/genobject.c index 147194c38a0a1..1b08b43ac22e9 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -3,6 +3,7 @@ #include "Python.h" #include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_ceval.h" // _PyEval_EvalFrame() +#include "pycore_genobject.h" // struct _Py_async_gen_state #include "pycore_object.h" // _PyObject_GC_UNTRACK() #include "pycore_pyerrors.h" // _PyErr_ClearExcState() #include "pycore_pystate.h" // _PyThreadState_GET() diff --git a/Objects/listobject.c b/Objects/listobject.c index be84cf9c330e3..e7023fb9eb1d2 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -3,6 +3,7 @@ #include "Python.h" #include "pycore_abstract.h" // _PyIndex_Check() #include "pycore_interp.h" // PyInterpreterState.list +#include "pycore_list.h" // struct _Py_list_state #include "pycore_object.h" // _PyObject_GC_TRACK() #include "pycore_tuple.h" // _PyTuple_FromArray() #include diff --git a/Objects/longobject.c b/Objects/longobject.c index ce4f0d72540d3..f6d5e7648be16 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -4,10 +4,11 @@ #include "Python.h" #include "pycore_bitutils.h" // _Py_popcount32() -#include "pycore_runtime.h" // _PY_NSMALLPOSINTS +#include "pycore_initconfig.h" // _PyStatus_OK() #include "pycore_long.h" // _Py_SmallInts #include "pycore_object.h" // _PyObject_InitVar() #include "pycore_pystate.h" // _Py_IsMainInterpreter() +#include "pycore_runtime.h" // _PY_NSMALLPOSINTS #include #include @@ -48,7 +49,7 @@ static PyObject * get_small_int(sdigit ival) { assert(IS_SMALL_INT(ival)); - PyObject *v = (PyObject *)&_PyRuntime.small_ints[_PY_NSMALLNEGINTS + ival]; + PyObject *v = (PyObject *)&_PyLong_SMALL_INTS[_PY_NSMALLNEGINTS + ival]; Py_INCREF(v); return v; } @@ -5828,31 +5829,51 @@ PyLong_GetInfo(void) return int_info; } + +/* runtime lifecycle */ + void -_PyLong_Init(PyInterpreterState *interp) +_PyLong_InitGlobalObjects(PyInterpreterState *interp) { - if (_PyRuntime.small_ints[0].ob_base.ob_base.ob_refcnt == 0) { - for (Py_ssize_t i=0; i < _PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS; i++) { - sdigit ival = (sdigit)i - _PY_NSMALLNEGINTS; - int size = (ival < 0) ? -1 : ((ival == 0) ? 0 : 1); - _PyRuntime.small_ints[i].ob_base.ob_base.ob_refcnt = 1; - _PyRuntime.small_ints[i].ob_base.ob_base.ob_type = &PyLong_Type; - _PyRuntime.small_ints[i].ob_base.ob_size = size; - _PyRuntime.small_ints[i].ob_digit[0] = (digit)abs(ival); - } + if (!_Py_IsMainInterpreter(interp)) { + return; + } + + PyLongObject *small_ints = _PyLong_SMALL_INTS; + if (small_ints[0].ob_base.ob_base.ob_refcnt != 0) { + // Py_Initialize() must be running a second time. + return; + } + + for (Py_ssize_t i=0; i < _PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS; i++) { + sdigit ival = (sdigit)i - _PY_NSMALLNEGINTS; + int size = (ival < 0) ? -1 : ((ival == 0) ? 0 : 1); + small_ints[i].ob_base.ob_base.ob_refcnt = 1; + small_ints[i].ob_base.ob_base.ob_type = &PyLong_Type; + small_ints[i].ob_base.ob_size = size; + small_ints[i].ob_digit[0] = (digit)abs(ival); } } -int -_PyLong_InitTypes(void) +PyStatus +_PyLong_InitTypes(PyInterpreterState *interp) { + if (!_Py_IsMainInterpreter(interp)) { + return _PyStatus_OK(); + } + + if (PyType_Ready(&PyLong_Type) < 0) { + return _PyStatus_ERR("Can't initialize int type"); + } + /* initialize int_info */ if (Int_InfoType.tp_name == NULL) { if (PyStructSequence_InitType2(&Int_InfoType, &int_info_desc) < 0) { - return -1; + return _PyStatus_ERR("can't init int info type"); } } - return 0; + + return _PyStatus_OK(); } void diff --git a/Objects/object.c b/Objects/object.c index a1c2e16b6fa2c..124485d64ab77 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -10,10 +10,10 @@ #include "pycore_namespace.h" // _PyNamespace_Type #include "pycore_object.h" // _PyType_CheckConsistency() #include "pycore_pyerrors.h" // _PyErr_Occurred() -#include "pycore_pylifecycle.h" // _PyTypes_InitSlotDefs() #include "pycore_pymem.h" // _PyMem_IsPtrFreed() #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_symtable.h" // PySTEntry_Type +#include "pycore_typeobject.h" // _PyTypes_InitSlotDefs() #include "pycore_unionobject.h" // _PyUnion_Type #include "frameobject.h" // PyFrame_Type #include "pycore_interpreteridobject.h" // _PyInterpreterID_Type @@ -1823,13 +1823,27 @@ PyObject _Py_NotImplementedStruct = { }; PyStatus -_PyTypes_Init(void) +_PyTypes_InitState(PyInterpreterState *interp) { + if (!_Py_IsMainInterpreter(interp)) { + return _PyStatus_OK(); + } + PyStatus status = _PyTypes_InitSlotDefs(); if (_PyStatus_EXCEPTION(status)) { return status; } + return _PyStatus_OK(); +} + +PyStatus +_PyTypes_InitTypes(PyInterpreterState *interp) +{ + if (!_Py_IsMainInterpreter(interp)) { + return _PyStatus_OK(); + } + #define INIT_TYPE(TYPE) \ do { \ if (PyType_Ready(&(TYPE)) < 0) { \ @@ -1843,13 +1857,11 @@ _PyTypes_Init(void) assert(PyBaseObject_Type.tp_base == NULL); assert(PyType_Type.tp_base == &PyBaseObject_Type); - // All other static types + // All other static types (unless initialized elsewhere) INIT_TYPE(PyAsyncGen_Type); INIT_TYPE(PyBool_Type); INIT_TYPE(PyByteArrayIter_Type); INIT_TYPE(PyByteArray_Type); - INIT_TYPE(PyBytesIter_Type); - INIT_TYPE(PyBytes_Type); INIT_TYPE(PyCFunction_Type); INIT_TYPE(PyCMethod_Type); INIT_TYPE(PyCallIter_Type); @@ -1873,7 +1885,6 @@ _PyTypes_Init(void) INIT_TYPE(PyDict_Type); INIT_TYPE(PyEllipsis_Type); INIT_TYPE(PyEnum_Type); - INIT_TYPE(PyFloat_Type); INIT_TYPE(PyFrame_Type); INIT_TYPE(PyFrozenSet_Type); INIT_TYPE(PyFunction_Type); @@ -1884,7 +1895,6 @@ _PyTypes_Init(void) INIT_TYPE(PyListRevIter_Type); INIT_TYPE(PyList_Type); INIT_TYPE(PyLongRangeIter_Type); - INIT_TYPE(PyLong_Type); INIT_TYPE(PyMemberDescr_Type); INIT_TYPE(PyMemoryView_Type); INIT_TYPE(PyMethodDescr_Type); @@ -1910,10 +1920,6 @@ _PyTypes_Init(void) INIT_TYPE(PyStdPrinter_Type); INIT_TYPE(PySuper_Type); INIT_TYPE(PyTraceBack_Type); - INIT_TYPE(PyTupleIter_Type); - INIT_TYPE(PyTuple_Type); - INIT_TYPE(PyUnicodeIter_Type); - INIT_TYPE(PyUnicode_Type); INIT_TYPE(PyWrapperDescr_Type); INIT_TYPE(Py_GenericAliasType); INIT_TYPE(_PyAnextAwaitable_Type); diff --git a/Objects/structseq.c b/Objects/structseq.c index 73795b677b404..a2eefb0455a17 100644 --- a/Objects/structseq.c +++ b/Objects/structseq.c @@ -12,6 +12,7 @@ #include "pycore_object.h" // _PyObject_GC_TRACK() #include "structmember.h" // PyMemberDef #include "pycore_structseq.h" // PyStructSequence_InitType() +#include "pycore_initconfig.h" // _PyStatus_OK() static const char visible_length_key[] = "n_sequence_fields"; static const char real_length_key[] = "n_fields"; @@ -583,13 +584,20 @@ PyStructSequence_NewType(PyStructSequence_Desc *desc) return type; } -int _PyStructSequence_Init(void) + +/* runtime lifecycle */ + +PyStatus _PyStructSequence_InitState(PyInterpreterState *interp) { + if (!_Py_IsMainInterpreter(interp)) { + return _PyStatus_OK(); + } + if (_PyUnicode_FromId(&PyId_n_sequence_fields) == NULL || _PyUnicode_FromId(&PyId_n_fields) == NULL || _PyUnicode_FromId(&PyId_n_unnamed_fields) == NULL) { - return -1; + return _PyStatus_ERR("can't initialize structseq state"); } - return 0; + return _PyStatus_OK(); } diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index e9d1b5926abb3..cb34c5eb15e4c 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -7,6 +7,7 @@ #include "pycore_initconfig.h" // _PyStatus_OK() #include "pycore_object.h" // _PyObject_GC_TRACK() #include "pycore_pyerrors.h" // _Py_FatalRefcountError() +#include "pycore_tuple.h" // struct _Py_tuple_state() /*[clinic input] class tuple "PyTupleObject *" "&PyTuple_Type" @@ -1066,7 +1067,7 @@ _PyTuple_ClearFreeList(PyInterpreterState *interp) PyStatus -_PyTuple_Init(PyInterpreterState *interp) +_PyTuple_InitGlobalObjects(PyInterpreterState *interp) { struct _Py_tuple_state *state = &interp->tuple; if (tuple_create_empty_tuple_singleton(state) < 0) { @@ -1076,6 +1077,24 @@ _PyTuple_Init(PyInterpreterState *interp) } +PyStatus +_PyTuple_InitTypes(PyInterpreterState *interp) +{ + if (!_Py_IsMainInterpreter(interp)) { + return _PyStatus_OK(); + } + + if (PyType_Ready(&PyTuple_Type) < 0) { + return _PyStatus_ERR("Can't initialize tuple type"); + } + + if (PyType_Ready(&PyTupleIter_Type) < 0) { + return _PyStatus_ERR("Can't initialize tuple iterator type"); + } + + return _PyStatus_OK(); +} + void _PyTuple_Fini(PyInterpreterState *interp) { diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 2fd93b61c0b2b..af35180cdb983 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -9,6 +9,7 @@ #include "pycore_object.h" // _PyType_HasFeature() #include "pycore_pyerrors.h" // _PyErr_Occurred() #include "pycore_pystate.h" // _PyThreadState_GET() +#include "pycore_typeobject.h" // struct type_cache #include "pycore_unionobject.h" // _Py_union_type_or #include "frameobject.h" // PyFrameObject #include "pycore_frame.h" // InterpreterFrame @@ -294,7 +295,7 @@ PyType_ClearCache(void) void -_PyType_Fini(PyInterpreterState *interp) +_PyTypes_Fini(PyInterpreterState *interp) { struct type_cache *cache = &interp->type_cache; type_cache_clear(cache, NULL); diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 532c48ad4d4aa..14449bce70839 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -53,6 +53,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "pycore_pylifecycle.h" // _Py_SetFileSystemEncoding() #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_ucnhash.h" // _PyUnicode_Name_CAPI +#include "pycore_unicodeobject.h" // struct _Py_unicode_state #include "stringlib/eq.h" // unicode_eq() #ifdef MS_WINDOWS @@ -15504,41 +15505,56 @@ PyTypeObject PyUnicode_Type = { /* Initialize the Unicode implementation */ +void +_PyUnicode_InitState(PyInterpreterState *interp) +{ + if (!_Py_IsMainInterpreter(interp)) { + return; + } + + /* initialize the linebreak bloom filter */ + const Py_UCS2 linebreak[] = { + 0x000A, /* LINE FEED */ + 0x000D, /* CARRIAGE RETURN */ + 0x001C, /* FILE SEPARATOR */ + 0x001D, /* GROUP SEPARATOR */ + 0x001E, /* RECORD SEPARATOR */ + 0x0085, /* NEXT LINE */ + 0x2028, /* LINE SEPARATOR */ + 0x2029, /* PARAGRAPH SEPARATOR */ + }; + bloom_linebreak = make_bloom_mask( + PyUnicode_2BYTE_KIND, linebreak, + Py_ARRAY_LENGTH(linebreak)); +} + + PyStatus -_PyUnicode_Init(PyInterpreterState *interp) +_PyUnicode_InitGlobalObjects(PyInterpreterState *interp) { struct _Py_unicode_state *state = &interp->unicode; if (unicode_create_empty_string_singleton(state) < 0) { return _PyStatus_NO_MEMORY(); } - if (_Py_IsMainInterpreter(interp)) { - /* initialize the linebreak bloom filter */ - const Py_UCS2 linebreak[] = { - 0x000A, /* LINE FEED */ - 0x000D, /* CARRIAGE RETURN */ - 0x001C, /* FILE SEPARATOR */ - 0x001D, /* GROUP SEPARATOR */ - 0x001E, /* RECORD SEPARATOR */ - 0x0085, /* NEXT LINE */ - 0x2028, /* LINE SEPARATOR */ - 0x2029, /* PARAGRAPH SEPARATOR */ - }; - bloom_linebreak = make_bloom_mask( - PyUnicode_2BYTE_KIND, linebreak, - Py_ARRAY_LENGTH(linebreak)); - } - return _PyStatus_OK(); } PyStatus -_PyUnicode_InitTypes(void) +_PyUnicode_InitTypes(PyInterpreterState *interp) { + if (!_Py_IsMainInterpreter(interp)) { + return _PyStatus_OK(); + } + if (PyType_Ready(&PyUnicode_Type) < 0) { return _PyStatus_ERR("Can't initialize unicode type"); } + if (PyType_Ready(&PyUnicodeIter_Type) < 0) { + return _PyStatus_ERR("Can't initialize unicode iterator type"); + } + if (PyType_Ready(&EncodingMapType) < 0) { return _PyStatus_ERR("Can't initialize encoding map type"); } diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index a2ee95e0ae9fc..e3a71ca645143 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -196,6 +196,7 @@ + @@ -203,11 +204,13 @@ + + @@ -218,6 +221,7 @@ + @@ -229,14 +233,17 @@ + + + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index c1667e3fb74fd..c99595755e3dc 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -468,6 +468,9 @@ Include\cpython + + Include\internal + Include\internal @@ -498,6 +501,9 @@ Include\internal + + Include\internal + Include\internal @@ -519,6 +525,9 @@ Include\internal + + Include\internal + Include\internal @@ -531,6 +540,9 @@ Include\internal + + Include\internal + Include\internal @@ -561,6 +573,9 @@ Include\internal + + Include\internal + Include\internal @@ -594,6 +609,9 @@ Include\internal + + Include\internal + Include\internal @@ -609,6 +627,9 @@ Include\internal + + Include\internal + Include\internal diff --git a/Python/context.c b/Python/context.c index a20ec7123731c..9ed73b7444d44 100644 --- a/Python/context.c +++ b/Python/context.c @@ -3,6 +3,7 @@ #include "pycore_context.h" #include "pycore_gc.h" // _PyObject_GC_MAY_BE_TRACKED() #include "pycore_hamt.h" +#include "pycore_initconfig.h" // _PyStatus_OK() #include "pycore_object.h" #include "pycore_pyerrors.h" #include "pycore_pystate.h" // _PyThreadState_GET() @@ -1317,15 +1318,20 @@ _PyContext_Fini(PyInterpreterState *interp) struct _Py_context_state *state = &interp->context; state->numfree = -1; #endif - _PyHamt_Fini(); + _PyHamt_Fini(interp); } -int -_PyContext_Init(void) +PyStatus +_PyContext_InitTypes(PyInterpreterState *interp) { - if (!_PyHamt_Init()) { - return 0; + if (!_Py_IsMainInterpreter(interp)) { + return _PyStatus_OK(); + } + + PyStatus status = _PyHamt_InitTypes(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; } if ((PyType_Ready(&PyContext_Type) < 0) || @@ -1333,7 +1339,7 @@ _PyContext_Init(void) (PyType_Ready(&PyContextToken_Type) < 0) || (PyType_Ready(&PyContextTokenMissing_Type) < 0)) { - return 0; + return _PyStatus_ERR("can't init context types"); } PyObject *missing = get_token_missing(); @@ -1341,9 +1347,9 @@ _PyContext_Init(void) PyContextToken_Type.tp_dict, "MISSING", missing)) { Py_DECREF(missing); - return 0; + return _PyStatus_ERR("can't init context types"); } Py_DECREF(missing); - return 1; + return _PyStatus_OK(); } diff --git a/Python/errors.c b/Python/errors.c index 44d2773acdb5c..5be15e54db25b 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -1241,8 +1241,12 @@ static PyStructSequence_Desc UnraisableHookArgs_desc = { PyStatus -_PyErr_InitTypes(void) +_PyErr_InitTypes(PyInterpreterState *interp) { + if (!_Py_IsMainInterpreter(interp)) { + return _PyStatus_OK(); + } + if (UnraisableHookArgsType.tp_name == NULL) { if (PyStructSequence_InitType2(&UnraisableHookArgsType, &UnraisableHookArgs_desc) < 0) { diff --git a/Python/hamt.c b/Python/hamt.c index e272e8808fd95..8c8e025a3eff3 100644 --- a/Python/hamt.c +++ b/Python/hamt.c @@ -2,6 +2,7 @@ #include "pycore_bitutils.h" // _Py_popcount32 #include "pycore_hamt.h" +#include "pycore_initconfig.h" // _PyStatus_OK() #include "pycore_object.h" // _PyObject_GC_TRACK() #include // offsetof() @@ -2952,9 +2953,13 @@ PyTypeObject _PyHamt_CollisionNode_Type = { }; -int -_PyHamt_Init(void) +PyStatus +_PyHamt_InitTypes(PyInterpreterState *interp) { + if (!_Py_IsMainInterpreter(interp)) { + return _PyStatus_OK(); + } + if ((PyType_Ready(&_PyHamt_Type) < 0) || (PyType_Ready(&_PyHamt_ArrayNode_Type) < 0) || (PyType_Ready(&_PyHamt_BitmapNode_Type) < 0) || @@ -2963,14 +2968,14 @@ _PyHamt_Init(void) (PyType_Ready(&_PyHamtValues_Type) < 0) || (PyType_Ready(&_PyHamtItems_Type) < 0)) { - return 0; + return _PyStatus_ERR("can't init hamt types"); } - return 1; + return _PyStatus_OK(); } void -_PyHamt_Fini(void) +_PyHamt_Fini(PyInterpreterState *interp) { Py_CLEAR(_empty_hamt); Py_CLEAR(_empty_bitmap_node); diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 2b386a11f9f6e..b6d73a9ce2216 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -2,18 +2,31 @@ #include "Python.h" +#include "pycore_bytesobject.h" // _PyBytes_InitTypes() #include "pycore_ceval.h" // _PyEval_FiniGIL() #include "pycore_context.h" // _PyContext_Init() +#include "pycore_exceptions.h" // _PyExc_InitTypes() +#include "pycore_dict.h" // _PyDict_Fini() #include "pycore_fileutils.h" // _Py_ResetForceASCII() +#include "pycore_floatobject.h" // _PyFloat_InitTypes() +#include "pycore_frame.h" // _PyFrame_Fini() +#include "pycore_genobject.h" // _PyAsyncGen_Fini() #include "pycore_import.h" // _PyImport_BootstrapImp() #include "pycore_initconfig.h" // _PyStatus_OK() +#include "pycore_list.h" // _PyList_Fini() +#include "pycore_long.h" // _PyLong_InitTypes() #include "pycore_object.h" // _PyDebug_PrintTotalRefs() #include "pycore_pathconfig.h" // _PyConfig_WritePathConfig() #include "pycore_pyerrors.h" // _PyErr_Occurred() #include "pycore_pylifecycle.h" // _PyErr_Print() #include "pycore_pystate.h" // _PyThreadState_GET() +#include "pycore_sliceobject.h" // _PySlice_Fini() +#include "pycore_structseq.h" // _PyStructSequence_InitState() #include "pycore_sysmodule.h" // _PySys_ClearAuditHooks() #include "pycore_traceback.h" // _Py_DumpTracebackThreads() +#include "pycore_tuple.h" // _PyTuple_InitTypes() +#include "pycore_typeobject.h" // _PyTypes_InitTypes() +#include "pycore_unicodeobject.h" // _PyUnicode_InitTypes() #include // setlocale() #include // getenv() @@ -659,27 +672,27 @@ pycore_create_interpreter(_PyRuntimeState *runtime, static PyStatus -pycore_init_singletons(PyInterpreterState *interp) +pycore_init_global_objects(PyInterpreterState *interp) { PyStatus status; - _PyLong_Init(interp); + _PyLong_InitGlobalObjects(interp); - if (_Py_IsMainInterpreter(interp)) { - _PyFloat_Init(); - } + _PyFloat_InitState(interp); - status = _PyBytes_Init(interp); + status = _PyBytes_InitGlobalObjects(interp); if (_PyStatus_EXCEPTION(status)) { return status; } - status = _PyUnicode_Init(interp); + status = _PyUnicode_InitGlobalObjects(interp); if (_PyStatus_EXCEPTION(status)) { return status; } - status = _PyTuple_Init(interp); + _PyUnicode_InitState(interp); + + status = _PyTuple_InitGlobalObjects(interp); if (_PyStatus_EXCEPTION(status)) { return status; } @@ -692,48 +705,70 @@ static PyStatus pycore_init_types(PyInterpreterState *interp) { PyStatus status; - int is_main_interp = _Py_IsMainInterpreter(interp); - if (is_main_interp) { - if (_PyStructSequence_Init() < 0) { - return _PyStatus_ERR("can't initialize structseq"); - } + status = _PyStructSequence_InitState(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; + } - status = _PyTypes_Init(); - if (_PyStatus_EXCEPTION(status)) { - return status; - } + status = _PyTypes_InitState(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; + } - if (_PyLong_InitTypes() < 0) { - return _PyStatus_ERR("can't init int type"); - } + status = _PyTypes_InitTypes(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; + } - status = _PyUnicode_InitTypes(); - if (_PyStatus_EXCEPTION(status)) { - return status; - } + status = _PyBytes_InitTypes(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; } - if (is_main_interp) { - if (_PyFloat_InitTypes() < 0) { - return _PyStatus_ERR("can't init float"); - } + status = _PyLong_InitTypes(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; } - status = _PyExc_Init(interp); + status = _PyUnicode_InitTypes(interp); if (_PyStatus_EXCEPTION(status)) { return status; } - status = _PyErr_InitTypes(); + status = _PyFloat_InitTypes(interp); if (_PyStatus_EXCEPTION(status)) { return status; } - if (is_main_interp) { - if (!_PyContext_Init()) { - return _PyStatus_ERR("can't init context"); - } + status = _PyTuple_InitTypes(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + + status = _PyExc_InitTypes(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + + status = _PyExc_InitGlobalObjects(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + + status = _PyExc_InitState(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + + status = _PyErr_InitTypes(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + + status = _PyContext_InitTypes(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; } return _PyStatus_OK(); @@ -799,7 +834,7 @@ pycore_interp_init(PyThreadState *tstate) // Create singletons before the first PyType_Ready() call, since // PyType_Ready() uses singletons like the Unicode empty string (tp_doc) // and the empty tuple singletons (tp_bases). - status = pycore_init_singletons(interp); + status = pycore_init_global_objects(interp); if (_PyStatus_EXCEPTION(status)) { return status; } @@ -1641,7 +1676,7 @@ finalize_interp_types(PyInterpreterState *interp) _PyFrame_Fini(interp); _PyAsyncGen_Fini(interp); _PyContext_Fini(interp); - _PyType_Fini(interp); + _PyTypes_Fini(interp); // Call _PyUnicode_ClearInterned() before _PyDict_Fini() since it uses // a dict internally. _PyUnicode_ClearInterned(interp); @@ -1655,7 +1690,6 @@ finalize_interp_types(PyInterpreterState *interp) _PyBytes_Fini(interp); _PyUnicode_Fini(interp); _PyFloat_Fini(interp); - _PyLong_Fini(interp); } From webhook-mailer at python.org Thu Dec 9 18:02:31 2021 From: webhook-mailer at python.org (vstinner) Date: Thu, 09 Dec 2021 23:02:31 -0000 Subject: [Python-checkins] bpo-46016: GHA Doc job now also runs "make check" (GH-30009) Message-ID: https://github.com/python/cpython/commit/da3cf4304f6dd530533bbd2c0913b674cd803744 commit: da3cf4304f6dd530533bbd2c0913b674cd803744 branch: main author: Victor Stinner committer: vstinner date: 2021-12-10T00:02:20+01:00 summary: bpo-46016: GHA Doc job now also runs "make check" (GH-30009) The GitHub Action documentation job now also runs "make check" to check the documentation. files: M .github/workflows/doc.yml diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index 755a4d5e173ee..ed44409d118a2 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -38,8 +38,15 @@ jobs: run: make -j4 - name: 'Install build dependencies' run: make -C Doc/ PYTHON=../python venv - - name: 'Build documentation' - run: xvfb-run make -C Doc/ PYTHON=../python SPHINXOPTS="-q -W --keep-going -j4" doctest html + # Run "check doctest html" as 3 steps to get a more readable output + # in the web UI + - name: 'Check documentation' + run: make -C Doc/ PYTHON=../python SPHINXOPTS="-q -W --keep-going -j4" check + # Use "xvfb-run" since some doctest tests open GUI windows + - name: 'Run documentation doctest' + run: xvfb-run make -C Doc/ PYTHON=../python SPHINXOPTS="-q -W --keep-going -j4" doctest + - name: 'Build HTML documentation' + run: make -C Doc/ PYTHON=../python SPHINXOPTS="-q -W --keep-going -j4" html - name: 'Upload' uses: actions/upload-artifact at v2.2.4 with: From webhook-mailer at python.org Thu Dec 9 20:52:20 2021 From: webhook-mailer at python.org (miss-islington) Date: Fri, 10 Dec 2021 01:52:20 -0000 Subject: [Python-checkins] bpo-43931: Export Python version as API data (GH-25577) Message-ID: https://github.com/python/cpython/commit/50669083fe16a42cba90b5dd8c1a017751f69fd8 commit: 50669083fe16a42cba90b5dd8c1a017751f69fd8 branch: main author: Gabriele N. Tornetta committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-09T17:52:05-08:00 summary: bpo-43931: Export Python version as API data (GH-25577) When Python is embedded in other applications, it is not easy to determine which version of Python is being used. This change exposes the Python version as part of the API data. Tools like Austin (https://github.com/P403n1x87/austin) can benefit from this data when targeting applications like uWSGI, as the Python version can then be inferred systematically by looking at the exported symbols rather than relying on unreliable pattern matching or other hacks (like remote code execution etc...). Automerge-Triggered-By: GH:pablogsal files: A Misc/NEWS.d/next/Core and Builtins/2021-04-24-15-39-23.bpo-43931.zpChDi.rst M Doc/c-api/apiabiversion.rst M Doc/c-api/init.rst M Doc/data/stable_abi.dat M Doc/whatsnew/3.11.rst M Include/pylifecycle.h M Lib/test/test_capi.py M Lib/test/test_stable_abi_ctypes.py M Misc/stable_abi.txt M Modules/_testcapimodule.c M PC/python3dll.c M Python/getversion.c diff --git a/Doc/c-api/apiabiversion.rst b/Doc/c-api/apiabiversion.rst index 04050f7dabe17..53a42e7f28ef1 100644 --- a/Doc/c-api/apiabiversion.rst +++ b/Doc/c-api/apiabiversion.rst @@ -58,5 +58,14 @@ See :ref:`stable` for a discussion of API and ABI stability across versions. Thus ``3.4.1a2`` is hexversion ``0x030401a2`` and ``3.10.0`` is hexversion ``0x030a00f0``. + This version is also available via the symbol :data:`Py_Version`. + +.. c:var:: const unsigned long Py_Version + + The Python runtime version number encoded in a single constant integer, with + the same format as the c:macro:`PY_VERSION_HEX` macro. + This contains the Python version used at run time. + + .. versionadded:: 3.11 All the given macros are defined in :source:`Include/patchlevel.h`. diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index 09dfc68fee57d..322b9e4d251e7 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -553,6 +553,8 @@ Process-wide parameters period. The returned string points into static storage; the caller should not modify its value. The value is available to Python code as :data:`sys.version`. + See also the :data:`Py_Version` constant. + .. c:function:: const char* Py_GetPlatform() diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat index 64a0a2a247cd2..02e54e5d7f14a 100644 --- a/Doc/data/stable_abi.dat +++ b/Doc/data/stable_abi.dat @@ -830,6 +830,7 @@ type,Py_UCS4,3.2, macro,Py_UNBLOCK_THREADS,3.2, var,Py_UTF8Mode,3.8, function,Py_VaBuildValue,3.2, +var,Py_Version,3.11, function,Py_XNewRef,3.10, type,Py_intptr_t,3.2, type,Py_ssize_t,3.2, diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 7a828663e7f34..8d1f4eba36eb2 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -626,6 +626,10 @@ New Features fields of the result from the exception instance (the ``value`` field). (Contributed by Irit Katriel in :issue:`45711`.) +* Added the :c:data:`Py_Version` constant which bears the same value as + :c:macro:`PY_VERSION_HEX`. + (Contributed by Gabriele N. Tornetta in :issue:`43931`.) + Porting to Python 3.11 ---------------------- diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index 4aecda235abf7..e4c3b09c963fe 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -62,6 +62,10 @@ typedef void (*PyOS_sighandler_t)(int); PyAPI_FUNC(PyOS_sighandler_t) PyOS_getsig(int); PyAPI_FUNC(PyOS_sighandler_t) PyOS_setsig(int, PyOS_sighandler_t); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030B0000 +PyAPI_DATA(const unsigned long) Py_Version; +#endif + #ifndef Py_LIMITED_API # define Py_CPYTHON_PYLIFECYCLE_H # include "cpython/pylifecycle.h" diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py index d51247003ded1..ecf3aa34ede7c 100644 --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -840,6 +840,9 @@ class Test_testcapi(unittest.TestCase): def test_widechar(self): _testcapi.test_widechar() + def test_version_api_data(self): + self.assertEqual(_testcapi.Py_Version, sys.hexversion) + class Test_testinternalcapi(unittest.TestCase): locals().update((name, getattr(_testinternalcapi, name)) diff --git a/Lib/test/test_stable_abi_ctypes.py b/Lib/test/test_stable_abi_ctypes.py index d0cd5c20dd5f4..9fd6b14b0232a 100644 --- a/Lib/test/test_stable_abi_ctypes.py +++ b/Lib/test/test_stable_abi_ctypes.py @@ -808,6 +808,7 @@ def test_available_symbols(self): "Py_SetRecursionLimit", "Py_UTF8Mode", "Py_VaBuildValue", + "Py_Version", "Py_XNewRef", "_PyArg_ParseTupleAndKeywords_SizeT", "_PyArg_ParseTuple_SizeT", diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-24-15-39-23.bpo-43931.zpChDi.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-24-15-39-23.bpo-43931.zpChDi.rst new file mode 100644 index 0000000000000..037512916878c --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-04-24-15-39-23.bpo-43931.zpChDi.rst @@ -0,0 +1,2 @@ +Added the :c:data:`Py_Version` constant which bears the same value as +:c:macro:`PY_VERSION_HEX`. Patch by Gabriele N. Tornetta. \ No newline at end of file diff --git a/Misc/stable_abi.txt b/Misc/stable_abi.txt index de6caa8c80746..9cb210c60cf24 100644 --- a/Misc/stable_abi.txt +++ b/Misc/stable_abi.txt @@ -2153,3 +2153,6 @@ data PyStructSequence_UnnamedField # (Detailed comments aren't really needed for further entries: from here on # we can use version control logs.) + +data Py_Version + added 3.11 diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 56d394985eb7c..6116365b2c0f7 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -7525,6 +7525,7 @@ PyInit__testcapi(void) PyModule_AddObject(m, "PY_SSIZE_T_MAX", PyLong_FromSsize_t(PY_SSIZE_T_MAX)); PyModule_AddObject(m, "PY_SSIZE_T_MIN", PyLong_FromSsize_t(PY_SSIZE_T_MIN)); PyModule_AddObject(m, "SIZEOF_TIME_T", PyLong_FromSsize_t(sizeof(time_t))); + PyModule_AddObject(m, "Py_Version", PyLong_FromUnsignedLong(Py_Version)); Py_INCREF(&PyInstanceMethod_Type); PyModule_AddObject(m, "instancemethod", (PyObject *)&PyInstanceMethod_Type); diff --git a/PC/python3dll.c b/PC/python3dll.c index 6e469357ede50..b2bb1706c4a2e 100755 --- a/PC/python3dll.c +++ b/PC/python3dll.c @@ -725,6 +725,7 @@ EXPORT_DATA(Py_FileSystemDefaultEncoding) EXPORT_DATA(Py_GenericAliasType) EXPORT_DATA(Py_HasFileSystemDefaultEncoding) EXPORT_DATA(Py_UTF8Mode) +EXPORT_DATA(Py_Version) EXPORT_DATA(PyBaseObject_Type) EXPORT_DATA(PyBool_Type) EXPORT_DATA(PyByteArray_Type) diff --git a/Python/getversion.c b/Python/getversion.c index c32b6f9d60d4b..46910451fdf85 100644 --- a/Python/getversion.c +++ b/Python/getversion.c @@ -13,3 +13,6 @@ Py_GetVersion(void) PY_VERSION, Py_GetBuildInfo(), Py_GetCompiler()); return version; } + +// Export the Python hex version as a constant. +const unsigned long Py_Version = PY_VERSION_HEX; From webhook-mailer at python.org Thu Dec 9 21:24:59 2021 From: webhook-mailer at python.org (rhettinger) Date: Fri, 10 Dec 2021 02:24:59 -0000 Subject: [Python-checkins] Move error test to the function that needs it. Improve error message. (GH-30008) Message-ID: https://github.com/python/cpython/commit/3fee7776e6ed8ab023a0220da1daf3160fda868b commit: 3fee7776e6ed8ab023a0220da1daf3160fda868b branch: main author: Raymond Hettinger committer: rhettinger date: 2021-12-09T20:24:50-06:00 summary: Move error test to the function that needs it. Improve error message. (GH-30008) files: M Lib/random.py M Lib/test/test_random.py diff --git a/Lib/random.py b/Lib/random.py index 92a71e14c480b..e8bc9416fcd94 100644 --- a/Lib/random.py +++ b/Lib/random.py @@ -233,10 +233,8 @@ def __init_subclass__(cls, /, **kwargs): break def _randbelow_with_getrandbits(self, n): - "Return a random int in the range [0,n). Returns 0 if n==0." + "Return a random int in the range [0,n). Defined for n > 0." - if not n: - return 0 getrandbits = self.getrandbits k = n.bit_length() # don't use (n-1) here because n can be 1 r = getrandbits(k) # 0 <= r < 2**k @@ -245,7 +243,7 @@ def _randbelow_with_getrandbits(self, n): return r def _randbelow_without_getrandbits(self, n, maxsize=1< 0. The implementation does not use getrandbits, but only random. """ @@ -256,8 +254,6 @@ def _randbelow_without_getrandbits(self, n, maxsize=1< https://github.com/python/cpython/commit/8c74713d0e349c27518080945d5f040dfd52a56e commit: 8c74713d0e349c27518080945d5f040dfd52a56e branch: main author: andrei kulakov committer: serhiy-storchaka date: 2021-12-10T11:40:06+02:00 summary: bpo-42182: stdtypes doc - update and fix links to several dunder methods (GH-27384) files: M Doc/library/stdtypes.rst diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index de77507458a0a..3c0ba94c73c6b 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -178,13 +178,14 @@ operators are only defined where they make sense; for example, they raise a single: __ge__() (instance method) Non-identical instances of a class normally compare as non-equal unless the -class defines the :meth:`__eq__` method. +class defines the :meth:`~object.__eq__` method. Instances of a class cannot be ordered with respect to other instances of the same class, or other types of object, unless the class defines enough of the -methods :meth:`__lt__`, :meth:`__le__`, :meth:`__gt__`, and :meth:`__ge__` (in -general, :meth:`__lt__` and :meth:`__eq__` are sufficient, if you want the -conventional meanings of the comparison operators). +methods :meth:`~object.__lt__`, :meth:`~object.__le__`, :meth:`~object.__gt__`, and +:meth:`~object.__ge__` (in general, :meth:`~object.__lt__` and +:meth:`~object.__eq__` are sufficient, if you want the conventional meanings of the +comparison operators). The behavior of the :keyword:`is` and :keyword:`is not` operators cannot be customized; also they can be applied to any two objects and never raise an @@ -698,7 +699,7 @@ Hashing of numeric types ------------------------ For numbers ``x`` and ``y``, possibly of different types, it's a requirement -that ``hash(x) == hash(y)`` whenever ``x == y`` (see the :meth:`__hash__` +that ``hash(x) == hash(y)`` whenever ``x == y`` (see the :meth:`~object.__hash__` method documentation for more details). For ease of implementation and efficiency across a variety of numeric types (including :class:`int`, :class:`float`, :class:`decimal.Decimal` and :class:`fractions.Fraction`) @@ -1334,7 +1335,7 @@ loops. range(start, stop[, step]) The arguments to the range constructor must be integers (either built-in - :class:`int` or any object that implements the ``__index__`` special + :class:`int` or any object that implements the :meth:`~object.__index__` special method). If the *step* argument is omitted, it defaults to ``1``. If the *start* argument is omitted, it defaults to ``0``. If *step* is zero, :exc:`ValueError` is raised. @@ -4793,9 +4794,9 @@ their implementation of the context management protocol. See the Python's :term:`generator`\s and the :class:`contextlib.contextmanager` decorator provide a convenient way to implement these protocols. If a generator function is decorated with the :class:`contextlib.contextmanager` decorator, it will return a -context manager implementing the necessary :meth:`__enter__` and -:meth:`__exit__` methods, rather than the iterator produced by an undecorated -generator function. +context manager implementing the necessary :meth:`~contextmanager.__enter__` and +:meth:`~contextmanager.__exit__` methods, rather than the iterator produced by an +undecorated generator function. Note that there is no specific slot for any of these methods in the type structure for Python objects in the Python/C API. Extension types wanting to From webhook-mailer at python.org Fri Dec 10 04:41:53 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Fri, 10 Dec 2021 09:41:53 -0000 Subject: [Python-checkins] bpo-46000: Improve NetBSD curses compatibility (GH-29947) Message-ID: https://github.com/python/cpython/commit/2fb797e93c6bbd44dfcbe23f63acfa240a87e48a commit: 2fb797e93c6bbd44dfcbe23f63acfa240a87e48a branch: main author: Thomas Klausner committer: serhiy-storchaka date: 2021-12-10T11:41:47+02:00 summary: bpo-46000: Improve NetBSD curses compatibility (GH-29947) files: A Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-42-44.bpo-46000.v_ru3k.rst M Modules/_cursesmodule.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-42-44.bpo-46000.v_ru3k.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-42-44.bpo-46000.v_ru3k.rst new file mode 100644 index 0000000000000..68e4bfa9e77b1 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-42-44.bpo-46000.v_ru3k.rst @@ -0,0 +1 @@ +Improve compatibility of the :mod:`curses` module with NetBSD curses. diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 3770a032e977d..7ebad692c2381 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1230,8 +1230,8 @@ PyCursesWindow_ChgAt(PyCursesWindowObject *self, PyObject *args) return NULL; } - color = (short)((attr >> 8) & 0xff); - attr = attr - (color << 8); + color = (short) PAIR_NUMBER(attr); + attr = attr & A_ATTRIBUTES; if (use_xy) { rtn = mvwchgat(self->win,y,x,num,attr,color,NULL); From webhook-mailer at python.org Fri Dec 10 04:42:53 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Fri, 10 Dec 2021 09:42:53 -0000 Subject: [Python-checkins] [3.9] bpo-45662: Fix the repr of InitVar with a type alias to the built-in class (GH-29291) (GH-29924) Message-ID: https://github.com/python/cpython/commit/fb8aad16401e081a6a9059c7b428f7e8aae85d58 commit: fb8aad16401e081a6a9059c7b428f7e8aae85d58 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: serhiy-storchaka date: 2021-12-10T11:42:49+02:00 summary: [3.9] bpo-45662: Fix the repr of InitVar with a type alias to the built-in class (GH-29291) (GH-29924) For example, InitVar[list[int]]. (cherry picked from commit 1fd4de5bddbbf2a97cdbac4d298c89e1156bdc6c) Co-authored-by: Serhiy Storchaka files: A Misc/NEWS.d/next/Library/2021-10-28-22-58-14.bpo-45662.sJd7Ir.rst M Lib/dataclasses.py M Lib/test/test_dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 68907058403fd..5ff67ad2ea9ea 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -207,7 +207,7 @@ def __init__(self, type): self.type = type def __repr__(self): - if isinstance(self.type, type): + if isinstance(self.type, type) and not isinstance(self.type, GenericAlias): type_name = self.type.__name__ else: # typing objects, e.g. List[int] diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index fa5adfcea1b43..9b6013456eb60 100644 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -1125,6 +1125,8 @@ def test_init_var_preserve_type(self): self.assertEqual(repr(InitVar[int]), 'dataclasses.InitVar[int]') self.assertEqual(repr(InitVar[List[int]]), 'dataclasses.InitVar[typing.List[int]]') + self.assertEqual(repr(InitVar[list[int]]), + 'dataclasses.InitVar[list[int]]') def test_init_var_inheritance(self): # Note that this deliberately tests that a dataclass need not diff --git a/Misc/NEWS.d/next/Library/2021-10-28-22-58-14.bpo-45662.sJd7Ir.rst b/Misc/NEWS.d/next/Library/2021-10-28-22-58-14.bpo-45662.sJd7Ir.rst new file mode 100644 index 0000000000000..050b443dd7cb2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-10-28-22-58-14.bpo-45662.sJd7Ir.rst @@ -0,0 +1,2 @@ +Fix the repr of :data:`dataclasses.InitVar` with a type alias to the +built-in class, e.g. ``InitVar[list[int]]``. From webhook-mailer at python.org Fri Dec 10 05:02:20 2021 From: webhook-mailer at python.org (miss-islington) Date: Fri, 10 Dec 2021 10:02:20 -0000 Subject: [Python-checkins] bpo-42182: stdtypes doc - update and fix links to several dunder methods (GH-27384) Message-ID: https://github.com/python/cpython/commit/64c2788f42c49c7094d3b6e5404fe8386a2b4779 commit: 64c2788f42c49c7094d3b6e5404fe8386a2b4779 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-10T02:02:14-08:00 summary: bpo-42182: stdtypes doc - update and fix links to several dunder methods (GH-27384) (cherry picked from commit 8c74713d0e349c27518080945d5f040dfd52a56e) Co-authored-by: andrei kulakov files: M Doc/library/stdtypes.rst diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 1b18abcd6c95c..e732bd8e42fb5 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -178,13 +178,14 @@ operators are only defined where they make sense; for example, they raise a single: __ge__() (instance method) Non-identical instances of a class normally compare as non-equal unless the -class defines the :meth:`__eq__` method. +class defines the :meth:`~object.__eq__` method. Instances of a class cannot be ordered with respect to other instances of the same class, or other types of object, unless the class defines enough of the -methods :meth:`__lt__`, :meth:`__le__`, :meth:`__gt__`, and :meth:`__ge__` (in -general, :meth:`__lt__` and :meth:`__eq__` are sufficient, if you want the -conventional meanings of the comparison operators). +methods :meth:`~object.__lt__`, :meth:`~object.__le__`, :meth:`~object.__gt__`, and +:meth:`~object.__ge__` (in general, :meth:`~object.__lt__` and +:meth:`~object.__eq__` are sufficient, if you want the conventional meanings of the +comparison operators). The behavior of the :keyword:`is` and :keyword:`is not` operators cannot be customized; also they can be applied to any two objects and never raise an @@ -660,7 +661,7 @@ Hashing of numeric types ------------------------ For numbers ``x`` and ``y``, possibly of different types, it's a requirement -that ``hash(x) == hash(y)`` whenever ``x == y`` (see the :meth:`__hash__` +that ``hash(x) == hash(y)`` whenever ``x == y`` (see the :meth:`~object.__hash__` method documentation for more details). For ease of implementation and efficiency across a variety of numeric types (including :class:`int`, :class:`float`, :class:`decimal.Decimal` and :class:`fractions.Fraction`) @@ -1296,7 +1297,7 @@ loops. range(start, stop[, step]) The arguments to the range constructor must be integers (either built-in - :class:`int` or any object that implements the ``__index__`` special + :class:`int` or any object that implements the :meth:`~object.__index__` special method). If the *step* argument is omitted, it defaults to ``1``. If the *start* argument is omitted, it defaults to ``0``. If *step* is zero, :exc:`ValueError` is raised. @@ -4755,9 +4756,9 @@ their implementation of the context management protocol. See the Python's :term:`generator`\s and the :class:`contextlib.contextmanager` decorator provide a convenient way to implement these protocols. If a generator function is decorated with the :class:`contextlib.contextmanager` decorator, it will return a -context manager implementing the necessary :meth:`__enter__` and -:meth:`__exit__` methods, rather than the iterator produced by an undecorated -generator function. +context manager implementing the necessary :meth:`~contextmanager.__enter__` and +:meth:`~contextmanager.__exit__` methods, rather than the iterator produced by an +undecorated generator function. Note that there is no specific slot for any of these methods in the type structure for Python objects in the Python/C API. Extension types wanting to From webhook-mailer at python.org Fri Dec 10 05:04:59 2021 From: webhook-mailer at python.org (miss-islington) Date: Fri, 10 Dec 2021 10:04:59 -0000 Subject: [Python-checkins] bpo-42182: stdtypes doc - update and fix links to several dunder methods (GH-27384) Message-ID: https://github.com/python/cpython/commit/40d765260ae08d152ee89ed9c1c621f4a0024fa6 commit: 40d765260ae08d152ee89ed9c1c621f4a0024fa6 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-10T02:04:54-08:00 summary: bpo-42182: stdtypes doc - update and fix links to several dunder methods (GH-27384) (cherry picked from commit 8c74713d0e349c27518080945d5f040dfd52a56e) Co-authored-by: andrei kulakov files: M Doc/library/stdtypes.rst diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index e0b9285eb32b1..c6ac6d2c712c1 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -178,13 +178,14 @@ operators are only defined where they make sense; for example, they raise a single: __ge__() (instance method) Non-identical instances of a class normally compare as non-equal unless the -class defines the :meth:`__eq__` method. +class defines the :meth:`~object.__eq__` method. Instances of a class cannot be ordered with respect to other instances of the same class, or other types of object, unless the class defines enough of the -methods :meth:`__lt__`, :meth:`__le__`, :meth:`__gt__`, and :meth:`__ge__` (in -general, :meth:`__lt__` and :meth:`__eq__` are sufficient, if you want the -conventional meanings of the comparison operators). +methods :meth:`~object.__lt__`, :meth:`~object.__le__`, :meth:`~object.__gt__`, and +:meth:`~object.__ge__` (in general, :meth:`~object.__lt__` and +:meth:`~object.__eq__` are sufficient, if you want the conventional meanings of the +comparison operators). The behavior of the :keyword:`is` and :keyword:`is not` operators cannot be customized; also they can be applied to any two objects and never raise an @@ -639,7 +640,7 @@ Hashing of numeric types ------------------------ For numbers ``x`` and ``y``, possibly of different types, it's a requirement -that ``hash(x) == hash(y)`` whenever ``x == y`` (see the :meth:`__hash__` +that ``hash(x) == hash(y)`` whenever ``x == y`` (see the :meth:`~object.__hash__` method documentation for more details). For ease of implementation and efficiency across a variety of numeric types (including :class:`int`, :class:`float`, :class:`decimal.Decimal` and :class:`fractions.Fraction`) @@ -1275,7 +1276,7 @@ loops. range(start, stop[, step]) The arguments to the range constructor must be integers (either built-in - :class:`int` or any object that implements the ``__index__`` special + :class:`int` or any object that implements the :meth:`~object.__index__` special method). If the *step* argument is omitted, it defaults to ``1``. If the *start* argument is omitted, it defaults to ``0``. If *step* is zero, :exc:`ValueError` is raised. @@ -4719,9 +4720,9 @@ their implementation of the context management protocol. See the Python's :term:`generator`\s and the :class:`contextlib.contextmanager` decorator provide a convenient way to implement these protocols. If a generator function is decorated with the :class:`contextlib.contextmanager` decorator, it will return a -context manager implementing the necessary :meth:`__enter__` and -:meth:`__exit__` methods, rather than the iterator produced by an undecorated -generator function. +context manager implementing the necessary :meth:`~contextmanager.__enter__` and +:meth:`~contextmanager.__exit__` methods, rather than the iterator produced by an +undecorated generator function. Note that there is no specific slot for any of these methods in the type structure for Python objects in the Python/C API. Extension types wanting to From webhook-mailer at python.org Fri Dec 10 05:29:31 2021 From: webhook-mailer at python.org (miss-islington) Date: Fri, 10 Dec 2021 10:29:31 -0000 Subject: [Python-checkins] bpo-46000: Improve NetBSD curses compatibility (GH-29947) Message-ID: https://github.com/python/cpython/commit/bb76410824e526ee075eac22812a577cca7583cf commit: bb76410824e526ee075eac22812a577cca7583cf branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-10T02:29:23-08:00 summary: bpo-46000: Improve NetBSD curses compatibility (GH-29947) (cherry picked from commit 2fb797e93c6bbd44dfcbe23f63acfa240a87e48a) Co-authored-by: Thomas Klausner files: A Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-42-44.bpo-46000.v_ru3k.rst M Modules/_cursesmodule.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-42-44.bpo-46000.v_ru3k.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-42-44.bpo-46000.v_ru3k.rst new file mode 100644 index 0000000000000..68e4bfa9e77b1 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-42-44.bpo-46000.v_ru3k.rst @@ -0,0 +1 @@ +Improve compatibility of the :mod:`curses` module with NetBSD curses. diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 511073f2ac137..a1de43599c99d 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1226,8 +1226,8 @@ PyCursesWindow_ChgAt(PyCursesWindowObject *self, PyObject *args) return NULL; } - color = (short)((attr >> 8) & 0xff); - attr = attr - (color << 8); + color = (short) PAIR_NUMBER(attr); + attr = attr & A_ATTRIBUTES; if (use_xy) { rtn = mvwchgat(self->win,y,x,num,attr,color,NULL); From webhook-mailer at python.org Fri Dec 10 06:21:24 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Fri, 10 Dec 2021 11:21:24 -0000 Subject: [Python-checkins] bpo-46000: Improve NetBSD curses compatibility (GH-29947) (GH-30023) Message-ID: https://github.com/python/cpython/commit/040f9f9c48f4e74e851d850275aa9e050a04d0c6 commit: 040f9f9c48f4e74e851d850275aa9e050a04d0c6 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: serhiy-storchaka date: 2021-12-10T13:21:19+02:00 summary: bpo-46000: Improve NetBSD curses compatibility (GH-29947) (GH-30023) (cherry picked from commit 2fb797e93c6bbd44dfcbe23f63acfa240a87e48a) Co-authored-by: Thomas Klausner files: A Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-42-44.bpo-46000.v_ru3k.rst M Modules/_cursesmodule.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-42-44.bpo-46000.v_ru3k.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-42-44.bpo-46000.v_ru3k.rst new file mode 100644 index 0000000000000..68e4bfa9e77b1 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-42-44.bpo-46000.v_ru3k.rst @@ -0,0 +1 @@ +Improve compatibility of the :mod:`curses` module with NetBSD curses. diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index a32cc4b88435c..f95677cee5750 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1077,8 +1077,8 @@ PyCursesWindow_ChgAt(PyCursesWindowObject *self, PyObject *args) return NULL; } - color = (short)((attr >> 8) & 0xff); - attr = attr - (color << 8); + color = (short) PAIR_NUMBER(attr); + attr = attr & A_ATTRIBUTES; if (use_xy) { rtn = mvwchgat(self->win,y,x,num,attr,color,NULL); From webhook-mailer at python.org Fri Dec 10 06:27:43 2021 From: webhook-mailer at python.org (tiran) Date: Fri, 10 Dec 2021 11:27:43 -0000 Subject: [Python-checkins] bpo-45723: Normalise configure user communication (GH-30024) Message-ID: https://github.com/python/cpython/commit/74b23c97cd5e178970a199066795cf0561f46b72 commit: 74b23c97cd5e178970a199066795cf0561f46b72 branch: main author: Erlend Egeberg Aasland committer: tiran date: 2021-12-10T12:27:38+01:00 summary: bpo-45723: Normalise configure user communication (GH-30024) files: M configure M configure.ac diff --git a/configure b/configure index 444dd675a2dda..3c2a9cf0a249d 100755 --- a/configure +++ b/configure @@ -6169,8 +6169,7 @@ if $CPP $CPPFLAGS conftest.c >conftest.out 2>/dev/null; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ANDROID_API_LEVEL" >&5 $as_echo "$ANDROID_API_LEVEL" >&6; } if test -z "$ANDROID_API_LEVEL"; then - echo 'Fatal: you must define __ANDROID_API__' - exit 1 + as_fn_error $? "Fatal: you must define __ANDROID_API__" "$LINENO" 5 fi cat >>confdefs.h <<_ACEOF @@ -6193,11 +6192,14 @@ fi rm -f conftest.c conftest.out # Check for unsupported systems -case $ac_sys_system/$ac_sys_release in -atheos*|Linux*/1*) - echo This system \($ac_sys_system/$ac_sys_release\) is no longer supported. - echo See README for details. - exit 1;; +case $ac_sys_system/$ac_sys_release in #( + atheos*|Linux*/1*) : + + as_fn_error $? "This system \($ac_sys_system/$ac_sys_release\) is no longer supported. See README for details." "$LINENO" 5 + + ;; #( + *) : + ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-suffix" >&5 @@ -13159,16 +13161,19 @@ fi if test "$ipv6" = "yes" -a "$ipv6lib" != "none"; then if test -d $ipv6libdir -a -f $ipv6libdir/lib$ipv6lib.a; then LIBS="-L$ipv6libdir -l$ipv6lib $LIBS" - echo "using lib$ipv6lib" + { $as_echo "$as_me:${as_lineno-$LINENO}: using lib$ipv6lib" >&5 +$as_echo "$as_me: using lib$ipv6lib" >&6;} else - if test $ipv6trylibc = "yes"; then - echo "using libc" - else - echo 'Fatal: no $ipv6lib library found. cannot continue.' - echo "You need to fetch lib$ipv6lib.a from appropriate" - echo 'ipv6 kit and compile beforehand.' - exit 1 - fi + if test "x$ipv6trylibc" = xyes; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: using libc" >&5 +$as_echo "$as_me: using libc" >&6;} + +else + + as_fn_error $? "No $ipv6lib library found; cannot continue. You need to fetch lib$ipv6lib.a from appropriate ipv6 kit and compile beforehand." "$LINENO" 5 + +fi fi fi @@ -16522,12 +16527,11 @@ fi if test "$ac_cv_func_getaddrinfo" = no -o "$ac_cv_buggy_getaddrinfo" = yes then - if test $ipv6 = yes - then - echo 'Fatal: You must get working getaddrinfo() function.' - echo ' or you can specify "--disable-ipv6"'. - exit 1 - fi + if test "x$ipv6" = xyes; then : + + as_fn_error $? "You must get working getaddrinfo() function or pass the \"--disable-ipv6\" option to configure." "$LINENO" 5 + +fi else $as_echo "#define HAVE_GETADDRINFO 1" >>confdefs.h @@ -25071,28 +25075,34 @@ $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi -echo "creating Modules/Setup.local" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating Modules/Setup.local" >&5 +$as_echo "$as_me: creating Modules/Setup.local" >&6;} if test ! -f Modules/Setup.local then echo "# Edit this file for local setup changes" >Modules/Setup.local fi -echo "creating Makefile" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating Makefile" >&5 +$as_echo "$as_me: creating Makefile" >&6;} $SHELL $srcdir/Modules/makesetup -c $srcdir/Modules/config.c.in \ -s Modules \ Modules/Setup.local $srcdir/Modules/Setup.bootstrap $srcdir/Modules/Setup mv config.c Modules if test -z "$PKG_CONFIG"; then - echo "" >&6 - echo "pkg-config is missing. Some dependencies may not be detected correctly." >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pkg-config is missing. Some dependencies may not be detected correctly." >&5 +$as_echo "$as_me: WARNING: pkg-config is missing. Some dependencies may not be detected correctly." >&2;} fi if test "$Py_OPT" = 'false' -a "$Py_DEBUG" != 'true'; then - echo "" >&6 - echo "" >&6 - echo "If you want a release build with all stable optimizations active (PGO, etc)," >&6 - echo "please run ./configure --enable-optimizations" >&6 - echo "" >&6 - echo "" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: + +If you want a release build with all stable optimizations active (PGO, etc), +please run ./configure --enable-optimizations +" >&5 +$as_echo "$as_me: + +If you want a release build with all stable optimizations active (PGO, etc), +please run ./configure --enable-optimizations +" >&6;} fi diff --git a/configure.ac b/configure.ac index 31544dde03fb0..fa5e63cf5c3f9 100644 --- a/configure.ac +++ b/configure.ac @@ -1037,8 +1037,7 @@ if $CPP $CPPFLAGS conftest.c >conftest.out 2>/dev/null; then _arm_arch=`sed -n -e '/__ARM_ARCH/d' -e 's/^arm_arch = //p' conftest.out` AC_MSG_RESULT([$ANDROID_API_LEVEL]) if test -z "$ANDROID_API_LEVEL"; then - echo 'Fatal: you must define __ANDROID_API__' - exit 1 + AC_MSG_ERROR([Fatal: you must define __ANDROID_API__]) fi AC_DEFINE_UNQUOTED(ANDROID_API_LEVEL, $ANDROID_API_LEVEL, [The Android API level.]) @@ -1054,12 +1053,14 @@ fi rm -f conftest.c conftest.out # Check for unsupported systems -case $ac_sys_system/$ac_sys_release in -atheos*|Linux*/1*) - echo This system \($ac_sys_system/$ac_sys_release\) is no longer supported. - echo See README for details. - exit 1;; -esac +AS_CASE([$ac_sys_system/$ac_sys_release], + [atheos*|Linux*/1*], [ + AC_MSG_ERROR([m4_normalize([ + This system \($ac_sys_system/$ac_sys_release\) is no longer supported. + See README for details. + ])]) + ] +) AC_MSG_CHECKING([for --with-suffix]) AC_ARG_WITH([suffix], @@ -3795,16 +3796,17 @@ fi if test "$ipv6" = "yes" -a "$ipv6lib" != "none"; then if test -d $ipv6libdir -a -f $ipv6libdir/lib$ipv6lib.a; then LIBS="-L$ipv6libdir -l$ipv6lib $LIBS" - echo "using lib$ipv6lib" + AC_MSG_NOTICE([using lib$ipv6lib]) else - if test $ipv6trylibc = "yes"; then - echo "using libc" - else - echo 'Fatal: no $ipv6lib library found. cannot continue.' - echo "You need to fetch lib$ipv6lib.a from appropriate" - echo 'ipv6 kit and compile beforehand.' - exit 1 - fi + AS_VAR_IF([ipv6trylibc], [yes], [ + AC_MSG_NOTICE([using libc]) + ], [ + AC_MSG_ERROR([m4_normalize([ + No $ipv6lib library found; cannot continue. + You need to fetch lib$ipv6lib.a from appropriate + ipv6 kit and compile beforehand. + ])]) + ]) fi fi @@ -4510,12 +4512,12 @@ dnl if ac_cv_func_getaddrinfo if test "$ac_cv_func_getaddrinfo" = no -o "$ac_cv_buggy_getaddrinfo" = yes then - if test $ipv6 = yes - then - echo 'Fatal: You must get working getaddrinfo() function.' - echo ' or you can specify "--disable-ipv6"'. - exit 1 - fi + AS_VAR_IF([ipv6], [yes], [ + AC_MSG_ERROR([m4_normalize([ + You must get working getaddrinfo() function + or pass the "--disable-ipv6" option to configure. + ])]) + ]) else AC_DEFINE(HAVE_GETADDRINFO, 1, [Define if you have the getaddrinfo function.]) fi @@ -6494,28 +6496,26 @@ AC_CONFIG_FILES([Modules/Setup.stdlib]) AC_CONFIG_FILES([Modules/ld_so_aix], [chmod +x Modules/ld_so_aix]) AC_OUTPUT -echo "creating Modules/Setup.local" >&AS_MESSAGE_FD +AC_MSG_NOTICE([creating Modules/Setup.local]) if test ! -f Modules/Setup.local then echo "# Edit this file for local setup changes" >Modules/Setup.local fi -echo "creating Makefile" >&AS_MESSAGE_FD +AC_MSG_NOTICE([creating Makefile]) $SHELL $srcdir/Modules/makesetup -c $srcdir/Modules/config.c.in \ -s Modules \ Modules/Setup.local $srcdir/Modules/Setup.bootstrap $srcdir/Modules/Setup mv config.c Modules if test -z "$PKG_CONFIG"; then - echo "" >&AS_MESSAGE_FD - echo "pkg-config is missing. Some dependencies may not be detected correctly." >&AS_MESSAGE_FD + AC_MSG_WARN([pkg-config is missing. Some dependencies may not be detected correctly.]) fi if test "$Py_OPT" = 'false' -a "$Py_DEBUG" != 'true'; then - echo "" >&AS_MESSAGE_FD - echo "" >&AS_MESSAGE_FD - echo "If you want a release build with all stable optimizations active (PGO, etc)," >&AS_MESSAGE_FD - echo "please run ./configure --enable-optimizations" >&AS_MESSAGE_FD - echo "" >&AS_MESSAGE_FD - echo "" >&AS_MESSAGE_FD + AC_MSG_NOTICE([ + +If you want a release build with all stable optimizations active (PGO, etc), +please run ./configure --enable-optimizations +]) fi From webhook-mailer at python.org Fri Dec 10 08:12:07 2021 From: webhook-mailer at python.org (tiran) Date: Fri, 10 Dec 2021 13:12:07 -0000 Subject: [Python-checkins] bpo-46023: Fix makesetup handling of disabled rule (GH-30001) Message-ID: https://github.com/python/cpython/commit/036bbb1d1b6156a1a72c40e9f907f302505085bc commit: 036bbb1d1b6156a1a72c40e9f907f302505085bc branch: main author: Christian Heimes committer: tiran date: 2021-12-10T14:11:55+01:00 summary: bpo-46023: Fix makesetup handling of disabled rule (GH-30001) files: A Misc/NEWS.d/next/Build/2021-12-09-10-25-11.bpo-46023.PLpNB6.rst M Modules/makesetup diff --git a/Misc/NEWS.d/next/Build/2021-12-09-10-25-11.bpo-46023.PLpNB6.rst b/Misc/NEWS.d/next/Build/2021-12-09-10-25-11.bpo-46023.PLpNB6.rst new file mode 100644 index 0000000000000..4ef9202559394 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-12-09-10-25-11.bpo-46023.PLpNB6.rst @@ -0,0 +1,2 @@ +:program:`makesetup` no longer builds extensions that have been marked as +*disabled*. This allows users to disable modules in ``Modules/Setup.local``. diff --git a/Modules/makesetup b/Modules/makesetup index 2335724e804cc..6d83b8f0cbb7a 100755 --- a/Modules/makesetup +++ b/Modules/makesetup @@ -206,6 +206,9 @@ sed -e 's/[ ]*#.*//' -e '/^[ ]*$/d' | cpps="\$(MODULE_${mods_upper}_CFLAGS)" libs="\$(MODULE_${mods_upper}_LDFLAGS)" fi + case $DISABLED in + *$mods*) doconfig=disabled;; + esac case $doconfig in yes) LIBS="$LIBS $libs" From webhook-mailer at python.org Fri Dec 10 12:14:07 2021 From: webhook-mailer at python.org (zooba) Date: Fri, 10 Dec 2021 17:14:07 -0000 Subject: [Python-checkins] bpo-45582: Fix test_embed failure during a PGO build on Windows (GH-30014) Message-ID: https://github.com/python/cpython/commit/3f398a77d37b5dfd51dabbc362d482a482fa885a commit: 3f398a77d37b5dfd51dabbc362d482a482fa885a branch: main author: neonene <53406459+neonene at users.noreply.github.com> committer: zooba date: 2021-12-10T17:13:55Z summary: bpo-45582: Fix test_embed failure during a PGO build on Windows (GH-30014) This defines VPATH differently in PGO instrumentation builds, to account for a different default output directory. It also adds sys._vpath on Windows to make the value available to sysconfig so that it can be used in tests. files: M Lib/sysconfig.py M Lib/test/test_embed.py M Modules/getpath.py M PCbuild/_freeze_module.vcxproj M PCbuild/python.props M PCbuild/pythoncore.vcxproj M Python/sysmodule.c diff --git a/Lib/sysconfig.py b/Lib/sysconfig.py index da918b7ba1904..ef335c69421f5 100644 --- a/Lib/sysconfig.py +++ b/Lib/sysconfig.py @@ -616,6 +616,7 @@ def get_config_vars(*args): if os.name == 'nt': _init_non_posix(_CONFIG_VARS) + _CONFIG_VARS['VPATH'] = sys._vpath if os.name == 'posix': _init_posix(_CONFIG_VARS) # For backward compatibility, see issue19555 diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index 8012d80bf3e55..879952413374e 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -1300,11 +1300,16 @@ def test_init_pybuilddir(self): def test_init_pybuilddir_win32(self): # Test path configuration with pybuilddir.txt configuration file - with self.tmpdir_with_python(r'PCbuild\arch') as tmpdir: + vpath = sysconfig.get_config_var("VPATH") + subdir = r'PCbuild\arch' + if os.path.normpath(vpath).count(os.sep) == 2: + subdir = os.path.join(subdir, 'instrumented') + + with self.tmpdir_with_python(subdir) as tmpdir: # The prefix is dirname(executable) + VPATH - prefix = os.path.normpath(os.path.join(tmpdir, r'..\..')) + prefix = os.path.normpath(os.path.join(tmpdir, vpath)) # The stdlib dir is dirname(executable) + VPATH + 'Lib' - stdlibdir = os.path.normpath(os.path.join(tmpdir, r'..\..\Lib')) + stdlibdir = os.path.normpath(os.path.join(tmpdir, vpath, 'Lib')) filename = os.path.join(tmpdir, 'pybuilddir.txt') with open(filename, "w", encoding="utf8") as fp: diff --git a/Modules/getpath.py b/Modules/getpath.py index 84c9760b11248..77f951dbedef3 100644 --- a/Modules/getpath.py +++ b/Modules/getpath.py @@ -187,7 +187,7 @@ elif os_name == 'nt': BUILDDIR_TXT = 'pybuilddir.txt' - BUILD_LANDMARK = r'..\..\Modules\Setup.local' + BUILD_LANDMARK = f'{VPATH}\\Modules\\Setup.local' DEFAULT_PROGRAM_NAME = f'python' STDLIB_SUBDIR = 'Lib' STDLIB_LANDMARKS = [f'{STDLIB_SUBDIR}\\os.py', f'{STDLIB_SUBDIR}\\os.pyc'] diff --git a/PCbuild/_freeze_module.vcxproj b/PCbuild/_freeze_module.vcxproj index 2c06a8956ae45..2beb425647407 100644 --- a/PCbuild/_freeze_module.vcxproj +++ b/PCbuild/_freeze_module.vcxproj @@ -226,7 +226,9 @@ - + + VPATH="$(PyVPath)";%(PreprocessorDefinitions) + diff --git a/PCbuild/python.props b/PCbuild/python.props index 7b85ad1c94f16..ce860764e445f 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -53,6 +53,10 @@ $(BuildPath)\ $(BuildPath)instrumented\ + + ..\\.. + ..\\..\\.. + $(EXTERNALS_DIR) $([System.IO.Path]::GetFullPath(`$(PySourcePath)externals`)) diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index e3a71ca645143..33abfaf53652f 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -115,7 +115,7 @@ PREFIX=NULL; EXEC_PREFIX=NULL; VERSION=NULL; - VPATH="..\\.."; + VPATH="$(PyVPath)"; PYDEBUGEXT="$(PyDebugExt)"; PLATLIBDIR="DLLs"; %(PreprocessorDefinitions) @@ -519,7 +519,9 @@ - + + VPATH="$(PyVPath)";%(PreprocessorDefinitions) + diff --git a/Python/sysmodule.c b/Python/sysmodule.c index af4f926f0e408..f912115560704 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -2823,6 +2823,8 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict) goto type_init_failed; } } + + SET_SYS_FROM_STRING("_vpath", VPATH); #endif /* float repr style: 0.03 (short) vs 0.029999999999999999 (legacy) */ From webhook-mailer at python.org Fri Dec 10 12:51:51 2021 From: webhook-mailer at python.org (vsajip) Date: Fri, 10 Dec 2021 17:51:51 -0000 Subject: [Python-checkins] [3.10] bpo-43749: Ensure current exe is copied when using venv on windows (GH-25216) (GH-30034) Message-ID: https://github.com/python/cpython/commit/bb8d645f3a09645686cf8f66bd46dcfa4efac713 commit: bb8d645f3a09645686cf8f66bd46dcfa4efac713 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: vsajip date: 2021-12-10T17:51:42Z summary: [3.10] bpo-43749: Ensure current exe is copied when using venv on windows (GH-25216) (GH-30034) Co-authored-by: Ian Norton files: M Lib/venv/__init__.py diff --git a/Lib/venv/__init__.py b/Lib/venv/__init__.py index ce1f5d710ad76..6f1af294ae63e 100644 --- a/Lib/venv/__init__.py +++ b/Lib/venv/__init__.py @@ -281,8 +281,9 @@ def setup_python(self, context): os.path.normcase(f).startswith(('python', 'vcruntime')) ] else: - suffixes = ['python.exe', 'python_d.exe', 'pythonw.exe', - 'pythonw_d.exe'] + suffixes = {'python.exe', 'python_d.exe', 'pythonw.exe', 'pythonw_d.exe'} + base_exe = os.path.basename(context.env_exe) + suffixes.add(base_exe) for suffix in suffixes: src = os.path.join(dirname, suffix) From webhook-mailer at python.org Fri Dec 10 13:06:15 2021 From: webhook-mailer at python.org (vsajip) Date: Fri, 10 Dec 2021 18:06:15 -0000 Subject: [Python-checkins] [3.9] bpo-43749: Ensure current exe is copied when using venv on windows (GH-25216) (GH-30033) Message-ID: https://github.com/python/cpython/commit/bad16f0cf71a6b11ef62f86be6b3d3567cd70a16 commit: bad16f0cf71a6b11ef62f86be6b3d3567cd70a16 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: vsajip date: 2021-12-10T18:06:07Z summary: [3.9] bpo-43749: Ensure current exe is copied when using venv on windows (GH-25216) (GH-30033) Co-authored-by: Ian Norton files: M Lib/venv/__init__.py diff --git a/Lib/venv/__init__.py b/Lib/venv/__init__.py index ce1f5d710ad76..6f1af294ae63e 100644 --- a/Lib/venv/__init__.py +++ b/Lib/venv/__init__.py @@ -281,8 +281,9 @@ def setup_python(self, context): os.path.normcase(f).startswith(('python', 'vcruntime')) ] else: - suffixes = ['python.exe', 'python_d.exe', 'pythonw.exe', - 'pythonw_d.exe'] + suffixes = {'python.exe', 'python_d.exe', 'pythonw.exe', 'pythonw_d.exe'} + base_exe = os.path.basename(context.env_exe) + suffixes.add(base_exe) for suffix in suffixes: src = os.path.join(dirname, suffix) From webhook-mailer at python.org Fri Dec 10 13:09:16 2021 From: webhook-mailer at python.org (tiran) Date: Fri, 10 Dec 2021 18:09:16 -0000 Subject: [Python-checkins] bpo-45654: No need to freeze types (GH-30028) Message-ID: https://github.com/python/cpython/commit/16638a4bdb802ae52d386a39d2dbef14de3fbc92 commit: 16638a4bdb802ae52d386a39d2dbef14de3fbc92 branch: main author: Christian Heimes committer: tiran date: 2021-12-10T19:09:09+01:00 summary: bpo-45654: No need to freeze types (GH-30028) files: M Lib/runpy.py M Makefile.pre.in M PCbuild/_freeze_module.vcxproj M PCbuild/_freeze_module.vcxproj.filters M PCbuild/pythoncore.vcxproj M Python/frozen.c M Tools/scripts/freeze_modules.py diff --git a/Lib/runpy.py b/Lib/runpy.py index caba121426238..949fd5939ba2c 100644 --- a/Lib/runpy.py +++ b/Lib/runpy.py @@ -14,18 +14,20 @@ import importlib.machinery # importlib first so we can test #15386 via -m import importlib.util import io -import types import os __all__ = [ "run_module", "run_path", ] +# avoid 'import types' just for ModuleType +ModuleType = type(sys) + class _TempModule(object): """Temporarily replace a module in sys.modules with an empty namespace""" def __init__(self, mod_name): self.mod_name = mod_name - self.module = types.ModuleType(mod_name) + self.module = ModuleType(mod_name) self._saved_module = [] def __enter__(self): diff --git a/Makefile.pre.in b/Makefile.pre.in index 57928eead4384..a182786e5b587 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -490,7 +490,6 @@ DEEPFREEZE_OBJS = \ Python/deepfreeze/os.o \ Python/deepfreeze/site.o \ Python/deepfreeze/stat.o \ - Python/deepfreeze/types.o \ Python/deepfreeze/importlib.util.o \ Python/deepfreeze/importlib.machinery.o \ Python/deepfreeze/runpy.o \ @@ -1014,9 +1013,6 @@ Python/deepfreeze/site.c: Python/frozen_modules/site.h $(DEEPFREEZE_DEPS) Python/deepfreeze/stat.c: Python/frozen_modules/stat.h $(DEEPFREEZE_DEPS) $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/stat.h -m stat -o Python/deepfreeze/stat.c -Python/deepfreeze/types.c: Python/frozen_modules/types.h $(DEEPFREEZE_DEPS) - $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/types.h -m types -o Python/deepfreeze/types.c - Python/deepfreeze/importlib.util.c: Python/frozen_modules/importlib.util.h $(DEEPFREEZE_DEPS) $(PYTHON_FOR_FREEZE) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/importlib.util.h -m importlib.util -o Python/deepfreeze/importlib.util.c @@ -1065,7 +1061,6 @@ FROZEN_FILES_IN = \ Lib/os.py \ Lib/site.py \ Lib/stat.py \ - Lib/types.py \ Lib/importlib/util.py \ Lib/importlib/machinery.py \ Lib/runpy.py \ @@ -1091,7 +1086,6 @@ FROZEN_FILES_OUT = \ Python/frozen_modules/os.h \ Python/frozen_modules/site.h \ Python/frozen_modules/stat.h \ - Python/frozen_modules/types.h \ Python/frozen_modules/importlib.util.h \ Python/frozen_modules/importlib.machinery.h \ Python/frozen_modules/runpy.h \ @@ -1154,9 +1148,6 @@ Python/frozen_modules/site.h: $(FREEZE_MODULE) Lib/site.py Python/frozen_modules/stat.h: $(FREEZE_MODULE) Lib/stat.py $(FREEZE_MODULE) stat $(srcdir)/Lib/stat.py Python/frozen_modules/stat.h -Python/frozen_modules/types.h: $(FREEZE_MODULE) Lib/types.py - $(FREEZE_MODULE) types $(srcdir)/Lib/types.py Python/frozen_modules/types.h - Python/frozen_modules/importlib.util.h: $(FREEZE_MODULE) Lib/importlib/util.py $(FREEZE_MODULE) importlib.util $(srcdir)/Lib/importlib/util.py Python/frozen_modules/importlib.util.h diff --git a/PCbuild/_freeze_module.vcxproj b/PCbuild/_freeze_module.vcxproj index 2beb425647407..11a6a87daf91b 100644 --- a/PCbuild/_freeze_module.vcxproj +++ b/PCbuild/_freeze_module.vcxproj @@ -332,13 +332,6 @@ $(IntDir)stat.g.c $(PySourcePath)Python\deepfreeze\df.stat.c - - types - $(IntDir)types.g.h - $(PySourcePath)Python\frozen_modules\types.h - $(IntDir)types.g.c - $(PySourcePath)Python\deepfreeze\df.types.c - importlib.util $(IntDir)importlib.util.g.h diff --git a/PCbuild/_freeze_module.vcxproj.filters b/PCbuild/_freeze_module.vcxproj.filters index 7690e5ee58890..d107849c85621 100644 --- a/PCbuild/_freeze_module.vcxproj.filters +++ b/PCbuild/_freeze_module.vcxproj.filters @@ -447,9 +447,6 @@ Python Files - - Python Files - Python Files diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 33abfaf53652f..098cc21072344 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -541,7 +541,6 @@ - diff --git a/Python/frozen.c b/Python/frozen.c index 377c32249a83e..25cf0a8d37c78 100644 --- a/Python/frozen.c +++ b/Python/frozen.c @@ -53,7 +53,6 @@ #include "frozen_modules/os.h" #include "frozen_modules/site.h" #include "frozen_modules/stat.h" -#include "frozen_modules/types.h" #include "frozen_modules/importlib.util.h" #include "frozen_modules/importlib.machinery.h" #include "frozen_modules/runpy.h" @@ -83,7 +82,6 @@ extern PyObject *_Py_get_posixpath_toplevel(void); extern PyObject *_Py_get_os_toplevel(void); extern PyObject *_Py_get_site_toplevel(void); extern PyObject *_Py_get_stat_toplevel(void); -extern PyObject *_Py_get_types_toplevel(void); extern PyObject *_Py_get_importlib_util_toplevel(void); extern PyObject *_Py_get_importlib_machinery_toplevel(void); extern PyObject *_Py_get_runpy_toplevel(void); @@ -126,7 +124,6 @@ static const struct _frozen stdlib_modules[] = { {"stat", _Py_M__stat, (int)sizeof(_Py_M__stat), GET_CODE(stat)}, /* runpy - run module with -m */ - {"types", _Py_M__types, (int)sizeof(_Py_M__types), GET_CODE(types)}, {"importlib.util", _Py_M__importlib_util, (int)sizeof(_Py_M__importlib_util), GET_CODE(importlib_util)}, {"importlib.machinery", _Py_M__importlib_machinery, (int)sizeof(_Py_M__importlib_machinery), GET_CODE(importlib_machinery)}, {"runpy", _Py_M__runpy, (int)sizeof(_Py_M__runpy), GET_CODE(runpy)}, diff --git a/Tools/scripts/freeze_modules.py b/Tools/scripts/freeze_modules.py index b0c953159dc34..58d1398560835 100644 --- a/Tools/scripts/freeze_modules.py +++ b/Tools/scripts/freeze_modules.py @@ -69,10 +69,9 @@ 'stat', ]), ('runpy - run module with -m', [ - "types", "importlib.util", "importlib.machinery", - "runpy" + "runpy", ]), (TESTS_SECTION, [ '__hello__', From webhook-mailer at python.org Fri Dec 10 18:00:24 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 10 Dec 2021 23:00:24 -0000 Subject: [Python-checkins] bpo-42114: ctypes documentation: fix winmode parameter default value (GH-29976) Message-ID: https://github.com/python/cpython/commit/c1051e08b3c6d9045322763876a4b0aea98d79f9 commit: c1051e08b3c6d9045322763876a4b0aea98d79f9 branch: main author: Louis Sautier committer: ambv date: 2021-12-11T00:00:02+01:00 summary: bpo-42114: ctypes documentation: fix winmode parameter default value (GH-29976) Signed-off-by: Louis Sautier files: M Doc/library/ctypes.rst diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst index b58b961a30de6..6e147fc66eb14 100644 --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -1319,7 +1319,7 @@ There are several ways to load shared libraries into the Python process. One way is to instantiate one of the following classes: -.. class:: CDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=0) +.. class:: CDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None) Instances of this class represent loaded shared libraries. Functions in these libraries use the standard C calling convention, and are assumed to return @@ -1341,7 +1341,7 @@ way is to instantiate one of the following classes: -- A tool to find DLL dependents. -.. class:: OleDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=0) +.. class:: OleDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None) Windows only: Instances of this class represent loaded shared libraries, functions in these libraries use the ``stdcall`` calling convention, and are @@ -1354,7 +1354,7 @@ way is to instantiate one of the following classes: :exc:`WindowsError` used to be raised. -.. class:: WinDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=0) +.. class:: WinDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None) Windows only: Instances of this class represent loaded shared libraries, functions in these libraries use the ``stdcall`` calling convention, and are From webhook-mailer at python.org Fri Dec 10 18:02:16 2021 From: webhook-mailer at python.org (iritkatriel) Date: Fri, 10 Dec 2021 23:02:16 -0000 Subject: [Python-checkins] bpo-45635: refactor print_exception_recursive into smaller functions to standardize error handling (GH-30015) Message-ID: https://github.com/python/cpython/commit/0fe104fce7da709edddb701baa2249e3275db1fd commit: 0fe104fce7da709edddb701baa2249e3275db1fd branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-12-10T23:02:10Z summary: bpo-45635: refactor print_exception_recursive into smaller functions to standardize error handling (GH-30015) Co-authored-by: Erlend Egeberg Aasland files: M Python/pythonrun.c diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 74b497c8f0627..4fff088fc3e10 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -956,7 +956,7 @@ print_exception_traceback(struct exception_print_context *ctx, PyObject *value) /* Prints the message line: module.qualname[: str(exc)] */ static int print_exception_message(struct exception_print_context *ctx, PyObject *type, - PyObject *value) + PyObject *value) { PyObject *f = ctx->file; @@ -1253,183 +1253,221 @@ print_chained(struct exception_print_context* ctx, PyObject *value, return 0; } -static void -print_exception_recursive(struct exception_print_context* ctx, PyObject *value) +/* Return true if value is in seen or there was a lookup error. + * Return false if lookup succeeded and the item was not found. + * We suppress errors because this makes us err on the side of + * under-printing which is better than over-printing irregular + * exceptions (e.g., unhashable ones). + */ +static bool +print_exception_seen_lookup(struct exception_print_context *ctx, + PyObject *value) { - int err = 0, res; - PyObject *cause, *context; + PyObject *check_id = PyLong_FromVoidPtr(value); + if (check_id == NULL) { + PyErr_Clear(); + return true; + } - if (ctx->seen != NULL) { - /* Exception chaining */ - PyObject *value_id = PyLong_FromVoidPtr(value); - if (value_id == NULL || PySet_Add(ctx->seen, value_id) == -1) - PyErr_Clear(); - else if (PyExceptionInstance_Check(value)) { - PyObject *check_id = NULL; - - cause = PyException_GetCause(value); - context = PyException_GetContext(value); - if (cause) { - check_id = PyLong_FromVoidPtr(cause); - if (check_id == NULL) { - res = -1; - } else { - res = PySet_Contains(ctx->seen, check_id); - Py_DECREF(check_id); - } - if (res == -1) - PyErr_Clear(); - if (res == 0) { - err = print_chained(ctx, cause, cause_message, "cause"); - } - } - else if (context && - !((PyBaseExceptionObject *)value)->suppress_context) { - check_id = PyLong_FromVoidPtr(context); - if (check_id == NULL) { - res = -1; - } else { - res = PySet_Contains(ctx->seen, check_id); - Py_DECREF(check_id); - } - if (res == -1) - PyErr_Clear(); - if (res == 0) { - err = print_chained(ctx, context, context_message, "context"); - } - } - Py_XDECREF(context); - Py_XDECREF(cause); - } + int in_seen = PySet_Contains(ctx->seen, check_id); + Py_DECREF(check_id); + if (in_seen == -1) { + PyErr_Clear(); + return true; + } + + if (in_seen == 1) { + /* value is in seen */ + return true; + } + return false; +} + +static int +print_exception_cause_and_context(struct exception_print_context *ctx, + PyObject *value) +{ + PyObject *value_id = PyLong_FromVoidPtr(value); + if (value_id == NULL || PySet_Add(ctx->seen, value_id) == -1) { + PyErr_Clear(); Py_XDECREF(value_id); + return 0; } - if (err) { - /* don't do anything else */ + Py_DECREF(value_id); + + if (!PyExceptionInstance_Check(value)) { + return 0; } - else if (!_PyBaseExceptionGroup_Check(value)) { - print_exception(ctx, value); + + PyObject *cause = PyException_GetCause(value); + if (cause) { + int err = 0; + if (!print_exception_seen_lookup(ctx, cause)) { + err = print_chained(ctx, cause, cause_message, "cause"); + } + Py_DECREF(cause); + return err; } - else if (ctx->exception_group_depth > ctx->max_group_depth) { - /* exception group but depth exceeds limit */ + if (((PyBaseExceptionObject *)value)->suppress_context) { + return 0; + } + PyObject *context = PyException_GetContext(value); + if (context) { + int err = 0; + if (!print_exception_seen_lookup(ctx, context)) { + err = print_chained(ctx, context, context_message, "context"); + } + Py_DECREF(context); + return err; + } + return 0; +} + +static int +print_exception_group(struct exception_print_context *ctx, PyObject *value) +{ + PyObject *f = ctx->file; - PyObject *line = PyUnicode_FromFormat( - "... (max_group_depth is %d)\n", ctx->max_group_depth); + if (ctx->exception_group_depth > ctx->max_group_depth) { + /* depth exceeds limit */ - if (line) { - PyObject *f = ctx->file; - if (err == 0) { - err = write_indented_margin(ctx, f); - } - if (err == 0) { - err = PyFile_WriteObject(line, f, Py_PRINT_RAW); - } - Py_DECREF(line); + if (write_indented_margin(ctx, f) < 0) { + return -1; } - else { - err = -1; + + PyObject *line = PyUnicode_FromFormat("... (max_group_depth is %d)\n", + ctx->max_group_depth); + if (line == NULL) { + return -1; } + int err = PyFile_WriteObject(line, f, Py_PRINT_RAW); + Py_DECREF(line); + return err; + } + + if (ctx->exception_group_depth == 0) { + ctx->exception_group_depth += 1; + } + print_exception(ctx, value); + + PyObject *excs = ((PyBaseExceptionGroupObject *)value)->excs; + assert(excs && PyTuple_Check(excs)); + Py_ssize_t num_excs = PyTuple_GET_SIZE(excs); + assert(num_excs > 0); + Py_ssize_t n; + if (num_excs <= ctx->max_group_width) { + n = num_excs; } else { - /* format exception group */ + n = ctx->max_group_width + 1; + } - if (ctx->exception_group_depth == 0) { - ctx->exception_group_depth += 1; + ctx->need_close = false; + for (Py_ssize_t i = 0; i < n; i++) { + bool last_exc = (i == n - 1); + if (last_exc) { + // The closing frame may be added in a recursive call + ctx->need_close = true; } - print_exception(ctx, value); - PyObject *excs = ((PyBaseExceptionGroupObject *)value)->excs; - assert(excs && PyTuple_Check(excs)); - Py_ssize_t num_excs = PyTuple_GET_SIZE(excs); - assert(num_excs > 0); - Py_ssize_t n; - if (num_excs <= ctx->max_group_width) { - n = num_excs; + if (_Py_WriteIndent(EXC_INDENT(ctx), f) < 0) { + return -1; + } + bool truncated = (i >= ctx->max_group_width); + PyObject *line; + if (!truncated) { + line = PyUnicode_FromFormat( + "%s+---------------- %zd ----------------\n", + (i == 0) ? "+-" : " ", i + 1); } else { - n = ctx->max_group_width + 1; + line = PyUnicode_FromFormat( + "%s+---------------- ... ----------------\n", + (i == 0) ? "+-" : " "); + } + if (line == NULL) { + return -1; + } + int err = PyFile_WriteObject(line, f, Py_PRINT_RAW); + Py_DECREF(line); + if (err < 0) { + return -1; } - PyObject *f = ctx->file; + ctx->exception_group_depth += 1; + PyObject *exc = PyTuple_GET_ITEM(excs, i); - ctx->need_close = false; - for (Py_ssize_t i = 0; i < n; i++) { - int last_exc = (i == n - 1); - if (last_exc) { - // The closing frame may be added in a recursive call - ctx->need_close = true; + if (!truncated) { + if (Py_EnterRecursiveCall(" in print_exception_recursive") != 0) { + return -1; } - PyObject *line; - bool truncated = (i >= ctx->max_group_width); - if (!truncated) { - line = PyUnicode_FromFormat( - "%s+---------------- %zd ----------------\n", - (i == 0) ? "+-" : " ", i + 1); + print_exception_recursive(ctx, exc); + Py_LeaveRecursiveCall(); + } + else { + Py_ssize_t excs_remaining = num_excs - ctx->max_group_width; + + if (write_indented_margin(ctx, f) < 0) { + return -1; } - else { - line = PyUnicode_FromFormat( - "%s+---------------- ... ----------------\n", - (i == 0) ? "+-" : " "); + + PyObject *line = PyUnicode_FromFormat( + "and %zd more exception%s\n", + excs_remaining, excs_remaining > 1 ? "s" : ""); + + if (line == NULL) { + return -1; } - if (line) { - if (err == 0) { - err = _Py_WriteIndent(EXC_INDENT(ctx), f); - } - if (err == 0) { - err = PyFile_WriteObject(line, f, Py_PRINT_RAW); - } - Py_DECREF(line); + int err = PyFile_WriteObject(line, f, Py_PRINT_RAW); + Py_DECREF(line); + if (err < 0) { + return -1; } - else { - err = -1; + } + + if (last_exc && ctx->need_close) { + if (_Py_WriteIndent(EXC_INDENT(ctx), f) < 0) { + return -1; } + if (PyFile_WriteString( + "+------------------------------------\n", f) < 0) { + return -1; + } + ctx->need_close = false; + } + ctx->exception_group_depth -= 1; + } - if (err == 0) { - ctx->exception_group_depth += 1; - PyObject *exc = PyTuple_GET_ITEM(excs, i); - - if (!truncated) { - if (!Py_EnterRecursiveCall(" in print_exception_recursive")) { - print_exception_recursive(ctx, exc); - Py_LeaveRecursiveCall(); - } - else { - err = -1; - } - } - else { - Py_ssize_t excs_remaining = num_excs - ctx->max_group_width; - PyObject *line = PyUnicode_FromFormat( - "and %zd more exception%s\n", - excs_remaining, excs_remaining > 1 ? "s" : ""); - - if (line) { - if (err == 0) { - err = write_indented_margin(ctx, f); - } - if (err == 0) { - err = PyFile_WriteObject(line, f, Py_PRINT_RAW); - } - Py_DECREF(line); - } - else { - err = -1; - } - } + if (ctx->exception_group_depth == 1) { + ctx->exception_group_depth -= 1; + } + return 0; +} - if (err == 0 && last_exc && ctx->need_close) { - err = _Py_WriteIndent(EXC_INDENT(ctx), f); - if (err == 0) { - err = PyFile_WriteString( - "+------------------------------------\n", f); - } - ctx->need_close = false; - } - ctx->exception_group_depth -= 1; - } +static void +print_exception_recursive(struct exception_print_context *ctx, PyObject *value) +{ + int err = 0; + if (ctx->seen != NULL) { + /* Exception chaining */ + err = print_exception_cause_and_context(ctx, value); + } + if (err) { + /* don't do anything else */ + } + else if (!_PyBaseExceptionGroup_Check(value)) { + print_exception(ctx, value); + } + else { + int prev_depth = ctx->exception_group_depth; + err = print_exception_group(ctx, value); + if (err < 0) { + /* restore the depth as long as we're ignoring errors */ + ctx->exception_group_depth = prev_depth; } - if (ctx->exception_group_depth == 1) { - ctx->exception_group_depth -= 1; + else { + assert(prev_depth == ctx->exception_group_depth); } } if (err != 0) From webhook-mailer at python.org Fri Dec 10 18:05:31 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 10 Dec 2021 23:05:31 -0000 Subject: [Python-checkins] bpo-27062: add `__all__` to inspect module (GH-30003) Message-ID: https://github.com/python/cpython/commit/810c1769f1c24ed907bdf3cc1086db4e602a28ae commit: 810c1769f1c24ed907bdf3cc1086db4e602a28ae branch: main author: Kumar Aditya <59607654+kumaraditya303 at users.noreply.github.com> committer: ambv date: 2021-12-11T00:05:23+01:00 summary: bpo-27062: add `__all__` to inspect module (GH-30003) files: A Misc/NEWS.d/next/Library/2021-12-09-11-50-32.bpo-27062.R5vii6.rst M Lib/inspect.py M Lib/test/test_inspect.py diff --git a/Lib/inspect.py b/Lib/inspect.py index 1eb2f2b575ef4..746f6e4f9f9f0 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -32,7 +32,106 @@ __author__ = ('Ka-Ping Yee ', 'Yury Selivanov ') - + +__all__ = [ + "ArgInfo", + "Arguments", + "Attribute", + "BlockFinder", + "BoundArguments", + "CORO_CLOSED", + "CORO_CREATED", + "CORO_RUNNING", + "CORO_SUSPENDED", + "CO_ASYNC_GENERATOR", + "CO_COROUTINE", + "CO_GENERATOR", + "CO_ITERABLE_COROUTINE", + "CO_NESTED", + "CO_NEWLOCALS", + "CO_NOFREE", + "CO_OPTIMIZED", + "CO_VARARGS", + "CO_VARKEYWORDS", + "ClassFoundException", + "ClosureVars", + "EndOfBlock", + "FrameInfo", + "FullArgSpec", + "GEN_CLOSED", + "GEN_CREATED", + "GEN_RUNNING", + "GEN_SUSPENDED", + "Parameter", + "Signature", + "TPFLAGS_IS_ABSTRACT", + "Traceback", + "classify_class_attrs", + "cleandoc", + "currentframe", + "findsource", + "formatannotation", + "formatannotationrelativeto", + "formatargvalues", + "get_annotations", + "getabsfile", + "getargs", + "getargvalues", + "getattr_static", + "getblock", + "getcallargs", + "getclasstree", + "getclosurevars", + "getcomments", + "getcoroutinelocals", + "getcoroutinestate", + "getdoc", + "getfile", + "getframeinfo", + "getfullargspec", + "getgeneratorlocals", + "getgeneratorstate", + "getinnerframes", + "getlineno", + "getmembers", + "getmembers_static", + "getmodule", + "getmodulename", + "getmro", + "getouterframes", + "getsource", + "getsourcefile", + "getsourcelines", + "indentsize", + "isabstract", + "isasyncgen", + "isasyncgenfunction", + "isawaitable", + "isbuiltin", + "isclass", + "iscode", + "iscoroutine", + "iscoroutinefunction", + "isdatadescriptor", + "isframe", + "isfunction", + "isgenerator", + "isgeneratorfunction", + "isgetsetdescriptor", + "ismemberdescriptor", + "ismethod", + "ismethoddescriptor", + "ismodule", + "isroutine", + "istraceback", + "signature", + "stack", + "trace", + "unwrap", + "walktree", +] + + import abc import ast import dis diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 33665cf3c79eb..c25256dfa26fd 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -107,6 +107,9 @@ def istest(self, predicate, exp): continue self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp)) + def test__all__(self): + support.check__all__(self, inspect, not_exported=("k", "v", "mod_dict", "modulesbyfile")) + def generator_function_example(self): for i in range(2): yield i diff --git a/Misc/NEWS.d/next/Library/2021-12-09-11-50-32.bpo-27062.R5vii6.rst b/Misc/NEWS.d/next/Library/2021-12-09-11-50-32.bpo-27062.R5vii6.rst new file mode 100644 index 0000000000000..3ca22b69d456f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-09-11-50-32.bpo-27062.R5vii6.rst @@ -0,0 +1 @@ +Add :attr:`__all__` to :mod:`inspect`, patch by Kumar Aditya. \ No newline at end of file From webhook-mailer at python.org Fri Dec 10 18:28:07 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 10 Dec 2021 23:28:07 -0000 Subject: [Python-checkins] bpo-46014: Add ability to use typing.Union with singledispatch (GH-30017) Message-ID: https://github.com/python/cpython/commit/3cb357a2e6ac18ee98db5d450414e773744e3c76 commit: 3cb357a2e6ac18ee98db5d450414e773744e3c76 branch: main author: Yurii Karabas <1998uriyyo at gmail.com> committer: ambv date: 2021-12-11T00:27:55+01:00 summary: bpo-46014: Add ability to use typing.Union with singledispatch (GH-30017) files: A Misc/NEWS.d/next/Library/2021-12-10-03-13-57.bpo-46014.3xYdST.rst M Lib/functools.py M Lib/test/test_functools.py diff --git a/Lib/functools.py b/Lib/functools.py index 77ec852805c10..ccac6f89996b6 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -837,6 +837,14 @@ def dispatch(cls): dispatch_cache[cls] = impl return impl + def _is_union_type(cls): + from typing import get_origin, Union + return get_origin(cls) in {Union, types.UnionType} + + def _is_valid_union_type(cls): + from typing import get_args + return _is_union_type(cls) and all(isinstance(arg, type) for arg in get_args(cls)) + def register(cls, func=None): """generic_func.register(cls, func) -> func @@ -845,7 +853,7 @@ def register(cls, func=None): """ nonlocal cache_token if func is None: - if isinstance(cls, type): + if isinstance(cls, type) or _is_valid_union_type(cls): return lambda f: register(cls, f) ann = getattr(cls, '__annotations__', {}) if not ann: @@ -859,12 +867,25 @@ def register(cls, func=None): # only import typing if annotation parsing is necessary from typing import get_type_hints argname, cls = next(iter(get_type_hints(func).items())) - if not isinstance(cls, type): - raise TypeError( - f"Invalid annotation for {argname!r}. " - f"{cls!r} is not a class." - ) - registry[cls] = func + if not isinstance(cls, type) and not _is_valid_union_type(cls): + if _is_union_type(cls): + raise TypeError( + f"Invalid annotation for {argname!r}. " + f"{cls!r} not all arguments are classes." + ) + else: + raise TypeError( + f"Invalid annotation for {argname!r}. " + f"{cls!r} is not a class." + ) + + if _is_union_type(cls): + from typing import get_args + + for arg in get_args(cls): + registry[arg] = func + else: + registry[cls] = func if cache_token is None and hasattr(cls, '__abstractmethods__'): cache_token = get_cache_token() dispatch_cache.clear() diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 08cf457cc17db..755ac038792b7 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -2684,6 +2684,17 @@ def _(arg: typing.Iterable[str]): 'typing.Iterable[str] is not a class.' )) + with self.assertRaises(TypeError) as exc: + @i.register + def _(arg: typing.Union[int, typing.Iterable[str]]): + return "Invalid Union" + self.assertTrue(str(exc.exception).startswith( + "Invalid annotation for 'arg'." + )) + self.assertTrue(str(exc.exception).endswith( + 'typing.Union[int, typing.Iterable[str]] not all arguments are classes.' + )) + def test_invalid_positional_argument(self): @functools.singledispatch def f(*args): @@ -2692,6 +2703,25 @@ def f(*args): with self.assertRaisesRegex(TypeError, msg): f() + def test_union(self): + @functools.singledispatch + def f(arg): + return "default" + + @f.register + def _(arg: typing.Union[str, bytes]): + return "typing.Union" + + @f.register + def _(arg: int | float): + return "types.UnionType" + + self.assertEqual(f([]), "default") + self.assertEqual(f(""), "typing.Union") + self.assertEqual(f(b""), "typing.Union") + self.assertEqual(f(1), "types.UnionType") + self.assertEqual(f(1.0), "types.UnionType") + class CachedCostItem: _cost = 1 diff --git a/Misc/NEWS.d/next/Library/2021-12-10-03-13-57.bpo-46014.3xYdST.rst b/Misc/NEWS.d/next/Library/2021-12-10-03-13-57.bpo-46014.3xYdST.rst new file mode 100644 index 0000000000000..90aacaf7e088f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-10-03-13-57.bpo-46014.3xYdST.rst @@ -0,0 +1,2 @@ +Add ability to use ``typing.Union`` and ``types.UnionType`` as dispatch +argument to ``functools.singledispatch``. Patch provided by Yurii Karabas. From webhook-mailer at python.org Fri Dec 10 18:29:39 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 10 Dec 2021 23:29:39 -0000 Subject: [Python-checkins] bpo-42114: ctypes documentation: fix winmode parameter default value (GH-29976) (GH-30038) Message-ID: https://github.com/python/cpython/commit/f8eebb0db720cd81fb736d9cbfd16faf2ec68b53 commit: f8eebb0db720cd81fb736d9cbfd16faf2ec68b53 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-12-11T00:29:28+01:00 summary: bpo-42114: ctypes documentation: fix winmode parameter default value (GH-29976) (GH-30038) Signed-off-by: Louis Sautier (cherry picked from commit c1051e08b3c6d9045322763876a4b0aea98d79f9) Co-authored-by: Louis Sautier files: M Doc/library/ctypes.rst diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst index b186f1d5753a6..c10e54f153243 100644 --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -1320,7 +1320,7 @@ There are several ways to load shared libraries into the Python process. One way is to instantiate one of the following classes: -.. class:: CDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=0) +.. class:: CDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None) Instances of this class represent loaded shared libraries. Functions in these libraries use the standard C calling convention, and are assumed to return @@ -1342,7 +1342,7 @@ way is to instantiate one of the following classes: -- A tool to find DLL dependents. -.. class:: OleDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=0) +.. class:: OleDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None) Windows only: Instances of this class represent loaded shared libraries, functions in these libraries use the ``stdcall`` calling convention, and are @@ -1355,7 +1355,7 @@ way is to instantiate one of the following classes: :exc:`WindowsError` used to be raised. -.. class:: WinDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=0) +.. class:: WinDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None) Windows only: Instances of this class represent loaded shared libraries, functions in these libraries use the ``stdcall`` calling convention, and are From webhook-mailer at python.org Fri Dec 10 18:29:51 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 10 Dec 2021 23:29:51 -0000 Subject: [Python-checkins] bpo-42114: ctypes documentation: fix winmode parameter default value (GH-29976) (GH-30037) Message-ID: https://github.com/python/cpython/commit/8f3728edcbc205913772f8dc04cccd8bdc476ff4 commit: 8f3728edcbc205913772f8dc04cccd8bdc476ff4 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-12-11T00:29:46+01:00 summary: bpo-42114: ctypes documentation: fix winmode parameter default value (GH-29976) (GH-30037) Signed-off-by: Louis Sautier (cherry picked from commit c1051e08b3c6d9045322763876a4b0aea98d79f9) Co-authored-by: Louis Sautier files: M Doc/library/ctypes.rst diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst index b186f1d5753a6..c10e54f153243 100644 --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -1320,7 +1320,7 @@ There are several ways to load shared libraries into the Python process. One way is to instantiate one of the following classes: -.. class:: CDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=0) +.. class:: CDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None) Instances of this class represent loaded shared libraries. Functions in these libraries use the standard C calling convention, and are assumed to return @@ -1342,7 +1342,7 @@ way is to instantiate one of the following classes: -- A tool to find DLL dependents. -.. class:: OleDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=0) +.. class:: OleDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None) Windows only: Instances of this class represent loaded shared libraries, functions in these libraries use the ``stdcall`` calling convention, and are @@ -1355,7 +1355,7 @@ way is to instantiate one of the following classes: :exc:`WindowsError` used to be raised. -.. class:: WinDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=0) +.. class:: WinDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None) Windows only: Instances of this class represent loaded shared libraries, functions in these libraries use the ``stdcall`` calling convention, and are From webhook-mailer at python.org Fri Dec 10 18:34:51 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 10 Dec 2021 23:34:51 -0000 Subject: [Python-checkins] bpo-43795: Document stable_abi.txt format and contents (GH-29956) Message-ID: https://github.com/python/cpython/commit/98e506ae8a7997658a08fbf77ac016d200588cb3 commit: 98e506ae8a7997658a08fbf77ac016d200588cb3 branch: main author: Petr Viktorin committer: ambv date: 2021-12-11T00:34:31+01:00 summary: bpo-43795: Document stable_abi.txt format and contents (GH-29956) Also mention that removals generally aren't allowed. files: M Misc/stable_abi.txt M Tools/scripts/stable_abi.py diff --git a/Misc/stable_abi.txt b/Misc/stable_abi.txt index 9cb210c60cf24..c4f5318712a54 100644 --- a/Misc/stable_abi.txt +++ b/Misc/stable_abi.txt @@ -10,6 +10,46 @@ # and PC/pythonXYstub.def +# The current format is a simple line-based one with significant indentation. +# Anything after a hash is a comment. + +# There are these kinds of top-level "items": +# - struct: A C struct. Currently this file does not distinguish between: +# - opaque structs, which the Limited API only handles via pointers +# (so these can change at any time) +# - structs where only certain members are part of the stable ABI (e.g. +# PyObject) +# - structs which must not be changed at all (e.g. PyType_Slot, which is +# fully defined and used in arrays) +# - function: A function that must be kept available (and exported, i.e. not +# converted to a macro). +# - const: A simple value, defined with `#define`. +# - macro: A preprocessor macro more complex than a simple `const` value. +# - data: An exported object, which must continue to be available but its exact +# value may change. +# - typedef: A C typedef which is used in other definitions in the limited API. +# Its size/layout/signature must not change. + +# Each top-level item can have details defined below it: +# - added: The version in which the item was added to the stable ABI. +# - ifdef: A feature macro: the item is only available if this macro is defined +# - abi_only: If present, the item is not part of the Limited API, but it *is* +# part of the stable ABI. The item will not show up in user-facing docs. +# Typically used for: +# - private functions called by public macros, e.g. _Py_BuildValue_SizeT +# - items that were part of the limited API in the past, and must remain part +# of the stable ABI. +# - a combination of the above (functions that were called by macros that +# were public in the past) + +# Removing items from this file is generally not allowed, and additions should +# be considered with that in mind. See the devguide for exact rules: +# https://devguide.python.org/c-api/#limited-api + +# User-facing docs are at: +# https://docs.python.org/3/c-api/stable.html#stable + + # Mentioned in PEP 384: struct PyObject diff --git a/Tools/scripts/stable_abi.py b/Tools/scripts/stable_abi.py index 0179f3c12fcbd..04b1f78e00adb 100755 --- a/Tools/scripts/stable_abi.py +++ b/Tools/scripts/stable_abi.py @@ -174,6 +174,7 @@ def raise_error(msg): parent.abi_only = True else: raise_error(f"unknown kind {kind!r}") + # When adding more, update the comment in stable_abi.txt. levels.append((entry, level)) return manifest From webhook-mailer at python.org Fri Dec 10 18:36:19 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 10 Dec 2021 23:36:19 -0000 Subject: [Python-checkins] [3.10] bpo-13236: Flush the output stream more often in unittest (GH-29864) (GH-29929) Message-ID: https://github.com/python/cpython/commit/83fa1291fd0a25216a4a9e990f423682fda67cbe commit: 83fa1291fd0a25216a4a9e990f423682fda67cbe branch: 3.10 author: Serhiy Storchaka committer: ambv date: 2021-12-11T00:36:15+01:00 summary: [3.10] bpo-13236: Flush the output stream more often in unittest (GH-29864) (GH-29929) It can prevent some losses when output to buffered stream.. (cherry picked from commit f42a06ba279c916fb67289e47f9bc60dc5dee4ee) Co-authored-by: Serhiy Storchaka files: A Misc/NEWS.d/next/Library/2021-11-30-13-52-02.bpo-13236.FmJIkO.rst M Lib/unittest/runner.py M Lib/unittest/test/test_program.py M Lib/unittest/test/test_result.py diff --git a/Lib/unittest/runner.py b/Lib/unittest/runner.py index 45e7e4c0458d4..caf159002d8bb 100644 --- a/Lib/unittest/runner.py +++ b/Lib/unittest/runner.py @@ -59,6 +59,7 @@ def addSuccess(self, test): super(TextTestResult, self).addSuccess(test) if self.showAll: self.stream.writeln("ok") + self.stream.flush() elif self.dots: self.stream.write('.') self.stream.flush() @@ -67,6 +68,7 @@ def addError(self, test, err): super(TextTestResult, self).addError(test, err) if self.showAll: self.stream.writeln("ERROR") + self.stream.flush() elif self.dots: self.stream.write('E') self.stream.flush() @@ -75,6 +77,7 @@ def addFailure(self, test, err): super(TextTestResult, self).addFailure(test, err) if self.showAll: self.stream.writeln("FAIL") + self.stream.flush() elif self.dots: self.stream.write('F') self.stream.flush() @@ -83,6 +86,7 @@ def addSkip(self, test, reason): super(TextTestResult, self).addSkip(test, reason) if self.showAll: self.stream.writeln("skipped {0!r}".format(reason)) + self.stream.flush() elif self.dots: self.stream.write("s") self.stream.flush() @@ -91,6 +95,7 @@ def addExpectedFailure(self, test, err): super(TextTestResult, self).addExpectedFailure(test, err) if self.showAll: self.stream.writeln("expected failure") + self.stream.flush() elif self.dots: self.stream.write("x") self.stream.flush() @@ -99,6 +104,7 @@ def addUnexpectedSuccess(self, test): super(TextTestResult, self).addUnexpectedSuccess(test) if self.showAll: self.stream.writeln("unexpected success") + self.stream.flush() elif self.dots: self.stream.write("u") self.stream.flush() @@ -106,6 +112,7 @@ def addUnexpectedSuccess(self, test): def printErrors(self): if self.dots or self.showAll: self.stream.writeln() + self.stream.flush() self.printErrorList('ERROR', self.errors) self.printErrorList('FAIL', self.failures) @@ -115,6 +122,7 @@ def printErrorList(self, flavour, errors): self.stream.writeln("%s: %s" % (flavour,self.getDescription(test))) self.stream.writeln(self.separator2) self.stream.writeln("%s" % err) + self.stream.flush() class TextTestRunner(object): @@ -218,4 +226,5 @@ def run(self, test): self.stream.writeln(" (%s)" % (", ".join(infos),)) else: self.stream.write("\n") + self.stream.flush() return result diff --git a/Lib/unittest/test/test_program.py b/Lib/unittest/test/test_program.py index eef82ff937ab7..939af81b3b4cd 100644 --- a/Lib/unittest/test/test_program.py +++ b/Lib/unittest/test/test_program.py @@ -6,6 +6,7 @@ from test import support import unittest import unittest.test +from .test_result import BufferedWriter class Test_TestProgram(unittest.TestCase): @@ -104,30 +105,39 @@ def run(self, test): program.testNames) def test_NonExit(self): + stream = BufferedWriter() program = unittest.main(exit=False, argv=["foobar"], - testRunner=unittest.TextTestRunner(stream=io.StringIO()), + testRunner=unittest.TextTestRunner(stream=stream), testLoader=self.FooBarLoader()) self.assertTrue(hasattr(program, 'result')) + self.assertIn('\nFAIL: testFail ', stream.getvalue()) + self.assertTrue(stream.getvalue().endswith('\n\nFAILED (failures=1)\n')) def test_Exit(self): + stream = BufferedWriter() self.assertRaises( SystemExit, unittest.main, argv=["foobar"], - testRunner=unittest.TextTestRunner(stream=io.StringIO()), + testRunner=unittest.TextTestRunner(stream=stream), exit=True, testLoader=self.FooBarLoader()) + self.assertIn('\nFAIL: testFail ', stream.getvalue()) + self.assertTrue(stream.getvalue().endswith('\n\nFAILED (failures=1)\n')) def test_ExitAsDefault(self): + stream = BufferedWriter() self.assertRaises( SystemExit, unittest.main, argv=["foobar"], - testRunner=unittest.TextTestRunner(stream=io.StringIO()), + testRunner=unittest.TextTestRunner(stream=stream), testLoader=self.FooBarLoader()) + self.assertIn('\nFAIL: testFail ', stream.getvalue()) + self.assertTrue(stream.getvalue().endswith('\n\nFAILED (failures=1)\n')) class InitialisableProgram(unittest.TestProgram): diff --git a/Lib/unittest/test/test_result.py b/Lib/unittest/test/test_result.py index d6efc7ef0662a..5416735f2923c 100644 --- a/Lib/unittest/test/test_result.py +++ b/Lib/unittest/test/test_result.py @@ -33,6 +33,22 @@ def bad_cleanup2(): raise ValueError('bad cleanup2') +class BufferedWriter: + def __init__(self): + self.result = '' + self.buffer = '' + + def write(self, arg): + self.buffer += arg + + def flush(self): + self.result += self.buffer + self.buffer = '' + + def getvalue(self): + return self.result + + class Test_TestResult(unittest.TestCase): # Note: there are not separate tests for TestResult.wasSuccessful(), # TestResult.errors, TestResult.failures, TestResult.testsRun or @@ -444,10 +460,13 @@ def testFailFast(self): self.assertTrue(result.shouldStop) def testFailFastSetByRunner(self): - runner = unittest.TextTestRunner(stream=io.StringIO(), failfast=True) + stream = BufferedWriter() + runner = unittest.TextTestRunner(stream=stream, failfast=True) def test(result): self.assertTrue(result.failfast) result = runner.run(test) + stream.flush() + self.assertTrue(stream.getvalue().endswith('\n\nOK\n')) classDict = dict(unittest.TestResult.__dict__) diff --git a/Misc/NEWS.d/next/Library/2021-11-30-13-52-02.bpo-13236.FmJIkO.rst b/Misc/NEWS.d/next/Library/2021-11-30-13-52-02.bpo-13236.FmJIkO.rst new file mode 100644 index 0000000000000..bfea8d4fca0e0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-30-13-52-02.bpo-13236.FmJIkO.rst @@ -0,0 +1,2 @@ +:class:`unittest.TextTestResult` and :class:`unittest.TextTestRunner` flush +now the output stream more often. From webhook-mailer at python.org Fri Dec 10 18:44:35 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 10 Dec 2021 23:44:35 -0000 Subject: [Python-checkins] bpo-42918: Improve build-in function compile() in mode 'single' (GH-29934) Message-ID: https://github.com/python/cpython/commit/28179aac796ed1debdce336c4b8ca18e8475d40d commit: 28179aac796ed1debdce336c4b8ca18e8475d40d branch: main author: Weipeng Hong committer: ambv date: 2021-12-11T00:44:26+01:00 summary: bpo-42918: Improve build-in function compile() in mode 'single' (GH-29934) Co-authored-by: Alex Waygood files: A Misc/NEWS.d/next/Core and Builtins/2021-12-06-15-32-12.bpo-42918.Czpgtg.rst M Lib/test/test_compile.py M Parser/pegen.c diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index f72c7ca68f363..f4ed6c706da66 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -504,6 +504,7 @@ def test_single_statement(self): self.compile_single("if x:\n f(x)") self.compile_single("if x:\n f(x)\nelse:\n g(x)") self.compile_single("class T:\n pass") + self.compile_single("c = '''\na=1\nb=2\nc=3\n'''") def test_bad_single_statement(self): self.assertInvalidSingle('1\n2') @@ -514,6 +515,7 @@ def test_bad_single_statement(self): self.assertInvalidSingle('f()\n# blah\nblah()') self.assertInvalidSingle('f()\nxy # blah\nblah()') self.assertInvalidSingle('x = 5 # comment\nx = 6\n') + self.assertInvalidSingle("c = '''\nd=1\n'''\na = 1\n\nb = 2\n") def test_particularly_evil_undecodable(self): # Issue 24022 diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-06-15-32-12.bpo-42918.Czpgtg.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-06-15-32-12.bpo-42918.Czpgtg.rst new file mode 100644 index 0000000000000..f03dadebcf3b3 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-06-15-32-12.bpo-42918.Czpgtg.rst @@ -0,0 +1,3 @@ +Fix bug where the built-in :func:`compile` function did not always raise a +:exc:`SyntaxError` when passed multiple statements in 'single' mode. Patch by +Weipeng Hong. diff --git a/Parser/pegen.c b/Parser/pegen.c index ede281ac89cd9..4158a81fd52f7 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -675,31 +675,13 @@ _PyPegen_number_token(Parser *p) t->end_col_offset, p->arena); } -static int // bool -newline_in_string(Parser *p, const char *cur) -{ - for (const char *c = cur; c >= p->tok->buf; c--) { - if (*c == '\'' || *c == '"') { - return 1; - } - } - return 0; -} - /* Check that the source for a single input statement really is a single statement by looking at what is left in the buffer after parsing. Trailing whitespace and comments are OK. */ static int // bool bad_single_statement(Parser *p) { - const char *cur = strchr(p->tok->buf, '\n'); - - /* Newlines are allowed if preceded by a line continuation character - or if they appear inside a string. */ - if (!cur || (cur != p->tok->buf && *(cur - 1) == '\\') - || newline_in_string(p, cur)) { - return 0; - } + char *cur = p->tok->cur; char c = *cur; for (;;) { From webhook-mailer at python.org Fri Dec 10 18:45:07 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 10 Dec 2021 23:45:07 -0000 Subject: [Python-checkins] bpo-37971: fix the position of decorator application (GH-30027) Message-ID: https://github.com/python/cpython/commit/b593bdc7803cc75461f6f8888ad03cb7d8dfc416 commit: b593bdc7803cc75461f6f8888ad03cb7d8dfc416 branch: main author: Carl Friedrich Bolz-Tereick committer: ambv date: 2021-12-11T00:45:02+01:00 summary: bpo-37971: fix the position of decorator application (GH-30027) The line numbers of actually calling the decorator functions of functions and classes was wrong (as opposed to loading them, were they have been correct previously too). Co-authored-by: ?ukasz Langa files: A Misc/NEWS.d/next/Core and Builtins/2021-12-10-13-42-17.bpo-37971.6BC1Tx.rst M Lib/test/test_trace.py M Lib/test/test_traceback.py M Python/compile.c diff --git a/Lib/test/test_trace.py b/Lib/test/test_trace.py index d63c1778c9d08..5f712111ca14e 100644 --- a/Lib/test/test_trace.py +++ b/Lib/test/test_trace.py @@ -205,9 +205,9 @@ def test_traced_decorated_function(self): (self.my_py_filename, firstlineno + 4): 1, (self.my_py_filename, firstlineno + 5): 1, (self.my_py_filename, firstlineno + 6): 1, - (self.my_py_filename, firstlineno + 7): 1, - (self.my_py_filename, firstlineno + 8): 1, - (self.my_py_filename, firstlineno + 9): 1, + (self.my_py_filename, firstlineno + 7): 2, + (self.my_py_filename, firstlineno + 8): 2, + (self.my_py_filename, firstlineno + 9): 2, (self.my_py_filename, firstlineno + 10): 1, (self.my_py_filename, firstlineno + 11): 1, } diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index a458b21b09466..97bd9bae1d58e 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -616,6 +616,51 @@ def test_specialization_variations(self): self.assertSpecialized(lambda: 1// 0, "~^^~~") + def test_decorator_application_lineno_correct(self): + def dec_error(func): + raise TypeError + def dec_fine(func): + return func + def applydecs(): + @dec_error + @dec_fine + def g(): pass + result_lines = self.get_exception(applydecs) + lineno_applydescs = applydecs.__code__.co_firstlineno + lineno_dec_error = dec_error.__code__.co_firstlineno + expected_error = ( + 'Traceback (most recent call last):\n' + f' File "{__file__}", line {self.callable_line}, in get_exception\n' + ' callable()\n' + ' ^^^^^^^^^^\n' + f' File "{__file__}", line {lineno_applydescs + 1}, in applydecs\n' + ' @dec_error\n' + ' ^^^^^^^^^\n' + f' File "{__file__}", line {lineno_dec_error + 1}, in dec_error\n' + ' raise TypeError\n' + ' ^^^^^^^^^^^^^^^\n' + ) + self.assertEqual(result_lines, expected_error.splitlines()) + + def applydecs_class(): + @dec_error + @dec_fine + class A: pass + result_lines = self.get_exception(applydecs_class) + lineno_applydescs_class = applydecs_class.__code__.co_firstlineno + expected_error = ( + 'Traceback (most recent call last):\n' + f' File "{__file__}", line {self.callable_line}, in get_exception\n' + ' callable()\n' + ' ^^^^^^^^^^\n' + f' File "{__file__}", line {lineno_applydescs_class + 1}, in applydecs_class\n' + ' @dec_error\n' + ' ^^^^^^^^^\n' + f' File "{__file__}", line {lineno_dec_error + 1}, in dec_error\n' + ' raise TypeError\n' + ' ^^^^^^^^^^^^^^^\n' + ) + self.assertEqual(result_lines, expected_error.splitlines()) @cpython_only @requires_debug_ranges() diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-10-13-42-17.bpo-37971.6BC1Tx.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-10-13-42-17.bpo-37971.6BC1Tx.rst new file mode 100644 index 0000000000000..17f44f0e5b0a2 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-10-13-42-17.bpo-37971.6BC1Tx.rst @@ -0,0 +1,3 @@ +Fix a bug where the line numbers given in a traceback when a decorator +application raised an exception were wrong. + diff --git a/Python/compile.c b/Python/compile.c index 6138031833ac9..bbdb0115be3be 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -2132,6 +2132,27 @@ compiler_decorators(struct compiler *c, asdl_expr_seq* decos) return 1; } +static int +compiler_apply_decorators(struct compiler *c, asdl_expr_seq* decos) +{ + if (!decos) + return 1; + + int old_lineno = c->u->u_lineno; + int old_end_lineno = c->u->u_end_lineno; + int old_col_offset = c->u->u_col_offset; + int old_end_col_offset = c->u->u_end_col_offset; + for (Py_ssize_t i = asdl_seq_LEN(decos) - 1; i > -1; i--) { + SET_LOC(c, (expr_ty)asdl_seq_GET(decos, i)); + ADDOP_I(c, CALL_FUNCTION, 1); + } + c->u->u_lineno = old_lineno; + c->u->u_end_lineno = old_end_lineno; + c->u->u_col_offset = old_col_offset; + c->u->u_end_col_offset = old_end_col_offset; + return 1; +} + static int compiler_visit_kwonlydefaults(struct compiler *c, asdl_arg_seq *kwonlyargs, asdl_expr_seq *kw_defaults) @@ -2462,11 +2483,8 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async) Py_DECREF(qualname); Py_DECREF(co); - /* decorators */ - for (i = 0; i < asdl_seq_LEN(decos); i++) { - ADDOP_I(c, CALL_FUNCTION, 1); - } - + if (!compiler_apply_decorators(c, decos)) + return 0; return compiler_nameop(c, name, Store); } @@ -2597,9 +2615,8 @@ compiler_class(struct compiler *c, stmt_ty s) return 0; /* 6. apply decorators */ - for (i = 0; i < asdl_seq_LEN(decos); i++) { - ADDOP_I(c, CALL_FUNCTION, 1); - } + if (!compiler_apply_decorators(c, decos)) + return 0; /* 7. store into */ if (!compiler_nameop(c, s->v.ClassDef.name, Store)) From webhook-mailer at python.org Fri Dec 10 18:46:55 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 10 Dec 2021 23:46:55 -0000 Subject: [Python-checkins] build(deps): bump actions/cache from 2.1.6 to 2.1.7 (GH-29875) Message-ID: https://github.com/python/cpython/commit/901cbbd2ca3194c4a8bd59a211b3b707c96708d7 commit: 901cbbd2ca3194c4a8bd59a211b3b707c96708d7 branch: main author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> committer: ambv date: 2021-12-11T00:46:49+01:00 summary: build(deps): bump actions/cache from 2.1.6 to 2.1.7 (GH-29875) Bumps [actions/cache](https://github.com/actions/cache) from 2.1.6 to 2.1.7. - [Release notes](https://github.com/actions/cache/releases) - [Commits](https://github.com/actions/cache/compare/v2.1.6...v2.1.7) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> files: M .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 99f05f3abec93..48671aa7a67cd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -176,7 +176,7 @@ jobs: echo "LD_LIBRARY_PATH=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}/lib" >> $GITHUB_ENV - name: 'Restore OpenSSL build' id: cache-openssl - uses: actions/cache at v2.1.6 + uses: actions/cache at v2.1.7 with: path: ./multissl/openssl/${{ env.OPENSSL_VER }} key: ${{ runner.os }}-multissl-openssl-${{ env.OPENSSL_VER }} @@ -239,7 +239,7 @@ jobs: echo "LD_LIBRARY_PATH=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}/lib" >> $GITHUB_ENV - name: 'Restore OpenSSL build' id: cache-openssl - uses: actions/cache at v2.1.6 + uses: actions/cache at v2.1.7 with: path: ./multissl/openssl/${{ env.OPENSSL_VER }} key: ${{ runner.os }}-multissl-openssl-${{ env.OPENSSL_VER }} @@ -283,7 +283,7 @@ jobs: echo "LD_LIBRARY_PATH=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}/lib" >> $GITHUB_ENV - name: 'Restore OpenSSL build' id: cache-openssl - uses: actions/cache at v2.1.6 + uses: actions/cache at v2.1.7 with: path: ./multissl/openssl/${{ env.OPENSSL_VER }} key: ${{ runner.os }}-multissl-openssl-${{ env.OPENSSL_VER }} From webhook-mailer at python.org Fri Dec 10 19:01:30 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 11 Dec 2021 00:01:30 -0000 Subject: [Python-checkins] [doc] Clarify MRO precedence in descriptor super binding section (GH-29539) (GH-29669) Message-ID: https://github.com/python/cpython/commit/4b224e8729365c3f0b1901cc2217e9591719a332 commit: 4b224e8729365c3f0b1901cc2217e9591719a332 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-12-11T01:01:16+01:00 summary: [doc] Clarify MRO precedence in descriptor super binding section (GH-29539) (GH-29669) A similar sentence is present in the 'Invocation from super' section of the descriptor HOWTO, where it is already correct. (cherry picked from commit ee49484c0f0d0d79e8fc40835da10b78f89ae503) Co-authored-by: Jouke Witteveen files: M Doc/reference/datamodel.rst diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 111417d937fbb..166c615149360 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1785,7 +1785,7 @@ Class Binding Super Binding If ``a`` is an instance of :class:`super`, then the binding ``super(B, obj).m()`` searches ``obj.__class__.__mro__`` for the base class ``A`` - immediately preceding ``B`` and then invokes the descriptor with the call: + immediately following ``B`` and then invokes the descriptor with the call: ``A.__dict__['m'].__get__(obj, obj.__class__)``. For instance bindings, the precedence of descriptor invocation depends on From webhook-mailer at python.org Fri Dec 10 19:01:42 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 11 Dec 2021 00:01:42 -0000 Subject: [Python-checkins] [doc] Clarify MRO precedence in descriptor super binding section (GH-29539) (GH-29670) Message-ID: https://github.com/python/cpython/commit/81a38293f2b2495bbb3b176c2912f5b6b5d3198d commit: 81a38293f2b2495bbb3b176c2912f5b6b5d3198d branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-12-11T01:01:35+01:00 summary: [doc] Clarify MRO precedence in descriptor super binding section (GH-29539) (GH-29670) A similar sentence is present in the 'Invocation from super' section of the descriptor HOWTO, where it is already correct. (cherry picked from commit ee49484c0f0d0d79e8fc40835da10b78f89ae503) Co-authored-by: Jouke Witteveen files: M Doc/reference/datamodel.rst diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 986a36cd804dd..a34ec45bf4adc 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1776,7 +1776,7 @@ Class Binding Super Binding If ``a`` is an instance of :class:`super`, then the binding ``super(B, obj).m()`` searches ``obj.__class__.__mro__`` for the base class ``A`` - immediately preceding ``B`` and then invokes the descriptor with the call: + immediately following ``B`` and then invokes the descriptor with the call: ``A.__dict__['m'].__get__(obj, obj.__class__)``. For instance bindings, the precedence of descriptor invocation depends on From webhook-mailer at python.org Fri Dec 10 19:02:04 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 11 Dec 2021 00:02:04 -0000 Subject: [Python-checkins] bpo-45859: Mark test_field_descriptor in test_collections as CPython-only (GH-29691) (GH-29710) Message-ID: https://github.com/python/cpython/commit/7c5b01b5101923fc38274c491bd55239ee9f0416 commit: 7c5b01b5101923fc38274c491bd55239ee9f0416 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-12-11T01:02:00+01:00 summary: bpo-45859: Mark test_field_descriptor in test_collections as CPython-only (GH-29691) (GH-29710) (cherry picked from commit 4fad314246399b69ef0c57ba8527d9efade99069) Co-authored-by: Carl Friedrich Bolz-Tereick files: M Lib/test/test_collections.py diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py index a961821230c7b..6b55b892091f3 100644 --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -589,6 +589,7 @@ class Point(namedtuple('_Point', ['x', 'y'])): a.w = 5 self.assertEqual(a.__dict__, {'w': 5}) + @support.cpython_only def test_field_descriptor(self): Point = namedtuple('Point', 'x y') p = Point(11, 22) From webhook-mailer at python.org Fri Dec 10 19:03:01 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 11 Dec 2021 00:03:01 -0000 Subject: [Python-checkins] bpo-45822: Minor cleanups to the test_Py_CompileString test (GH-29750) (GH-29758) Message-ID: https://github.com/python/cpython/commit/e1e3f648ad6ab467356d2d14e1d208583c1a76c6 commit: e1e3f648ad6ab467356d2d14e1d208583c1a76c6 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-12-11T01:02:56+01:00 summary: bpo-45822: Minor cleanups to the test_Py_CompileString test (GH-29750) (GH-29758) (cherry picked from commit abfc794bbf2c6a0939ddd81b6e700c46944ba87a) Co-authored-by: Pablo Galindo Salgado files: M Lib/test/test_capi.py M Modules/_testcapimodule.c diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py index 974e3d03a6172..b5cb3ad0bc07a 100644 --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -631,6 +631,14 @@ def test_pyobject_bytes_from_null(self): s = _testcapi.pyobject_bytes_from_null() self.assertEqual(s, b'') + def test_Py_CompileString(self): + # Check that Py_CompileString respects the coding cookie + _compile = _testcapi.Py_CompileString + code = b"# -*- coding: latin1 -*-\nprint('\xc2\xa4')\n" + result = _compile(code) + expected = compile(code, "", "exec") + self.assertEqual(result.co_consts, expected.co_consts) + class TestPendingCalls(unittest.TestCase): @@ -1013,14 +1021,6 @@ def test_state_access(self): with self.assertRaises(TypeError): increment_count(1, 2, 3) - def test_Py_CompileString(self): - # Check that Py_CompileString respects the coding cookie - _compile = _testcapi.Py_CompileString - code = b"# -*- coding: latin1 -*-\nprint('\xc2\xa4')\n" - result = _compile(code) - expected = compile(code, "", "exec") - self.assertEqual(result.co_consts, expected.co_consts) - if __name__ == "__main__": unittest.main() diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 9f25b64eb1671..c5c942820b66f 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -400,7 +400,7 @@ pycompilestring(PyObject* self, PyObject *obj) { if (the_string == NULL) { return NULL; } - return Py_CompileString(the_string, "blech", Py_file_input); + return Py_CompileString(the_string, "", Py_file_input); } static PyObject* From webhook-mailer at python.org Fri Dec 10 19:03:20 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 11 Dec 2021 00:03:20 -0000 Subject: [Python-checkins] bpo-45822: Minor cleanups to the test_Py_CompileString test (GH-29750) (GH-29759) Message-ID: https://github.com/python/cpython/commit/5f622f1d5c5425ed1e992da6611edfb486a9bf7c commit: 5f622f1d5c5425ed1e992da6611edfb486a9bf7c branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-12-11T01:03:15+01:00 summary: bpo-45822: Minor cleanups to the test_Py_CompileString test (GH-29750) (GH-29759) (cherry picked from commit abfc794bbf2c6a0939ddd81b6e700c46944ba87a) Co-authored-by: Pablo Galindo Salgado files: M Lib/test/test_capi.py M Modules/_testcapimodule.c diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py index 23e65df67190c..87f327414b54e 100644 --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -549,6 +549,14 @@ def test_pyobject_bytes_from_null(self): s = _testcapi.pyobject_bytes_from_null() self.assertEqual(s, b'') + def test_Py_CompileString(self): + # Check that Py_CompileString respects the coding cookie + _compile = _testcapi.Py_CompileString + code = b"# -*- coding: latin1 -*-\nprint('\xc2\xa4')\n" + result = _compile(code) + expected = compile(code, "", "exec") + self.assertEqual(result.co_consts, expected.co_consts) + class TestPendingCalls(unittest.TestCase): @@ -926,14 +934,6 @@ def test_state_access(self): with self.assertRaises(TypeError): increment_count(1, 2, 3) - def test_Py_CompileString(self): - # Check that Py_CompileString respects the coding cookie - _compile = _testcapi.Py_CompileString - code = b"# -*- coding: latin1 -*-\nprint('\xc2\xa4')\n" - result = _compile(code) - expected = compile(code, "", "exec") - self.assertEqual(result.co_consts, expected.co_consts) - if __name__ == "__main__": unittest.main() diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index d1f756395373d..ad1b07454355e 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -339,7 +339,7 @@ pycompilestring(PyObject* self, PyObject *obj) { if (the_string == NULL) { return NULL; } - return Py_CompileString(the_string, "blech", Py_file_input); + return Py_CompileString(the_string, "", Py_file_input); } static PyObject* From webhook-mailer at python.org Fri Dec 10 19:04:04 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 11 Dec 2021 00:04:04 -0000 Subject: [Python-checkins] Fix markup buglet in Doc/howto/annotations.rst (GH-29802) (GH-29805) Message-ID: https://github.com/python/cpython/commit/0f21bac6ce1c688bbe82fcb055e0a59926e43249 commit: 0f21bac6ce1c688bbe82fcb055e0a59926e43249 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-12-11T01:03:55+01:00 summary: Fix markup buglet in Doc/howto/annotations.rst (GH-29802) (GH-29805) (cherry picked from commit 94daf39b2f7e9b50e7ae7a16caeef804f8e37ae3) Co-authored-by: Guido van Rossum files: M Doc/howto/annotations.rst diff --git a/Doc/howto/annotations.rst b/Doc/howto/annotations.rst index 3e61103e99c9a..2bc2f2d4c839e 100644 --- a/Doc/howto/annotations.rst +++ b/Doc/howto/annotations.rst @@ -156,7 +156,7 @@ Manually Un-Stringizing Stringized Annotations require annotating with string values that specifically *can't* be evaluated. For example: - * :pep:`604` union types using `|`, before support for this + * :pep:`604` union types using ``|``, before support for this was added to Python 3.10. * Definitions that aren't needed at runtime, only imported when :const:`typing.TYPE_CHECKING` is true. From webhook-mailer at python.org Fri Dec 10 19:04:25 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 11 Dec 2021 00:04:25 -0000 Subject: [Python-checkins] bpo-19737: Improved the documentation for globals (GH-29823) Message-ID: https://github.com/python/cpython/commit/4fe5585240f64c3d14eb635ff82b163f92074b3a commit: 4fe5585240f64c3d14eb635ff82b163f92074b3a branch: main author: 180909 <734461790 at qq.com> committer: ambv date: 2021-12-11T01:04:21+01:00 summary: bpo-19737: Improved the documentation for globals (GH-29823) Co-authored-by: Alex Waygood Co-authored-by: ?ukasz Langa files: A Misc/NEWS.d/next/Documentation/2021-11-28-22-43-21.bpo-19737.cOOubB.rst M Doc/library/functions.rst diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 0da2619685bff..ebcd6c801d70e 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -733,9 +733,9 @@ are always available. They are listed here in alphabetical order. .. function:: globals() - Return a dictionary representing the current global symbol table. This is always - the dictionary of the current module (inside a function or method, this is the - module where it is defined, not the module from which it is called). + Return the dictionary implementing the current module namespace. For code within + functions, this is set when the function is defined and remains the same + regardless of where the function is called. .. function:: hasattr(object, name) diff --git a/Misc/NEWS.d/next/Documentation/2021-11-28-22-43-21.bpo-19737.cOOubB.rst b/Misc/NEWS.d/next/Documentation/2021-11-28-22-43-21.bpo-19737.cOOubB.rst new file mode 100644 index 0000000000000..a3e16c9fdd0e6 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-11-28-22-43-21.bpo-19737.cOOubB.rst @@ -0,0 +1 @@ +Update the documentation for the :func:`globals` function. From webhook-mailer at python.org Fri Dec 10 19:32:29 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 11 Dec 2021 00:32:29 -0000 Subject: [Python-checkins] bpo-19737: Improved the documentation for globals (GH-29823) (GH-30041) Message-ID: https://github.com/python/cpython/commit/1f7000808e8385e2a29ffd0ef6aac9a6139d3d92 commit: 1f7000808e8385e2a29ffd0ef6aac9a6139d3d92 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-12-11T01:32:13+01:00 summary: bpo-19737: Improved the documentation for globals (GH-29823) (GH-30041) Co-authored-by: Alex Waygood Co-authored-by: ?ukasz Langa (cherry picked from commit 4fe5585240f64c3d14eb635ff82b163f92074b3a) Co-authored-by: 180909 <734461790 at qq.com> files: A Misc/NEWS.d/next/Documentation/2021-11-28-22-43-21.bpo-19737.cOOubB.rst M Doc/library/functions.rst diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 307d67978559c..a117d30c0b0d5 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -733,9 +733,9 @@ are always available. They are listed here in alphabetical order. .. function:: globals() - Return a dictionary representing the current global symbol table. This is always - the dictionary of the current module (inside a function or method, this is the - module where it is defined, not the module from which it is called). + Return the dictionary implementing the current module namespace. For code within + functions, this is set when the function is defined and remains the same + regardless of where the function is called. .. function:: hasattr(object, name) diff --git a/Misc/NEWS.d/next/Documentation/2021-11-28-22-43-21.bpo-19737.cOOubB.rst b/Misc/NEWS.d/next/Documentation/2021-11-28-22-43-21.bpo-19737.cOOubB.rst new file mode 100644 index 0000000000000..a3e16c9fdd0e6 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-11-28-22-43-21.bpo-19737.cOOubB.rst @@ -0,0 +1 @@ +Update the documentation for the :func:`globals` function. From webhook-mailer at python.org Fri Dec 10 19:32:33 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 11 Dec 2021 00:32:33 -0000 Subject: [Python-checkins] bpo-19737: Improved the documentation for globals (GH-29823) (GH-30042) Message-ID: https://github.com/python/cpython/commit/9299e3a39c3b1dd7d5db0d88080249c2dab3070f commit: 9299e3a39c3b1dd7d5db0d88080249c2dab3070f branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-12-11T01:32:29+01:00 summary: bpo-19737: Improved the documentation for globals (GH-29823) (GH-30042) Co-authored-by: Alex Waygood Co-authored-by: ?ukasz Langa (cherry picked from commit 4fe5585240f64c3d14eb635ff82b163f92074b3a) Co-authored-by: 180909 <734461790 at qq.com> files: A Misc/NEWS.d/next/Documentation/2021-11-28-22-43-21.bpo-19737.cOOubB.rst M Doc/library/functions.rst diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 4acbc67b2d69b..4aa900c547714 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -686,9 +686,9 @@ are always available. They are listed here in alphabetical order. .. function:: globals() - Return a dictionary representing the current global symbol table. This is always - the dictionary of the current module (inside a function or method, this is the - module where it is defined, not the module from which it is called). + Return the dictionary implementing the current module namespace. For code within + functions, this is set when the function is defined and remains the same + regardless of where the function is called. .. function:: hasattr(object, name) diff --git a/Misc/NEWS.d/next/Documentation/2021-11-28-22-43-21.bpo-19737.cOOubB.rst b/Misc/NEWS.d/next/Documentation/2021-11-28-22-43-21.bpo-19737.cOOubB.rst new file mode 100644 index 0000000000000..a3e16c9fdd0e6 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-11-28-22-43-21.bpo-19737.cOOubB.rst @@ -0,0 +1 @@ +Update the documentation for the :func:`globals` function. From webhook-mailer at python.org Fri Dec 10 19:34:50 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 11 Dec 2021 00:34:50 -0000 Subject: [Python-checkins] [3.10] bpo-13236: Flush the output stream more often in unittest (GH-29929) (GH-30039) Message-ID: https://github.com/python/cpython/commit/d55a03e02e69fb7f639998de71ed3f44c2f4f999 commit: d55a03e02e69fb7f639998de71ed3f44c2f4f999 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-12-11T01:34:46+01:00 summary: [3.10] bpo-13236: Flush the output stream more often in unittest (GH-29929) (GH-30039) It can prevent some losses when output to buffered stream.. (cherry picked from commit 83fa1291fd0a25216a4a9e990f423682fda67cbe) Co-authored-by: Serhiy Storchaka files: A Misc/NEWS.d/next/Library/2021-11-30-13-52-02.bpo-13236.FmJIkO.rst M Lib/unittest/runner.py M Lib/unittest/test/test_program.py M Lib/unittest/test/test_result.py diff --git a/Lib/unittest/runner.py b/Lib/unittest/runner.py index 45e7e4c0458d4..caf159002d8bb 100644 --- a/Lib/unittest/runner.py +++ b/Lib/unittest/runner.py @@ -59,6 +59,7 @@ def addSuccess(self, test): super(TextTestResult, self).addSuccess(test) if self.showAll: self.stream.writeln("ok") + self.stream.flush() elif self.dots: self.stream.write('.') self.stream.flush() @@ -67,6 +68,7 @@ def addError(self, test, err): super(TextTestResult, self).addError(test, err) if self.showAll: self.stream.writeln("ERROR") + self.stream.flush() elif self.dots: self.stream.write('E') self.stream.flush() @@ -75,6 +77,7 @@ def addFailure(self, test, err): super(TextTestResult, self).addFailure(test, err) if self.showAll: self.stream.writeln("FAIL") + self.stream.flush() elif self.dots: self.stream.write('F') self.stream.flush() @@ -83,6 +86,7 @@ def addSkip(self, test, reason): super(TextTestResult, self).addSkip(test, reason) if self.showAll: self.stream.writeln("skipped {0!r}".format(reason)) + self.stream.flush() elif self.dots: self.stream.write("s") self.stream.flush() @@ -91,6 +95,7 @@ def addExpectedFailure(self, test, err): super(TextTestResult, self).addExpectedFailure(test, err) if self.showAll: self.stream.writeln("expected failure") + self.stream.flush() elif self.dots: self.stream.write("x") self.stream.flush() @@ -99,6 +104,7 @@ def addUnexpectedSuccess(self, test): super(TextTestResult, self).addUnexpectedSuccess(test) if self.showAll: self.stream.writeln("unexpected success") + self.stream.flush() elif self.dots: self.stream.write("u") self.stream.flush() @@ -106,6 +112,7 @@ def addUnexpectedSuccess(self, test): def printErrors(self): if self.dots or self.showAll: self.stream.writeln() + self.stream.flush() self.printErrorList('ERROR', self.errors) self.printErrorList('FAIL', self.failures) @@ -115,6 +122,7 @@ def printErrorList(self, flavour, errors): self.stream.writeln("%s: %s" % (flavour,self.getDescription(test))) self.stream.writeln(self.separator2) self.stream.writeln("%s" % err) + self.stream.flush() class TextTestRunner(object): @@ -218,4 +226,5 @@ def run(self, test): self.stream.writeln(" (%s)" % (", ".join(infos),)) else: self.stream.write("\n") + self.stream.flush() return result diff --git a/Lib/unittest/test/test_program.py b/Lib/unittest/test/test_program.py index eef82ff937ab7..939af81b3b4cd 100644 --- a/Lib/unittest/test/test_program.py +++ b/Lib/unittest/test/test_program.py @@ -6,6 +6,7 @@ from test import support import unittest import unittest.test +from .test_result import BufferedWriter class Test_TestProgram(unittest.TestCase): @@ -104,30 +105,39 @@ def run(self, test): program.testNames) def test_NonExit(self): + stream = BufferedWriter() program = unittest.main(exit=False, argv=["foobar"], - testRunner=unittest.TextTestRunner(stream=io.StringIO()), + testRunner=unittest.TextTestRunner(stream=stream), testLoader=self.FooBarLoader()) self.assertTrue(hasattr(program, 'result')) + self.assertIn('\nFAIL: testFail ', stream.getvalue()) + self.assertTrue(stream.getvalue().endswith('\n\nFAILED (failures=1)\n')) def test_Exit(self): + stream = BufferedWriter() self.assertRaises( SystemExit, unittest.main, argv=["foobar"], - testRunner=unittest.TextTestRunner(stream=io.StringIO()), + testRunner=unittest.TextTestRunner(stream=stream), exit=True, testLoader=self.FooBarLoader()) + self.assertIn('\nFAIL: testFail ', stream.getvalue()) + self.assertTrue(stream.getvalue().endswith('\n\nFAILED (failures=1)\n')) def test_ExitAsDefault(self): + stream = BufferedWriter() self.assertRaises( SystemExit, unittest.main, argv=["foobar"], - testRunner=unittest.TextTestRunner(stream=io.StringIO()), + testRunner=unittest.TextTestRunner(stream=stream), testLoader=self.FooBarLoader()) + self.assertIn('\nFAIL: testFail ', stream.getvalue()) + self.assertTrue(stream.getvalue().endswith('\n\nFAILED (failures=1)\n')) class InitialisableProgram(unittest.TestProgram): diff --git a/Lib/unittest/test/test_result.py b/Lib/unittest/test/test_result.py index 0f7f3b7e37193..2d29f79809d60 100644 --- a/Lib/unittest/test/test_result.py +++ b/Lib/unittest/test/test_result.py @@ -34,6 +34,22 @@ def bad_cleanup2(): raise ValueError('bad cleanup2') +class BufferedWriter: + def __init__(self): + self.result = '' + self.buffer = '' + + def write(self, arg): + self.buffer += arg + + def flush(self): + self.result += self.buffer + self.buffer = '' + + def getvalue(self): + return self.result + + class Test_TestResult(unittest.TestCase): # Note: there are not separate tests for TestResult.wasSuccessful(), # TestResult.errors, TestResult.failures, TestResult.testsRun or @@ -445,10 +461,13 @@ def testFailFast(self): self.assertTrue(result.shouldStop) def testFailFastSetByRunner(self): - runner = unittest.TextTestRunner(stream=io.StringIO(), failfast=True) + stream = BufferedWriter() + runner = unittest.TextTestRunner(stream=stream, failfast=True) def test(result): self.assertTrue(result.failfast) result = runner.run(test) + stream.flush() + self.assertTrue(stream.getvalue().endswith('\n\nOK\n')) classDict = dict(unittest.TestResult.__dict__) diff --git a/Misc/NEWS.d/next/Library/2021-11-30-13-52-02.bpo-13236.FmJIkO.rst b/Misc/NEWS.d/next/Library/2021-11-30-13-52-02.bpo-13236.FmJIkO.rst new file mode 100644 index 0000000000000..bfea8d4fca0e0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-30-13-52-02.bpo-13236.FmJIkO.rst @@ -0,0 +1,2 @@ +:class:`unittest.TextTestResult` and :class:`unittest.TextTestRunner` flush +now the output stream more often. From webhook-mailer at python.org Sat Dec 11 08:43:48 2021 From: webhook-mailer at python.org (zooba) Date: Sat, 11 Dec 2021 13:43:48 -0000 Subject: [Python-checkins] bpo-46048: Fix parsing of single character lines in getpath readlines() (GH-30048) Message-ID: https://github.com/python/cpython/commit/971ece8e1738b1107dda692cc44c6d8ddce384cd commit: 971ece8e1738b1107dda692cc44c6d8ddce384cd branch: main author: Steve Dower committer: zooba date: 2021-12-11T13:43:40Z summary: bpo-46048: Fix parsing of single character lines in getpath readlines() (GH-30048) files: A Misc/NEWS.d/next/Core and Builtins/2021-12-11-13-14-42.bpo-46048._-OGD9.rst M Lib/test/test_site.py M Modules/getpath.c diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py index 76d35daed0b80..199022a1054f3 100644 --- a/Lib/test/test_site.py +++ b/Lib/test/test_site.py @@ -594,6 +594,26 @@ def _calc_sys_path_for_underpth_nosite(self, sys_prefix, lines): sys_path.append(abs_path) return sys_path + def test_underpth_basic(self): + libpath = test.support.STDLIB_DIR + exe_prefix = os.path.dirname(sys.executable) + pth_lines = ['#.', '# ..', *sys.path, '.', '..'] + exe_file = self._create_underpth_exe(pth_lines) + sys_path = self._calc_sys_path_for_underpth_nosite( + os.path.dirname(exe_file), + pth_lines) + + output = subprocess.check_output([exe_file, '-c', + 'import sys; print("\\n".join(sys.path) if sys.flags.no_site else "")' + ], encoding='ansi') + actual_sys_path = output.rstrip().split('\n') + self.assertTrue(actual_sys_path, "sys.flags.no_site was False") + self.assertEqual( + actual_sys_path, + sys_path, + "sys.path is incorrect" + ) + def test_underpth_nosite_file(self): libpath = test.support.STDLIB_DIR exe_prefix = os.path.dirname(sys.executable) diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-11-13-14-42.bpo-46048._-OGD9.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-11-13-14-42.bpo-46048._-OGD9.rst new file mode 100644 index 0000000000000..647fb6df7a87b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-11-13-14-42.bpo-46048._-OGD9.rst @@ -0,0 +1,2 @@ +Fixes parsing of :file:`._pth` files on startup so that single-character +paths are correctly read. diff --git a/Modules/getpath.c b/Modules/getpath.c index fedb41cdb3788..3adce4653342f 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -386,11 +386,11 @@ getpath_readlines(PyObject *Py_UNUSED(self), PyObject *args) wchar_t *p1 = wbuffer; wchar_t *p2 = p1; while ((p2 = wcschr(p1, L'\n')) != NULL) { - size_t cb = p2 - p1; - while (cb && (p1[cb] == L'\n' || p1[cb] == L'\r')) { + Py_ssize_t cb = p2 - p1; + while (cb >= 0 && (p1[cb] == L'\n' || p1[cb] == L'\r')) { --cb; } - PyObject *u = PyUnicode_FromWideChar(p1, cb ? cb + 1 : 0); + PyObject *u = PyUnicode_FromWideChar(p1, cb >= 0 ? cb + 1 : 0); if (!u || PyList_Append(r, u) < 0) { Py_XDECREF(u); Py_CLEAR(r); From webhook-mailer at python.org Sat Dec 11 10:06:21 2021 From: webhook-mailer at python.org (zooba) Date: Sat, 11 Dec 2021 15:06:21 -0000 Subject: [Python-checkins] bpo-46049: Fixes ._pth support on non-Windows (GH-30051) Message-ID: https://github.com/python/cpython/commit/bfc59ed0a00106f5ba4a32a0c5b3dbe71d12665d commit: bfc59ed0a00106f5ba4a32a0c5b3dbe71d12665d branch: main author: Steve Dower committer: zooba date: 2021-12-11T15:06:17Z summary: bpo-46049: Fixes ._pth support on non-Windows (GH-30051) files: A Misc/NEWS.d/next/Core and Builtins/2021-12-11-13-49-19.bpo-46049.9dNto2.rst M Lib/test/test_site.py M Modules/getpath.c M Modules/getpath.py diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py index 199022a1054f3..c54d868cb234f 100644 --- a/Lib/test/test_site.py +++ b/Lib/test/test_site.py @@ -564,26 +564,39 @@ def test_startup_interactivehook_isolated_explicit(self): 'import site, sys; site.enablerlcompleter(); sys.exit(hasattr(sys, "__interactivehook__"))']).wait() self.assertTrue(r, "'__interactivehook__' not added by enablerlcompleter()") - at unittest.skipUnless(sys.platform == 'win32', "only supported on Windows") class _pthFileTests(unittest.TestCase): - def _create_underpth_exe(self, lines, exe_pth=True): - import _winapi - temp_dir = tempfile.mkdtemp() - self.addCleanup(os_helper.rmtree, temp_dir) - exe_file = os.path.join(temp_dir, os.path.split(sys.executable)[1]) - dll_src_file = _winapi.GetModuleFileName(sys.dllhandle) - dll_file = os.path.join(temp_dir, os.path.split(dll_src_file)[1]) - shutil.copy(sys.executable, exe_file) - shutil.copy(dll_src_file, dll_file) - if exe_pth: - _pth_file = os.path.splitext(exe_file)[0] + '._pth' - else: - _pth_file = os.path.splitext(dll_file)[0] + '._pth' - with open(_pth_file, 'w') as f: - for line in lines: - print(line, file=f) - return exe_file + if sys.platform == 'win32': + def _create_underpth_exe(self, lines, exe_pth=True): + import _winapi + temp_dir = tempfile.mkdtemp() + self.addCleanup(os_helper.rmtree, temp_dir) + exe_file = os.path.join(temp_dir, os.path.split(sys.executable)[1]) + dll_src_file = _winapi.GetModuleFileName(sys.dllhandle) + dll_file = os.path.join(temp_dir, os.path.split(dll_src_file)[1]) + shutil.copy(sys.executable, exe_file) + shutil.copy(dll_src_file, dll_file) + if exe_pth: + _pth_file = os.path.splitext(exe_file)[0] + '._pth' + else: + _pth_file = os.path.splitext(dll_file)[0] + '._pth' + with open(_pth_file, 'w') as f: + for line in lines: + print(line, file=f) + return exe_file + else: + def _create_underpth_exe(self, lines, exe_pth=True): + if not exe_pth: + raise unittest.SkipTest("library ._pth file not supported on this platform") + temp_dir = tempfile.mkdtemp() + self.addCleanup(os_helper.rmtree, temp_dir) + exe_file = os.path.join(temp_dir, os.path.split(sys.executable)[1]) + os.symlink(sys.executable, exe_file) + _pth_file = exe_file + '._pth' + with open(_pth_file, 'w') as f: + for line in lines: + print(line, file=f) + return exe_file def _calc_sys_path_for_underpth_nosite(self, sys_prefix, lines): sys_path = [] @@ -605,7 +618,7 @@ def test_underpth_basic(self): output = subprocess.check_output([exe_file, '-c', 'import sys; print("\\n".join(sys.path) if sys.flags.no_site else "")' - ], encoding='ansi') + ], encoding='utf-8', errors='surrogateescape') actual_sys_path = output.rstrip().split('\n') self.assertTrue(actual_sys_path, "sys.flags.no_site was False") self.assertEqual( @@ -630,10 +643,10 @@ def test_underpth_nosite_file(self): env = os.environ.copy() env['PYTHONPATH'] = 'from-env' - env['PATH'] = '{};{}'.format(exe_prefix, os.getenv('PATH')) + env['PATH'] = '{}{}{}'.format(exe_prefix, os.pathsep, os.getenv('PATH')) output = subprocess.check_output([exe_file, '-c', 'import sys; print("\\n".join(sys.path) if sys.flags.no_site else "")' - ], env=env, encoding='ansi') + ], env=env, encoding='utf-8', errors='surrogateescape') actual_sys_path = output.rstrip().split('\n') self.assertTrue(actual_sys_path, "sys.flags.no_site was False") self.assertEqual( @@ -666,7 +679,6 @@ def test_underpth_file(self): )], env=env) self.assertTrue(rc, "sys.path is incorrect") - def test_underpth_dll_file(self): libpath = test.support.STDLIB_DIR exe_prefix = os.path.dirname(sys.executable) diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-11-13-49-19.bpo-46049.9dNto2.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-11-13-49-19.bpo-46049.9dNto2.rst new file mode 100644 index 0000000000000..07c6cb45614b6 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-11-13-49-19.bpo-46049.9dNto2.rst @@ -0,0 +1 @@ +Ensure :file:`._pth` files work as intended on platforms other than Windows. diff --git a/Modules/getpath.c b/Modules/getpath.c index 3adce4653342f..fdfe929514530 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -141,7 +141,7 @@ getpath_hassuffix(PyObject *Py_UNUSED(self), PyObject *args) if (path) { suffix = PyUnicode_AsWideCharString(suffixobj, &suffixLen); if (suffix) { - if (suffixLen < len || + if (suffixLen > len || #ifdef MS_WINDOWS wcsicmp(&path[len - suffixLen], suffix) != 0 #else diff --git a/Modules/getpath.py b/Modules/getpath.py index 77f951dbedef3..37d2ea03b0bbd 100644 --- a/Modules/getpath.py +++ b/Modules/getpath.py @@ -407,24 +407,22 @@ def search_up(prefix, *landmarks, test=isfile): # Calling Py_SetPythonHome() or Py_SetPath() will override ._pth search, # but environment variables and command-line options cannot. if not py_setpath and not home_was_set: - # Check adjacent to the main DLL/dylib/so - if library: - try: - pth = readlines(library.rpartition('.')[0] + '._pth') - pth_dir = dirname(library) - except FileNotFoundError: - pass - - # Check adjacent to the original executable, even if we - # redirected to actually launch Python. This may allow a - # venv to override the base_executable's ._pth file, but - # it cannot override the library's one. - if not pth_dir: - try: - pth = readlines(executable.rpartition('.')[0] + '._pth') - pth_dir = dirname(executable) - except FileNotFoundError: - pass + # 1. Check adjacent to the main DLL/dylib/so (if set) + # 2. Check adjacent to the original executable + # 3. Check adjacent to our actual executable + # This may allow a venv to override the base_executable's + # ._pth file, but it cannot override the library's one. + for p in [library, executable, real_executable]: + if p: + if os_name == 'nt' and (hassuffix(p, 'exe') or hassuffix(p, 'dll')): + p = p.rpartition('.')[0] + p += '._pth' + try: + pth = readlines(p) + pth_dir = dirname(p) + break + except OSError: + pass # If we found a ._pth file, disable environment and home # detection now. Later, we will do the rest. From webhook-mailer at python.org Sat Dec 11 13:28:08 2021 From: webhook-mailer at python.org (asvetlov) Date: Sat, 11 Dec 2021 18:28:08 -0000 Subject: [Python-checkins] [3.10] bpo-46040: Fix removal text for @asyncio.coroutine (GH-30061) Message-ID: https://github.com/python/cpython/commit/991736697dff693b6c9f8964bb7540081bbf4ddb commit: 991736697dff693b6c9f8964bb7540081bbf4ddb branch: 3.10 author: Andrew Svetlov committer: asvetlov date: 2021-12-11T20:27:47+02:00 summary: [3.10] bpo-46040: Fix removal text for @asyncio.coroutine (GH-30061) files: A Misc/NEWS.d/next/Documentation/2021-12-11-20-03-09.bpo-46040.qrsG0C.rst M Doc/library/asyncio-task.rst diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index f18b0e347b631..1175b0537c051 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -1085,7 +1085,7 @@ enforced. This decorator should not be used for :keyword:`async def` coroutines. - .. deprecated-removed:: 3.8 3.10 + .. deprecated-removed:: 3.8 3.11 Use :keyword:`async def` instead. diff --git a/Misc/NEWS.d/next/Documentation/2021-12-11-20-03-09.bpo-46040.qrsG0C.rst b/Misc/NEWS.d/next/Documentation/2021-12-11-20-03-09.bpo-46040.qrsG0C.rst new file mode 100644 index 0000000000000..c63b2c92b3790 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-12-11-20-03-09.bpo-46040.qrsG0C.rst @@ -0,0 +1,2 @@ +Fix removal Python version for ``@asyncio.coroutine``, the correct value is +3.11. From webhook-mailer at python.org Sat Dec 11 16:12:26 2021 From: webhook-mailer at python.org (ericvsmith) Date: Sat, 11 Dec 2021 21:12:26 -0000 Subject: [Python-checkins] bpo-44674: Use unhashability as a proxy for mutability for default dataclass __init__ arguments. (GH-29867) Message-ID: https://github.com/python/cpython/commit/e029c53e1a408b89a4e3edf30a9b38b094f9c880 commit: e029c53e1a408b89a4e3edf30a9b38b094f9c880 branch: main author: Eric V. Smith committer: ericvsmith date: 2021-12-11T16:12:17-05:00 summary: bpo-44674: Use unhashability as a proxy for mutability for default dataclass __init__ arguments. (GH-29867) `@dataclass` in 3.10 prohibits using list, dict, or set as default values. It does this to avoid the mutable default problem. This test is both too strict, and not strict enough. Too strict, because some immutable subclasses should be safe, and not strict enough, because other mutable types should be prohibited. With this change applied, `@dataclass` now uses unhashability as a proxy for mutability: if objects aren't hashable, they're assumed to be mutable. files: A Misc/NEWS.d/next/Library/2021-11-29-19-37-20.bpo-44674.NijWLt.rst M Doc/library/dataclasses.rst M Lib/dataclasses.py M Lib/test/test_dataclasses.py diff --git a/Doc/library/dataclasses.rst b/Doc/library/dataclasses.rst index b06547074378f..3592429d06a4c 100644 --- a/Doc/library/dataclasses.rst +++ b/Doc/library/dataclasses.rst @@ -712,9 +712,9 @@ Mutable default values creation they also share this behavior. There is no general way for Data Classes to detect this condition. Instead, the :func:`dataclass` decorator will raise a :exc:`TypeError` if it - detects a default parameter of type ``list``, ``dict``, or ``set``. - This is a partial solution, but it does protect against many common - errors. + detects an unhashable default parameter. The assumption is that if + a value is unhashable, it is mutable. This is a partial solution, + but it does protect against many common errors. Using default factory functions is a way to create new instances of mutable types as default values for fields:: @@ -724,3 +724,9 @@ Mutable default values x: list = field(default_factory=list) assert D().x is not D().x + + .. versionchanged:: 3.11 + Instead of looking for and disallowing objects of type ``list``, + ``dict``, or ``set``, unhashable objects are now not allowed as + default values. Unhashability is used to approximate + mutability. diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 3f85d859b1642..b327462080f99 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -808,8 +808,10 @@ def _get_field(cls, a_name, a_type, default_kw_only): raise TypeError(f'field {f.name} is a ClassVar but specifies ' 'kw_only') - # For real fields, disallow mutable defaults for known types. - if f._field_type is _FIELD and isinstance(f.default, (list, dict, set)): + # For real fields, disallow mutable defaults. Use unhashable as a proxy + # indicator for mutability. Read the __hash__ attribute from the class, + # not the instance. + if f._field_type is _FIELD and f.default.__class__.__hash__ is None: raise ValueError(f'mutable default {type(f.default)} for field ' f'{f.name} is not allowed: use default_factory') diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index ef5009ab11677..69e7685083009 100644 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -501,6 +501,32 @@ class C: self.assertNotEqual(C(3), C(4, 10)) self.assertNotEqual(C(3, 10), C(4, 10)) + def test_no_unhashable_default(self): + # See bpo-44674. + class Unhashable: + __hash__ = None + + unhashable_re = 'mutable default .* for field a is not allowed' + with self.assertRaisesRegex(ValueError, unhashable_re): + @dataclass + class A: + a: dict = {} + + with self.assertRaisesRegex(ValueError, unhashable_re): + @dataclass + class A: + a: Any = Unhashable() + + # Make sure that the machinery looking for hashability is using the + # class's __hash__, not the instance's __hash__. + with self.assertRaisesRegex(ValueError, unhashable_re): + unhashable = Unhashable() + # This shouldn't make the variable hashable. + unhashable.__hash__ = lambda: 0 + @dataclass + class A: + a: Any = unhashable + def test_hash_field_rules(self): # Test all 6 cases of: # hash=True/False/None diff --git a/Misc/NEWS.d/next/Library/2021-11-29-19-37-20.bpo-44674.NijWLt.rst b/Misc/NEWS.d/next/Library/2021-11-29-19-37-20.bpo-44674.NijWLt.rst new file mode 100644 index 0000000000000..79e7a08b3b174 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-29-19-37-20.bpo-44674.NijWLt.rst @@ -0,0 +1,6 @@ +Change how dataclasses disallows mutable default values. It used to +use a list of known types (list, dict, set). Now it disallows +unhashable objects to be defaults. It's using unhashability as a +proxy for mutability. Patch by Eric V. Smith, idea by Raymond +Hettinger. + From webhook-mailer at python.org Sat Dec 11 16:28:35 2021 From: webhook-mailer at python.org (pablogsal) Date: Sat, 11 Dec 2021 21:28:35 -0000 Subject: [Python-checkins] bpo-46042: Improve SyntaxError locations in the symbol table (GH-30059) Message-ID: https://github.com/python/cpython/commit/59435eea08d30796174552c0ca03c59b41adf8a5 commit: 59435eea08d30796174552c0ca03c59b41adf8a5 branch: main author: Pablo Galindo Salgado committer: pablogsal date: 2021-12-11T21:28:24Z summary: bpo-46042: Improve SyntaxError locations in the symbol table (GH-30059) files: A Misc/NEWS.d/next/Core and Builtins/2021-12-11-17-40-34.bpo-46042.aqYxku.rst M Include/internal/pycore_symtable.h M Lib/test/test_exceptions.py M Python/symtable.c diff --git a/Include/internal/pycore_symtable.h b/Include/internal/pycore_symtable.h index 4c1b7d3519ccf..28935f4ed5501 100644 --- a/Include/internal/pycore_symtable.h +++ b/Include/internal/pycore_symtable.h @@ -13,6 +13,13 @@ struct _mod; // Type defined in pycore_ast.h typedef enum _block_type { FunctionBlock, ClassBlock, ModuleBlock, AnnotationBlock } _Py_block_ty; +typedef enum _comprehension_type { + NoComprehension = 0, + ListComprehension = 1, + DictComprehension = 2, + SetComprehension = 3, + GeneratorExpression = 4 } _Py_comprehension_ty; + struct _symtable_entry; struct symtable { @@ -42,14 +49,14 @@ typedef struct _symtable_entry { PyObject *ste_varnames; /* list of function parameters */ PyObject *ste_children; /* list of child blocks */ PyObject *ste_directives;/* locations of global and nonlocal statements */ - _Py_block_ty ste_type; /* module, class, or function */ + _Py_block_ty ste_type; /* module, class or function */ int ste_nested; /* true if block is nested */ unsigned ste_free : 1; /* true if block has free variables */ unsigned ste_child_free : 1; /* true if a child block has free vars, including free refs to globals */ unsigned ste_generator : 1; /* true if namespace is a generator */ unsigned ste_coroutine : 1; /* true if namespace is a coroutine */ - unsigned ste_comprehension : 1; /* true if namespace is a list comprehension */ + _Py_comprehension_ty ste_comprehension; /* Kind of comprehension (if any) */ unsigned ste_varargs : 1; /* true if block has varargs */ unsigned ste_varkeywords : 1; /* true if block has varkeywords */ unsigned ste_returns_value : 1; /* true if namespace uses return with diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index a954ecb8f7c25..c861d8fe9eb42 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -268,9 +268,10 @@ def baz(): check(b"\xef\xbb\xbf#coding: utf8\nprint('\xe6\x88\x91')\n", 0, -1) # Errors thrown by symtable.c - check('x = [(yield i) for i in range(3)]', 1, 5) - check('def f():\n from _ import *', 1, 1) - check('def f(x, x):\n pass', 1, 1) + check('x = [(yield i) for i in range(3)]', 1, 7) + check('def f():\n from _ import *', 2, 17) + check('def f(x, x):\n pass', 1, 10) + check('{i for i in range(5) if (j := 0) for j in range(5)}', 1, 38) check('def f(x):\n nonlocal x', 2, 3) check('def f(x):\n x = 1\n global x', 3, 3) check('nonlocal x', 1, 1) diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-11-17-40-34.bpo-46042.aqYxku.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-11-17-40-34.bpo-46042.aqYxku.rst new file mode 100644 index 0000000000000..7a302bcd7648b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-11-17-40-34.bpo-46042.aqYxku.rst @@ -0,0 +1,2 @@ +Improve the location of the caret in :exc:`SyntaxError` exceptions emitted +by the symbol table. Patch by Pablo Galindo. diff --git a/Python/symtable.c b/Python/symtable.c index dc5426cf3b426..7a1f0609d3542 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -49,6 +49,12 @@ "'%s' can not be used within an annotation" +#define LOCATION(x) \ + (x)->lineno, (x)->col_offset, (x)->end_lineno, (x)->end_col_offset + +#define ST_LOCATION(x) \ + (x)->ste_lineno, (x)->ste_col_offset, (x)->ste_end_lineno, (x)->ste_end_col_offset + static PySTEntryObject * ste_new(struct symtable *st, identifier name, _Py_block_ty block, void *key, int lineno, int col_offset, @@ -96,7 +102,7 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block, ste->ste_child_free = 0; ste->ste_generator = 0; ste->ste_coroutine = 0; - ste->ste_comprehension = 0; + ste->ste_comprehension = NoComprehension; ste->ste_returns_value = 0; ste->ste_needs_class_closure = 0; ste->ste_comp_iter_target = 0; @@ -221,6 +227,7 @@ static int symtable_visit_withitem(struct symtable *st, withitem_ty item); static int symtable_visit_match_case(struct symtable *st, match_case_ty m); static int symtable_visit_pattern(struct symtable *st, pattern_ty s); static int symtable_raise_if_annotation_block(struct symtable *st, const char *, expr_ty); +static int symtable_raise_if_comprehension_block(struct symtable *st, expr_ty); static identifier top = NULL, lambda = NULL, genexpr = NULL, @@ -1025,7 +1032,8 @@ symtable_lookup(struct symtable *st, PyObject *name) } static int -symtable_add_def_helper(struct symtable *st, PyObject *name, int flag, struct _symtable_entry *ste) +symtable_add_def_helper(struct symtable *st, PyObject *name, int flag, struct _symtable_entry *ste, + int lineno, int col_offset, int end_lineno, int end_col_offset) { PyObject *o; PyObject *dict; @@ -1042,10 +1050,8 @@ symtable_add_def_helper(struct symtable *st, PyObject *name, int flag, struct _s /* Is it better to use 'mangled' or 'name' here? */ PyErr_Format(PyExc_SyntaxError, DUPLICATE_ARGUMENT, name); PyErr_RangedSyntaxLocationObject(st->st_filename, - ste->ste_lineno, - ste->ste_col_offset + 1, - ste->ste_end_lineno, - ste->ste_end_col_offset + 1); + lineno, col_offset + 1, + end_lineno, end_col_offset + 1); goto error; } val |= flag; @@ -1066,10 +1072,8 @@ symtable_add_def_helper(struct symtable *st, PyObject *name, int flag, struct _s PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_INNER_LOOP_CONFLICT, name); PyErr_RangedSyntaxLocationObject(st->st_filename, - ste->ste_lineno, - ste->ste_col_offset + 1, - ste->ste_end_lineno, - ste->ste_end_col_offset + 1); + lineno, col_offset + 1, + end_lineno, end_col_offset + 1); goto error; } val |= DEF_COMP_ITER; @@ -1114,8 +1118,11 @@ symtable_add_def_helper(struct symtable *st, PyObject *name, int flag, struct _s } static int -symtable_add_def(struct symtable *st, PyObject *name, int flag) { - return symtable_add_def_helper(st, name, flag, st->st_cur); +symtable_add_def(struct symtable *st, PyObject *name, int flag, + int lineno, int col_offset, int end_lineno, int end_col_offset) +{ + return symtable_add_def_helper(st, name, flag, st->st_cur, + lineno, col_offset, end_lineno, end_col_offset); } /* VISIT, VISIT_SEQ and VIST_SEQ_TAIL take an ASDL type as their second argument. @@ -1200,7 +1207,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) } switch (s->kind) { case FunctionDef_kind: - if (!symtable_add_def(st, s->v.FunctionDef.name, DEF_LOCAL)) + if (!symtable_add_def(st, s->v.FunctionDef.name, DEF_LOCAL, LOCATION(s))) VISIT_QUIT(st, 0); if (s->v.FunctionDef.args->defaults) VISIT_SEQ(st, expr, s->v.FunctionDef.args->defaults); @@ -1213,8 +1220,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) VISIT_SEQ(st, expr, s->v.FunctionDef.decorator_list); if (!symtable_enter_block(st, s->v.FunctionDef.name, FunctionBlock, (void *)s, - s->lineno, s->col_offset, - s->end_lineno, s->end_col_offset)) + LOCATION(s))) VISIT_QUIT(st, 0); VISIT(st, arguments, s->v.FunctionDef.args); VISIT_SEQ(st, stmt, s->v.FunctionDef.body); @@ -1223,7 +1229,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) break; case ClassDef_kind: { PyObject *tmp; - if (!symtable_add_def(st, s->v.ClassDef.name, DEF_LOCAL)) + if (!symtable_add_def(st, s->v.ClassDef.name, DEF_LOCAL, LOCATION(s))) VISIT_QUIT(st, 0); VISIT_SEQ(st, expr, s->v.ClassDef.bases); VISIT_SEQ(st, keyword, s->v.ClassDef.keywords); @@ -1276,12 +1282,12 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) } if (s->v.AnnAssign.simple && !symtable_add_def(st, e_name->v.Name.id, - DEF_ANNOT | DEF_LOCAL)) { + DEF_ANNOT | DEF_LOCAL, LOCATION(e_name))) { VISIT_QUIT(st, 0); } else { if (s->v.AnnAssign.value - && !symtable_add_def(st, e_name->v.Name.id, DEF_LOCAL)) { + && !symtable_add_def(st, e_name->v.Name.id, DEF_LOCAL, LOCATION(e_name))) { VISIT_QUIT(st, 0); } } @@ -1378,7 +1384,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) s->end_col_offset + 1); VISIT_QUIT(st, 0); } - if (!symtable_add_def(st, name, DEF_GLOBAL)) + if (!symtable_add_def(st, name, DEF_GLOBAL, LOCATION(s))) VISIT_QUIT(st, 0); if (!symtable_record_directive(st, name, s->lineno, s->col_offset, s->end_lineno, s->end_col_offset)) @@ -1413,7 +1419,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) s->end_col_offset + 1); VISIT_QUIT(st, 0); } - if (!symtable_add_def(st, name, DEF_NONLOCAL)) + if (!symtable_add_def(st, name, DEF_NONLOCAL, LOCATION(s))) VISIT_QUIT(st, 0); if (!symtable_record_directive(st, name, s->lineno, s->col_offset, s->end_lineno, s->end_col_offset)) @@ -1434,7 +1440,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) VISIT_SEQ(st, stmt, s->v.With.body); break; case AsyncFunctionDef_kind: - if (!symtable_add_def(st, s->v.AsyncFunctionDef.name, DEF_LOCAL)) + if (!symtable_add_def(st, s->v.AsyncFunctionDef.name, DEF_LOCAL, LOCATION(s))) VISIT_QUIT(st, 0); if (s->v.AsyncFunctionDef.args->defaults) VISIT_SEQ(st, expr, s->v.AsyncFunctionDef.args->defaults); @@ -1509,27 +1515,25 @@ symtable_extend_namedexpr_scope(struct symtable *st, expr_ty e) if (ste->ste_type == FunctionBlock) { long target_in_scope = _PyST_GetSymbol(ste, target_name); if (target_in_scope & DEF_GLOBAL) { - if (!symtable_add_def(st, target_name, DEF_GLOBAL)) + if (!symtable_add_def(st, target_name, DEF_GLOBAL, LOCATION(e))) VISIT_QUIT(st, 0); } else { - if (!symtable_add_def(st, target_name, DEF_NONLOCAL)) + if (!symtable_add_def(st, target_name, DEF_NONLOCAL, LOCATION(e))) VISIT_QUIT(st, 0); } - if (!symtable_record_directive(st, target_name, e->lineno, e->col_offset, - e->end_lineno, e->end_col_offset)) + if (!symtable_record_directive(st, target_name, LOCATION(e))) VISIT_QUIT(st, 0); - return symtable_add_def_helper(st, target_name, DEF_LOCAL, ste); + return symtable_add_def_helper(st, target_name, DEF_LOCAL, ste, LOCATION(e)); } /* If we find a ModuleBlock entry, add as GLOBAL */ if (ste->ste_type == ModuleBlock) { - if (!symtable_add_def(st, target_name, DEF_GLOBAL)) + if (!symtable_add_def(st, target_name, DEF_GLOBAL, LOCATION(e))) VISIT_QUIT(st, 0); - if (!symtable_record_directive(st, target_name, e->lineno, e->col_offset, - e->end_lineno, e->end_col_offset)) + if (!symtable_record_directive(st, target_name, LOCATION(e))) VISIT_QUIT(st, 0); - return symtable_add_def_helper(st, target_name, DEF_GLOBAL, ste); + return symtable_add_def_helper(st, target_name, DEF_GLOBAL, ste, LOCATION(e)); } /* Disallow usage in ClassBlock */ if (ste->ste_type == ClassBlock) { @@ -1652,6 +1656,9 @@ symtable_visit_expr(struct symtable *st, expr_ty e) if (e->v.Yield.value) VISIT(st, expr, e->v.Yield.value); st->st_cur->ste_generator = 1; + if (st->st_cur->ste_comprehension) { + return symtable_raise_if_comprehension_block(st, e); + } break; case YieldFrom_kind: if (!symtable_raise_if_annotation_block(st, "yield expression", e)) { @@ -1659,6 +1666,9 @@ symtable_visit_expr(struct symtable *st, expr_ty e) } VISIT(st, expr, e->v.YieldFrom.value); st->st_cur->ste_generator = 1; + if (st->st_cur->ste_comprehension) { + return symtable_raise_if_comprehension_block(st, e); + } break; case Await_kind: if (!symtable_raise_if_annotation_block(st, "await expression", e)) { @@ -1708,14 +1718,14 @@ symtable_visit_expr(struct symtable *st, expr_ty e) break; case Name_kind: if (!symtable_add_def(st, e->v.Name.id, - e->v.Name.ctx == Load ? USE : DEF_LOCAL)) + e->v.Name.ctx == Load ? USE : DEF_LOCAL, LOCATION(e))) VISIT_QUIT(st, 0); /* Special-case super: it counts as a use of __class__ */ if (e->v.Name.ctx == Load && st->st_cur->ste_type == FunctionBlock && _PyUnicode_EqualToASCIIString(e->v.Name.id, "super")) { if (!GET_IDENTIFIER(__class__) || - !symtable_add_def(st, __class__, USE)) + !symtable_add_def(st, __class__, USE, LOCATION(e))) VISIT_QUIT(st, 0); } break; @@ -1750,14 +1760,14 @@ symtable_visit_pattern(struct symtable *st, pattern_ty p) break; case MatchStar_kind: if (p->v.MatchStar.name) { - symtable_add_def(st, p->v.MatchStar.name, DEF_LOCAL); + symtable_add_def(st, p->v.MatchStar.name, DEF_LOCAL, LOCATION(p)); } break; case MatchMapping_kind: VISIT_SEQ(st, expr, p->v.MatchMapping.keys); VISIT_SEQ(st, pattern, p->v.MatchMapping.patterns); if (p->v.MatchMapping.rest) { - symtable_add_def(st, p->v.MatchMapping.rest, DEF_LOCAL); + symtable_add_def(st, p->v.MatchMapping.rest, DEF_LOCAL, LOCATION(p)); } break; case MatchClass_kind: @@ -1770,7 +1780,7 @@ symtable_visit_pattern(struct symtable *st, pattern_ty p) VISIT(st, pattern, p->v.MatchAs.pattern); } if (p->v.MatchAs.name) { - symtable_add_def(st, p->v.MatchAs.name, DEF_LOCAL); + symtable_add_def(st, p->v.MatchAs.name, DEF_LOCAL, LOCATION(p)); } break; case MatchOr_kind: @@ -1786,7 +1796,7 @@ symtable_implicit_arg(struct symtable *st, int pos) PyObject *id = PyUnicode_FromFormat(".%d", pos); if (id == NULL) return 0; - if (!symtable_add_def(st, id, DEF_PARAM)) { + if (!symtable_add_def(st, id, DEF_PARAM, ST_LOCATION(st->st_cur))) { Py_DECREF(id); return 0; } @@ -1804,7 +1814,7 @@ symtable_visit_params(struct symtable *st, asdl_arg_seq *args) for (i = 0; i < asdl_seq_LEN(args); i++) { arg_ty arg = (arg_ty)asdl_seq_GET(args, i); - if (!symtable_add_def(st, arg->arg, DEF_PARAM)) + if (!symtable_add_def(st, arg->arg, DEF_PARAM, LOCATION(arg))) return 0; } @@ -1888,12 +1898,12 @@ symtable_visit_arguments(struct symtable *st, arguments_ty a) if (a->kwonlyargs && !symtable_visit_params(st, a->kwonlyargs)) return 0; if (a->vararg) { - if (!symtable_add_def(st, a->vararg->arg, DEF_PARAM)) + if (!symtable_add_def(st, a->vararg->arg, DEF_PARAM, LOCATION(a->vararg))) return 0; st->st_cur->ste_varargs = 1; } if (a->kwarg) { - if (!symtable_add_def(st, a->kwarg->arg, DEF_PARAM)) + if (!symtable_add_def(st, a->kwarg->arg, DEF_PARAM, LOCATION(a->kwarg))) return 0; st->st_cur->ste_varkeywords = 1; } @@ -1907,7 +1917,7 @@ symtable_visit_excepthandler(struct symtable *st, excepthandler_ty eh) if (eh->v.ExceptHandler.type) VISIT(st, expr, eh->v.ExceptHandler.type); if (eh->v.ExceptHandler.name) - if (!symtable_add_def(st, eh->v.ExceptHandler.name, DEF_LOCAL)) + if (!symtable_add_def(st, eh->v.ExceptHandler.name, DEF_LOCAL, LOCATION(eh))) return 0; VISIT_SEQ(st, stmt, eh->v.ExceptHandler.body); return 1; @@ -1955,16 +1965,16 @@ symtable_visit_alias(struct symtable *st, alias_ty a) Py_INCREF(store_name); } if (!_PyUnicode_EqualToASCIIString(name, "*")) { - int r = symtable_add_def(st, store_name, DEF_IMPORT); + int r = symtable_add_def(st, store_name, DEF_IMPORT, LOCATION(a)); Py_DECREF(store_name); return r; } else { if (st->st_cur->ste_type != ModuleBlock) { - int lineno = st->st_cur->ste_lineno; - int col_offset = st->st_cur->ste_col_offset; - int end_lineno = st->st_cur->ste_end_lineno; - int end_col_offset = st->st_cur->ste_end_col_offset; + int lineno = a->lineno; + int col_offset = a->col_offset; + int end_lineno = a->end_lineno; + int end_col_offset = a->end_col_offset; PyErr_SetString(PyExc_SyntaxError, IMPORT_STAR_WARNING); PyErr_RangedSyntaxLocationObject(st->st_filename, lineno, col_offset + 1, @@ -2022,10 +2032,23 @@ symtable_handle_comprehension(struct symtable *st, expr_ty e, e->end_lineno, e->end_col_offset)) { return 0; } + switch(e->kind) { + case ListComp_kind: + st->st_cur->ste_comprehension = ListComprehension; + break; + case SetComp_kind: + st->st_cur->ste_comprehension = SetComprehension; + break; + case DictComp_kind: + st->st_cur->ste_comprehension = DictComprehension; + break; + default: + st->st_cur->ste_comprehension = GeneratorExpression; + break; + } if (outermost->is_async) { st->st_cur->ste_coroutine = 1; } - st->st_cur->ste_comprehension = 1; /* Outermost iter is received as an argument */ if (!symtable_implicit_arg(st, 0)) { @@ -2042,20 +2065,6 @@ symtable_handle_comprehension(struct symtable *st, expr_ty e, if (value) VISIT(st, expr, value); VISIT(st, expr, elt); - if (st->st_cur->ste_generator) { - PyErr_SetString(PyExc_SyntaxError, - (e->kind == ListComp_kind) ? "'yield' inside list comprehension" : - (e->kind == SetComp_kind) ? "'yield' inside set comprehension" : - (e->kind == DictComp_kind) ? "'yield' inside dict comprehension" : - "'yield' inside generator expression"); - PyErr_RangedSyntaxLocationObject(st->st_filename, - st->st_cur->ste_lineno, - st->st_cur->ste_col_offset + 1, - st->st_cur->ste_end_lineno, - st->st_cur->ste_end_col_offset + 1); - symtable_exit_block(st); - return 0; - } st->st_cur->ste_generator = is_generator; int is_async = st->st_cur->ste_coroutine && !is_generator; if (!symtable_exit_block(st)) { @@ -2116,6 +2125,20 @@ symtable_raise_if_annotation_block(struct symtable *st, const char *name, expr_t return 0; } +static int +symtable_raise_if_comprehension_block(struct symtable *st, expr_ty e) { + _Py_comprehension_ty type = st->st_cur->ste_comprehension; + PyErr_SetString(PyExc_SyntaxError, + (type == ListComprehension) ? "'yield' inside list comprehension" : + (type == SetComprehension) ? "'yield' inside set comprehension" : + (type == DictComprehension) ? "'yield' inside dict comprehension" : + "'yield' inside generator expression"); + PyErr_RangedSyntaxLocationObject(st->st_filename, + e->lineno, e->col_offset + 1, + e->end_lineno, e->end_col_offset + 1); + VISIT_QUIT(st, 0); +} + struct symtable * _Py_SymtableStringObjectFlags(const char *str, PyObject *filename, int start, PyCompilerFlags *flags) From webhook-mailer at python.org Sat Dec 11 20:24:18 2021 From: webhook-mailer at python.org (pablogsal) Date: Sun, 12 Dec 2021 01:24:18 -0000 Subject: [Python-checkins] bpo-46042: Improve SyntaxError locations in the symbol table (GH-30059) (GH-30064) Message-ID: https://github.com/python/cpython/commit/438817fdd5b731d486285d205bed2e78b655c0d6 commit: 438817fdd5b731d486285d205bed2e78b655c0d6 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: pablogsal date: 2021-12-12T01:24:12Z summary: bpo-46042: Improve SyntaxError locations in the symbol table (GH-30059) (GH-30064) (cherry picked from commit 59435eea08d30796174552c0ca03c59b41adf8a5) Co-authored-by: Pablo Galindo Salgado Co-authored-by: Pablo Galindo Salgado files: A Misc/NEWS.d/next/Core and Builtins/2021-12-11-17-40-34.bpo-46042.aqYxku.rst M Doc/data/python3.10.abi M Include/internal/pycore_symtable.h M Lib/test/test_exceptions.py M Python/symtable.c diff --git a/Doc/data/python3.10.abi b/Doc/data/python3.10.abi index 94dcf74411b4b..b7886ae28f700 100644 --- a/Doc/data/python3.10.abi +++ b/Doc/data/python3.10.abi @@ -1005,6 +1005,7 @@ + @@ -1641,10 +1642,7 @@ - - - - + @@ -1820,13 +1818,13 @@ - + - + @@ -1898,15 +1896,15 @@ - - - + + + @@ -1916,7 +1914,7 @@ - + @@ -1952,66 +1950,66 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -2020,82 +2018,82 @@ - + - + - + - + - + + + + - + - + - + - + - - - - + - + - + - + - + - + - + - + - + - + @@ -2104,16 +2102,16 @@ - + - + - + @@ -2122,10 +2120,10 @@ - + - + @@ -2149,16 +2147,16 @@ - + - + - + - + @@ -2167,46 +2165,46 @@ - + - + - + - + - + - + - + - + - + - + - + - + @@ -2215,13 +2213,13 @@ - + - + - + @@ -2260,19 +2258,19 @@ - + - + - + - + @@ -2314,10 +2312,10 @@ - + - + @@ -2325,22 +2323,19 @@ - - - - + - + - + @@ -2367,7 +2362,7 @@ - + @@ -2375,113 +2370,113 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -2491,16 +2486,16 @@ - + - + - + - + @@ -3012,23 +3007,23 @@ - - + + - + - + - + - + - + @@ -3368,7 +3363,7 @@ - + @@ -3410,13 +3405,7 @@ - - - - - - - + @@ -3425,9 +3414,6 @@ - - - @@ -3456,50 +3442,50 @@ - - + + - - + + - - - - + + + + - - + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + @@ -3927,7 +3913,7 @@ - + @@ -3979,12 +3965,12 @@ - - + + - - + + @@ -4371,7 +4357,7 @@ - + @@ -4764,105 +4750,105 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -5116,27 +5102,27 @@ - + - + - + - + - + - + - + @@ -5323,39 +5309,39 @@ - + - + - + - + - + - + - + - + - + - + - + - + @@ -5513,192 +5499,192 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -5868,7 +5854,7 @@ - + @@ -7052,7 +7038,7 @@ - + @@ -7153,8 +7139,8 @@ - - + + @@ -8046,38 +8032,38 @@ - - - - + + + + - - - - + + + + - - + + - - - - + + + + - - + + - - + + @@ -8413,11 +8399,11 @@ - + - + @@ -8985,7 +8971,7 @@ - + @@ -9962,7 +9948,7 @@ - + @@ -10104,6 +10090,9 @@ + + + @@ -10320,7 +10309,7 @@ - + @@ -10788,8 +10777,8 @@ - - + + @@ -11691,7 +11680,7 @@ - + @@ -11745,7 +11734,7 @@ - + @@ -11814,7 +11803,7 @@ - + @@ -12319,30 +12308,30 @@ - - + + - - + + - - - + + + - - - + + + - - + + - - + + @@ -12355,21 +12344,21 @@ - - + + - + - + - - + + - + @@ -12430,125 +12419,125 @@ - + - + - - + + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -12768,36 +12757,36 @@ - - - + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + @@ -13229,22 +13218,22 @@ - - - - - + + + + + - - - + + + - - - - + + + + @@ -14513,17 +14502,20 @@ - - - - - - + + + + + + + + + @@ -14533,7 +14525,7 @@ - + @@ -14545,10 +14537,10 @@ - + - + @@ -14557,7 +14549,7 @@ - + @@ -14599,7 +14591,7 @@ - + @@ -14651,14 +14643,20 @@ - - - + + + + + + + + + - - - + + + @@ -14714,105 +14712,105 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -15211,10 +15209,10 @@ - + - + @@ -15235,7 +15233,7 @@ - + @@ -15775,7 +15773,7 @@ - + @@ -15954,27 +15952,27 @@ - + - + - + - + - + - + - + @@ -16148,6 +16146,9 @@ + + + @@ -16466,7 +16467,7 @@ - + @@ -16933,7 +16934,7 @@ - + @@ -17137,7 +17138,7 @@ - + @@ -17224,51 +17225,51 @@ - + - - + + - - + + - - - + + + - - + + - - + + - - - + + + - + - - + + - - + + - - - + + + - + @@ -17278,175 +17279,175 @@ - - + + - + - + - + - + - + - + - - + + - - + + - - + + - + - + - - - + + + - - + + - - + + - - + + - + - - + + - - + + - - - + + + - + - + - - - + + + - + - - + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - + - - + + - - + + - - + + - - + + - - + + - + - - + + @@ -17457,21 +17458,21 @@ - + - - + + - - + + - - - - + + + + @@ -17534,7 +17535,7 @@ - + @@ -18080,135 +18081,144 @@ - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + + + + + + + - + - - + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -18216,15 +18226,15 @@ - - - - - - - - - + + + + + + + + + @@ -18389,10 +18399,10 @@ - + - + @@ -18424,17 +18434,17 @@ - + - + - + - + @@ -18444,16 +18454,16 @@ - + - + - + @@ -18484,27 +18494,27 @@ - + - + - + - + - + @@ -18525,7 +18535,7 @@ - + @@ -18631,13 +18641,13 @@ - + - + - + @@ -18683,14 +18693,14 @@ - + - + @@ -18704,7 +18714,7 @@ - + @@ -18712,19 +18722,19 @@ - - + + - + - + @@ -18828,7 +18838,7 @@ - + @@ -18902,9 +18912,9 @@ - + - + @@ -19002,39 +19012,39 @@ - + - + - + - + - + - + - + - + - + - + @@ -19046,46 +19056,46 @@ - + - - - - - - - - + + + + + + + + - + - + - + - + - + - + - + @@ -19093,23 +19103,23 @@ - + - + - + - + @@ -19181,20 +19191,20 @@ - - - - + + + + - + - + @@ -19275,10 +19285,10 @@ - + - + @@ -19385,7 +19395,7 @@ - + @@ -19393,18 +19403,18 @@ - - + + - + - - + + - + @@ -19420,15 +19430,15 @@ - + - + - - + + @@ -20215,42 +20225,42 @@ - + - + - + - + - + - - + + - + - + - + - - + + - - + + @@ -20286,7 +20296,7 @@ - + @@ -20409,7 +20419,7 @@ - + @@ -20681,7 +20691,7 @@ - + @@ -20691,7 +20701,7 @@ - + @@ -20702,8 +20712,8 @@ - - - + + + diff --git a/Include/internal/pycore_symtable.h b/Include/internal/pycore_symtable.h index f3505f8949be4..a2e520b8e25fe 100644 --- a/Include/internal/pycore_symtable.h +++ b/Include/internal/pycore_symtable.h @@ -13,6 +13,13 @@ struct _mod; // Type defined in pycore_ast.h typedef enum _block_type { FunctionBlock, ClassBlock, ModuleBlock, AnnotationBlock } _Py_block_ty; +typedef enum _comprehension_type { + NoComprehension = 0, + ListComprehension = 1, + DictComprehension = 2, + SetComprehension = 3, + GeneratorExpression = 4 } _Py_comprehension_ty; + struct _symtable_entry; struct symtable { @@ -42,14 +49,14 @@ typedef struct _symtable_entry { PyObject *ste_varnames; /* list of function parameters */ PyObject *ste_children; /* list of child blocks */ PyObject *ste_directives;/* locations of global and nonlocal statements */ - _Py_block_ty ste_type; /* module, class, or function */ + _Py_block_ty ste_type; /* module, class or function */ int ste_nested; /* true if block is nested */ unsigned ste_free : 1; /* true if block has free variables */ unsigned ste_child_free : 1; /* true if a child block has free vars, including free refs to globals */ unsigned ste_generator : 1; /* true if namespace is a generator */ unsigned ste_coroutine : 1; /* true if namespace is a coroutine */ - unsigned ste_comprehension : 1; /* true if namespace is a list comprehension */ + _Py_comprehension_ty ste_comprehension; /* Kind of comprehension (if any) */ unsigned ste_varargs : 1; /* true if block has varargs */ unsigned ste_varkeywords : 1; /* true if block has varkeywords */ unsigned ste_returns_value : 1; /* true if namespace uses return with diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index bc5f83a5d2dc8..9acb16c518210 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -268,9 +268,10 @@ def baz(): check(b"\xef\xbb\xbf#coding: utf8\nprint('\xe6\x88\x91')\n", 0, -1) # Errors thrown by symtable.c - check('x = [(yield i) for i in range(3)]', 1, 5) - check('def f():\n from _ import *', 1, 1) - check('def f(x, x):\n pass', 1, 1) + check('x = [(yield i) for i in range(3)]', 1, 7) + check('def f():\n from _ import *', 2, 17) + check('def f(x, x):\n pass', 1, 10) + check('{i for i in range(5) if (j := 0) for j in range(5)}', 1, 38) check('def f(x):\n nonlocal x', 2, 3) check('def f(x):\n x = 1\n global x', 3, 3) check('nonlocal x', 1, 1) diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-11-17-40-34.bpo-46042.aqYxku.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-11-17-40-34.bpo-46042.aqYxku.rst new file mode 100644 index 0000000000000..7a302bcd7648b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-11-17-40-34.bpo-46042.aqYxku.rst @@ -0,0 +1,2 @@ +Improve the location of the caret in :exc:`SyntaxError` exceptions emitted +by the symbol table. Patch by Pablo Galindo. diff --git a/Python/symtable.c b/Python/symtable.c index 62bd1e2ec48f8..07f9d1132c797 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -49,6 +49,12 @@ "'%s' can not be used within an annotation" +#define LOCATION(x) \ + (x)->lineno, (x)->col_offset, (x)->end_lineno, (x)->end_col_offset + +#define ST_LOCATION(x) \ + (x)->ste_lineno, (x)->ste_col_offset, (x)->ste_end_lineno, (x)->ste_end_col_offset + static PySTEntryObject * ste_new(struct symtable *st, identifier name, _Py_block_ty block, void *key, int lineno, int col_offset, @@ -96,7 +102,7 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block, ste->ste_child_free = 0; ste->ste_generator = 0; ste->ste_coroutine = 0; - ste->ste_comprehension = 0; + ste->ste_comprehension = NoComprehension; ste->ste_returns_value = 0; ste->ste_needs_class_closure = 0; ste->ste_comp_iter_target = 0; @@ -221,6 +227,7 @@ static int symtable_visit_withitem(struct symtable *st, withitem_ty item); static int symtable_visit_match_case(struct symtable *st, match_case_ty m); static int symtable_visit_pattern(struct symtable *st, pattern_ty s); static int symtable_raise_if_annotation_block(struct symtable *st, const char *, expr_ty); +static int symtable_raise_if_comprehension_block(struct symtable *st, expr_ty); static identifier top = NULL, lambda = NULL, genexpr = NULL, @@ -1024,7 +1031,8 @@ symtable_lookup(struct symtable *st, PyObject *name) } static int -symtable_add_def_helper(struct symtable *st, PyObject *name, int flag, struct _symtable_entry *ste) +symtable_add_def_helper(struct symtable *st, PyObject *name, int flag, struct _symtable_entry *ste, + int lineno, int col_offset, int end_lineno, int end_col_offset) { PyObject *o; PyObject *dict; @@ -1041,10 +1049,8 @@ symtable_add_def_helper(struct symtable *st, PyObject *name, int flag, struct _s /* Is it better to use 'mangled' or 'name' here? */ PyErr_Format(PyExc_SyntaxError, DUPLICATE_ARGUMENT, name); PyErr_RangedSyntaxLocationObject(st->st_filename, - ste->ste_lineno, - ste->ste_col_offset + 1, - ste->ste_end_lineno, - ste->ste_end_col_offset + 1); + lineno, col_offset + 1, + end_lineno, end_col_offset + 1); goto error; } val |= flag; @@ -1065,10 +1071,8 @@ symtable_add_def_helper(struct symtable *st, PyObject *name, int flag, struct _s PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_INNER_LOOP_CONFLICT, name); PyErr_RangedSyntaxLocationObject(st->st_filename, - ste->ste_lineno, - ste->ste_col_offset + 1, - ste->ste_end_lineno, - ste->ste_end_col_offset + 1); + lineno, col_offset + 1, + end_lineno, end_col_offset + 1); goto error; } val |= DEF_COMP_ITER; @@ -1113,8 +1117,11 @@ symtable_add_def_helper(struct symtable *st, PyObject *name, int flag, struct _s } static int -symtable_add_def(struct symtable *st, PyObject *name, int flag) { - return symtable_add_def_helper(st, name, flag, st->st_cur); +symtable_add_def(struct symtable *st, PyObject *name, int flag, + int lineno, int col_offset, int end_lineno, int end_col_offset) +{ + return symtable_add_def_helper(st, name, flag, st->st_cur, + lineno, col_offset, end_lineno, end_col_offset); } /* VISIT, VISIT_SEQ and VIST_SEQ_TAIL take an ASDL type as their second argument. @@ -1199,7 +1206,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) } switch (s->kind) { case FunctionDef_kind: - if (!symtable_add_def(st, s->v.FunctionDef.name, DEF_LOCAL)) + if (!symtable_add_def(st, s->v.FunctionDef.name, DEF_LOCAL, LOCATION(s))) VISIT_QUIT(st, 0); if (s->v.FunctionDef.args->defaults) VISIT_SEQ(st, expr, s->v.FunctionDef.args->defaults); @@ -1212,8 +1219,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) VISIT_SEQ(st, expr, s->v.FunctionDef.decorator_list); if (!symtable_enter_block(st, s->v.FunctionDef.name, FunctionBlock, (void *)s, - s->lineno, s->col_offset, - s->end_lineno, s->end_col_offset)) + LOCATION(s))) VISIT_QUIT(st, 0); VISIT(st, arguments, s->v.FunctionDef.args); VISIT_SEQ(st, stmt, s->v.FunctionDef.body); @@ -1222,7 +1228,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) break; case ClassDef_kind: { PyObject *tmp; - if (!symtable_add_def(st, s->v.ClassDef.name, DEF_LOCAL)) + if (!symtable_add_def(st, s->v.ClassDef.name, DEF_LOCAL, LOCATION(s))) VISIT_QUIT(st, 0); VISIT_SEQ(st, expr, s->v.ClassDef.bases); VISIT_SEQ(st, keyword, s->v.ClassDef.keywords); @@ -1275,12 +1281,12 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) } if (s->v.AnnAssign.simple && !symtable_add_def(st, e_name->v.Name.id, - DEF_ANNOT | DEF_LOCAL)) { + DEF_ANNOT | DEF_LOCAL, LOCATION(e_name))) { VISIT_QUIT(st, 0); } else { if (s->v.AnnAssign.value - && !symtable_add_def(st, e_name->v.Name.id, DEF_LOCAL)) { + && !symtable_add_def(st, e_name->v.Name.id, DEF_LOCAL, LOCATION(e_name))) { VISIT_QUIT(st, 0); } } @@ -1377,7 +1383,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) s->end_col_offset + 1); VISIT_QUIT(st, 0); } - if (!symtable_add_def(st, name, DEF_GLOBAL)) + if (!symtable_add_def(st, name, DEF_GLOBAL, LOCATION(s))) VISIT_QUIT(st, 0); if (!symtable_record_directive(st, name, s->lineno, s->col_offset, s->end_lineno, s->end_col_offset)) @@ -1412,7 +1418,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) s->end_col_offset + 1); VISIT_QUIT(st, 0); } - if (!symtable_add_def(st, name, DEF_NONLOCAL)) + if (!symtable_add_def(st, name, DEF_NONLOCAL, LOCATION(s))) VISIT_QUIT(st, 0); if (!symtable_record_directive(st, name, s->lineno, s->col_offset, s->end_lineno, s->end_col_offset)) @@ -1433,7 +1439,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) VISIT_SEQ(st, stmt, s->v.With.body); break; case AsyncFunctionDef_kind: - if (!symtable_add_def(st, s->v.AsyncFunctionDef.name, DEF_LOCAL)) + if (!symtable_add_def(st, s->v.AsyncFunctionDef.name, DEF_LOCAL, LOCATION(s))) VISIT_QUIT(st, 0); if (s->v.AsyncFunctionDef.args->defaults) VISIT_SEQ(st, expr, s->v.AsyncFunctionDef.args->defaults); @@ -1508,27 +1514,25 @@ symtable_extend_namedexpr_scope(struct symtable *st, expr_ty e) if (ste->ste_type == FunctionBlock) { long target_in_scope = _PyST_GetSymbol(ste, target_name); if (target_in_scope & DEF_GLOBAL) { - if (!symtable_add_def(st, target_name, DEF_GLOBAL)) + if (!symtable_add_def(st, target_name, DEF_GLOBAL, LOCATION(e))) VISIT_QUIT(st, 0); } else { - if (!symtable_add_def(st, target_name, DEF_NONLOCAL)) + if (!symtable_add_def(st, target_name, DEF_NONLOCAL, LOCATION(e))) VISIT_QUIT(st, 0); } - if (!symtable_record_directive(st, target_name, e->lineno, e->col_offset, - e->end_lineno, e->end_col_offset)) + if (!symtable_record_directive(st, target_name, LOCATION(e))) VISIT_QUIT(st, 0); - return symtable_add_def_helper(st, target_name, DEF_LOCAL, ste); + return symtable_add_def_helper(st, target_name, DEF_LOCAL, ste, LOCATION(e)); } /* If we find a ModuleBlock entry, add as GLOBAL */ if (ste->ste_type == ModuleBlock) { - if (!symtable_add_def(st, target_name, DEF_GLOBAL)) + if (!symtable_add_def(st, target_name, DEF_GLOBAL, LOCATION(e))) VISIT_QUIT(st, 0); - if (!symtable_record_directive(st, target_name, e->lineno, e->col_offset, - e->end_lineno, e->end_col_offset)) + if (!symtable_record_directive(st, target_name, LOCATION(e))) VISIT_QUIT(st, 0); - return symtable_add_def_helper(st, target_name, DEF_GLOBAL, ste); + return symtable_add_def_helper(st, target_name, DEF_GLOBAL, ste, LOCATION(e)); } /* Disallow usage in ClassBlock */ if (ste->ste_type == ClassBlock) { @@ -1651,6 +1655,9 @@ symtable_visit_expr(struct symtable *st, expr_ty e) if (e->v.Yield.value) VISIT(st, expr, e->v.Yield.value); st->st_cur->ste_generator = 1; + if (st->st_cur->ste_comprehension) { + return symtable_raise_if_comprehension_block(st, e); + } break; case YieldFrom_kind: if (!symtable_raise_if_annotation_block(st, "yield expression", e)) { @@ -1658,6 +1665,9 @@ symtable_visit_expr(struct symtable *st, expr_ty e) } VISIT(st, expr, e->v.YieldFrom.value); st->st_cur->ste_generator = 1; + if (st->st_cur->ste_comprehension) { + return symtable_raise_if_comprehension_block(st, e); + } break; case Await_kind: if (!symtable_raise_if_annotation_block(st, "await expression", e)) { @@ -1707,14 +1717,14 @@ symtable_visit_expr(struct symtable *st, expr_ty e) break; case Name_kind: if (!symtable_add_def(st, e->v.Name.id, - e->v.Name.ctx == Load ? USE : DEF_LOCAL)) + e->v.Name.ctx == Load ? USE : DEF_LOCAL, LOCATION(e))) VISIT_QUIT(st, 0); /* Special-case super: it counts as a use of __class__ */ if (e->v.Name.ctx == Load && st->st_cur->ste_type == FunctionBlock && _PyUnicode_EqualToASCIIString(e->v.Name.id, "super")) { if (!GET_IDENTIFIER(__class__) || - !symtable_add_def(st, __class__, USE)) + !symtable_add_def(st, __class__, USE, LOCATION(e))) VISIT_QUIT(st, 0); } break; @@ -1749,14 +1759,14 @@ symtable_visit_pattern(struct symtable *st, pattern_ty p) break; case MatchStar_kind: if (p->v.MatchStar.name) { - symtable_add_def(st, p->v.MatchStar.name, DEF_LOCAL); + symtable_add_def(st, p->v.MatchStar.name, DEF_LOCAL, LOCATION(p)); } break; case MatchMapping_kind: VISIT_SEQ(st, expr, p->v.MatchMapping.keys); VISIT_SEQ(st, pattern, p->v.MatchMapping.patterns); if (p->v.MatchMapping.rest) { - symtable_add_def(st, p->v.MatchMapping.rest, DEF_LOCAL); + symtable_add_def(st, p->v.MatchMapping.rest, DEF_LOCAL, LOCATION(p)); } break; case MatchClass_kind: @@ -1769,7 +1779,7 @@ symtable_visit_pattern(struct symtable *st, pattern_ty p) VISIT(st, pattern, p->v.MatchAs.pattern); } if (p->v.MatchAs.name) { - symtable_add_def(st, p->v.MatchAs.name, DEF_LOCAL); + symtable_add_def(st, p->v.MatchAs.name, DEF_LOCAL, LOCATION(p)); } break; case MatchOr_kind: @@ -1785,7 +1795,7 @@ symtable_implicit_arg(struct symtable *st, int pos) PyObject *id = PyUnicode_FromFormat(".%d", pos); if (id == NULL) return 0; - if (!symtable_add_def(st, id, DEF_PARAM)) { + if (!symtable_add_def(st, id, DEF_PARAM, ST_LOCATION(st->st_cur))) { Py_DECREF(id); return 0; } @@ -1803,7 +1813,7 @@ symtable_visit_params(struct symtable *st, asdl_arg_seq *args) for (i = 0; i < asdl_seq_LEN(args); i++) { arg_ty arg = (arg_ty)asdl_seq_GET(args, i); - if (!symtable_add_def(st, arg->arg, DEF_PARAM)) + if (!symtable_add_def(st, arg->arg, DEF_PARAM, LOCATION(arg))) return 0; } @@ -1887,12 +1897,12 @@ symtable_visit_arguments(struct symtable *st, arguments_ty a) if (a->kwonlyargs && !symtable_visit_params(st, a->kwonlyargs)) return 0; if (a->vararg) { - if (!symtable_add_def(st, a->vararg->arg, DEF_PARAM)) + if (!symtable_add_def(st, a->vararg->arg, DEF_PARAM, LOCATION(a->vararg))) return 0; st->st_cur->ste_varargs = 1; } if (a->kwarg) { - if (!symtable_add_def(st, a->kwarg->arg, DEF_PARAM)) + if (!symtable_add_def(st, a->kwarg->arg, DEF_PARAM, LOCATION(a->kwarg))) return 0; st->st_cur->ste_varkeywords = 1; } @@ -1906,7 +1916,7 @@ symtable_visit_excepthandler(struct symtable *st, excepthandler_ty eh) if (eh->v.ExceptHandler.type) VISIT(st, expr, eh->v.ExceptHandler.type); if (eh->v.ExceptHandler.name) - if (!symtable_add_def(st, eh->v.ExceptHandler.name, DEF_LOCAL)) + if (!symtable_add_def(st, eh->v.ExceptHandler.name, DEF_LOCAL, LOCATION(eh))) return 0; VISIT_SEQ(st, stmt, eh->v.ExceptHandler.body); return 1; @@ -1954,16 +1964,16 @@ symtable_visit_alias(struct symtable *st, alias_ty a) Py_INCREF(store_name); } if (!_PyUnicode_EqualToASCIIString(name, "*")) { - int r = symtable_add_def(st, store_name, DEF_IMPORT); + int r = symtable_add_def(st, store_name, DEF_IMPORT, LOCATION(a)); Py_DECREF(store_name); return r; } else { if (st->st_cur->ste_type != ModuleBlock) { - int lineno = st->st_cur->ste_lineno; - int col_offset = st->st_cur->ste_col_offset; - int end_lineno = st->st_cur->ste_end_lineno; - int end_col_offset = st->st_cur->ste_end_col_offset; + int lineno = a->lineno; + int col_offset = a->col_offset; + int end_lineno = a->end_lineno; + int end_col_offset = a->end_col_offset; PyErr_SetString(PyExc_SyntaxError, IMPORT_STAR_WARNING); PyErr_RangedSyntaxLocationObject(st->st_filename, lineno, col_offset + 1, @@ -2021,10 +2031,23 @@ symtable_handle_comprehension(struct symtable *st, expr_ty e, e->end_lineno, e->end_col_offset)) { return 0; } + switch(e->kind) { + case ListComp_kind: + st->st_cur->ste_comprehension = ListComprehension; + break; + case SetComp_kind: + st->st_cur->ste_comprehension = SetComprehension; + break; + case DictComp_kind: + st->st_cur->ste_comprehension = DictComprehension; + break; + default: + st->st_cur->ste_comprehension = GeneratorExpression; + break; + } if (outermost->is_async) { st->st_cur->ste_coroutine = 1; } - st->st_cur->ste_comprehension = 1; /* Outermost iter is received as an argument */ if (!symtable_implicit_arg(st, 0)) { @@ -2041,20 +2064,6 @@ symtable_handle_comprehension(struct symtable *st, expr_ty e, if (value) VISIT(st, expr, value); VISIT(st, expr, elt); - if (st->st_cur->ste_generator) { - PyErr_SetString(PyExc_SyntaxError, - (e->kind == ListComp_kind) ? "'yield' inside list comprehension" : - (e->kind == SetComp_kind) ? "'yield' inside set comprehension" : - (e->kind == DictComp_kind) ? "'yield' inside dict comprehension" : - "'yield' inside generator expression"); - PyErr_RangedSyntaxLocationObject(st->st_filename, - st->st_cur->ste_lineno, - st->st_cur->ste_col_offset + 1, - st->st_cur->ste_end_lineno, - st->st_cur->ste_end_col_offset + 1); - symtable_exit_block(st); - return 0; - } st->st_cur->ste_generator = is_generator; return symtable_exit_block(st); } @@ -2108,6 +2117,20 @@ symtable_raise_if_annotation_block(struct symtable *st, const char *name, expr_t return 0; } +static int +symtable_raise_if_comprehension_block(struct symtable *st, expr_ty e) { + _Py_comprehension_ty type = st->st_cur->ste_comprehension; + PyErr_SetString(PyExc_SyntaxError, + (type == ListComprehension) ? "'yield' inside list comprehension" : + (type == SetComprehension) ? "'yield' inside set comprehension" : + (type == DictComprehension) ? "'yield' inside dict comprehension" : + "'yield' inside generator expression"); + PyErr_RangedSyntaxLocationObject(st->st_filename, + e->lineno, e->col_offset + 1, + e->end_lineno, e->end_col_offset + 1); + VISIT_QUIT(st, 0); +} + struct symtable * _Py_SymtableStringObjectFlags(const char *str, PyObject *filename, int start, PyCompilerFlags *flags) From webhook-mailer at python.org Sun Dec 12 02:07:14 2021 From: webhook-mailer at python.org (pablogsal) Date: Sun, 12 Dec 2021 07:07:14 -0000 Subject: [Python-checkins] bpo-46054: Fix parsing error when parsing non-utf8 characters in source files (GH-30068) Message-ID: https://github.com/python/cpython/commit/4325a766f5f603ef6dfb8c4d5798e5e73cb5efd5 commit: 4325a766f5f603ef6dfb8c4d5798e5e73cb5efd5 branch: main author: Pablo Galindo Salgado committer: pablogsal date: 2021-12-12T07:06:50Z summary: bpo-46054: Fix parsing error when parsing non-utf8 characters in source files (GH-30068) files: A Misc/NEWS.d/next/Core and Builtins/2021-12-12-05-30-21.bpo-46054.2P-foG.rst M Lib/test/test_exceptions.py M Parser/tokenizer.c diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index c861d8fe9eb42..102102669db16 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -2387,6 +2387,18 @@ def test_encodings(self): finally: unlink(TESTFN) + def test_non_utf8(self): + # Check non utf-8 characters + try: + with open(TESTFN, 'bw') as testfile: + testfile.write(b'\x7fELF\x02\x01\x01\x00\x00\x00') + rc, out, err = script_helper.assert_python_failure('-Wd', '-X', 'utf8', TESTFN) + err = err.decode('utf-8').splitlines() + + self.assertEqual(err[-1], "SyntaxError: invalid non-printable character U+007F") + finally: + unlink(TESTFN) + def test_attributes_new_constructor(self): args = ("bad.py", 1, 2, "abcdefg", 1, 100) the_exception = SyntaxError("bad bad", args) diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-12-05-30-21.bpo-46054.2P-foG.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-12-05-30-21.bpo-46054.2P-foG.rst new file mode 100644 index 0000000000000..6ca91f03445e2 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-12-05-30-21.bpo-46054.2P-foG.rst @@ -0,0 +1,2 @@ +Fix parser error when parsing non-utf8 characters in source files. Patch by +Pablo Galindo. diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c index 6358cdf654e18..a560572ac6197 100644 --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -819,10 +819,10 @@ tok_readline_raw(struct tok_state *tok) tok_concatenate_interactive_new_line(tok, line) == -1) { return 0; } - if (*tok->inp == '\0') { + tok->inp = strchr(tok->inp, '\0'); + if (tok->inp == tok->buf) { return 0; } - tok->inp = strchr(tok->inp, '\0'); } while (tok->inp[-1] != '\n'); return 1; } @@ -984,12 +984,9 @@ tok_underflow_file(struct tok_state *tok) { } /* The default encoding is UTF-8, so make sure we don't have any non-UTF-8 sequences in it. */ - if (!tok->encoding - && (tok->decoding_state != STATE_NORMAL || tok->lineno >= 2)) { - if (!ensure_utf8(tok->cur, tok)) { - error_ret(tok); - return 0; - } + if (!tok->encoding && !ensure_utf8(tok->cur, tok)) { + error_ret(tok); + return 0; } assert(tok->done == E_OK); return tok->done == E_OK; From webhook-mailer at python.org Sun Dec 12 03:41:19 2021 From: webhook-mailer at python.org (asvetlov) Date: Sun, 12 Dec 2021 08:41:19 -0000 Subject: [Python-checkins] bpo-45874: Handle empty query string correctly in urllib.parse.parse_qsl (#29716) Message-ID: https://github.com/python/cpython/commit/e6fe10d34096a23be7d26271cf6aba429313b01d commit: e6fe10d34096a23be7d26271cf6aba429313b01d branch: main author: Christian Sattler committer: asvetlov date: 2021-12-12T10:41:12+02:00 summary: bpo-45874: Handle empty query string correctly in urllib.parse.parse_qsl (#29716) files: A Misc/NEWS.d/next/Library/2021-12-02-11-55-45.bpo-45874.dtJIsN.rst M Lib/test/test_cgi.py M Lib/urllib/parse.py diff --git a/Lib/test/test_cgi.py b/Lib/test/test_cgi.py index c1b893d3fe534..06762f8872a30 100644 --- a/Lib/test/test_cgi.py +++ b/Lib/test/test_cgi.py @@ -51,7 +51,7 @@ def do_test(buf, method): return ComparableException(err) parse_strict_test_cases = [ - ("", ValueError("bad query field: ''")), + ("", {}), ("&", ValueError("bad query field: ''")), ("&&", ValueError("bad query field: ''")), # Should the next few really be valid? diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py index bf16d0f42e579..67ba308c409a2 100644 --- a/Lib/urllib/parse.py +++ b/Lib/urllib/parse.py @@ -740,12 +740,13 @@ def parse_qsl(qs, keep_blank_values=False, strict_parsing=False, # is less than max_num_fields. This prevents a memory exhaustion DOS # attack via post bodies with many fields. if max_num_fields is not None: - num_fields = 1 + qs.count(separator) + num_fields = 1 + qs.count(separator) if qs else 0 if max_num_fields < num_fields: raise ValueError('Max number of fields exceeded') r = [] - for name_value in qs.split(separator): + query_args = qs.split(separator) if qs else [] + for name_value in query_args: if not name_value and not strict_parsing: continue nv = name_value.split('=', 1) diff --git a/Misc/NEWS.d/next/Library/2021-12-02-11-55-45.bpo-45874.dtJIsN.rst b/Misc/NEWS.d/next/Library/2021-12-02-11-55-45.bpo-45874.dtJIsN.rst new file mode 100644 index 0000000000000..ef793cf30a80e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-02-11-55-45.bpo-45874.dtJIsN.rst @@ -0,0 +1,3 @@ +The empty query string, consisting of no query arguments, is now handled +correctly in ``urllib.parse.parse_qsl``. This caused problems before when +strict parsing was enabled. From webhook-mailer at python.org Sun Dec 12 03:45:28 2021 From: webhook-mailer at python.org (asvetlov) Date: Sun, 12 Dec 2021 08:45:28 -0000 Subject: [Python-checkins] bpo-45855: Replaced deprecated `PyImport_ImportModuleNoBlock` with PyImport_ImportModule (GH-30046) Message-ID: https://github.com/python/cpython/commit/41026c3155012d6ea50e01205c163b6739c675b8 commit: 41026c3155012d6ea50e01205c163b6739c675b8 branch: main author: Kumar Aditya <59607654+kumaraditya303 at users.noreply.github.com> committer: asvetlov date: 2021-12-12T10:45:20+02:00 summary: bpo-45855: Replaced deprecated `PyImport_ImportModuleNoBlock` with PyImport_ImportModule (GH-30046) files: A Misc/NEWS.d/next/C API/2021-12-11-08-41-36.bpo-45855.Lq2_gR.rst M Modules/_ctypes/callbacks.c M Modules/_cursesmodule.c M Modules/_datetimemodule.c M Modules/posixmodule.c M Modules/signalmodule.c M Modules/timemodule.c M Objects/capsule.c M Parser/pegen.c M Parser/tokenizer.c M Python/codecs.c M Python/traceback.c diff --git a/Misc/NEWS.d/next/C API/2021-12-11-08-41-36.bpo-45855.Lq2_gR.rst b/Misc/NEWS.d/next/C API/2021-12-11-08-41-36.bpo-45855.Lq2_gR.rst new file mode 100644 index 0000000000000..03258df00420f --- /dev/null +++ b/Misc/NEWS.d/next/C API/2021-12-11-08-41-36.bpo-45855.Lq2_gR.rst @@ -0,0 +1 @@ +Replaced deprecated usage of :c:func:`PyImport_ImportModuleNoBlock` with :c:func:`PyImport_ImportModule` in stdlib modules. Patch by Kumar Aditya. \ No newline at end of file diff --git a/Modules/_ctypes/callbacks.c b/Modules/_ctypes/callbacks.c index 0f7789a973e8f..01d703745bc60 100644 --- a/Modules/_ctypes/callbacks.c +++ b/Modules/_ctypes/callbacks.c @@ -490,7 +490,7 @@ long Call_GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) if (context == NULL) context = PyUnicode_InternFromString("_ctypes.DllGetClassObject"); - mod = PyImport_ImportModuleNoBlock("ctypes"); + mod = PyImport_ImportModule("ctypes"); if (!mod) { PyErr_WriteUnraisable(context ? context : Py_None); /* There has been a warning before about this already */ @@ -563,7 +563,7 @@ long Call_CanUnloadNow(void) if (context == NULL) context = PyUnicode_InternFromString("_ctypes.DllCanUnloadNow"); - mod = PyImport_ImportModuleNoBlock("ctypes"); + mod = PyImport_ImportModule("ctypes"); if (!mod) { /* OutputDebugString("Could not import ctypes"); */ /* We assume that this error can only occur when shutting diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 7ebad692c2381..bf742dacf0110 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -3959,7 +3959,7 @@ static int update_lines_cols(void) { PyObject *o; - PyObject *m = PyImport_ImportModuleNoBlock("curses"); + PyObject *m = PyImport_ImportModule("curses"); _Py_IDENTIFIER(LINES); _Py_IDENTIFIER(COLS); diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 67441eba28f7f..fda8401b84cd1 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -1625,7 +1625,7 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple, goto Done; { PyObject *format; - PyObject *time = PyImport_ImportModuleNoBlock("time"); + PyObject *time = PyImport_ImportModule("time"); if (time == NULL) goto Done; @@ -1655,7 +1655,7 @@ static PyObject * time_time(void) { PyObject *result = NULL; - PyObject *time = PyImport_ImportModuleNoBlock("time"); + PyObject *time = PyImport_ImportModule("time"); if (time != NULL) { _Py_IDENTIFIER(time); @@ -1678,7 +1678,7 @@ build_struct_time(int y, int m, int d, int hh, int mm, int ss, int dstflag) PyObject *args; - time = PyImport_ImportModuleNoBlock("time"); + time = PyImport_ImportModule("time"); if (time == NULL) { return NULL; } @@ -5161,7 +5161,7 @@ datetime_strptime(PyObject *cls, PyObject *args) return NULL; if (module == NULL) { - module = PyImport_ImportModuleNoBlock("_strptime"); + module = PyImport_ImportModule("_strptime"); if (module == NULL) return NULL; } diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 2d95efebb1033..b3a5757a8221d 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -8219,7 +8219,7 @@ wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru) memset(ru, 0, sizeof(*ru)); } - PyObject *m = PyImport_ImportModuleNoBlock("resource"); + PyObject *m = PyImport_ImportModule("resource"); if (m == NULL) return NULL; struct_rusage = PyObject_GetAttr(m, get_posix_state(module)->struct_rusage); diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index bc891e8af3c0b..2013f16ed440e 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -765,7 +765,7 @@ signal_set_wakeup_fd(PyObject *self, PyObject *args, PyObject *kwds) is_socket = 0; if (sockfd != INVALID_FD) { /* Import the _socket module to call WSAStartup() */ - mod = PyImport_ImportModuleNoBlock("_socket"); + mod = PyImport_ImportModule("_socket"); if (mod == NULL) return NULL; Py_DECREF(mod); diff --git a/Modules/timemodule.c b/Modules/timemodule.c index bb713908eb1e4..dd81d352fd713 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -895,7 +895,7 @@ time_strptime(PyObject *self, PyObject *args) PyObject *module, *func, *result; _Py_IDENTIFIER(_strptime_time); - module = PyImport_ImportModuleNoBlock("_strptime"); + module = PyImport_ImportModule("_strptime"); if (!module) return NULL; @@ -1075,7 +1075,7 @@ time_tzset(PyObject *self, PyObject *unused) { PyObject* m; - m = PyImport_ImportModuleNoBlock("time"); + m = PyImport_ImportModule("time"); if (m == NULL) { return NULL; } diff --git a/Objects/capsule.c b/Objects/capsule.c index 800a6c4b25c6d..9c9dcf33f9f75 100644 --- a/Objects/capsule.c +++ b/Objects/capsule.c @@ -215,7 +215,7 @@ PyCapsule_Import(const char *name, int no_block) if (object == NULL) { if (no_block) { - object = PyImport_ImportModuleNoBlock(trace); + object = PyImport_ImportModule(trace); } else { object = PyImport_ImportModule(trace); if (!object) { diff --git a/Parser/pegen.c b/Parser/pegen.c index 4158a81fd52f7..870085e7285e3 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -88,7 +88,7 @@ init_normalization(Parser *p) if (p->normalize) { return 1; } - PyObject *m = PyImport_ImportModuleNoBlock("unicodedata"); + PyObject *m = PyImport_ImportModule("unicodedata"); if (!m) { return 0; diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c index a560572ac6197..5e35d6fa621b1 100644 --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -461,7 +461,7 @@ fp_setreadl(struct tok_state *tok, const char* enc) return 0; } - io = PyImport_ImportModuleNoBlock("io"); + io = PyImport_ImportModule("io"); if (io == NULL) return 0; diff --git a/Python/codecs.c b/Python/codecs.c index b7c8db7e8b618..343b6e2d03396 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -1527,7 +1527,7 @@ static int _PyCodecRegistry_Init(void) } } - mod = PyImport_ImportModuleNoBlock("encodings"); + mod = PyImport_ImportModule("encodings"); if (mod == NULL) { return -1; } diff --git a/Python/traceback.c b/Python/traceback.c index b0ff5e9a6b075..4d6cbaae8da6c 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -447,7 +447,7 @@ display_source_line_with_margin(PyObject *f, PyObject *filename, int lineno, int } } - io = PyImport_ImportModuleNoBlock("io"); + io = PyImport_ImportModule("io"); if (io == NULL) return -1; binary = _PyObject_CallMethodId(io, &PyId_open, "Os", filename, "rb"); From webhook-mailer at python.org Sun Dec 12 04:47:12 2021 From: webhook-mailer at python.org (asvetlov) Date: Sun, 12 Dec 2021 09:47:12 -0000 Subject: [Python-checkins] Re-add `reuse_address` parameter to `create_server` (GH-29733) Message-ID: https://github.com/python/cpython/commit/f3c16a5e72aaf06bec863fa3a172f3deaa491bc9 commit: f3c16a5e72aaf06bec863fa3a172f3deaa491bc9 branch: main author: Jim Crist-Harif committer: asvetlov date: 2021-12-12T11:47:01+02:00 summary: Re-add `reuse_address` parameter to `create_server` (GH-29733) This parameter was accidentally removed when fixing https://bugs.python.org/issue45129, this reverts the unnecessary changes there. Co-authored-by: Andrew Svetlov files: M Lib/asyncio/base_events.py diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index cfaf082587bb2..cbf6d5db0a002 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -1394,6 +1394,7 @@ async def create_server( sock=None, backlog=100, ssl=None, + reuse_address=None, reuse_port=None, ssl_handshake_timeout=None, start_serving=True): @@ -1424,6 +1425,8 @@ async def create_server( raise ValueError( 'host/port and sock can not be specified at the same time') + if reuse_address is None: + reuse_address = os.name == "posix" and sys.platform != "cygwin" sockets = [] if host == '': hosts = [None] @@ -1453,6 +1456,9 @@ async def create_server( af, socktype, proto, exc_info=True) continue sockets.append(sock) + if reuse_address: + sock.setsockopt( + socket.SOL_SOCKET, socket.SO_REUSEADDR, True) if reuse_port: _set_reuseport(sock) # Disable IPv4/IPv6 dual stack support (enabled by From webhook-mailer at python.org Sun Dec 12 04:49:57 2021 From: webhook-mailer at python.org (birkenfeld) Date: Sun, 12 Dec 2021 09:49:57 -0000 Subject: [Python-checkins] bpo-45855: document that `no_block` has no use anymore in PyCapsule_Import (#29665) Message-ID: https://github.com/python/cpython/commit/f4095e53ab708d95e019c909d5928502775ba68f commit: f4095e53ab708d95e019c909d5928502775ba68f branch: main author: Georg Brandl committer: birkenfeld date: 2021-12-12T10:49:50+01:00 summary: bpo-45855: document that `no_block` has no use anymore in PyCapsule_Import (#29665) files: A Misc/NEWS.d/next/C API/2021-12-12-10-09-02.bpo-45855.MVsTDj.rst M Doc/c-api/capsule.rst M Objects/capsule.c diff --git a/Doc/c-api/capsule.rst b/Doc/c-api/capsule.rst index 908e92653dd48..2c4cfc48f9a27 100644 --- a/Doc/c-api/capsule.rst +++ b/Doc/c-api/capsule.rst @@ -103,13 +103,14 @@ Refer to :ref:`using-capsules` for more information on using these objects. Import a pointer to a C object from a capsule attribute in a module. The *name* parameter should specify the full name to the attribute, as in ``module.attribute``. The *name* stored in the capsule must match this - string exactly. If *no_block* is true, import the module without blocking - (using :c:func:`PyImport_ImportModuleNoBlock`). If *no_block* is false, - import the module conventionally (using :c:func:`PyImport_ImportModule`). + string exactly. Return the capsule's internal *pointer* on success. On failure, set an exception and return ``NULL``. + .. versionchanged:: 3.3 + *no_block* has no effect anymore. + .. c:function:: int PyCapsule_IsValid(PyObject *capsule, const char *name) diff --git a/Misc/NEWS.d/next/C API/2021-12-12-10-09-02.bpo-45855.MVsTDj.rst b/Misc/NEWS.d/next/C API/2021-12-12-10-09-02.bpo-45855.MVsTDj.rst new file mode 100644 index 0000000000000..e00d56e0e4ad2 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2021-12-12-10-09-02.bpo-45855.MVsTDj.rst @@ -0,0 +1,2 @@ +Document that the *no_block* argument to :c:func:`PyCapsule_Import` is a +no-op now. diff --git a/Objects/capsule.c b/Objects/capsule.c index 9c9dcf33f9f75..606e50e696113 100644 --- a/Objects/capsule.c +++ b/Objects/capsule.c @@ -214,13 +214,9 @@ PyCapsule_Import(const char *name, int no_block) } if (object == NULL) { - if (no_block) { - object = PyImport_ImportModule(trace); - } else { - object = PyImport_ImportModule(trace); - if (!object) { - PyErr_Format(PyExc_ImportError, "PyCapsule_Import could not import module \"%s\"", trace); - } + object = PyImport_ImportModule(trace); + if (!object) { + PyErr_Format(PyExc_ImportError, "PyCapsule_Import could not import module \"%s\"", trace); } } else { PyObject *object2 = PyObject_GetAttrString(object, trace); From webhook-mailer at python.org Sun Dec 12 11:52:53 2021 From: webhook-mailer at python.org (pablogsal) Date: Sun, 12 Dec 2021 16:52:53 -0000 Subject: [Python-checkins] bpo-46054: Fix parsing error when parsing non-utf8 characters in source files (GH-30068) (GH-30069) Message-ID: https://github.com/python/cpython/commit/94483f1e3cec182fabe19268e579f63045bc984a commit: 94483f1e3cec182fabe19268e579f63045bc984a branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: pablogsal date: 2021-12-12T16:52:49Z summary: bpo-46054: Fix parsing error when parsing non-utf8 characters in source files (GH-30068) (GH-30069) (cherry picked from commit 4325a766f5f603ef6dfb8c4d5798e5e73cb5efd5) Co-authored-by: Pablo Galindo Salgado Co-authored-by: Pablo Galindo Salgado files: A Misc/NEWS.d/next/Core and Builtins/2021-12-12-05-30-21.bpo-46054.2P-foG.rst M Lib/test/test_exceptions.py M Parser/tokenizer.c diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 9acb16c518210..cc0640dda0980 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -2368,6 +2368,18 @@ def test_encodings(self): finally: unlink(TESTFN) + def test_non_utf8(self): + # Check non utf-8 characters + try: + with open(TESTFN, 'bw') as testfile: + testfile.write(b"\x89") + rc, out, err = script_helper.assert_python_failure('-Wd', '-X', 'utf8', TESTFN) + err = err.decode('utf-8').splitlines() + + self.assertIn("SyntaxError: Non-UTF-8 code starting with '\\x89' in file", err[-1]) + finally: + unlink(TESTFN) + def test_attributes_new_constructor(self): args = ("bad.py", 1, 2, "abcdefg", 1, 100) the_exception = SyntaxError("bad bad", args) diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-12-05-30-21.bpo-46054.2P-foG.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-12-05-30-21.bpo-46054.2P-foG.rst new file mode 100644 index 0000000000000..6ca91f03445e2 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-12-05-30-21.bpo-46054.2P-foG.rst @@ -0,0 +1,2 @@ +Fix parser error when parsing non-utf8 characters in source files. Patch by +Pablo Galindo. diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c index 672fdb92ec86f..8e9c69d0785af 100644 --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -818,10 +818,10 @@ tok_readline_raw(struct tok_state *tok) tok_concatenate_interactive_new_line(tok, line) == -1) { return 0; } - if (*tok->inp == '\0') { + tok->inp = strchr(tok->inp, '\0'); + if (tok->inp == tok->buf) { return 0; } - tok->inp = strchr(tok->inp, '\0'); } while (tok->inp[-1] != '\n'); return 1; } @@ -983,12 +983,9 @@ tok_underflow_file(struct tok_state *tok) { } /* The default encoding is UTF-8, so make sure we don't have any non-UTF-8 sequences in it. */ - if (!tok->encoding - && (tok->decoding_state != STATE_NORMAL || tok->lineno >= 2)) { - if (!ensure_utf8(tok->cur, tok)) { - error_ret(tok); - return 0; - } + if (!tok->encoding && !ensure_utf8(tok->cur, tok)) { + error_ret(tok); + return 0; } assert(tok->done == E_OK); return tok->done == E_OK; From webhook-mailer at python.org Sun Dec 12 11:53:05 2021 From: webhook-mailer at python.org (pablogsal) Date: Sun, 12 Dec 2021 16:53:05 -0000 Subject: [Python-checkins] bpo-46054: Correct non-utf8 character tests in test_exceptions (GH-30074) Message-ID: https://github.com/python/cpython/commit/c6d1c52c166968fb722ae26d44aa2c1c030dc613 commit: c6d1c52c166968fb722ae26d44aa2c1c030dc613 branch: main author: Pablo Galindo Salgado committer: pablogsal date: 2021-12-12T16:53:00Z summary: bpo-46054: Correct non-utf8 character tests in test_exceptions (GH-30074) files: M Lib/test/test_exceptions.py diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 102102669db16..ffcb5e1ff5ad1 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -2391,11 +2391,11 @@ def test_non_utf8(self): # Check non utf-8 characters try: with open(TESTFN, 'bw') as testfile: - testfile.write(b'\x7fELF\x02\x01\x01\x00\x00\x00') + testfile.write(b"\x89") rc, out, err = script_helper.assert_python_failure('-Wd', '-X', 'utf8', TESTFN) err = err.decode('utf-8').splitlines() - self.assertEqual(err[-1], "SyntaxError: invalid non-printable character U+007F") + self.assertIn("SyntaxError: Non-UTF-8 code starting with '\\x89' in file", err[-1]) finally: unlink(TESTFN) From webhook-mailer at python.org Sun Dec 12 13:06:01 2021 From: webhook-mailer at python.org (miss-islington) Date: Sun, 12 Dec 2021 18:06:01 -0000 Subject: [Python-checkins] Remove erroneous padding in dataclasses (GH-30076) Message-ID: https://github.com/python/cpython/commit/d0669c5e69735e9073823438ead252db1a54ce6a commit: d0669c5e69735e9073823438ead252db1a54ce6a branch: main author: Andre Delfino committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-12T10:05:48-08:00 summary: Remove erroneous padding in dataclasses (GH-30076) Automerge-Triggered-By: GH:ericvsmith files: M Doc/library/dataclasses.rst diff --git a/Doc/library/dataclasses.rst b/Doc/library/dataclasses.rst index 3592429d06a4c..6bc493c957753 100644 --- a/Doc/library/dataclasses.rst +++ b/Doc/library/dataclasses.rst @@ -653,80 +653,80 @@ re-ordered :meth:`__init__` parameter list. Default factory functions ------------------------- - If a :func:`field` specifies a ``default_factory``, it is called with - zero arguments when a default value for the field is needed. For - example, to create a new instance of a list, use:: +If a :func:`field` specifies a ``default_factory``, it is called with +zero arguments when a default value for the field is needed. For +example, to create a new instance of a list, use:: - mylist: list = field(default_factory=list) + mylist: list = field(default_factory=list) - If a field is excluded from :meth:`__init__` (using ``init=False``) - and the field also specifies ``default_factory``, then the default - factory function will always be called from the generated - :meth:`__init__` function. This happens because there is no other - way to give the field an initial value. +If a field is excluded from :meth:`__init__` (using ``init=False``) +and the field also specifies ``default_factory``, then the default +factory function will always be called from the generated +:meth:`__init__` function. This happens because there is no other +way to give the field an initial value. Mutable default values ---------------------- - Python stores default member variable values in class attributes. - Consider this example, not using dataclasses:: +Python stores default member variable values in class attributes. +Consider this example, not using dataclasses:: - class C: - x = [] - def add(self, element): - self.x.append(element) + class C: + x = [] + def add(self, element): + self.x.append(element) - o1 = C() - o2 = C() - o1.add(1) - o2.add(2) - assert o1.x == [1, 2] - assert o1.x is o2.x + o1 = C() + o2 = C() + o1.add(1) + o2.add(2) + assert o1.x == [1, 2] + assert o1.x is o2.x - Note that the two instances of class ``C`` share the same class - variable ``x``, as expected. +Note that the two instances of class ``C`` share the same class +variable ``x``, as expected. - Using dataclasses, *if* this code was valid:: +Using dataclasses, *if* this code was valid:: - @dataclass - class D: - x: List = [] - def add(self, element): - self.x += element - - it would generate code similar to:: - - class D: - x = [] - def __init__(self, x=x): - self.x = x - def add(self, element): - self.x += element - - assert D().x is D().x - - This has the same issue as the original example using class ``C``. - That is, two instances of class ``D`` that do not specify a value - for ``x`` when creating a class instance will share the same copy - of ``x``. Because dataclasses just use normal Python class - creation they also share this behavior. There is no general way - for Data Classes to detect this condition. Instead, the - :func:`dataclass` decorator will raise a :exc:`TypeError` if it - detects an unhashable default parameter. The assumption is that if - a value is unhashable, it is mutable. This is a partial solution, - but it does protect against many common errors. - - Using default factory functions is a way to create new instances of - mutable types as default values for fields:: + @dataclass + class D: + x: List = [] + def add(self, element): + self.x += element + +it would generate code similar to:: + + class D: + x = [] + def __init__(self, x=x): + self.x = x + def add(self, element): + self.x += element + + assert D().x is D().x + +This has the same issue as the original example using class ``C``. +That is, two instances of class ``D`` that do not specify a value +for ``x`` when creating a class instance will share the same copy +of ``x``. Because dataclasses just use normal Python class +creation they also share this behavior. There is no general way +for Data Classes to detect this condition. Instead, the +:func:`dataclass` decorator will raise a :exc:`TypeError` if it +detects an unhashable default parameter. The assumption is that if +a value is unhashable, it is mutable. This is a partial solution, +but it does protect against many common errors. + +Using default factory functions is a way to create new instances of +mutable types as default values for fields:: - @dataclass - class D: - x: list = field(default_factory=list) + @dataclass + class D: + x: list = field(default_factory=list) - assert D().x is not D().x + assert D().x is not D().x - .. versionchanged:: 3.11 - Instead of looking for and disallowing objects of type ``list``, - ``dict``, or ``set``, unhashable objects are now not allowed as - default values. Unhashability is used to approximate - mutability. +.. versionchanged:: 3.11 + Instead of looking for and disallowing objects of type ``list``, + ``dict``, or ``set``, unhashable objects are now not allowed as + default values. Unhashability is used to approximate + mutability. From webhook-mailer at python.org Mon Dec 13 04:20:27 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Mon, 13 Dec 2021 09:20:27 -0000 Subject: [Python-checkins] bpo-45840: Improve cross-references in the data model documentation (GH-29633) (GH-30077) Message-ID: https://github.com/python/cpython/commit/7da90251ae80f5faac938b659675ff159d565537 commit: 7da90251ae80f5faac938b659675ff159d565537 branch: 3.10 author: Alex Waygood committer: serhiy-storchaka date: 2021-12-13T11:20:21+02:00 summary: bpo-45840: Improve cross-references in the data model documentation (GH-29633) (GH-30077) (cherry picked from commit c0521fe49fd75e794a38a216813658ab40185834) files: A Misc/NEWS.d/next/Documentation/2021-11-19-02-02-32.bpo-45840.A51B2S.rst M Doc/reference/datamodel.rst diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 166c615149360..d2e586a1989dd 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -188,7 +188,7 @@ Ellipsis representation in computers. The string representations of the numeric classes, computed by - :meth:`__repr__` and :meth:`__str__`, have the following + :meth:`~object.__repr__` and :meth:`~object.__str__`, have the following properties: * They are valid numeric literals which, when passed to their @@ -677,7 +677,8 @@ Callable types returns an :term:`asynchronous iterator` object which can be used in an :keyword:`async for` statement to execute the body of the function. - Calling the asynchronous iterator's :meth:`aiterator.__anext__` method + Calling the asynchronous iterator's + :meth:`aiterator.__anext__ ` method will return an :term:`awaitable` which when awaited will execute until it provides a value using the :keyword:`yield` expression. When the function executes an empty :keyword:`return` @@ -715,13 +716,13 @@ Callable types Classes Classes are callable. These objects normally act as factories for new instances of themselves, but variations are possible for class types that - override :meth:`__new__`. The arguments of the call are passed to - :meth:`__new__` and, in the typical case, to :meth:`__init__` to + override :meth:`~object.__new__`. The arguments of the call are passed to + :meth:`__new__` and, in the typical case, to :meth:`~object.__init__` to initialize the new instance. Class Instances Instances of arbitrary classes can be made callable by defining a - :meth:`__call__` method in their class. + :meth:`~object.__call__` method in their class. Modules @@ -880,14 +881,14 @@ Class instances section :ref:`descriptors` for another way in which attributes of a class retrieved via its instances may differ from the objects actually stored in the class's :attr:`~object.__dict__`. If no class attribute is found, and the - object's class has a :meth:`__getattr__` method, that is called to satisfy + object's class has a :meth:`~object.__getattr__` method, that is called to satisfy the lookup. .. index:: triple: class instance; attribute; assignment Attribute assignments and deletions update the instance's dictionary, never a - class's dictionary. If the class has a :meth:`__setattr__` or - :meth:`__delattr__` method, this is called instead of updating the instance + class's dictionary. If the class has a :meth:`~object.__setattr__` or + :meth:`~object.__delattr__` method, this is called instead of updating the instance dictionary directly. .. index:: @@ -1141,7 +1142,8 @@ Internal types Slice objects .. index:: builtin: slice - Slice objects are used to represent slices for :meth:`__getitem__` + Slice objects are used to represent slices for + :meth:`~object.__getitem__` methods. They are also created by the built-in :func:`slice` function. .. index:: @@ -1194,7 +1196,8 @@ A class can implement certain operations that are invoked by special syntax (such as arithmetic operations or subscripting and slicing) by defining methods with special names. This is Python's approach to :dfn:`operator overloading`, allowing classes to define their own behavior with respect to language -operators. For instance, if a class defines a method named :meth:`__getitem__`, +operators. For instance, if a class defines a method named +:meth:`~object.__getitem__`, and ``x`` is an instance of this class, then ``x[i]`` is roughly equivalent to ``type(x).__getitem__(x, i)``. Except where mentioned, attempts to execute an operation raise an exception when no appropriate method is defined (typically @@ -1202,9 +1205,9 @@ operation raise an exception when no appropriate method is defined (typically Setting a special method to ``None`` indicates that the corresponding operation is not available. For example, if a class sets -:meth:`__iter__` to ``None``, the class is not iterable, so calling +:meth:`~object.__iter__` to ``None``, the class is not iterable, so calling :func:`iter` on its instances will raise a :exc:`TypeError` (without -falling back to :meth:`__getitem__`). [#]_ +falling back to :meth:`~object.__getitem__`). [#]_ When implementing a class that emulates any built-in type, it is important that the emulation only be implemented to the degree that it makes sense for the @@ -1754,7 +1757,8 @@ Invoking Descriptors In general, a descriptor is an object attribute with "binding behavior", one whose attribute access has been overridden by methods in the descriptor -protocol: :meth:`__get__`, :meth:`__set__`, and :meth:`__delete__`. If any of +protocol: :meth:`~object.__get__`, :meth:`~object.__set__`, and +:meth:`~object.__delete__`. If any of those methods are defined for an object, it is said to be a descriptor. The default behavior for attribute access is to get, set, or delete the @@ -1790,7 +1794,8 @@ Super Binding For instance bindings, the precedence of descriptor invocation depends on which descriptor methods are defined. A descriptor can define any combination -of :meth:`__get__`, :meth:`__set__` and :meth:`__delete__`. If it does not +of :meth:`~object.__get__`, :meth:`~object.__set__` and +:meth:`~object.__delete__`. If it does not define :meth:`__get__`, then accessing the attribute will return the descriptor object itself unless there is a value in the object's instance dictionary. If the descriptor defines :meth:`__set__` and/or :meth:`__delete__`, it is a data @@ -1801,7 +1806,8 @@ descriptors have just the :meth:`__get__` method. Data descriptors with instance dictionary. In contrast, non-data descriptors can be overridden by instances. -Python methods (including :func:`staticmethod` and :func:`classmethod`) are +Python methods (including those decorated with +:func:`@staticmethod ` and :func:`@classmethod `) are implemented as non-data descriptors. Accordingly, instances can redefine and override methods. This allows individual instances to acquire behaviors that differ from other instances of the same class. @@ -1816,46 +1822,50 @@ __slots__ ^^^^^^^^^ *__slots__* allow us to explicitly declare data members (like -properties) and deny the creation of *__dict__* and *__weakref__* +properties) and deny the creation of :attr:`~object.__dict__` and *__weakref__* (unless explicitly declared in *__slots__* or available in a parent.) -The space saved over using *__dict__* can be significant. +The space saved over using :attr:`~object.__dict__` can be significant. Attribute lookup speed can be significantly improved as well. .. data:: object.__slots__ This class variable can be assigned a string, iterable, or sequence of strings with variable names used by instances. *__slots__* reserves space - for the declared variables and prevents the automatic creation of *__dict__* + for the declared variables and prevents the automatic creation of + :attr:`~object.__dict__` and *__weakref__* for each instance. Notes on using *__slots__* """""""""""""""""""""""""" -* When inheriting from a class without *__slots__*, the *__dict__* and +* When inheriting from a class without *__slots__*, the + :attr:`~object.__dict__` and *__weakref__* attribute of the instances will always be accessible. -* Without a *__dict__* variable, instances cannot be assigned new variables not +* Without a :attr:`~object.__dict__` variable, instances cannot be assigned new + variables not listed in the *__slots__* definition. Attempts to assign to an unlisted variable name raises :exc:`AttributeError`. If dynamic assignment of new variables is desired, then add ``'__dict__'`` to the sequence of strings in the *__slots__* declaration. * Without a *__weakref__* variable for each instance, classes defining - *__slots__* do not support weak references to its instances. If weak reference + *__slots__* do not support :mod:`weak references ` to its instances. + If weak reference support is needed, then add ``'__weakref__'`` to the sequence of strings in the *__slots__* declaration. -* *__slots__* are implemented at the class level by creating descriptors - (:ref:`descriptors`) for each variable name. As a result, class attributes +* *__slots__* are implemented at the class level by creating :ref:`descriptors ` + for each variable name. As a result, class attributes cannot be used to set default values for instance variables defined by *__slots__*; otherwise, the class attribute would overwrite the descriptor assignment. * The action of a *__slots__* declaration is not limited to the class where it is defined. *__slots__* declared in parents are available in - child classes. However, child subclasses will get a *__dict__* and + child classes. However, child subclasses will get a :attr:`~object.__dict__` and *__weakref__* unless they also define *__slots__* (which should only contain names of any *additional* slots). @@ -1871,14 +1881,17 @@ Notes on using *__slots__* used; however, in the future, special meaning may be assigned to the values corresponding to each key. -* *__class__* assignment works only if both classes have the same *__slots__*. +* :attr:`~instance.__class__` assignment works only if both classes have the + same *__slots__*. -* Multiple inheritance with multiple slotted parent classes can be used, +* :ref:`Multiple inheritance ` with multiple slotted parent + classes can be used, but only one parent is allowed to have attributes created by slots (the other bases must have empty slot layouts) - violations raise :exc:`TypeError`. -* If an iterator is used for *__slots__* then a descriptor is created for each +* If an :term:`iterator` is used for *__slots__* then a :term:`descriptor` is + created for each of the iterator's values. However, the *__slots__* attribute will be an empty iterator. @@ -1887,7 +1900,7 @@ Notes on using *__slots__* Customizing class creation -------------------------- -Whenever a class inherits from another class, *__init_subclass__* is +Whenever a class inherits from another class, :meth:`~object.__init_subclass__` is called on that class. This way, it is possible to write classes which change the behavior of subclasses. This is closely related to class decorators, but where class decorators only affect the specific class they're @@ -1928,7 +1941,7 @@ class defining the method. When a class is created, :meth:`type.__new__` scans the class variables -and makes callbacks to those with a :meth:`__set_name__` hook. +and makes callbacks to those with a :meth:`~object.__set_name__` hook. .. method:: object.__set_name__(self, owner, name) @@ -2040,7 +2053,8 @@ Once the appropriate metaclass has been identified, then the class namespace is prepared. If the metaclass has a ``__prepare__`` attribute, it is called as ``namespace = metaclass.__prepare__(name, bases, **kwds)`` (where the additional keyword arguments, if any, come from the class definition). The -``__prepare__`` method should be implemented as a :func:`classmethod`. The +``__prepare__`` method should be implemented as a +:func:`classmethod `. The namespace returned by ``__prepare__`` is passed in to ``__new__``, but when the final class object is created the namespace is copied into a new ``dict``. @@ -2338,31 +2352,36 @@ Emulating container types ------------------------- The following methods can be defined to implement container objects. Containers -usually are sequences (such as lists or tuples) or mappings (like dictionaries), +usually are :term:`sequences ` (such as :class:`lists ` or +:class:`tuples `) or :term:`mappings ` (like +:class:`dictionaries `), but can represent other containers as well. The first set of methods is used either to emulate a sequence or to emulate a mapping; the difference is that for a sequence, the allowable keys should be the integers *k* for which ``0 <= k < -N`` where *N* is the length of the sequence, or slice objects, which define a +N`` where *N* is the length of the sequence, or :class:`slice` objects, which define a range of items. It is also recommended that mappings provide the methods :meth:`keys`, :meth:`values`, :meth:`items`, :meth:`get`, :meth:`clear`, :meth:`setdefault`, :meth:`pop`, :meth:`popitem`, :meth:`!copy`, and -:meth:`update` behaving similar to those for Python's standard dictionary +:meth:`update` behaving similar to those for Python's standard :class:`dictionary ` objects. The :mod:`collections.abc` module provides a :class:`~collections.abc.MutableMapping` -abstract base class to help create those methods from a base set of -:meth:`__getitem__`, :meth:`__setitem__`, :meth:`__delitem__`, and :meth:`keys`. +:term:`abstract base class` to help create those methods from a base set of +:meth:`~object.__getitem__`, :meth:`~object.__setitem__`, :meth:`~object.__delitem__`, and :meth:`keys`. Mutable sequences should provide methods :meth:`append`, :meth:`count`, :meth:`index`, :meth:`extend`, :meth:`insert`, :meth:`pop`, :meth:`remove`, -:meth:`reverse` and :meth:`sort`, like Python standard list objects. Finally, +:meth:`reverse` and :meth:`sort`, like Python standard :class:`list` +objects. Finally, sequence types should implement addition (meaning concatenation) and -multiplication (meaning repetition) by defining the methods :meth:`__add__`, -:meth:`__radd__`, :meth:`__iadd__`, :meth:`__mul__`, :meth:`__rmul__` and -:meth:`__imul__` described below; they should not define other numerical +multiplication (meaning repetition) by defining the methods +:meth:`~object.__add__`, :meth:`~object.__radd__`, :meth:`~object.__iadd__`, +:meth:`~object.__mul__`, :meth:`~object.__rmul__` and :meth:`~object.__imul__` +described below; they should not define other numerical operators. It is recommended that both mappings and sequences implement the -:meth:`__contains__` method to allow efficient use of the ``in`` operator; for +:meth:`~object.__contains__` method to allow efficient use of the ``in`` +operator; for mappings, ``in`` should search the mapping's keys; for sequences, it should search through the values. It is further recommended that both mappings and -sequences implement the :meth:`__iter__` method to allow efficient iteration +sequences implement the :meth:`~object.__iter__` method to allow efficient iteration through the container; for mappings, :meth:`__iter__` should iterate through the object's keys; for sequences, it should iterate through the values. @@ -2774,7 +2793,8 @@ exception:: TypeError: object of type 'C' has no len() The rationale behind this behaviour lies with a number of special methods such -as :meth:`__hash__` and :meth:`__repr__` that are implemented by all objects, +as :meth:`~object.__hash__` and :meth:`~object.__repr__` that are implemented +by all objects, including type objects. If the implicit lookup of these methods used the conventional lookup process, they would fail when invoked on the type object itself:: @@ -2797,7 +2817,7 @@ the instance when looking up special methods:: In addition to bypassing any instance attributes in the interest of correctness, implicit special method lookup generally also bypasses the -:meth:`__getattribute__` method even of the object's metaclass:: +:meth:`~object.__getattribute__` method even of the object's metaclass:: >>> class Meta(type): ... def __getattribute__(*args): @@ -2821,7 +2841,7 @@ correctness, implicit special method lookup generally also bypasses the >>> len(c) # Implicit lookup 10 -Bypassing the :meth:`__getattribute__` machinery in this fashion +Bypassing the :meth:`~object.__getattribute__` machinery in this fashion provides significant scope for speed optimisations within the interpreter, at the cost of some flexibility in the handling of special methods (the special method *must* be set on the class @@ -2838,7 +2858,7 @@ Coroutines Awaitable Objects ----------------- -An :term:`awaitable` object generally implements an :meth:`__await__` method. +An :term:`awaitable` object generally implements an :meth:`~object.__await__` method. :term:`Coroutine objects ` returned from :keyword:`async def` functions are awaitable. @@ -2846,7 +2866,7 @@ are awaitable. The :term:`generator iterator` objects returned from generators decorated with :func:`types.coroutine` or :func:`asyncio.coroutine` - are also awaitable, but they do not implement :meth:`__await__`. + are also awaitable, but they do not implement :meth:`~object.__await__`. .. method:: object.__await__(self) @@ -2865,7 +2885,7 @@ Coroutine Objects ----------------- :term:`Coroutine objects ` are :term:`awaitable` objects. -A coroutine's execution can be controlled by calling :meth:`__await__` and +A coroutine's execution can be controlled by calling :meth:`~object.__await__` and iterating over the result. When the coroutine has finished executing and returns, the iterator raises :exc:`StopIteration`, and the exception's :attr:`~StopIteration.value` attribute holds the return value. If the @@ -2884,7 +2904,7 @@ generators, coroutines do not directly support iteration. Starts or resumes execution of the coroutine. If *value* is ``None``, this is equivalent to advancing the iterator returned by - :meth:`__await__`. If *value* is not ``None``, this method delegates + :meth:`~object.__await__`. If *value* is not ``None``, this method delegates to the :meth:`~generator.send` method of the iterator that caused the coroutine to suspend. The result (return value, :exc:`StopIteration`, or other exception) is the same as when @@ -2897,7 +2917,7 @@ generators, coroutines do not directly support iteration. the coroutine to suspend, if it has such a method. Otherwise, the exception is raised at the suspension point. The result (return value, :exc:`StopIteration`, or other exception) is the same as - when iterating over the :meth:`__await__` return value, described + when iterating over the :meth:`~object.__await__` return value, described above. If the exception is not caught in the coroutine, it propagates back to the caller. @@ -2951,11 +2971,11 @@ An example of an asynchronous iterable object:: .. versionadded:: 3.5 .. versionchanged:: 3.7 - Prior to Python 3.7, ``__aiter__`` could return an *awaitable* + Prior to Python 3.7, :meth:`~object.__aiter__` could return an *awaitable* that would resolve to an :term:`asynchronous iterator `. - Starting with Python 3.7, ``__aiter__`` must return an + Starting with Python 3.7, :meth:`~object.__aiter__` must return an asynchronous iterator object. Returning anything else will result in a :exc:`TypeError` error. @@ -2998,8 +3018,9 @@ An example of an asynchronous context manager class:: controlled conditions. It generally isn't a good idea though, since it can lead to some very strange behaviour if it is handled incorrectly. -.. [#] The :meth:`__hash__`, :meth:`__iter__`, :meth:`__reversed__`, and - :meth:`__contains__` methods have special handling for this; others +.. [#] The :meth:`~object.__hash__`, :meth:`~object.__iter__`, + :meth:`~object.__reversed__`, and :meth:`~object.__contains__` methods have + special handling for this; others will still raise a :exc:`TypeError`, but may do so by relying on the behavior that ``None`` is not callable. @@ -3010,5 +3031,6 @@ An example of an asynchronous context manager class:: *blocking* such fallback. .. [#] For operands of the same type, it is assumed that if the non-reflected - method -- such as :meth:`__add__` -- fails then the overall operation is not + method -- such as :meth:`~object.__add__` -- fails then the overall + operation is not supported, which is why the reflected method is not called. diff --git a/Misc/NEWS.d/next/Documentation/2021-11-19-02-02-32.bpo-45840.A51B2S.rst b/Misc/NEWS.d/next/Documentation/2021-11-19-02-02-32.bpo-45840.A51B2S.rst new file mode 100644 index 0000000000000..87371e5b76bc1 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-11-19-02-02-32.bpo-45840.A51B2S.rst @@ -0,0 +1 @@ +Improve cross-references in the documentation for the data model. From webhook-mailer at python.org Mon Dec 13 04:22:00 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Mon, 13 Dec 2021 09:22:00 -0000 Subject: [Python-checkins] bpo-27718: Fix help for the signal module (GH-30063) Message-ID: https://github.com/python/cpython/commit/e08c0d8eec528f1d7a282ee19bcadb9aae9ec123 commit: e08c0d8eec528f1d7a282ee19bcadb9aae9ec123 branch: main author: Serhiy Storchaka committer: serhiy-storchaka date: 2021-12-13T11:21:55+02:00 summary: bpo-27718: Fix help for the signal module (GH-30063) Functions signal(), getsignal(), pthread_sigmask(), sigpending(), sigwait() and valid_signals() were omitted. If __all__ is not defined all non-builtin functions should have correct __module__. files: A Misc/NEWS.d/next/Library/2021-12-11-22-51-30.bpo-27718.MgQiGl.rst M Lib/signal.py M Lib/test/test_signal.py diff --git a/Lib/signal.py b/Lib/signal.py index d4a6d6fe2ada8..50b215b29d2fa 100644 --- a/Lib/signal.py +++ b/Lib/signal.py @@ -1,6 +1,5 @@ import _signal from _signal import * -from functools import wraps as _wraps from enum import IntEnum as _IntEnum _globals = globals() @@ -42,6 +41,16 @@ def _enum_to_int(value): return value +# Similar to functools.wraps(), but only assign __doc__. +# __module__ should be preserved, +# __name__ and __qualname__ are already fine, +# __annotations__ is not set. +def _wraps(wrapped): + def decorator(wrapper): + wrapper.__doc__ = wrapped.__doc__ + return wrapper + return decorator + @_wraps(_signal.signal) def signal(signalnum, handler): handler = _signal.signal(_enum_to_int(signalnum), _enum_to_int(handler)) @@ -59,7 +68,6 @@ def getsignal(signalnum): def pthread_sigmask(how, mask): sigs_set = _signal.pthread_sigmask(how, mask) return set(_int_to_enum(x, Signals) for x in sigs_set) - pthread_sigmask.__doc__ = _signal.pthread_sigmask.__doc__ if 'sigpending' in _globals: @@ -73,7 +81,6 @@ def sigpending(): def sigwait(sigset): retsig = _signal.sigwait(sigset) return _int_to_enum(retsig, Signals) - sigwait.__doc__ = _signal.sigwait if 'valid_signals' in _globals: diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py index daecf196fa146..3f0e7270eb26f 100644 --- a/Lib/test/test_signal.py +++ b/Lib/test/test_signal.py @@ -1,5 +1,6 @@ import enum import errno +import inspect import os import random import signal @@ -60,6 +61,14 @@ def test_enums(self): ) enum._test_simple_enum(CheckedSigmasks, Sigmasks) + def test_functions_module_attr(self): + # Issue #27718: If __all__ is not defined all non-builtin functions + # should have correct __module__ to be displayed by pydoc. + for name in dir(signal): + value = getattr(signal, name) + if inspect.isroutine(value) and not inspect.isbuiltin(value): + self.assertEqual(value.__module__, 'signal') + @unittest.skipIf(sys.platform == "win32", "Not valid on Windows") class PosixTests(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Library/2021-12-11-22-51-30.bpo-27718.MgQiGl.rst b/Misc/NEWS.d/next/Library/2021-12-11-22-51-30.bpo-27718.MgQiGl.rst new file mode 100644 index 0000000000000..c68e98ff0630b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-11-22-51-30.bpo-27718.MgQiGl.rst @@ -0,0 +1,2 @@ +Fix help for the :mod:`signal` module. Some functions (e.g. ``signal()`` and +``getsignal()``) were omitted. From webhook-mailer at python.org Mon Dec 13 05:04:40 2021 From: webhook-mailer at python.org (iritkatriel) Date: Mon, 13 Dec 2021 10:04:40 -0000 Subject: [Python-checkins] bpo-37602: Clarify that the lib2to3 nonzero fixer changes only definitions (GH-30075) Message-ID: https://github.com/python/cpython/commit/481f3ffdbe40bd19677a1ba0ac2e7cece8949b47 commit: 481f3ffdbe40bd19677a1ba0ac2e7cece8949b47 branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-12-13T10:04:34Z summary: bpo-37602: Clarify that the lib2to3 nonzero fixer changes only definitions (GH-30075) files: M Doc/library/2to3.rst diff --git a/Doc/library/2to3.rst b/Doc/library/2to3.rst index 9a1644a97c0ae..fce02e2800933 100644 --- a/Doc/library/2to3.rst +++ b/Doc/library/2to3.rst @@ -338,7 +338,8 @@ and off individually. They are described here in more detail. .. 2to3fixer:: nonzero - Renames :meth:`__nonzero__` to :meth:`~object.__bool__`. + Renames definitions of methods called :meth:`__nonzero__` + to :meth:`~object.__bool__`. .. 2to3fixer:: numliterals From webhook-mailer at python.org Mon Dec 13 05:15:14 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Mon, 13 Dec 2021 10:15:14 -0000 Subject: [Python-checkins] [3.10] bpo-27718: Fix help for the signal module (GH-30063) (GH-30080) Message-ID: https://github.com/python/cpython/commit/e55deaabd8de338138cf29aea6890996e794c997 commit: e55deaabd8de338138cf29aea6890996e794c997 branch: 3.10 author: Serhiy Storchaka committer: serhiy-storchaka date: 2021-12-13T12:14:51+02:00 summary: [3.10] bpo-27718: Fix help for the signal module (GH-30063) (GH-30080) Functions signal(), getsignal(), pthread_sigmask(), sigpending(), sigwait() and valid_signals() were omitted. If __all__ is not defined all non-builtin functions should have correct __module__. (cherry picked from commit e08c0d8eec528f1d7a282ee19bcadb9aae9ec123) files: A Misc/NEWS.d/next/Library/2021-12-11-22-51-30.bpo-27718.MgQiGl.rst M Lib/signal.py M Lib/test/test_signal.py diff --git a/Lib/signal.py b/Lib/signal.py index d4a6d6fe2ada8..50b215b29d2fa 100644 --- a/Lib/signal.py +++ b/Lib/signal.py @@ -1,6 +1,5 @@ import _signal from _signal import * -from functools import wraps as _wraps from enum import IntEnum as _IntEnum _globals = globals() @@ -42,6 +41,16 @@ def _enum_to_int(value): return value +# Similar to functools.wraps(), but only assign __doc__. +# __module__ should be preserved, +# __name__ and __qualname__ are already fine, +# __annotations__ is not set. +def _wraps(wrapped): + def decorator(wrapper): + wrapper.__doc__ = wrapped.__doc__ + return wrapper + return decorator + @_wraps(_signal.signal) def signal(signalnum, handler): handler = _signal.signal(_enum_to_int(signalnum), _enum_to_int(handler)) @@ -59,7 +68,6 @@ def getsignal(signalnum): def pthread_sigmask(how, mask): sigs_set = _signal.pthread_sigmask(how, mask) return set(_int_to_enum(x, Signals) for x in sigs_set) - pthread_sigmask.__doc__ = _signal.pthread_sigmask.__doc__ if 'sigpending' in _globals: @@ -73,7 +81,6 @@ def sigpending(): def sigwait(sigset): retsig = _signal.sigwait(sigset) return _int_to_enum(retsig, Signals) - sigwait.__doc__ = _signal.sigwait if 'valid_signals' in _globals: diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py index 2144d619630d1..c2b5861fc3e9c 100644 --- a/Lib/test/test_signal.py +++ b/Lib/test/test_signal.py @@ -1,4 +1,5 @@ import errno +import inspect import os import random import signal @@ -33,6 +34,14 @@ def test_enums(self): self.assertIsInstance(sig, signal.Signals) self.assertEqual(sys.platform, "win32") + def test_functions_module_attr(self): + # Issue #27718: If __all__ is not defined all non-builtin functions + # should have correct __module__ to be displayed by pydoc. + for name in dir(signal): + value = getattr(signal, name) + if inspect.isroutine(value) and not inspect.isbuiltin(value): + self.assertEqual(value.__module__, 'signal') + @unittest.skipIf(sys.platform == "win32", "Not valid on Windows") class PosixTests(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Library/2021-12-11-22-51-30.bpo-27718.MgQiGl.rst b/Misc/NEWS.d/next/Library/2021-12-11-22-51-30.bpo-27718.MgQiGl.rst new file mode 100644 index 0000000000000..c68e98ff0630b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-11-22-51-30.bpo-27718.MgQiGl.rst @@ -0,0 +1,2 @@ +Fix help for the :mod:`signal` module. Some functions (e.g. ``signal()`` and +``getsignal()``) were omitted. From webhook-mailer at python.org Mon Dec 13 05:43:40 2021 From: webhook-mailer at python.org (miss-islington) Date: Mon, 13 Dec 2021 10:43:40 -0000 Subject: [Python-checkins] [3.10] bpo-27718: Fix help for the signal module (GH-30063) (GH-30080) Message-ID: https://github.com/python/cpython/commit/80f98b1614cc8e58d8a5ec72c94d27f663e23035 commit: 80f98b1614cc8e58d8a5ec72c94d27f663e23035 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-13T02:43:13-08:00 summary: [3.10] bpo-27718: Fix help for the signal module (GH-30063) (GH-30080) Functions signal(), getsignal(), pthread_sigmask(), sigpending(), sigwait() and valid_signals() were omitted. If __all__ is not defined all non-builtin functions should have correct __module__. (cherry picked from commit e08c0d8eec528f1d7a282ee19bcadb9aae9ec123) (cherry picked from commit e55deaabd8de338138cf29aea6890996e794c997) Co-authored-by: Serhiy Storchaka files: A Misc/NEWS.d/next/Library/2021-12-11-22-51-30.bpo-27718.MgQiGl.rst M Lib/signal.py M Lib/test/test_signal.py diff --git a/Lib/signal.py b/Lib/signal.py index d4a6d6fe2ada8..50b215b29d2fa 100644 --- a/Lib/signal.py +++ b/Lib/signal.py @@ -1,6 +1,5 @@ import _signal from _signal import * -from functools import wraps as _wraps from enum import IntEnum as _IntEnum _globals = globals() @@ -42,6 +41,16 @@ def _enum_to_int(value): return value +# Similar to functools.wraps(), but only assign __doc__. +# __module__ should be preserved, +# __name__ and __qualname__ are already fine, +# __annotations__ is not set. +def _wraps(wrapped): + def decorator(wrapper): + wrapper.__doc__ = wrapped.__doc__ + return wrapper + return decorator + @_wraps(_signal.signal) def signal(signalnum, handler): handler = _signal.signal(_enum_to_int(signalnum), _enum_to_int(handler)) @@ -59,7 +68,6 @@ def getsignal(signalnum): def pthread_sigmask(how, mask): sigs_set = _signal.pthread_sigmask(how, mask) return set(_int_to_enum(x, Signals) for x in sigs_set) - pthread_sigmask.__doc__ = _signal.pthread_sigmask.__doc__ if 'sigpending' in _globals: @@ -73,7 +81,6 @@ def sigpending(): def sigwait(sigset): retsig = _signal.sigwait(sigset) return _int_to_enum(retsig, Signals) - sigwait.__doc__ = _signal.sigwait if 'valid_signals' in _globals: diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py index f18e72f6fc96b..f91d33271dbb4 100644 --- a/Lib/test/test_signal.py +++ b/Lib/test/test_signal.py @@ -1,4 +1,5 @@ import errno +import inspect import os import random import signal @@ -32,6 +33,14 @@ def test_enums(self): self.assertIsInstance(sig, signal.Signals) self.assertEqual(sys.platform, "win32") + def test_functions_module_attr(self): + # Issue #27718: If __all__ is not defined all non-builtin functions + # should have correct __module__ to be displayed by pydoc. + for name in dir(signal): + value = getattr(signal, name) + if inspect.isroutine(value) and not inspect.isbuiltin(value): + self.assertEqual(value.__module__, 'signal') + @unittest.skipIf(sys.platform == "win32", "Not valid on Windows") class PosixTests(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Library/2021-12-11-22-51-30.bpo-27718.MgQiGl.rst b/Misc/NEWS.d/next/Library/2021-12-11-22-51-30.bpo-27718.MgQiGl.rst new file mode 100644 index 0000000000000..c68e98ff0630b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-11-22-51-30.bpo-27718.MgQiGl.rst @@ -0,0 +1,2 @@ +Fix help for the :mod:`signal` module. Some functions (e.g. ``signal()`` and +``getsignal()``) were omitted. From webhook-mailer at python.org Mon Dec 13 05:46:00 2021 From: webhook-mailer at python.org (iritkatriel) Date: Mon, 13 Dec 2021 10:46:00 -0000 Subject: [Python-checkins] bpo-37602: Clarify that the lib2to3 nonzero fixer changes only definitions (GH-30075) (GH-30083) Message-ID: https://github.com/python/cpython/commit/80eb8ab81fbe46497f16071b311c9d8e13ec2d3b commit: 80eb8ab81fbe46497f16071b311c9d8e13ec2d3b branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-12-13T10:45:55Z summary: bpo-37602: Clarify that the lib2to3 nonzero fixer changes only definitions (GH-30075) (GH-30083) (cherry picked from commit 481f3ffdbe40bd19677a1ba0ac2e7cece8949b47) Co-authored-by: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> files: M Doc/library/2to3.rst diff --git a/Doc/library/2to3.rst b/Doc/library/2to3.rst index 1d7bd26287290..36c051db50dca 100644 --- a/Doc/library/2to3.rst +++ b/Doc/library/2to3.rst @@ -333,7 +333,8 @@ and off individually. They are described here in more detail. .. 2to3fixer:: nonzero - Renames :meth:`__nonzero__` to :meth:`~object.__bool__`. + Renames definitions of methods called :meth:`__nonzero__` + to :meth:`~object.__bool__`. .. 2to3fixer:: numliterals From webhook-mailer at python.org Mon Dec 13 05:47:43 2021 From: webhook-mailer at python.org (iritkatriel) Date: Mon, 13 Dec 2021 10:47:43 -0000 Subject: [Python-checkins] [3.10] bpo-37602: Clarify that the lib2to3 nonzero fixer changes only definitions (GH-30075) (GH-30085) Message-ID: https://github.com/python/cpython/commit/310bae628a9b065d29dbdbf4f7f5beb9fcc72ace commit: 310bae628a9b065d29dbdbf4f7f5beb9fcc72ace branch: 3.10 author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-12-13T10:47:38Z summary: [3.10] bpo-37602: Clarify that the lib2to3 nonzero fixer changes only definitions (GH-30075) (GH-30085) (cherry picked from commit 481f3ffdbe40bd19677a1ba0ac2e7cece8949b47) Co-authored-by: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> files: M Doc/library/2to3.rst diff --git a/Doc/library/2to3.rst b/Doc/library/2to3.rst index 2a13776e29336..5e1b010e9bb5f 100644 --- a/Doc/library/2to3.rst +++ b/Doc/library/2to3.rst @@ -333,7 +333,8 @@ and off individually. They are described here in more detail. .. 2to3fixer:: nonzero - Renames :meth:`__nonzero__` to :meth:`~object.__bool__`. + Renames definitions of methods called :meth:`__nonzero__` + to :meth:`~object.__bool__`. .. 2to3fixer:: numliterals From webhook-mailer at python.org Mon Dec 13 07:14:37 2021 From: webhook-mailer at python.org (asvetlov) Date: Mon, 13 Dec 2021 12:14:37 -0000 Subject: [Python-checkins] bpo-16594: Add allow_reuse_port on socketserver (GH-30072) Message-ID: https://github.com/python/cpython/commit/b56774bd93822e1598bb5d6c1d0b1fe8c45a750d commit: b56774bd93822e1598bb5d6c1d0b1fe8c45a750d branch: main author: AN Long committer: asvetlov date: 2021-12-13T14:14:17+02:00 summary: bpo-16594: Add allow_reuse_port on socketserver (GH-30072) * bpo-16594: Add allow_reuse_port on socketserver * ?? Added by blurb_it. Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> files: A Misc/NEWS.d/next/Library/2021-12-12-13-41-47.bpo-16594.yfC7L4.rst M Lib/socketserver.py diff --git a/Lib/socketserver.py b/Lib/socketserver.py index 0d9583d56a4d7..5e070bc3912af 100644 --- a/Lib/socketserver.py +++ b/Lib/socketserver.py @@ -187,6 +187,7 @@ class BaseServer: - address_family - socket_type - allow_reuse_address + - allow_reuse_port Instance variables: @@ -425,6 +426,7 @@ class TCPServer(BaseServer): - socket_type - request_queue_size (only for stream sockets) - allow_reuse_address + - allow_reuse_port Instance variables: @@ -442,6 +444,8 @@ class TCPServer(BaseServer): allow_reuse_address = False + allow_reuse_port = False + def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True): """Constructor. May be extended, do not override.""" BaseServer.__init__(self, server_address, RequestHandlerClass) @@ -463,6 +467,8 @@ def server_bind(self): """ if self.allow_reuse_address: self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + if self.allow_reuse_port: + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) self.socket.bind(self.server_address) self.server_address = self.socket.getsockname() @@ -519,6 +525,8 @@ class UDPServer(TCPServer): allow_reuse_address = False + allow_reuse_port = False + socket_type = socket.SOCK_DGRAM max_packet_size = 8192 diff --git a/Misc/NEWS.d/next/Library/2021-12-12-13-41-47.bpo-16594.yfC7L4.rst b/Misc/NEWS.d/next/Library/2021-12-12-13-41-47.bpo-16594.yfC7L4.rst new file mode 100644 index 0000000000000..a977a6b21dd64 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-12-13-41-47.bpo-16594.yfC7L4.rst @@ -0,0 +1 @@ +Add allow allow_reuse_port flag in socketserver. \ No newline at end of file From webhook-mailer at python.org Mon Dec 13 07:19:13 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Mon, 13 Dec 2021 12:19:13 -0000 Subject: [Python-checkins] [3.9] bpo-45840: Improve cross-references in the data model documentation (GH-29633) (GH-30081) Message-ID: https://github.com/python/cpython/commit/2029c58097e49b5aedc152ab65958a9db35ebd1e commit: 2029c58097e49b5aedc152ab65958a9db35ebd1e branch: 3.9 author: Alex Waygood committer: serhiy-storchaka date: 2021-12-13T14:19:08+02:00 summary: [3.9] bpo-45840: Improve cross-references in the data model documentation (GH-29633) (GH-30081) Backport of GH-29633 to the 3.9 branch files: A Misc/NEWS.d/next/Documentation/2021-11-19-02-02-32.bpo-45840.A51B2S.rst M Doc/reference/datamodel.rst diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index a34ec45bf4adc..1f0fc17ad360e 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -188,7 +188,7 @@ Ellipsis representation in computers. The string representations of the numeric classes, computed by - :meth:`__repr__` and :meth:`__str__`, have the following + :meth:`~object.__repr__` and :meth:`~object.__str__`, have the following properties: * They are valid numeric literals which, when passed to their @@ -674,7 +674,8 @@ Callable types returns an asynchronous iterator object which can be used in an :keyword:`async for` statement to execute the body of the function. - Calling the asynchronous iterator's :meth:`aiterator.__anext__` method + Calling the asynchronous iterator's + :meth:`aiterator.__anext__ ` method will return an :term:`awaitable` which when awaited will execute until it provides a value using the :keyword:`yield` expression. When the function executes an empty :keyword:`return` @@ -712,13 +713,13 @@ Callable types Classes Classes are callable. These objects normally act as factories for new instances of themselves, but variations are possible for class types that - override :meth:`__new__`. The arguments of the call are passed to - :meth:`__new__` and, in the typical case, to :meth:`__init__` to + override :meth:`~object.__new__`. The arguments of the call are passed to + :meth:`__new__` and, in the typical case, to :meth:`~object.__init__` to initialize the new instance. Class Instances Instances of arbitrary classes can be made callable by defining a - :meth:`__call__` method in their class. + :meth:`~object.__call__` method in their class. Modules @@ -848,14 +849,14 @@ Class instances section :ref:`descriptors` for another way in which attributes of a class retrieved via its instances may differ from the objects actually stored in the class's :attr:`~object.__dict__`. If no class attribute is found, and the - object's class has a :meth:`__getattr__` method, that is called to satisfy + object's class has a :meth:`~object.__getattr__` method, that is called to satisfy the lookup. .. index:: triple: class instance; attribute; assignment Attribute assignments and deletions update the instance's dictionary, never a - class's dictionary. If the class has a :meth:`__setattr__` or - :meth:`__delattr__` method, this is called instead of updating the instance + class's dictionary. If the class has a :meth:`~object.__setattr__` or + :meth:`~object.__delattr__` method, this is called instead of updating the instance dictionary directly. .. index:: @@ -1109,7 +1110,8 @@ Internal types Slice objects .. index:: builtin: slice - Slice objects are used to represent slices for :meth:`__getitem__` + Slice objects are used to represent slices for + :meth:`~object.__getitem__` methods. They are also created by the built-in :func:`slice` function. .. index:: @@ -1163,7 +1165,8 @@ A class can implement certain operations that are invoked by special syntax (such as arithmetic operations or subscripting and slicing) by defining methods with special names. This is Python's approach to :dfn:`operator overloading`, allowing classes to define their own behavior with respect to language -operators. For instance, if a class defines a method named :meth:`__getitem__`, +operators. For instance, if a class defines a method named +:meth:`~object.__getitem__`, and ``x`` is an instance of this class, then ``x[i]`` is roughly equivalent to ``type(x).__getitem__(x, i)``. Except where mentioned, attempts to execute an operation raise an exception when no appropriate method is defined (typically @@ -1171,9 +1174,9 @@ operation raise an exception when no appropriate method is defined (typically Setting a special method to ``None`` indicates that the corresponding operation is not available. For example, if a class sets -:meth:`__iter__` to ``None``, the class is not iterable, so calling +:meth:`~object.__iter__` to ``None``, the class is not iterable, so calling :func:`iter` on its instances will raise a :exc:`TypeError` (without -falling back to :meth:`__getitem__`). [#]_ +falling back to :meth:`~object.__getitem__`). [#]_ When implementing a class that emulates any built-in type, it is important that the emulation only be implemented to the degree that it makes sense for the @@ -1745,7 +1748,8 @@ Invoking Descriptors In general, a descriptor is an object attribute with "binding behavior", one whose attribute access has been overridden by methods in the descriptor -protocol: :meth:`__get__`, :meth:`__set__`, and :meth:`__delete__`. If any of +protocol: :meth:`~object.__get__`, :meth:`~object.__set__`, and +:meth:`~object.__delete__`. If any of those methods are defined for an object, it is said to be a descriptor. The default behavior for attribute access is to get, set, or delete the @@ -1781,7 +1785,8 @@ Super Binding For instance bindings, the precedence of descriptor invocation depends on which descriptor methods are defined. A descriptor can define any combination -of :meth:`__get__`, :meth:`__set__` and :meth:`__delete__`. If it does not +of :meth:`~object.__get__`, :meth:`~object.__set__` and +:meth:`~object.__delete__`. If it does not define :meth:`__get__`, then accessing the attribute will return the descriptor object itself unless there is a value in the object's instance dictionary. If the descriptor defines :meth:`__set__` and/or :meth:`__delete__`, it is a data @@ -1792,7 +1797,8 @@ descriptors have just the :meth:`__get__` method. Data descriptors with instance dictionary. In contrast, non-data descriptors can be overridden by instances. -Python methods (including :func:`staticmethod` and :func:`classmethod`) are +Python methods (including those decorated with +:func:`@staticmethod ` and :func:`@classmethod `) are implemented as non-data descriptors. Accordingly, instances can redefine and override methods. This allows individual instances to acquire behaviors that differ from other instances of the same class. @@ -1807,46 +1813,50 @@ __slots__ ^^^^^^^^^ *__slots__* allow us to explicitly declare data members (like -properties) and deny the creation of *__dict__* and *__weakref__* +properties) and deny the creation of :attr:`~object.__dict__` and *__weakref__* (unless explicitly declared in *__slots__* or available in a parent.) -The space saved over using *__dict__* can be significant. +The space saved over using :attr:`~object.__dict__` can be significant. Attribute lookup speed can be significantly improved as well. .. data:: object.__slots__ This class variable can be assigned a string, iterable, or sequence of strings with variable names used by instances. *__slots__* reserves space - for the declared variables and prevents the automatic creation of *__dict__* + for the declared variables and prevents the automatic creation of + :attr:`~object.__dict__` and *__weakref__* for each instance. Notes on using *__slots__* """""""""""""""""""""""""" -* When inheriting from a class without *__slots__*, the *__dict__* and +* When inheriting from a class without *__slots__*, the + :attr:`~object.__dict__` and *__weakref__* attribute of the instances will always be accessible. -* Without a *__dict__* variable, instances cannot be assigned new variables not +* Without a :attr:`~object.__dict__` variable, instances cannot be assigned new + variables not listed in the *__slots__* definition. Attempts to assign to an unlisted variable name raises :exc:`AttributeError`. If dynamic assignment of new variables is desired, then add ``'__dict__'`` to the sequence of strings in the *__slots__* declaration. * Without a *__weakref__* variable for each instance, classes defining - *__slots__* do not support weak references to its instances. If weak reference + *__slots__* do not support :mod:`weak references ` to its instances. + If weak reference support is needed, then add ``'__weakref__'`` to the sequence of strings in the *__slots__* declaration. -* *__slots__* are implemented at the class level by creating descriptors - (:ref:`descriptors`) for each variable name. As a result, class attributes +* *__slots__* are implemented at the class level by creating :ref:`descriptors ` + for each variable name. As a result, class attributes cannot be used to set default values for instance variables defined by *__slots__*; otherwise, the class attribute would overwrite the descriptor assignment. * The action of a *__slots__* declaration is not limited to the class where it is defined. *__slots__* declared in parents are available in - child classes. However, child subclasses will get a *__dict__* and + child classes. However, child subclasses will get a :attr:`~object.__dict__` and *__weakref__* unless they also define *__slots__* (which should only contain names of any *additional* slots). @@ -1862,14 +1872,17 @@ Notes on using *__slots__* used; however, in the future, special meaning may be assigned to the values corresponding to each key. -* *__class__* assignment works only if both classes have the same *__slots__*. +* :attr:`~instance.__class__` assignment works only if both classes have the + same *__slots__*. -* Multiple inheritance with multiple slotted parent classes can be used, +* :ref:`Multiple inheritance ` with multiple slotted parent + classes can be used, but only one parent is allowed to have attributes created by slots (the other bases must have empty slot layouts) - violations raise :exc:`TypeError`. -* If an iterator is used for *__slots__* then a descriptor is created for each +* If an :term:`iterator` is used for *__slots__* then a :term:`descriptor` is + created for each of the iterator's values. However, the *__slots__* attribute will be an empty iterator. @@ -1878,7 +1891,7 @@ Notes on using *__slots__* Customizing class creation -------------------------- -Whenever a class inherits from another class, *__init_subclass__* is +Whenever a class inherits from another class, :meth:`~object.__init_subclass__` is called on that class. This way, it is possible to write classes which change the behavior of subclasses. This is closely related to class decorators, but where class decorators only affect the specific class they're @@ -2004,7 +2017,8 @@ Once the appropriate metaclass has been identified, then the class namespace is prepared. If the metaclass has a ``__prepare__`` attribute, it is called as ``namespace = metaclass.__prepare__(name, bases, **kwds)`` (where the additional keyword arguments, if any, come from the class definition). The -``__prepare__`` method should be implemented as a :func:`classmethod`. The +``__prepare__`` method should be implemented as a +:func:`classmethod `. The namespace returned by ``__prepare__`` is passed in to ``__new__``, but when the final class object is created the namespace is copied into a new ``dict``. @@ -2302,31 +2316,36 @@ Emulating container types ------------------------- The following methods can be defined to implement container objects. Containers -usually are sequences (such as lists or tuples) or mappings (like dictionaries), +usually are :term:`sequences ` (such as :class:`lists ` or +:class:`tuples `) or :term:`mappings ` (like +:class:`dictionaries `), but can represent other containers as well. The first set of methods is used either to emulate a sequence or to emulate a mapping; the difference is that for a sequence, the allowable keys should be the integers *k* for which ``0 <= k < -N`` where *N* is the length of the sequence, or slice objects, which define a +N`` where *N* is the length of the sequence, or :class:`slice` objects, which define a range of items. It is also recommended that mappings provide the methods :meth:`keys`, :meth:`values`, :meth:`items`, :meth:`get`, :meth:`clear`, :meth:`setdefault`, :meth:`pop`, :meth:`popitem`, :meth:`!copy`, and -:meth:`update` behaving similar to those for Python's standard dictionary +:meth:`update` behaving similar to those for Python's standard :class:`dictionary ` objects. The :mod:`collections.abc` module provides a :class:`~collections.abc.MutableMapping` -abstract base class to help create those methods from a base set of -:meth:`__getitem__`, :meth:`__setitem__`, :meth:`__delitem__`, and :meth:`keys`. +:term:`abstract base class` to help create those methods from a base set of +:meth:`~object.__getitem__`, :meth:`~object.__setitem__`, :meth:`~object.__delitem__`, and :meth:`keys`. Mutable sequences should provide methods :meth:`append`, :meth:`count`, :meth:`index`, :meth:`extend`, :meth:`insert`, :meth:`pop`, :meth:`remove`, -:meth:`reverse` and :meth:`sort`, like Python standard list objects. Finally, +:meth:`reverse` and :meth:`sort`, like Python standard :class:`list` +objects. Finally, sequence types should implement addition (meaning concatenation) and -multiplication (meaning repetition) by defining the methods :meth:`__add__`, -:meth:`__radd__`, :meth:`__iadd__`, :meth:`__mul__`, :meth:`__rmul__` and -:meth:`__imul__` described below; they should not define other numerical +multiplication (meaning repetition) by defining the methods +:meth:`~object.__add__`, :meth:`~object.__radd__`, :meth:`~object.__iadd__`, +:meth:`~object.__mul__`, :meth:`~object.__rmul__` and :meth:`~object.__imul__` +described below; they should not define other numerical operators. It is recommended that both mappings and sequences implement the -:meth:`__contains__` method to allow efficient use of the ``in`` operator; for +:meth:`~object.__contains__` method to allow efficient use of the ``in`` +operator; for mappings, ``in`` should search the mapping's keys; for sequences, it should search through the values. It is further recommended that both mappings and -sequences implement the :meth:`__iter__` method to allow efficient iteration +sequences implement the :meth:`~object.__iter__` method to allow efficient iteration through the container; for mappings, :meth:`__iter__` should iterate through the object's keys; for sequences, it should iterate through the values. @@ -2715,7 +2734,8 @@ exception:: TypeError: object of type 'C' has no len() The rationale behind this behaviour lies with a number of special methods such -as :meth:`__hash__` and :meth:`__repr__` that are implemented by all objects, +as :meth:`~object.__hash__` and :meth:`~object.__repr__` that are implemented +by all objects, including type objects. If the implicit lookup of these methods used the conventional lookup process, they would fail when invoked on the type object itself:: @@ -2738,7 +2758,7 @@ the instance when looking up special methods:: In addition to bypassing any instance attributes in the interest of correctness, implicit special method lookup generally also bypasses the -:meth:`__getattribute__` method even of the object's metaclass:: +:meth:`~object.__getattribute__` method even of the object's metaclass:: >>> class Meta(type): ... def __getattribute__(*args): @@ -2762,7 +2782,7 @@ correctness, implicit special method lookup generally also bypasses the >>> len(c) # Implicit lookup 10 -Bypassing the :meth:`__getattribute__` machinery in this fashion +Bypassing the :meth:`~object.__getattribute__` machinery in this fashion provides significant scope for speed optimisations within the interpreter, at the cost of some flexibility in the handling of special methods (the special method *must* be set on the class @@ -2779,7 +2799,7 @@ Coroutines Awaitable Objects ----------------- -An :term:`awaitable` object generally implements an :meth:`__await__` method. +An :term:`awaitable` object generally implements an :meth:`~object.__await__` method. :term:`Coroutine objects ` returned from :keyword:`async def` functions are awaitable. @@ -2787,7 +2807,7 @@ are awaitable. The :term:`generator iterator` objects returned from generators decorated with :func:`types.coroutine` or :func:`asyncio.coroutine` - are also awaitable, but they do not implement :meth:`__await__`. + are also awaitable, but they do not implement :meth:`~object.__await__`. .. method:: object.__await__(self) @@ -2806,7 +2826,7 @@ Coroutine Objects ----------------- :term:`Coroutine objects ` are :term:`awaitable` objects. -A coroutine's execution can be controlled by calling :meth:`__await__` and +A coroutine's execution can be controlled by calling :meth:`~object.__await__` and iterating over the result. When the coroutine has finished executing and returns, the iterator raises :exc:`StopIteration`, and the exception's :attr:`~StopIteration.value` attribute holds the return value. If the @@ -2825,7 +2845,7 @@ generators, coroutines do not directly support iteration. Starts or resumes execution of the coroutine. If *value* is ``None``, this is equivalent to advancing the iterator returned by - :meth:`__await__`. If *value* is not ``None``, this method delegates + :meth:`~object.__await__`. If *value* is not ``None``, this method delegates to the :meth:`~generator.send` method of the iterator that caused the coroutine to suspend. The result (return value, :exc:`StopIteration`, or other exception) is the same as when @@ -2838,7 +2858,7 @@ generators, coroutines do not directly support iteration. the coroutine to suspend, if it has such a method. Otherwise, the exception is raised at the suspension point. The result (return value, :exc:`StopIteration`, or other exception) is the same as - when iterating over the :meth:`__await__` return value, described + when iterating over the :meth:`~object.__await__` return value, described above. If the exception is not caught in the coroutine, it propagates back to the caller. @@ -2892,11 +2912,11 @@ An example of an asynchronous iterable object:: .. versionadded:: 3.5 .. versionchanged:: 3.7 - Prior to Python 3.7, ``__aiter__`` could return an *awaitable* + Prior to Python 3.7, :meth:`~object.__aiter__` could return an *awaitable* that would resolve to an :term:`asynchronous iterator `. - Starting with Python 3.7, ``__aiter__`` must return an + Starting with Python 3.7, :meth:`~object.__aiter__` must return an asynchronous iterator object. Returning anything else will result in a :exc:`TypeError` error. @@ -2939,8 +2959,9 @@ An example of an asynchronous context manager class:: controlled conditions. It generally isn't a good idea though, since it can lead to some very strange behaviour if it is handled incorrectly. -.. [#] The :meth:`__hash__`, :meth:`__iter__`, :meth:`__reversed__`, and - :meth:`__contains__` methods have special handling for this; others +.. [#] The :meth:`~object.__hash__`, :meth:`~object.__iter__`, + :meth:`~object.__reversed__`, and :meth:`~object.__contains__` methods have + special handling for this; others will still raise a :exc:`TypeError`, but may do so by relying on the behavior that ``None`` is not callable. @@ -2951,5 +2972,6 @@ An example of an asynchronous context manager class:: *blocking* such fallback. .. [#] For operands of the same type, it is assumed that if the non-reflected - method -- such as :meth:`__add__` -- fails then the overall operation is not + method -- such as :meth:`~object.__add__` -- fails then the overall + operation is not supported, which is why the reflected method is not called. diff --git a/Misc/NEWS.d/next/Documentation/2021-11-19-02-02-32.bpo-45840.A51B2S.rst b/Misc/NEWS.d/next/Documentation/2021-11-19-02-02-32.bpo-45840.A51B2S.rst new file mode 100644 index 0000000000000..87371e5b76bc1 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-11-19-02-02-32.bpo-45840.A51B2S.rst @@ -0,0 +1 @@ +Improve cross-references in the documentation for the data model. From webhook-mailer at python.org Mon Dec 13 07:39:45 2021 From: webhook-mailer at python.org (asvetlov) Date: Mon, 13 Dec 2021 12:39:45 -0000 Subject: [Python-checkins] Clarify new_event_loop return value. (GH-30078) Message-ID: https://github.com/python/cpython/commit/e09705f58fc2ff3cc2720c6337ae3f48bb7cb090 commit: e09705f58fc2ff3cc2720c6337ae3f48bb7cb090 branch: main author: Paul Bryan committer: asvetlov date: 2021-12-13T14:39:22+02:00 summary: Clarify new_event_loop return value. (GH-30078) files: M Doc/library/asyncio-eventloop.rst diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index 497128ee17f37..a3609d3925833 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -64,7 +64,7 @@ an event loop: .. function:: new_event_loop() - Create a new event loop object. + Create and return a new event loop object. Note that the behaviour of :func:`get_event_loop`, :func:`set_event_loop`, and :func:`new_event_loop` functions can be altered by From webhook-mailer at python.org Mon Dec 13 07:58:04 2021 From: webhook-mailer at python.org (corona10) Date: Mon, 13 Dec 2021 12:58:04 -0000 Subject: [Python-checkins] bpo-45919: Use WinAPI GetFileType() in is_valid_fd() (GH-30082) Message-ID: https://github.com/python/cpython/commit/191c431de7d9b23484dd16f67e62c6e85a1fac7f commit: 191c431de7d9b23484dd16f67e62c6e85a1fac7f branch: main author: Dong-hee Na committer: corona10 date: 2021-12-13T21:57:59+09:00 summary: bpo-45919: Use WinAPI GetFileType() in is_valid_fd() (GH-30082) files: M Python/pylifecycle.c diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index b6d73a9ce2216..a9eb38775c42a 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -2182,23 +2182,21 @@ is_valid_fd(int fd) #if defined(F_GETFD) && ( \ defined(__linux__) || \ defined(__APPLE__) || \ - defined(MS_WINDOWS) || \ defined(__wasm__)) - int res; - _Py_BEGIN_SUPPRESS_IPH - res = fcntl(fd, F_GETFD); - _Py_END_SUPPRESS_IPH - return res >= 0; -#elif defined(__linux__) || defined(MS_WINDOWS) - int fd2; - _Py_BEGIN_SUPPRESS_IPH - fd2 = dup(fd); + return fcntl(fd, F_GETFD) >= 0; +#elif defined(__linux__) + int fd2 = dup(fd); if (fd2 >= 0) { close(fd2); } - _Py_END_SUPPRESS_IPH - return (fd2 >= 0); +#elif defined(MS_WINDOWS) + HANDLE hfile; + _Py_BEGIN_SUPPRESS_IPH + hfile = (HANDLE)_get_osfhandle(fd); + _Py_END_SUPPRESS_IPH + return (hfile != INVALID_HANDLE_VALUE + && GetFileType(hfile) != FILE_TYPE_UNKNOWN); #else struct stat st; return (fstat(fd, &st) == 0); From webhook-mailer at python.org Mon Dec 13 08:25:10 2021 From: webhook-mailer at python.org (asvetlov) Date: Mon, 13 Dec 2021 13:25:10 -0000 Subject: [Python-checkins] Clarify new_event_loop return value. (GH-30078) (GH-30088) Message-ID: https://github.com/python/cpython/commit/bcb5d66b8f9a35e7de8e285b980bb81ebbfdd400 commit: bcb5d66b8f9a35e7de8e285b980bb81ebbfdd400 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: asvetlov date: 2021-12-13T15:24:50+02:00 summary: Clarify new_event_loop return value. (GH-30078) (GH-30088) (cherry picked from commit e09705f58fc2ff3cc2720c6337ae3f48bb7cb090) Co-authored-by: Paul Bryan files: M Doc/library/asyncio-eventloop.rst diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index 252fb426e5b39..b1700c996928b 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -64,7 +64,7 @@ an event loop: .. function:: new_event_loop() - Create a new event loop object. + Create and return a new event loop object. Note that the behaviour of :func:`get_event_loop`, :func:`set_event_loop`, and :func:`new_event_loop` functions can be altered by From webhook-mailer at python.org Mon Dec 13 08:25:59 2021 From: webhook-mailer at python.org (asvetlov) Date: Mon, 13 Dec 2021 13:25:59 -0000 Subject: [Python-checkins] Clarify new_event_loop return value. (GH-30078) (GH-30089) Message-ID: https://github.com/python/cpython/commit/9b687596df80e4cd40a13b2486cc12fcef903257 commit: 9b687596df80e4cd40a13b2486cc12fcef903257 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: asvetlov date: 2021-12-13T15:25:54+02:00 summary: Clarify new_event_loop return value. (GH-30078) (GH-30089) (cherry picked from commit e09705f58fc2ff3cc2720c6337ae3f48bb7cb090) Co-authored-by: Paul Bryan files: M Doc/library/asyncio-eventloop.rst diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index 73799d005c157..140851ce2e448 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -59,7 +59,7 @@ an event loop: .. function:: new_event_loop() - Create a new event loop object. + Create and return a new event loop object. Note that the behaviour of :func:`get_event_loop`, :func:`set_event_loop`, and :func:`new_event_loop` functions can be altered by From webhook-mailer at python.org Mon Dec 13 12:23:08 2021 From: webhook-mailer at python.org (vstinner) Date: Mon, 13 Dec 2021 17:23:08 -0000 Subject: [Python-checkins] bpo-45643: Add signal.SIGSTKFLT on platforms where this is defined (GH-29266) Message-ID: https://github.com/python/cpython/commit/a62be77266b1beadd42d4952186332bc0847b7d6 commit: a62be77266b1beadd42d4952186332bc0847b7d6 branch: main author: Gareth Rees committer: vstinner date: 2021-12-13T18:22:43+01:00 summary: bpo-45643: Add signal.SIGSTKFLT on platforms where this is defined (GH-29266) files: A Misc/NEWS.d/next/Library/2021-10-28-11-40-59.bpo-45643.jeiPiX.rst M Doc/library/signal.rst M Modules/signalmodule.c diff --git a/Doc/library/signal.rst b/Doc/library/signal.rst index 63821866a012b..abc30362da9e2 100644 --- a/Doc/library/signal.rst +++ b/Doc/library/signal.rst @@ -197,6 +197,16 @@ The variables defined in the :mod:`signal` module are: Segmentation fault: invalid memory reference. +.. data:: SIGSTKFLT + + Stack fault on coprocessor. The Linux kernel does not raise this signal: it + can only be raised in user space. + + .. availability:: Linux, on architectures where the signal is available. See + the man page :manpage:`signal(7)` for further information. + + .. versionadded:: 3.11 + .. data:: SIGTERM Termination signal. diff --git a/Misc/NEWS.d/next/Library/2021-10-28-11-40-59.bpo-45643.jeiPiX.rst b/Misc/NEWS.d/next/Library/2021-10-28-11-40-59.bpo-45643.jeiPiX.rst new file mode 100644 index 0000000000000..e1592ed53ab25 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-10-28-11-40-59.bpo-45643.jeiPiX.rst @@ -0,0 +1 @@ +Added :data:`signal.SIGSTKFLT` on platforms where this signal is defined. diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index 2013f16ed440e..9316a9eed7684 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -1554,6 +1554,9 @@ signal_add_constants(PyObject *module) #ifdef SIGINFO ADD_INT_MACRO(SIGINFO); #endif +#ifdef SIGSTKFLT + ADD_INT_MACRO(SIGSTKFLT); +#endif // ITIMER_xxx constants #ifdef ITIMER_REAL From webhook-mailer at python.org Mon Dec 13 14:48:55 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 13 Dec 2021 19:48:55 -0000 Subject: [Python-checkins] bpo-45949: Pure Python freeze module for cross builds (GH-29899) Message-ID: https://github.com/python/cpython/commit/eb483c46d62707bdf705491f76cf1fa9642fb47e commit: eb483c46d62707bdf705491f76cf1fa9642fb47e branch: main author: Christian Heimes committer: tiran date: 2021-12-13T20:48:46+01:00 summary: bpo-45949: Pure Python freeze module for cross builds (GH-29899) files: A Misc/NEWS.d/next/Build/2021-12-02-23-21-18.bpo-45949.OTSo9X.rst A Programs/_freeze_module.py M Doc/using/configure.rst M Makefile.pre.in M Programs/_freeze_module.c M Tools/scripts/deepfreeze.py M Tools/scripts/freeze_modules.py M configure M configure.ac diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index 7802a7c810b29..b2a2936db738b 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -518,9 +518,8 @@ Cross Compiling Options Cross compiling, also known as cross building, can be used to build Python for another CPU architecture or platform. Cross compiling requires a Python -interpreter and the :program:`_freeze_module` binary from another build. The -version of the build Python and :program:`_freeze_module` command must be -the same as the cross compiled host Python. +interpreter for the build platform. The version of the build Python must match +the version of the cross compiled host Python. .. cmdoption:: --build=BUILD @@ -530,13 +529,7 @@ the same as the cross compiled host Python. cross-compile to build programs to run on HOST (target platform) -.. cmdoption:: --with-freeze-module=Programs/_freeze_module - - path to ``_freeze_module`` binary for cross compiling. - - .. versionadded:: 3.11 - -.. cmdoption:: --with-build-python=python3.xx +.. cmdoption:: --with-build-python=path/to/python path to build ``python`` binary for cross compiling @@ -559,7 +552,6 @@ Cross compiling example:: CONFIG_SITE=config.site-aarch64 ../configure \ --build=x86_64-pc-linux-gnu \ --host=aarch64-unknown-linux-gnu \ - --with-freeze-module=../x86_64/Programs/_freeze_module \ --with-build-python=../x86_64/python diff --git a/Makefile.pre.in b/Makefile.pre.in index a182786e5b587..fb114979a5dff 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -283,14 +283,19 @@ BUILDPYTHON= python$(BUILDEXE) PYTHON_FOR_REGEN?=@PYTHON_FOR_REGEN@ UPDATE_FILE=$(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/update_file.py PYTHON_FOR_BUILD=@PYTHON_FOR_BUILD@ -# Standard builds use _bootstrap_python for freezing, cross compiling -# uses build Python, which must have the same version and bytecode, -PYTHON_FOR_FREEZE?=@PYTHON_FOR_FREEZE@ + +# Normal builds use Programs/_freeze_module.c for bootstrapping and +# ./_bootstrap_python Programs/_freeze_module.py for remaining modules +# Cross builds use an external "build Python" for all modules. +PYTHON_FOR_FREEZE=@PYTHON_FOR_FREEZE@ +FREEZE_MODULE_BOOTSTRAP=@FREEZE_MODULE_BOOTSTRAP@ +FREEZE_MODULE_BOOTSTRAP_DEPS=@FREEZE_MODULE_BOOTSTRAP_DEPS@ +FREEZE_MODULE=@FREEZE_MODULE@ +FREEZE_MODULE_DEPS=@FREEZE_MODULE_DEPS@ + _PYTHON_HOST_PLATFORM=@_PYTHON_HOST_PLATFORM@ BUILD_GNU_TYPE= @build@ HOST_GNU_TYPE= @host@ -# Allow developers to override freeze_module command for cross building (bpo-45886) -FREEZE_MODULE?=@FREEZE_MODULE@ # Tcl and Tk config info from --with-tcltk-includes and -libs options TCLTK_INCLUDES= @TCLTK_INCLUDES@ @@ -967,7 +972,7 @@ _bootstrap_python: $(LIBRARY_OBJS_OMIT_FROZEN) Programs/_bootstrap_python.o Modu .PHONY: regen-deepfreeze regen-deepfreeze: $(DEEPFREEZE_OBJS) -DEEPFREEZE_DEPS=$(srcdir)/Tools/scripts/deepfreeze.py _bootstrap_python +DEEPFREEZE_DEPS=$(srcdir)/Tools/scripts/deepfreeze.py $(FREEZE_MODULE_DEPS) # BEGIN: deepfreeze modules @@ -1044,6 +1049,30 @@ Python/deepfreeze/frozen_only.c: Python/frozen_modules/frozen_only.h $(DEEPFREEZ ############################################################################ # frozen modules (including importlib) +# +# Freezing is a multi step process. It works differently for standard builds +# and cross builds. Standard builds use Programs/_freeze_module and +# _bootstrap_python for freezing and deepfreezing, so users can build Python +# without an existing Python installation. Cross builds cannot execute +# compiled binaries and therefore rely on an external build Python +# interpreter. The build interpreter must have same version and same bytecode +# as the host (target) binary. +# +# Standard build process: +# 1) compile minimal core objects for Py_Compile*() and PyMarshal_Write*(). +# 2) build Programs/_freeze_module binary. +# 3) create frozen module headers for importlib and getpath. +# 4) build _bootstrap_python binary. +# 5) create remaining frozen module headers with +# ``./_bootstrap_python Programs/_freeze_module.py``. The pure Python +# script is used to test the cross compile code path. +# 6) deepfreeze modules with _bootstrap_python +# +# Cross compile process: +# 1) create all frozen module headers with external build Python and +# Programs/_freeze_module.py script. +# 2) deepfreeze modules with external build Python. +# # FROZEN_FILES_* are auto-generated by Tools/scripts/freeze_modules.py. FROZEN_FILES_IN = \ @@ -1104,83 +1133,83 @@ Modules/getpath_noop.o: $(srcdir)/Modules/getpath_noop.c Makefile Programs/_freeze_module: Programs/_freeze_module.o Modules/getpath_noop.o $(LIBRARY_OBJS_OMIT_FROZEN) $(LINKCC) $(PY_CORE_LDFLAGS) -o $@ Programs/_freeze_module.o Modules/getpath_noop.o $(LIBRARY_OBJS_OMIT_FROZEN) $(LIBS) $(MODLIBS) $(SYSLIBS) +# We manually freeze getpath.py rather than through freeze_modules +Python/frozen_modules/getpath.h: Modules/getpath.py $(FREEZE_MODULE_BOOTSTRAP_DEPS) + $(FREEZE_MODULE_BOOTSTRAP) getpath $(srcdir)/Modules/getpath.py Python/frozen_modules/getpath.h + # BEGIN: freezing modules -Python/frozen_modules/importlib._bootstrap.h: $(FREEZE_MODULE) Lib/importlib/_bootstrap.py - $(FREEZE_MODULE) importlib._bootstrap $(srcdir)/Lib/importlib/_bootstrap.py Python/frozen_modules/importlib._bootstrap.h +Python/frozen_modules/importlib._bootstrap.h: Lib/importlib/_bootstrap.py $(FREEZE_MODULE_BOOTSTRAP_DEPS) + $(FREEZE_MODULE_BOOTSTRAP) importlib._bootstrap $(srcdir)/Lib/importlib/_bootstrap.py Python/frozen_modules/importlib._bootstrap.h -Python/frozen_modules/importlib._bootstrap_external.h: $(FREEZE_MODULE) Lib/importlib/_bootstrap_external.py - $(FREEZE_MODULE) importlib._bootstrap_external $(srcdir)/Lib/importlib/_bootstrap_external.py Python/frozen_modules/importlib._bootstrap_external.h +Python/frozen_modules/importlib._bootstrap_external.h: Lib/importlib/_bootstrap_external.py $(FREEZE_MODULE_BOOTSTRAP_DEPS) + $(FREEZE_MODULE_BOOTSTRAP) importlib._bootstrap_external $(srcdir)/Lib/importlib/_bootstrap_external.py Python/frozen_modules/importlib._bootstrap_external.h -Python/frozen_modules/zipimport.h: $(FREEZE_MODULE) Lib/zipimport.py - $(FREEZE_MODULE) zipimport $(srcdir)/Lib/zipimport.py Python/frozen_modules/zipimport.h +Python/frozen_modules/zipimport.h: Lib/zipimport.py $(FREEZE_MODULE_BOOTSTRAP_DEPS) + $(FREEZE_MODULE_BOOTSTRAP) zipimport $(srcdir)/Lib/zipimport.py Python/frozen_modules/zipimport.h -Python/frozen_modules/abc.h: $(FREEZE_MODULE) Lib/abc.py +Python/frozen_modules/abc.h: Lib/abc.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) abc $(srcdir)/Lib/abc.py Python/frozen_modules/abc.h -Python/frozen_modules/codecs.h: $(FREEZE_MODULE) Lib/codecs.py +Python/frozen_modules/codecs.h: Lib/codecs.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) codecs $(srcdir)/Lib/codecs.py Python/frozen_modules/codecs.h -Python/frozen_modules/io.h: $(FREEZE_MODULE) Lib/io.py +Python/frozen_modules/io.h: Lib/io.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) io $(srcdir)/Lib/io.py Python/frozen_modules/io.h -Python/frozen_modules/_collections_abc.h: $(FREEZE_MODULE) Lib/_collections_abc.py +Python/frozen_modules/_collections_abc.h: Lib/_collections_abc.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) _collections_abc $(srcdir)/Lib/_collections_abc.py Python/frozen_modules/_collections_abc.h -Python/frozen_modules/_sitebuiltins.h: $(FREEZE_MODULE) Lib/_sitebuiltins.py +Python/frozen_modules/_sitebuiltins.h: Lib/_sitebuiltins.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) _sitebuiltins $(srcdir)/Lib/_sitebuiltins.py Python/frozen_modules/_sitebuiltins.h -Python/frozen_modules/genericpath.h: $(FREEZE_MODULE) Lib/genericpath.py +Python/frozen_modules/genericpath.h: Lib/genericpath.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) genericpath $(srcdir)/Lib/genericpath.py Python/frozen_modules/genericpath.h -Python/frozen_modules/ntpath.h: $(FREEZE_MODULE) Lib/ntpath.py +Python/frozen_modules/ntpath.h: Lib/ntpath.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) ntpath $(srcdir)/Lib/ntpath.py Python/frozen_modules/ntpath.h -Python/frozen_modules/posixpath.h: $(FREEZE_MODULE) Lib/posixpath.py +Python/frozen_modules/posixpath.h: Lib/posixpath.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) posixpath $(srcdir)/Lib/posixpath.py Python/frozen_modules/posixpath.h -Python/frozen_modules/os.h: $(FREEZE_MODULE) Lib/os.py +Python/frozen_modules/os.h: Lib/os.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) os $(srcdir)/Lib/os.py Python/frozen_modules/os.h -Python/frozen_modules/site.h: $(FREEZE_MODULE) Lib/site.py +Python/frozen_modules/site.h: Lib/site.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) site $(srcdir)/Lib/site.py Python/frozen_modules/site.h -Python/frozen_modules/stat.h: $(FREEZE_MODULE) Lib/stat.py +Python/frozen_modules/stat.h: Lib/stat.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) stat $(srcdir)/Lib/stat.py Python/frozen_modules/stat.h -Python/frozen_modules/importlib.util.h: $(FREEZE_MODULE) Lib/importlib/util.py +Python/frozen_modules/importlib.util.h: Lib/importlib/util.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) importlib.util $(srcdir)/Lib/importlib/util.py Python/frozen_modules/importlib.util.h -Python/frozen_modules/importlib.machinery.h: $(FREEZE_MODULE) Lib/importlib/machinery.py +Python/frozen_modules/importlib.machinery.h: Lib/importlib/machinery.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) importlib.machinery $(srcdir)/Lib/importlib/machinery.py Python/frozen_modules/importlib.machinery.h -Python/frozen_modules/runpy.h: $(FREEZE_MODULE) Lib/runpy.py +Python/frozen_modules/runpy.h: Lib/runpy.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) runpy $(srcdir)/Lib/runpy.py Python/frozen_modules/runpy.h -Python/frozen_modules/__hello__.h: $(FREEZE_MODULE) Lib/__hello__.py +Python/frozen_modules/__hello__.h: Lib/__hello__.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) __hello__ $(srcdir)/Lib/__hello__.py Python/frozen_modules/__hello__.h -Python/frozen_modules/__phello__.h: $(FREEZE_MODULE) Lib/__phello__/__init__.py +Python/frozen_modules/__phello__.h: Lib/__phello__/__init__.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) __phello__ $(srcdir)/Lib/__phello__/__init__.py Python/frozen_modules/__phello__.h -Python/frozen_modules/__phello__.ham.h: $(FREEZE_MODULE) Lib/__phello__/ham/__init__.py +Python/frozen_modules/__phello__.ham.h: Lib/__phello__/ham/__init__.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) __phello__.ham $(srcdir)/Lib/__phello__/ham/__init__.py Python/frozen_modules/__phello__.ham.h -Python/frozen_modules/__phello__.ham.eggs.h: $(FREEZE_MODULE) Lib/__phello__/ham/eggs.py +Python/frozen_modules/__phello__.ham.eggs.h: Lib/__phello__/ham/eggs.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) __phello__.ham.eggs $(srcdir)/Lib/__phello__/ham/eggs.py Python/frozen_modules/__phello__.ham.eggs.h -Python/frozen_modules/__phello__.spam.h: $(FREEZE_MODULE) Lib/__phello__/spam.py +Python/frozen_modules/__phello__.spam.h: Lib/__phello__/spam.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) __phello__.spam $(srcdir)/Lib/__phello__/spam.py Python/frozen_modules/__phello__.spam.h -Python/frozen_modules/frozen_only.h: $(FREEZE_MODULE) Tools/freeze/flag.py +Python/frozen_modules/frozen_only.h: Tools/freeze/flag.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) frozen_only $(srcdir)/Tools/freeze/flag.py Python/frozen_modules/frozen_only.h # END: freezing modules -# We manually freeze getpath.py rather than through freeze_modules -Python/frozen_modules/getpath.h: $(FREEZE_MODULE) Modules/getpath.py - $(FREEZE_MODULE) getpath $(srcdir)/Modules/getpath.py Python/frozen_modules/getpath.h - Tools/scripts/freeze_modules.py: $(FREEZE_MODULE) .PHONY: regen-frozen diff --git a/Misc/NEWS.d/next/Build/2021-12-02-23-21-18.bpo-45949.OTSo9X.rst b/Misc/NEWS.d/next/Build/2021-12-02-23-21-18.bpo-45949.OTSo9X.rst new file mode 100644 index 0000000000000..c746d71b1dcae --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-12-02-23-21-18.bpo-45949.OTSo9X.rst @@ -0,0 +1,3 @@ +Use pure Python ``freeze_module`` for all but importlib bootstrap files. +``--with-freeze-module`` :program:`configure` option is no longer needed for +cross builds. diff --git a/Programs/_freeze_module.c b/Programs/_freeze_module.c index e3f6c11c8b073..d50787666f81c 100644 --- a/Programs/_freeze_module.c +++ b/Programs/_freeze_module.c @@ -5,6 +5,8 @@ This is used directly by Tools/scripts/freeze_modules.py, and indirectly by "make regen-frozen". See Python/frozen.c for more info. + + Keep this file in sync with Programs/_freeze_module.py. */ #include diff --git a/Programs/_freeze_module.py b/Programs/_freeze_module.py new file mode 100644 index 0000000000000..ba638eef6c4cd --- /dev/null +++ b/Programs/_freeze_module.py @@ -0,0 +1,68 @@ +"""Python implementation of Programs/_freeze_module.c + +The pure Python implementation uses same functions and arguments as the C +implementation. + +The generated byte code is slightly different because +compile() sets the PyCF_SOURCE_IS_UTF8 flag and objects have a +reference count > 1. Marshal adds the `FLAG_REF` flag and creates a +reference `hashtable`. +""" + +import marshal +import sys + +header = "/* Auto-generated by Programs/_freeze_module.py */" + + +def read_text(inpath: str) -> bytes: + with open(inpath, "rb") as f: + return f.read() + + +def compile_and_marshal(name: str, text: bytes) -> bytes: + filename = f"" + # exec == Py_file_input + code = compile(text, filename, "exec", optimize=0, dont_inherit=True) + return marshal.dumps(code) + + +def get_varname(name: str, prefix: str) -> str: + return f"{prefix}{name.replace('.', '_')}" + + +def write_code(outfile, marshalled: bytes, varname: str) -> None: + data_size = len(marshalled) + + outfile.write(f"const unsigned char {varname}[] = {{\n") + + for n in range(0, data_size, 16): + outfile.write(" ") + outfile.write(",".join(str(i) for i in marshalled[n : n + 16])) + outfile.write(",\n") + outfile.write("};\n") + + +def write_frozen(outpath: str, inpath: str, name: str, marshalled: bytes) -> None: + with open(outpath, "w") as outfile: + outfile.write(header) + outfile.write("\n") + arrayname = get_varname(name, "_Py_M__") + write_code(outfile, marshalled, arrayname) + + +def main(): + if len(sys.argv) != 4: + sys.exit("need to specify the name, input and output paths\n") + + name = sys.argv[1] + inpath = sys.argv[2] + outpath = sys.argv[3] + + text = read_text(inpath) + marshalled = compile_and_marshal(name, text) + write_frozen(outpath, inpath, name, marshalled) + + +if __name__ == "__main__": + main() diff --git a/Tools/scripts/deepfreeze.py b/Tools/scripts/deepfreeze.py index 30ca7bb0b6090..002d680e10c2f 100644 --- a/Tools/scripts/deepfreeze.py +++ b/Tools/scripts/deepfreeze.py @@ -393,13 +393,14 @@ def generate(self, name: str, obj: object) -> str: } """ -FROZEN_COMMENT = "/* Auto-generated by Programs/_freeze_module.c */" +FROZEN_COMMENT_C = "/* Auto-generated by Programs/_freeze_module.c */" +FROZEN_COMMENT_PY = "/* Auto-generated by Programs/_freeze_module.py */" FROZEN_DATA_LINE = r"\s*(\d+,\s*)+\s*" def is_frozen_header(source: str) -> bool: - return source.startswith(FROZEN_COMMENT) + return source.startswith((FROZEN_COMMENT_C, FROZEN_COMMENT_PY)) def decode_frozen_data(source: str) -> types.CodeType: diff --git a/Tools/scripts/freeze_modules.py b/Tools/scripts/freeze_modules.py index 58d1398560835..cbe8bf1ce60cd 100644 --- a/Tools/scripts/freeze_modules.py +++ b/Tools/scripts/freeze_modules.py @@ -264,6 +264,10 @@ def ispkg(self): else: return os.path.basename(self.pyfile) == '__init__.py' + @property + def isbootstrap(self): + return self.id in BOOTSTRAP + def resolve_frozen_file(frozenid, destdir): """Return the filename corresponding to the given frozen ID. @@ -476,7 +480,7 @@ def regen_frozen(modules): indent = ' ' lastsection = None for mod in modules: - if mod.frozenid in BOOTSTRAP: + if mod.isbootstrap: lines = bootstraplines elif mod.section == TESTS_SECTION: lines = testlines @@ -585,10 +589,17 @@ def regen_makefile(modules): pyfile = relpath_for_posix_display(src.pyfile, ROOT_DIR) pyfiles.append(f'\t\t{pyfile} \\') - freeze = (f'$(FREEZE_MODULE) {src.frozenid} ' - f'$(srcdir)/{pyfile} {frozen_header}') + if src.isbootstrap: + freezecmd = '$(FREEZE_MODULE_BOOTSTRAP)' + freezedep = '$(FREEZE_MODULE_BOOTSTRAP_DEPS)' + else: + freezecmd = '$(FREEZE_MODULE)' + freezedep = '$(FREEZE_MODULE_DEPS)' + + freeze = (f'{freezecmd} {src.frozenid} ' + f'$(srcdir)/{pyfile} {frozen_header}') rules.extend([ - f'{frozen_header}: $(FREEZE_MODULE) {pyfile}', + f'{frozen_header}: {pyfile} {freezedep}', f'\t{freeze}', '', ]) diff --git a/configure b/configure index 3c2a9cf0a249d..583e7d1fe3b32 100755 --- a/configure +++ b/configure @@ -933,9 +933,12 @@ CONFIG_ARGS SOVERSION VERSION PYTHON_FOR_REGEN +FREEZE_MODULE_DEPS +FREEZE_MODULE +FREEZE_MODULE_BOOTSTRAP_DEPS +FREEZE_MODULE_BOOTSTRAP PYTHON_FOR_FREEZE PYTHON_FOR_BUILD -FREEZE_MODULE host_os host_vendor host_cpu @@ -991,7 +994,6 @@ SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking -with_freeze_module with_build_python with_pkg_config enable_universalsdk @@ -1726,8 +1728,6 @@ Optional Features: Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --with-freeze-module=Programs/_freeze_module - path to _freeze_module binary for cross compiling --with-build-python=python3.11 path to build python binary for cross compiling (default: _bootstrap_python or python3.11) @@ -3196,38 +3196,6 @@ fi rm -f pybuilddir.txt -# Check whether --with-freeze-module was given. -if test "${with_freeze_module+set}" = set; then : - withval=$with_freeze_module; - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-freeze-module" >&5 -$as_echo_n "checking for --with-freeze-module... " >&6; } - if test "x$cross_compiling" = xno; then : - as_fn_error $? "--with-freeze-module only applies to cross compiling" "$LINENO" 5 -fi - if test "$with_freeze_module" = yes -o "$with_freeze_module" = no; then - as_fn_error $? "invalid --with-freeze-module option: expected path, not \"$with_freeze_module\"" "$LINENO" 5 - fi - if ! $(command -v "$with_freeze_module" >/dev/null 2>&1); then - as_fn_error $? "invalid or missing freeze module binary \"$with_freeze_module\"" "$LINENO" 5 - fi - FREEZE_MODULE="$with_freeze_module" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FREEZE_MODULE" >&5 -$as_echo "$FREEZE_MODULE" >&6; } - -else - - if test "x$cross_compiling" = xyes; then : - as_fn_error $? "Cross compiling requires --with-freeze-module" "$LINENO" 5 - -fi - FREEZE_MODULE=Programs/_freeze_module - - -fi - - - - # Check whether --with-build-python was given. if test "${with_build_python+set}" = set; then : withval=$with_build_python; @@ -3274,6 +3242,27 @@ $as_echo_n "checking for Python interpreter freezing... " >&6; } $as_echo "$PYTHON_FOR_FREEZE" >&6; } +if test "x$cross_compiling" = xyes; then : + + FREEZE_MODULE_BOOTSTRAP='$(PYTHON_FOR_FREEZE) $(srcdir)/Programs/_freeze_module.py' + FREEZE_MODULE_BOOTSTRAP_DEPS='$(srcdir)/Programs/_freeze_module.py' + FREEZE_MODULE='$(FREEZE_MODULE_BOOTSTRAP)' + FREEZE_MODULE_DEPS='$(FREEZE_MODULE_BOOTSTRAP_DEPS)' + +else + + FREEZE_MODULE_BOOTSTRAP='./Programs/_freeze_module' + FREEZE_MODULE_BOOTSTRAP_DEPS="Programs/_freeze_module" + FREEZE_MODULE='$(PYTHON_FOR_FREEZE) $(srcdir)/Programs/_freeze_module.py' + FREEZE_MODULE_DEPS="_bootstrap_python \$(srcdir)/Programs/_freeze_module.py" + + +fi + + + + + for ac_prog in python$PACKAGE_VERSION python3.10 python3.9 python3.8 python3.7 python3.6 python3 python do # Extract the first word of "$ac_prog", so it can be a program name with args. diff --git a/configure.ac b/configure.ac index fa5e63cf5c3f9..5256a61289e22 100644 --- a/configure.ac +++ b/configure.ac @@ -100,32 +100,6 @@ AS_VAR_IF([cross_compiling], [maybe], # pybuilddir.txt will be created by --generate-posix-vars in the Makefile rm -f pybuilddir.txt -dnl cross-compiling needs a freeze_module binary for build platform -AC_ARG_WITH( - [freeze-module], - [AS_HELP_STRING([--with-freeze-module=Programs/_freeze_module], - [path to _freeze_module binary for cross compiling])], - [ - AC_MSG_CHECKING([for --with-freeze-module]) - AS_VAR_IF([cross_compiling], [no], AC_MSG_ERROR([--with-freeze-module only applies to cross compiling])) - if test "$with_freeze_module" = yes -o "$with_freeze_module" = no; then - AC_MSG_ERROR([invalid --with-freeze-module option: expected path, not "$with_freeze_module"]) - fi - if ! $(command -v "$with_freeze_module" >/dev/null 2>&1); then - AC_MSG_ERROR([invalid or missing freeze module binary "$with_freeze_module"]) - fi - FREEZE_MODULE="$with_freeze_module" - AC_MSG_RESULT([$FREEZE_MODULE]) - ], [ - AS_VAR_IF([cross_compiling], [yes], - [AC_MSG_ERROR([Cross compiling requires --with-freeze-module])] - ) - FREEZE_MODULE=Programs/_freeze_module - ] -) -AC_SUBST([FREEZE_MODULE]) - -dnl build-python is used for cross compiling and macOS framework builds. AC_ARG_WITH( [build-python], [AS_HELP_STRING([--with-build-python=python]PYTHON_VERSION, @@ -162,6 +136,27 @@ AC_MSG_CHECKING([for Python interpreter freezing]) AC_MSG_RESULT([$PYTHON_FOR_FREEZE]) AC_SUBST([PYTHON_FOR_FREEZE]) +AS_VAR_IF([cross_compiling], [yes], + [ + dnl external build Python, freezing depends on Programs/_freeze_module.py + FREEZE_MODULE_BOOTSTRAP='$(PYTHON_FOR_FREEZE) $(srcdir)/Programs/_freeze_module.py' + FREEZE_MODULE_BOOTSTRAP_DEPS='$(srcdir)/Programs/_freeze_module.py' + FREEZE_MODULE='$(FREEZE_MODULE_BOOTSTRAP)' + FREEZE_MODULE_DEPS='$(FREEZE_MODULE_BOOTSTRAP_DEPS)' + ], + [ + dnl internal build tools also depend on Programs/_freeze_module and _bootstrap_python. + FREEZE_MODULE_BOOTSTRAP='./Programs/_freeze_module' + FREEZE_MODULE_BOOTSTRAP_DEPS="Programs/_freeze_module" + FREEZE_MODULE='$(PYTHON_FOR_FREEZE) $(srcdir)/Programs/_freeze_module.py' + FREEZE_MODULE_DEPS="_bootstrap_python \$(srcdir)/Programs/_freeze_module.py" + ] +) +AC_SUBST([FREEZE_MODULE_BOOTSTRAP]) +AC_SUBST([FREEZE_MODULE_BOOTSTRAP_DEPS]) +AC_SUBST([FREEZE_MODULE]) +AC_SUBST([FREEZE_MODULE_DEPS]) + AC_CHECK_PROGS([PYTHON_FOR_REGEN], [python$PACKAGE_VERSION python3.10 python3.9 python3.8 python3.7 python3.6 python3 python], [python3]) From webhook-mailer at python.org Mon Dec 13 19:53:45 2021 From: webhook-mailer at python.org (vsajip) Date: Tue, 14 Dec 2021 00:53:45 -0000 Subject: [Python-checkins] =?utf-8?q?bpo-46063=3A_Improve_algorithm_for_c?= =?utf-8?q?omputing_which_rolled-over_log_file=E2=80=A6_=28GH-30093=29?= Message-ID: https://github.com/python/cpython/commit/cb589d1b6bad4b75852c2e2a471a3800d5efdca7 commit: cb589d1b6bad4b75852c2e2a471a3800d5efdca7 branch: main author: Vinay Sajip committer: vsajip date: 2021-12-14T00:53:37Z summary: bpo-46063: Improve algorithm for computing which rolled-over log file? (GH-30093) files: M Doc/library/logging.handlers.rst M Lib/logging/handlers.py M Lib/test/test_logging.py diff --git a/Doc/library/logging.handlers.rst b/Doc/library/logging.handlers.rst index 56256900ac99c..f5ef80ea044c6 100644 --- a/Doc/library/logging.handlers.rst +++ b/Doc/library/logging.handlers.rst @@ -234,6 +234,19 @@ need to override. return the same output every time for a given input, otherwise the rollover behaviour may not work as expected. + It's also worth noting that care should be taken when using a namer to + preserve certain attributes in the filename which are used during rotation. + For example, :class:`RotatingFileHandler` expects to have a set of log files + whose names contain successive integers, so that rotation works as expected, + and :class:`TimedRotatingFileHandler` deletes old log files (based on the + ``backupCount`` parameter passed to the handler's initializer) by determining + the oldest files to delete. For this to happen, the filenames should be + sortable using the date/time portion of the filename, and a namer needs to + respect this. (If a namer is wanted that doesn't respect this scheme, it will + need to be used in a subclass of :class:`TimedRotatingFileHandler` which + overrides the :meth:`~TimedRotatingFileHandler.getFilesToDelete` method to + fit in with the custom naming scheme.) + .. versionadded:: 3.3 @@ -443,6 +456,10 @@ timed intervals. Outputs the record to the file, catering for rollover as described above. + .. method:: getFilesToDelete() + + Returns a list of filenames which should be deleted as part of rollover. These + are the absolute paths of the oldest backup log files written by the handler. .. _socket-handler: diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py index d42c48de5f062..78e919d195d97 100644 --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -1,4 +1,4 @@ -# Copyright 2001-2016 by Vinay Sajip. All Rights Reserved. +# Copyright 2001-2021 by Vinay Sajip. All Rights Reserved. # # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose and without fee is hereby granted, @@ -18,7 +18,7 @@ Additional handlers for the logging package for Python. The core package is based on PEP 282 and comments thereto in comp.lang.python. -Copyright (C) 2001-2016 Vinay Sajip. All Rights Reserved. +Copyright (C) 2001-2021 Vinay Sajip. All Rights Reserved. To use, simply 'import logging.handlers' and log away! """ @@ -366,9 +366,22 @@ def getFilesToDelete(self): fileNames = os.listdir(dirName) result = [] # See bpo-44753: Don't use the extension when computing the prefix. - prefix = os.path.splitext(baseName)[0] + "." + n, e = os.path.splitext(baseName) + prefix = n + '.' plen = len(prefix) for fileName in fileNames: + if self.namer is None: + # Our files will always start with baseName + if not fileName.startswith(baseName): + continue + else: + # Our files could be just about anything after custom naming, but + # likely candidates are of the form + # foo.log.DATETIME_SUFFIX or foo.DATETIME_SUFFIX.log + if (not fileName.startswith(baseName) and fileName.endswith(e) and + len(fileName) > (plen + 1) and not fileName[plen+1].isdigit()): + continue + if fileName[:plen] == prefix: suffix = fileName[plen:] # See bpo-45628: The date/time suffix could be anywhere in the diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 85b6e5f392111..c85d26e4bab69 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -1,4 +1,4 @@ -# Copyright 2001-2019 by Vinay Sajip. All Rights Reserved. +# Copyright 2001-2021 by Vinay Sajip. All Rights Reserved. # # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose and without fee is hereby granted, @@ -16,7 +16,7 @@ """Test harness for the logging module. Run all tests. -Copyright (C) 2001-2019 Vinay Sajip. All Rights Reserved. +Copyright (C) 2001-2021 Vinay Sajip. All Rights Reserved. """ import logging @@ -36,6 +36,7 @@ import queue import random import re +import shutil import socket import struct import sys @@ -5434,6 +5435,53 @@ def test_compute_rollover_weekly_attime(self): finally: rh.close() + def test_compute_files_to_delete(self): + # See bpo-46063 for background + wd = tempfile.mkdtemp(prefix='test_logging_') + self.addCleanup(shutil.rmtree, wd) + times = [] + dt = datetime.datetime.now() + for i in range(10): + times.append(dt.strftime('%Y-%m-%d_%H-%M-%S')) + dt += datetime.timedelta(seconds=5) + prefixes = ('a.b', 'a.b.c', 'd.e', 'd.e.f') + files = [] + rotators = [] + for prefix in prefixes: + p = os.path.join(wd, '%s.log' % prefix) + rotator = logging.handlers.TimedRotatingFileHandler(p, when='s', + interval=5, + backupCount=7) + rotators.append(rotator) + if prefix.startswith('a.b'): + for t in times: + files.append('%s.log.%s' % (prefix, t)) + else: + rotator.namer = lambda name: name.replace('.log', '') + '.log' + for t in times: + files.append('%s.%s.log' % (prefix, t)) + # Create empty files + for fn in files: + p = os.path.join(wd, fn) + with open(p, 'wb') as f: + pass + # Now the checks that only the correct files are offered up for deletion + for i, prefix in enumerate(prefixes): + rotator = rotators[i] + candidates = rotator.getFilesToDelete() + self.assertEqual(len(candidates), 3) + if prefix.startswith('a.b'): + p = '%s.log.' % prefix + for c in candidates: + d, fn = os.path.split(c) + self.assertTrue(fn.startswith(p)) + else: + for c in candidates: + d, fn = os.path.split(c) + self.assertTrue(fn.endswith('.log')) + self.assertTrue(fn.startswith(prefix + '.') and + fn[len(prefix) + 2].isdigit()) + def secs(**kw): return datetime.timedelta(**kw) // datetime.timedelta(seconds=1) From webhook-mailer at python.org Mon Dec 13 20:04:11 2021 From: webhook-mailer at python.org (ericsnowcurrently) Date: Tue, 14 Dec 2021 01:04:11 -0000 Subject: [Python-checkins] bpo-45953: Statically initialize the small ints. (gh-30092) Message-ID: https://github.com/python/cpython/commit/121f1f893a39d0b58d3d2b5597505c154ecaac2a commit: 121f1f893a39d0b58d3d2b5597505c154ecaac2a branch: main author: Eric Snow committer: ericsnowcurrently date: 2021-12-13T18:04:05-07:00 summary: bpo-45953: Statically initialize the small ints. (gh-30092) The array of small PyLong objects has been statically declared. Here I also statically initialize them. Consequently they are no longer initialized dynamically during runtime init. I've also moved them under a new sub-struct in _PyRuntimeState, in preparation for static allocation and initialization of other global objects. https://bugs.python.org/issue45953 files: A Include/internal/pycore_global_objects.h D Include/internal/pycore_long_state.h M Include/internal/pycore_long.h M Include/internal/pycore_runtime.h M Makefile.pre.in M Objects/longobject.c M PCbuild/pythoncore.vcxproj M PCbuild/pythoncore.vcxproj.filters M Python/pylifecycle.c diff --git a/Include/internal/pycore_global_objects.h b/Include/internal/pycore_global_objects.h new file mode 100644 index 0000000000000..6cae3bca6be45 --- /dev/null +++ b/Include/internal/pycore_global_objects.h @@ -0,0 +1,337 @@ +#ifndef Py_INTERNAL_GLOBAL_OBJECTS_H +#define Py_INTERNAL_GLOBAL_OBJECTS_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + + +#define _PyObject_IMMORTAL_INIT(type) \ + { \ + .ob_refcnt = 999999999, \ + .ob_type = type, \ + } +#define _PyVarObject_IMMORTAL_INIT(type, size) \ + { \ + .ob_base = _PyObject_IMMORTAL_INIT(type), \ + .ob_size = size, \ + } + + +/* int objects */ + +#define _PY_NSMALLPOSINTS 257 +#define _PY_NSMALLNEGINTS 5 + +#define _PyLong_DIGIT_INIT(val) \ + { \ + _PyVarObject_IMMORTAL_INIT(&PyLong_Type, \ + ((val) == 0 ? 0 : ((val) > 0 ? 1 : -1))), \ + .ob_digit = { ((val) >= 0 ? (val) : -(val)) }, \ + } + + +/********************** + * the global objects * + **********************/ + +// Only immutable objects should be considered runtime-global. +// All others must be per-interpreter. + +#define _Py_GLOBAL_OBJECT(NAME) \ + _PyRuntime.global_objects.NAME +#define _Py_SINGLETON(NAME) \ + _Py_GLOBAL_OBJECT(singletons.NAME) + +struct _Py_global_objects { + struct { + /* Small integers are preallocated in this array so that they + * can be shared. + * The integers that are preallocated are those in the range + * -_PY_NSMALLNEGINTS (inclusive) to _PY_NSMALLPOSINTS (exclusive). + */ + PyLongObject small_ints[_PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS]; + } singletons; +}; + +#define _Py_global_objects_INIT { \ + .singletons = { \ + .small_ints = { \ + _PyLong_DIGIT_INIT(-5), \ + _PyLong_DIGIT_INIT(-4), \ + _PyLong_DIGIT_INIT(-3), \ + _PyLong_DIGIT_INIT(-2), \ + _PyLong_DIGIT_INIT(-1), \ + _PyLong_DIGIT_INIT(0), \ + _PyLong_DIGIT_INIT(1), \ + _PyLong_DIGIT_INIT(2), \ + _PyLong_DIGIT_INIT(3), \ + _PyLong_DIGIT_INIT(4), \ + _PyLong_DIGIT_INIT(5), \ + _PyLong_DIGIT_INIT(6), \ + _PyLong_DIGIT_INIT(7), \ + _PyLong_DIGIT_INIT(8), \ + _PyLong_DIGIT_INIT(9), \ + _PyLong_DIGIT_INIT(10), \ + _PyLong_DIGIT_INIT(11), \ + _PyLong_DIGIT_INIT(12), \ + _PyLong_DIGIT_INIT(13), \ + _PyLong_DIGIT_INIT(14), \ + _PyLong_DIGIT_INIT(15), \ + _PyLong_DIGIT_INIT(16), \ + _PyLong_DIGIT_INIT(17), \ + _PyLong_DIGIT_INIT(18), \ + _PyLong_DIGIT_INIT(19), \ + _PyLong_DIGIT_INIT(20), \ + _PyLong_DIGIT_INIT(21), \ + _PyLong_DIGIT_INIT(22), \ + _PyLong_DIGIT_INIT(23), \ + _PyLong_DIGIT_INIT(24), \ + _PyLong_DIGIT_INIT(25), \ + _PyLong_DIGIT_INIT(26), \ + _PyLong_DIGIT_INIT(27), \ + _PyLong_DIGIT_INIT(28), \ + _PyLong_DIGIT_INIT(29), \ + _PyLong_DIGIT_INIT(30), \ + _PyLong_DIGIT_INIT(31), \ + _PyLong_DIGIT_INIT(32), \ + _PyLong_DIGIT_INIT(33), \ + _PyLong_DIGIT_INIT(34), \ + _PyLong_DIGIT_INIT(35), \ + _PyLong_DIGIT_INIT(36), \ + _PyLong_DIGIT_INIT(37), \ + _PyLong_DIGIT_INIT(38), \ + _PyLong_DIGIT_INIT(39), \ + _PyLong_DIGIT_INIT(40), \ + _PyLong_DIGIT_INIT(41), \ + _PyLong_DIGIT_INIT(42), \ + _PyLong_DIGIT_INIT(43), \ + _PyLong_DIGIT_INIT(44), \ + _PyLong_DIGIT_INIT(45), \ + _PyLong_DIGIT_INIT(46), \ + _PyLong_DIGIT_INIT(47), \ + _PyLong_DIGIT_INIT(48), \ + _PyLong_DIGIT_INIT(49), \ + _PyLong_DIGIT_INIT(50), \ + _PyLong_DIGIT_INIT(51), \ + _PyLong_DIGIT_INIT(52), \ + _PyLong_DIGIT_INIT(53), \ + _PyLong_DIGIT_INIT(54), \ + _PyLong_DIGIT_INIT(55), \ + _PyLong_DIGIT_INIT(56), \ + _PyLong_DIGIT_INIT(57), \ + _PyLong_DIGIT_INIT(58), \ + _PyLong_DIGIT_INIT(59), \ + _PyLong_DIGIT_INIT(60), \ + _PyLong_DIGIT_INIT(61), \ + _PyLong_DIGIT_INIT(62), \ + _PyLong_DIGIT_INIT(63), \ + _PyLong_DIGIT_INIT(64), \ + _PyLong_DIGIT_INIT(65), \ + _PyLong_DIGIT_INIT(66), \ + _PyLong_DIGIT_INIT(67), \ + _PyLong_DIGIT_INIT(68), \ + _PyLong_DIGIT_INIT(69), \ + _PyLong_DIGIT_INIT(70), \ + _PyLong_DIGIT_INIT(71), \ + _PyLong_DIGIT_INIT(72), \ + _PyLong_DIGIT_INIT(73), \ + _PyLong_DIGIT_INIT(74), \ + _PyLong_DIGIT_INIT(75), \ + _PyLong_DIGIT_INIT(76), \ + _PyLong_DIGIT_INIT(77), \ + _PyLong_DIGIT_INIT(78), \ + _PyLong_DIGIT_INIT(79), \ + _PyLong_DIGIT_INIT(80), \ + _PyLong_DIGIT_INIT(81), \ + _PyLong_DIGIT_INIT(82), \ + _PyLong_DIGIT_INIT(83), \ + _PyLong_DIGIT_INIT(84), \ + _PyLong_DIGIT_INIT(85), \ + _PyLong_DIGIT_INIT(86), \ + _PyLong_DIGIT_INIT(87), \ + _PyLong_DIGIT_INIT(88), \ + _PyLong_DIGIT_INIT(89), \ + _PyLong_DIGIT_INIT(90), \ + _PyLong_DIGIT_INIT(91), \ + _PyLong_DIGIT_INIT(92), \ + _PyLong_DIGIT_INIT(93), \ + _PyLong_DIGIT_INIT(94), \ + _PyLong_DIGIT_INIT(95), \ + _PyLong_DIGIT_INIT(96), \ + _PyLong_DIGIT_INIT(97), \ + _PyLong_DIGIT_INIT(98), \ + _PyLong_DIGIT_INIT(99), \ + _PyLong_DIGIT_INIT(100), \ + _PyLong_DIGIT_INIT(101), \ + _PyLong_DIGIT_INIT(102), \ + _PyLong_DIGIT_INIT(103), \ + _PyLong_DIGIT_INIT(104), \ + _PyLong_DIGIT_INIT(105), \ + _PyLong_DIGIT_INIT(106), \ + _PyLong_DIGIT_INIT(107), \ + _PyLong_DIGIT_INIT(108), \ + _PyLong_DIGIT_INIT(109), \ + _PyLong_DIGIT_INIT(110), \ + _PyLong_DIGIT_INIT(111), \ + _PyLong_DIGIT_INIT(112), \ + _PyLong_DIGIT_INIT(113), \ + _PyLong_DIGIT_INIT(114), \ + _PyLong_DIGIT_INIT(115), \ + _PyLong_DIGIT_INIT(116), \ + _PyLong_DIGIT_INIT(117), \ + _PyLong_DIGIT_INIT(118), \ + _PyLong_DIGIT_INIT(119), \ + _PyLong_DIGIT_INIT(120), \ + _PyLong_DIGIT_INIT(121), \ + _PyLong_DIGIT_INIT(122), \ + _PyLong_DIGIT_INIT(123), \ + _PyLong_DIGIT_INIT(124), \ + _PyLong_DIGIT_INIT(125), \ + _PyLong_DIGIT_INIT(126), \ + _PyLong_DIGIT_INIT(127), \ + _PyLong_DIGIT_INIT(128), \ + _PyLong_DIGIT_INIT(129), \ + _PyLong_DIGIT_INIT(130), \ + _PyLong_DIGIT_INIT(131), \ + _PyLong_DIGIT_INIT(132), \ + _PyLong_DIGIT_INIT(133), \ + _PyLong_DIGIT_INIT(134), \ + _PyLong_DIGIT_INIT(135), \ + _PyLong_DIGIT_INIT(136), \ + _PyLong_DIGIT_INIT(137), \ + _PyLong_DIGIT_INIT(138), \ + _PyLong_DIGIT_INIT(139), \ + _PyLong_DIGIT_INIT(140), \ + _PyLong_DIGIT_INIT(141), \ + _PyLong_DIGIT_INIT(142), \ + _PyLong_DIGIT_INIT(143), \ + _PyLong_DIGIT_INIT(144), \ + _PyLong_DIGIT_INIT(145), \ + _PyLong_DIGIT_INIT(146), \ + _PyLong_DIGIT_INIT(147), \ + _PyLong_DIGIT_INIT(148), \ + _PyLong_DIGIT_INIT(149), \ + _PyLong_DIGIT_INIT(150), \ + _PyLong_DIGIT_INIT(151), \ + _PyLong_DIGIT_INIT(152), \ + _PyLong_DIGIT_INIT(153), \ + _PyLong_DIGIT_INIT(154), \ + _PyLong_DIGIT_INIT(155), \ + _PyLong_DIGIT_INIT(156), \ + _PyLong_DIGIT_INIT(157), \ + _PyLong_DIGIT_INIT(158), \ + _PyLong_DIGIT_INIT(159), \ + _PyLong_DIGIT_INIT(160), \ + _PyLong_DIGIT_INIT(161), \ + _PyLong_DIGIT_INIT(162), \ + _PyLong_DIGIT_INIT(163), \ + _PyLong_DIGIT_INIT(164), \ + _PyLong_DIGIT_INIT(165), \ + _PyLong_DIGIT_INIT(166), \ + _PyLong_DIGIT_INIT(167), \ + _PyLong_DIGIT_INIT(168), \ + _PyLong_DIGIT_INIT(169), \ + _PyLong_DIGIT_INIT(170), \ + _PyLong_DIGIT_INIT(171), \ + _PyLong_DIGIT_INIT(172), \ + _PyLong_DIGIT_INIT(173), \ + _PyLong_DIGIT_INIT(174), \ + _PyLong_DIGIT_INIT(175), \ + _PyLong_DIGIT_INIT(176), \ + _PyLong_DIGIT_INIT(177), \ + _PyLong_DIGIT_INIT(178), \ + _PyLong_DIGIT_INIT(179), \ + _PyLong_DIGIT_INIT(180), \ + _PyLong_DIGIT_INIT(181), \ + _PyLong_DIGIT_INIT(182), \ + _PyLong_DIGIT_INIT(183), \ + _PyLong_DIGIT_INIT(184), \ + _PyLong_DIGIT_INIT(185), \ + _PyLong_DIGIT_INIT(186), \ + _PyLong_DIGIT_INIT(187), \ + _PyLong_DIGIT_INIT(188), \ + _PyLong_DIGIT_INIT(189), \ + _PyLong_DIGIT_INIT(190), \ + _PyLong_DIGIT_INIT(191), \ + _PyLong_DIGIT_INIT(192), \ + _PyLong_DIGIT_INIT(193), \ + _PyLong_DIGIT_INIT(194), \ + _PyLong_DIGIT_INIT(195), \ + _PyLong_DIGIT_INIT(196), \ + _PyLong_DIGIT_INIT(197), \ + _PyLong_DIGIT_INIT(198), \ + _PyLong_DIGIT_INIT(199), \ + _PyLong_DIGIT_INIT(200), \ + _PyLong_DIGIT_INIT(201), \ + _PyLong_DIGIT_INIT(202), \ + _PyLong_DIGIT_INIT(203), \ + _PyLong_DIGIT_INIT(204), \ + _PyLong_DIGIT_INIT(205), \ + _PyLong_DIGIT_INIT(206), \ + _PyLong_DIGIT_INIT(207), \ + _PyLong_DIGIT_INIT(208), \ + _PyLong_DIGIT_INIT(209), \ + _PyLong_DIGIT_INIT(210), \ + _PyLong_DIGIT_INIT(211), \ + _PyLong_DIGIT_INIT(212), \ + _PyLong_DIGIT_INIT(213), \ + _PyLong_DIGIT_INIT(214), \ + _PyLong_DIGIT_INIT(215), \ + _PyLong_DIGIT_INIT(216), \ + _PyLong_DIGIT_INIT(217), \ + _PyLong_DIGIT_INIT(218), \ + _PyLong_DIGIT_INIT(219), \ + _PyLong_DIGIT_INIT(220), \ + _PyLong_DIGIT_INIT(221), \ + _PyLong_DIGIT_INIT(222), \ + _PyLong_DIGIT_INIT(223), \ + _PyLong_DIGIT_INIT(224), \ + _PyLong_DIGIT_INIT(225), \ + _PyLong_DIGIT_INIT(226), \ + _PyLong_DIGIT_INIT(227), \ + _PyLong_DIGIT_INIT(228), \ + _PyLong_DIGIT_INIT(229), \ + _PyLong_DIGIT_INIT(230), \ + _PyLong_DIGIT_INIT(231), \ + _PyLong_DIGIT_INIT(232), \ + _PyLong_DIGIT_INIT(233), \ + _PyLong_DIGIT_INIT(234), \ + _PyLong_DIGIT_INIT(235), \ + _PyLong_DIGIT_INIT(236), \ + _PyLong_DIGIT_INIT(237), \ + _PyLong_DIGIT_INIT(238), \ + _PyLong_DIGIT_INIT(239), \ + _PyLong_DIGIT_INIT(240), \ + _PyLong_DIGIT_INIT(241), \ + _PyLong_DIGIT_INIT(242), \ + _PyLong_DIGIT_INIT(243), \ + _PyLong_DIGIT_INIT(244), \ + _PyLong_DIGIT_INIT(245), \ + _PyLong_DIGIT_INIT(246), \ + _PyLong_DIGIT_INIT(247), \ + _PyLong_DIGIT_INIT(248), \ + _PyLong_DIGIT_INIT(249), \ + _PyLong_DIGIT_INIT(250), \ + _PyLong_DIGIT_INIT(251), \ + _PyLong_DIGIT_INIT(252), \ + _PyLong_DIGIT_INIT(253), \ + _PyLong_DIGIT_INIT(254), \ + _PyLong_DIGIT_INIT(255), \ + _PyLong_DIGIT_INIT(256), \ + }, \ + }, \ +} + +static inline void +_Py_global_objects_reset(struct _Py_global_objects *objects) +{ +} + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_GLOBAL_OBJECTS_H */ diff --git a/Include/internal/pycore_long.h b/Include/internal/pycore_long.h index a5639ceb6924a..4d1a0d0424969 100644 --- a/Include/internal/pycore_long.h +++ b/Include/internal/pycore_long.h @@ -8,19 +8,24 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#include "pycore_long_state.h" // _PyLong_SMALL_INTS -#include "pycore_pystate.h" // _PyThreadState_GET() +#include "pycore_global_objects.h" // _PY_NSMALLNEGINTS #include "pycore_runtime.h" // _PyRuntime /* runtime lifecycle */ -extern void _PyLong_InitGlobalObjects(PyInterpreterState *); extern PyStatus _PyLong_InitTypes(PyInterpreterState *); /* other API */ +#define _PyLong_SMALL_INTS _Py_SINGLETON(small_ints) + +// _PyLong_GetZero() and _PyLong_GetOne() must always be available +#if _PY_NSMALLPOSINTS < 2 +# error "_PY_NSMALLPOSINTS must be greater than 1" +#endif + // Return a borrowed reference to the zero singleton. // The function cannot return NULL. static inline PyObject* _PyLong_GetZero(void) diff --git a/Include/internal/pycore_long_state.h b/Include/internal/pycore_long_state.h deleted file mode 100644 index 5fe8e623a9eff..0000000000000 --- a/Include/internal/pycore_long_state.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef Py_INTERNAL_LONG_STATE_H -#define Py_INTERNAL_LONG_STATE_H -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef Py_BUILD_CORE -# error "this header requires Py_BUILD_CORE define" -#endif - -#define _PY_NSMALLPOSINTS 257 -#define _PY_NSMALLNEGINTS 5 - -// _PyLong_GetZero() and _PyLong_GetOne() must always be available -#if _PY_NSMALLPOSINTS < 2 -# error "_PY_NSMALLPOSINTS must be greater than 1" -#endif - -struct _Py_long_state { - /* Small integers are preallocated in this array so that they - * can be shared. - * The integers that are preallocated are those in the range - *-_PY_NSMALLNEGINTS (inclusive) to _PY_NSMALLPOSINTS (not inclusive). - */ - PyLongObject small_ints[_PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS]; -}; - -#define _PyLong_SMALL_INTS _PyRuntime.int_state.small_ints - -#ifdef __cplusplus -} -#endif -#endif /* !Py_INTERNAL_LONG_STATE_H */ diff --git a/Include/internal/pycore_runtime.h b/Include/internal/pycore_runtime.h index bd88510d1f056..725c859ea7853 100644 --- a/Include/internal/pycore_runtime.h +++ b/Include/internal/pycore_runtime.h @@ -8,10 +8,10 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#include "pycore_atomic.h" /* _Py_atomic_address */ -#include "pycore_gil.h" // struct _gil_runtime_state -#include "pycore_long_state.h" // struct _Py_long_state -#include "pycore_unicodeobject.h" // struct _Py_unicode_runtime_ids +#include "pycore_atomic.h" /* _Py_atomic_address */ +#include "pycore_gil.h" // struct _gil_runtime_state +#include "pycore_global_objects.h" // struct _Py_global_objects +#include "pycore_unicodeobject.h" // struct _Py_unicode_runtime_ids /* ceval state */ @@ -101,8 +101,6 @@ typedef struct pyruntimestate { unsigned long main_thread; - struct _Py_long_state int_state; - #define NEXITFUNCS 32 void (*exitfuncs[NEXITFUNCS])(void); int nexitfuncs; @@ -120,12 +118,14 @@ typedef struct pyruntimestate { struct _Py_unicode_runtime_ids unicode_ids; - // XXX Consolidate globals found via the check-c-globals script. + struct _Py_global_objects global_objects; + // If anything gets added after global_objects then + // _PyRuntimeState_reset() needs to get updated to clear it. } _PyRuntimeState; #define _PyRuntimeState_INIT \ { \ - ._initialized = 0, \ + .global_objects = _Py_global_objects_INIT, \ } /* Note: _PyRuntimeState_INIT sets other fields to 0/NULL */ @@ -133,7 +133,8 @@ static inline void _PyRuntimeState_reset(_PyRuntimeState *runtime) { /* Make it match _PyRuntimeState_INIT. */ - memset(runtime, 0, sizeof(*runtime)); + memset(runtime, 0, (size_t)&runtime->global_objects - (size_t)runtime); + _Py_global_objects_reset(&runtime->global_objects); } diff --git a/Makefile.pre.in b/Makefile.pre.in index fb114979a5dff..59c92a0568022 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1613,6 +1613,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/internal/pycore_genobject.h \ $(srcdir)/Include/internal/pycore_getopt.h \ $(srcdir)/Include/internal/pycore_gil.h \ + $(srcdir)/Include/internal/pycore_global_objects.h \ $(srcdir)/Include/internal/pycore_hamt.h \ $(srcdir)/Include/internal/pycore_hashtable.h \ $(srcdir)/Include/internal/pycore_import.h \ @@ -1621,7 +1622,6 @@ PYTHON_HEADERS= \ $(srcdir)/Include/internal/pycore_interpreteridobject.h \ $(srcdir)/Include/internal/pycore_list.h \ $(srcdir)/Include/internal/pycore_long.h \ - $(srcdir)/Include/internal/pycore_long_state.h \ $(srcdir)/Include/internal/pycore_moduleobject.h \ $(srcdir)/Include/internal/pycore_namespace.h \ $(srcdir)/Include/internal/pycore_object.h \ diff --git a/Objects/longobject.c b/Objects/longobject.c index f6d5e7648be16..77434e67642f5 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -5832,29 +5832,6 @@ PyLong_GetInfo(void) /* runtime lifecycle */ -void -_PyLong_InitGlobalObjects(PyInterpreterState *interp) -{ - if (!_Py_IsMainInterpreter(interp)) { - return; - } - - PyLongObject *small_ints = _PyLong_SMALL_INTS; - if (small_ints[0].ob_base.ob_base.ob_refcnt != 0) { - // Py_Initialize() must be running a second time. - return; - } - - for (Py_ssize_t i=0; i < _PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS; i++) { - sdigit ival = (sdigit)i - _PY_NSMALLNEGINTS; - int size = (ival < 0) ? -1 : ((ival == 0) ? 0 : 1); - small_ints[i].ob_base.ob_base.ob_refcnt = 1; - small_ints[i].ob_base.ob_base.ob_type = &PyLong_Type; - small_ints[i].ob_base.ob_size = size; - small_ints[i].ob_digit[0] = (digit)abs(ival); - } -} - PyStatus _PyLong_InitTypes(PyInterpreterState *interp) { @@ -5875,9 +5852,3 @@ _PyLong_InitTypes(PyInterpreterState *interp) return _PyStatus_OK(); } - -void -_PyLong_Fini(PyInterpreterState *interp) -{ - (void)interp; -} diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 098cc21072344..83ae2f08749aa 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -213,6 +213,7 @@ + @@ -221,7 +222,6 @@ - diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index c99595755e3dc..cc0a2b0f75924 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -549,6 +549,9 @@ Include\internal + + Include\internal + Include\internal @@ -573,9 +576,6 @@ Include\internal - - Include\internal - Include\internal diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index a9eb38775c42a..22281a311918e 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -676,8 +676,6 @@ pycore_init_global_objects(PyInterpreterState *interp) { PyStatus status; - _PyLong_InitGlobalObjects(interp); - _PyFloat_InitState(interp); status = _PyBytes_InitGlobalObjects(interp); From webhook-mailer at python.org Mon Dec 13 20:18:03 2021 From: webhook-mailer at python.org (vsajip) Date: Tue, 14 Dec 2021 01:18:03 -0000 Subject: [Python-checkins] =?utf-8?q?=5B3=2E10=5D_bpo-46063=3A_Improve_al?= =?utf-8?q?gorithm_for_computing_which_rolled-over_log_file=E2=80=A6_=28GH?= =?utf-8?q?-30093=29_=28GH-30094=29?= Message-ID: https://github.com/python/cpython/commit/f84e2f6c0aca97c59ec8ce21715ae9bd89893307 commit: f84e2f6c0aca97c59ec8ce21715ae9bd89893307 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: vsajip date: 2021-12-14T01:17:56Z summary: [3.10] bpo-46063: Improve algorithm for computing which rolled-over log file? (GH-30093) (GH-30094) Co-authored-by: Vinay Sajip files: M Doc/library/logging.handlers.rst M Lib/logging/handlers.py M Lib/test/test_logging.py diff --git a/Doc/library/logging.handlers.rst b/Doc/library/logging.handlers.rst index 73c542ba7c7b8..a664efdc62526 100644 --- a/Doc/library/logging.handlers.rst +++ b/Doc/library/logging.handlers.rst @@ -231,6 +231,19 @@ need to override. return the same output every time for a given input, otherwise the rollover behaviour may not work as expected. + It's also worth noting that care should be taken when using a namer to + preserve certain attributes in the filename which are used during rotation. + For example, :class:`RotatingFileHandler` expects to have a set of log files + whose names contain successive integers, so that rotation works as expected, + and :class:`TimedRotatingFileHandler` deletes old log files (based on the + ``backupCount`` parameter passed to the handler's initializer) by determining + the oldest files to delete. For this to happen, the filenames should be + sortable using the date/time portion of the filename, and a namer needs to + respect this. (If a namer is wanted that doesn't respect this scheme, it will + need to be used in a subclass of :class:`TimedRotatingFileHandler` which + overrides the :meth:`~TimedRotatingFileHandler.getFilesToDelete` method to + fit in with the custom naming scheme.) + .. versionadded:: 3.3 @@ -440,6 +453,10 @@ timed intervals. Outputs the record to the file, catering for rollover as described above. + .. method:: getFilesToDelete() + + Returns a list of filenames which should be deleted as part of rollover. These + are the absolute paths of the oldest backup log files written by the handler. .. _socket-handler: diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py index 4e8f0a8cc2f46..61a39958c0ac0 100644 --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -1,4 +1,4 @@ -# Copyright 2001-2016 by Vinay Sajip. All Rights Reserved. +# Copyright 2001-2021 by Vinay Sajip. All Rights Reserved. # # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose and without fee is hereby granted, @@ -18,7 +18,7 @@ Additional handlers for the logging package for Python. The core package is based on PEP 282 and comments thereto in comp.lang.python. -Copyright (C) 2001-2016 Vinay Sajip. All Rights Reserved. +Copyright (C) 2001-2021 Vinay Sajip. All Rights Reserved. To use, simply 'import logging.handlers' and log away! """ @@ -366,9 +366,22 @@ def getFilesToDelete(self): fileNames = os.listdir(dirName) result = [] # See bpo-44753: Don't use the extension when computing the prefix. - prefix = os.path.splitext(baseName)[0] + "." + n, e = os.path.splitext(baseName) + prefix = n + '.' plen = len(prefix) for fileName in fileNames: + if self.namer is None: + # Our files will always start with baseName + if not fileName.startswith(baseName): + continue + else: + # Our files could be just about anything after custom naming, but + # likely candidates are of the form + # foo.log.DATETIME_SUFFIX or foo.DATETIME_SUFFIX.log + if (not fileName.startswith(baseName) and fileName.endswith(e) and + len(fileName) > (plen + 1) and not fileName[plen+1].isdigit()): + continue + if fileName[:plen] == prefix: suffix = fileName[plen:] # See bpo-45628: The date/time suffix could be anywhere in the diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 93f6e5f85a0a3..b74f20156ffd8 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -1,4 +1,4 @@ -# Copyright 2001-2019 by Vinay Sajip. All Rights Reserved. +# Copyright 2001-2021 by Vinay Sajip. All Rights Reserved. # # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose and without fee is hereby granted, @@ -16,7 +16,7 @@ """Test harness for the logging module. Run all tests. -Copyright (C) 2001-2019 Vinay Sajip. All Rights Reserved. +Copyright (C) 2001-2021 Vinay Sajip. All Rights Reserved. """ import logging @@ -36,6 +36,7 @@ import queue import random import re +import shutil import socket import struct import sys @@ -5408,6 +5409,53 @@ def test_compute_rollover_weekly_attime(self): finally: rh.close() + def test_compute_files_to_delete(self): + # See bpo-46063 for background + wd = tempfile.mkdtemp(prefix='test_logging_') + self.addCleanup(shutil.rmtree, wd) + times = [] + dt = datetime.datetime.now() + for i in range(10): + times.append(dt.strftime('%Y-%m-%d_%H-%M-%S')) + dt += datetime.timedelta(seconds=5) + prefixes = ('a.b', 'a.b.c', 'd.e', 'd.e.f') + files = [] + rotators = [] + for prefix in prefixes: + p = os.path.join(wd, '%s.log' % prefix) + rotator = logging.handlers.TimedRotatingFileHandler(p, when='s', + interval=5, + backupCount=7) + rotators.append(rotator) + if prefix.startswith('a.b'): + for t in times: + files.append('%s.log.%s' % (prefix, t)) + else: + rotator.namer = lambda name: name.replace('.log', '') + '.log' + for t in times: + files.append('%s.%s.log' % (prefix, t)) + # Create empty files + for fn in files: + p = os.path.join(wd, fn) + with open(p, 'wb') as f: + pass + # Now the checks that only the correct files are offered up for deletion + for i, prefix in enumerate(prefixes): + rotator = rotators[i] + candidates = rotator.getFilesToDelete() + self.assertEqual(len(candidates), 3) + if prefix.startswith('a.b'): + p = '%s.log.' % prefix + for c in candidates: + d, fn = os.path.split(c) + self.assertTrue(fn.startswith(p)) + else: + for c in candidates: + d, fn = os.path.split(c) + self.assertTrue(fn.endswith('.log')) + self.assertTrue(fn.startswith(prefix + '.') and + fn[len(prefix) + 2].isdigit()) + def secs(**kw): return datetime.timedelta(**kw) // datetime.timedelta(seconds=1) From webhook-mailer at python.org Mon Dec 13 20:19:55 2021 From: webhook-mailer at python.org (vsajip) Date: Tue, 14 Dec 2021 01:19:55 -0000 Subject: [Python-checkins] =?utf-8?q?=5B3=2E9=5D_bpo-46063=3A_Improve_alg?= =?utf-8?q?orithm_for_computing_which_rolled-over_log_file=E2=80=A6_=28GH-?= =?utf-8?q?30093=29_=28GH-30095=29?= Message-ID: https://github.com/python/cpython/commit/94234228abbb84945a48049a7515dea960bc9834 commit: 94234228abbb84945a48049a7515dea960bc9834 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: vsajip date: 2021-12-14T01:19:50Z summary: [3.9] bpo-46063: Improve algorithm for computing which rolled-over log file? (GH-30093) (GH-30095) files: M Doc/library/logging.handlers.rst M Lib/logging/handlers.py M Lib/test/test_logging.py diff --git a/Doc/library/logging.handlers.rst b/Doc/library/logging.handlers.rst index 059ab3d3a3444..f16bf3286335d 100644 --- a/Doc/library/logging.handlers.rst +++ b/Doc/library/logging.handlers.rst @@ -231,6 +231,19 @@ need to override. return the same output every time for a given input, otherwise the rollover behaviour may not work as expected. + It's also worth noting that care should be taken when using a namer to + preserve certain attributes in the filename which are used during rotation. + For example, :class:`RotatingFileHandler` expects to have a set of log files + whose names contain successive integers, so that rotation works as expected, + and :class:`TimedRotatingFileHandler` deletes old log files (based on the + ``backupCount`` parameter passed to the handler's initializer) by determining + the oldest files to delete. For this to happen, the filenames should be + sortable using the date/time portion of the filename, and a namer needs to + respect this. (If a namer is wanted that doesn't respect this scheme, it will + need to be used in a subclass of :class:`TimedRotatingFileHandler` which + overrides the :meth:`~TimedRotatingFileHandler.getFilesToDelete` method to + fit in with the custom naming scheme.) + .. versionadded:: 3.3 @@ -440,6 +453,10 @@ timed intervals. Outputs the record to the file, catering for rollover as described above. + .. method:: getFilesToDelete() + + Returns a list of filenames which should be deleted as part of rollover. These + are the absolute paths of the oldest backup log files written by the handler. .. _socket-handler: diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py index f8040c498c10d..572e370110a0d 100644 --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -1,4 +1,4 @@ -# Copyright 2001-2016 by Vinay Sajip. All Rights Reserved. +# Copyright 2001-2021 by Vinay Sajip. All Rights Reserved. # # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose and without fee is hereby granted, @@ -18,7 +18,7 @@ Additional handlers for the logging package for Python. The core package is based on PEP 282 and comments thereto in comp.lang.python. -Copyright (C) 2001-2016 Vinay Sajip. All Rights Reserved. +Copyright (C) 2001-2021 Vinay Sajip. All Rights Reserved. To use, simply 'import logging.handlers' and log away! """ @@ -363,9 +363,22 @@ def getFilesToDelete(self): fileNames = os.listdir(dirName) result = [] # See bpo-44753: Don't use the extension when computing the prefix. - prefix = os.path.splitext(baseName)[0] + "." + n, e = os.path.splitext(baseName) + prefix = n + '.' plen = len(prefix) for fileName in fileNames: + if self.namer is None: + # Our files will always start with baseName + if not fileName.startswith(baseName): + continue + else: + # Our files could be just about anything after custom naming, but + # likely candidates are of the form + # foo.log.DATETIME_SUFFIX or foo.DATETIME_SUFFIX.log + if (not fileName.startswith(baseName) and fileName.endswith(e) and + len(fileName) > (plen + 1) and not fileName[plen+1].isdigit()): + continue + if fileName[:plen] == prefix: suffix = fileName[plen:] # See bpo-45628: The date/time suffix could be anywhere in the diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 876c91f64eb7c..858adc72b46a3 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -1,4 +1,4 @@ -# Copyright 2001-2019 by Vinay Sajip. All Rights Reserved. +# Copyright 2001-2021 by Vinay Sajip. All Rights Reserved. # # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose and without fee is hereby granted, @@ -16,7 +16,7 @@ """Test harness for the logging module. Run all tests. -Copyright (C) 2001-2019 Vinay Sajip. All Rights Reserved. +Copyright (C) 2001-2021 Vinay Sajip. All Rights Reserved. """ import logging @@ -36,6 +36,7 @@ import queue import random import re +import shutil import socket import struct import sys @@ -5284,6 +5285,53 @@ def test_compute_rollover_weekly_attime(self): finally: rh.close() + def test_compute_files_to_delete(self): + # See bpo-46063 for background + wd = tempfile.mkdtemp(prefix='test_logging_') + self.addCleanup(shutil.rmtree, wd) + times = [] + dt = datetime.datetime.now() + for i in range(10): + times.append(dt.strftime('%Y-%m-%d_%H-%M-%S')) + dt += datetime.timedelta(seconds=5) + prefixes = ('a.b', 'a.b.c', 'd.e', 'd.e.f') + files = [] + rotators = [] + for prefix in prefixes: + p = os.path.join(wd, '%s.log' % prefix) + rotator = logging.handlers.TimedRotatingFileHandler(p, when='s', + interval=5, + backupCount=7) + rotators.append(rotator) + if prefix.startswith('a.b'): + for t in times: + files.append('%s.log.%s' % (prefix, t)) + else: + rotator.namer = lambda name: name.replace('.log', '') + '.log' + for t in times: + files.append('%s.%s.log' % (prefix, t)) + # Create empty files + for fn in files: + p = os.path.join(wd, fn) + with open(p, 'wb') as f: + pass + # Now the checks that only the correct files are offered up for deletion + for i, prefix in enumerate(prefixes): + rotator = rotators[i] + candidates = rotator.getFilesToDelete() + self.assertEqual(len(candidates), 3) + if prefix.startswith('a.b'): + p = '%s.log.' % prefix + for c in candidates: + d, fn = os.path.split(c) + self.assertTrue(fn.startswith(p)) + else: + for c in candidates: + d, fn = os.path.split(c) + self.assertTrue(fn.endswith('.log')) + self.assertTrue(fn.startswith(prefix + '.') and + fn[len(prefix) + 2].isdigit()) + def secs(**kw): return datetime.timedelta(**kw) // datetime.timedelta(seconds=1) From webhook-mailer at python.org Mon Dec 13 20:31:46 2021 From: webhook-mailer at python.org (corona10) Date: Tue, 14 Dec 2021 01:31:46 -0000 Subject: [Python-checkins] bpo-45919: Remove out of date comment (GH-30090) Message-ID: https://github.com/python/cpython/commit/9130a4d62032468e0d4949aaa49c29afb0d854ca commit: 9130a4d62032468e0d4949aaa49c29afb0d854ca branch: main author: Dong-hee Na committer: corona10 date: 2021-12-14T10:31:41+09:00 summary: bpo-45919: Remove out of date comment (GH-30090) files: M Python/pylifecycle.c diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 22281a311918e..b2f58f4e3e8a3 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -2166,13 +2166,15 @@ is_valid_fd(int fd) some platforms. fcntl(fd, F_GETFD) is even faster, because it only checks the process table. + It is preferred over dup() when available, since it cannot fail with the + "too many open files" error (EMFILE). bpo-30225: On macOS Tiger, when stdout is redirected to a pipe and the other side of the pipe is closed, dup(1) succeed, whereas fstat(1, &st) fails with EBADF. FreeBSD has similar issue (bpo-32849). - Only use dup() on platforms where dup() is enough to detect invalid FD in - corner cases: on Linux and Windows (bpo-32849). + Only use dup() on Linux where dup() is enough to detect invalid FD + (bpo-32849). */ if (fd < 0) { return 0; From webhook-mailer at python.org Tue Dec 14 08:01:18 2021 From: webhook-mailer at python.org (berkerpeksag) Date: Tue, 14 Dec 2021 13:01:18 -0000 Subject: [Python-checkins] bpo-23469: Delete Wing IDE configuration files (GH-30067) Message-ID: https://github.com/python/cpython/commit/d46d08d9474cb00b697dbdbb12cc7ce8f8ddfcec commit: d46d08d9474cb00b697dbdbb12cc7ce8f8ddfcec branch: main author: Kumar Aditya <59607654+kumaraditya303 at users.noreply.github.com> committer: berkerpeksag date: 2021-12-14T15:01:13+02:00 summary: bpo-23469: Delete Wing IDE configuration files (GH-30067) files: D Misc/python-wing3.wpr D Misc/python-wing4.wpr D Misc/python-wing5.wpr M Misc/README diff --git a/Misc/README b/Misc/README index 8e8acbc5b3cec..e4dd2005411a8 100644 --- a/Misc/README +++ b/Misc/README @@ -16,7 +16,6 @@ Porting Mini-FAQ on porting to new platforms python-config.in Python script template for python-config python.man UNIX man page for the python interpreter python.pc.in Package configuration info template for pkg-config -python-wing*.wpr Wing IDE project file README The file you're reading now README.AIX Information about using Python on AIX README.coverity Information about running Coverity's Prevent on Python diff --git a/Misc/python-wing3.wpr b/Misc/python-wing3.wpr deleted file mode 100755 index abe789412d9ca..0000000000000 --- a/Misc/python-wing3.wpr +++ /dev/null @@ -1,13 +0,0 @@ -#!wing -#!version=3.0 -################################################################## -# Wing IDE project file # -################################################################## -[project attributes] -proj.directory-list = [{'dirloc': loc('..'), - 'excludes': [u'Lib/__pycache__'], - 'filter': '*', - 'include_hidden': False, - 'recursive': True, - 'watch_for_changes': True}] -proj.file-type = 'shared' diff --git a/Misc/python-wing4.wpr b/Misc/python-wing4.wpr deleted file mode 100755 index 7adfdbdacf730..0000000000000 --- a/Misc/python-wing4.wpr +++ /dev/null @@ -1,18 +0,0 @@ -#!wing -#!version=4.0 -################################################################## -# Wing IDE project file # -################################################################## -[project attributes] -proj.directory-list = [{'dirloc': loc('..'), - 'excludes': [u'.hg', - u'Lib/unittest/__pycache__', - u'Lib/unittest/test/__pycache__', - u'Lib/__pycache__', - u'build', - u'Doc/build'], - 'filter': '*', - 'include_hidden': False, - 'recursive': True, - 'watch_for_changes': True}] -proj.file-type = 'shared' diff --git a/Misc/python-wing5.wpr b/Misc/python-wing5.wpr deleted file mode 100755 index 0e1ae635438c8..0000000000000 --- a/Misc/python-wing5.wpr +++ /dev/null @@ -1,18 +0,0 @@ -#!wing -#!version=5.0 -################################################################## -# Wing IDE project file # -################################################################## -[project attributes] -proj.directory-list = [{'dirloc': loc('..'), - 'excludes': [u'.hg', - u'Lib/unittest/__pycache__', - u'Lib/unittest/test/__pycache__', - u'Lib/__pycache__', - u'build', - u'Doc/build'], - 'filter': '*', - 'include_hidden': False, - 'recursive': True, - 'watch_for_changes': True}] -proj.file-type = 'shared' From webhook-mailer at python.org Tue Dec 14 09:42:57 2021 From: webhook-mailer at python.org (tiran) Date: Tue, 14 Dec 2021 14:42:57 -0000 Subject: [Python-checkins] bpo-46023: Skip build if module is marked as DISABLED (GH-30100) Message-ID: https://github.com/python/cpython/commit/74821b30539bba3cf0ac4148923ec0e9b826508e commit: 74821b30539bba3cf0ac4148923ec0e9b826508e branch: main author: Christian Heimes committer: tiran date: 2021-12-14T15:42:46+01:00 summary: bpo-46023: Skip build if module is marked as DISABLED (GH-30100) files: M Modules/Setup.bootstrap M Modules/makesetup diff --git a/Modules/Setup.bootstrap b/Modules/Setup.bootstrap index d543f087b89fc..f23da60b37ad0 100644 --- a/Modules/Setup.bootstrap +++ b/Modules/Setup.bootstrap @@ -3,6 +3,7 @@ # --- # Built-in modules required to get a functioning interpreter; # cannot be built as shared! +*static* # module C APIs are used in core atexit atexitmodule.c diff --git a/Modules/makesetup b/Modules/makesetup index 6d83b8f0cbb7a..3909650ed7c41 100755 --- a/Modules/makesetup +++ b/Modules/makesetup @@ -207,7 +207,10 @@ sed -e 's/[ ]*#.*//' -e '/^[ ]*$/d' | libs="\$(MODULE_${mods_upper}_LDFLAGS)" fi case $DISABLED in - *$mods*) doconfig=disabled;; + *$mods*) + # disabled by previous rule / Setup file + continue + ;; esac case $doconfig in yes) From webhook-mailer at python.org Tue Dec 14 10:04:39 2021 From: webhook-mailer at python.org (Fidget-Spinner) Date: Tue, 14 Dec 2021 15:04:39 -0000 Subject: [Python-checkins] bpo-46059: Clarify pattern-matching example in "control flow" docs (GH-30079) Message-ID: https://github.com/python/cpython/commit/1cbb88736c32ac30fd530371adf53fe7554be0a5 commit: 1cbb88736c32ac30fd530371adf53fe7554be0a5 branch: main author: Alex Waygood committer: Fidget-Spinner <28750310+Fidget-Spinner at users.noreply.github.com> date: 2021-12-14T23:04:29+08:00 summary: bpo-46059: Clarify pattern-matching example in "control flow" docs (GH-30079) The "Color" example in the pattern-matching section of the "control flow" documentation is not immediately runnable, leading to confusion. Co-authored-by: Ken Jin <28750310+Fidget-Spinner at users.noreply.github.com> files: M Doc/tutorial/controlflow.rst diff --git a/Doc/tutorial/controlflow.rst b/Doc/tutorial/controlflow.rst index a819756602612..fad8746014646 100644 --- a/Doc/tutorial/controlflow.rst +++ b/Doc/tutorial/controlflow.rst @@ -395,9 +395,11 @@ Several other key features of this statement: from enum import Enum class Color(Enum): - RED = 0 - GREEN = 1 - BLUE = 2 + RED = 'red' + GREEN = 'green' + BLUE = 'blue' + + color = Color(input("Enter your choice of 'red', 'blue' or 'green': ")) match color: case Color.RED: From webhook-mailer at python.org Tue Dec 14 10:25:53 2021 From: webhook-mailer at python.org (miss-islington) Date: Tue, 14 Dec 2021 15:25:53 -0000 Subject: [Python-checkins] bpo-46059: Clarify pattern-matching example in "control flow" docs (GH-30079) Message-ID: https://github.com/python/cpython/commit/503803d8c19be91becc09ca59f3febcbc324d6d2 commit: 503803d8c19be91becc09ca59f3febcbc324d6d2 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-14T07:25:32-08:00 summary: bpo-46059: Clarify pattern-matching example in "control flow" docs (GH-30079) The "Color" example in the pattern-matching section of the "control flow" documentation is not immediately runnable, leading to confusion. Co-authored-by: Ken Jin <28750310+Fidget-Spinner at users.noreply.github.com> (cherry picked from commit 1cbb88736c32ac30fd530371adf53fe7554be0a5) Co-authored-by: Alex Waygood files: M Doc/tutorial/controlflow.rst diff --git a/Doc/tutorial/controlflow.rst b/Doc/tutorial/controlflow.rst index a819756602612..fad8746014646 100644 --- a/Doc/tutorial/controlflow.rst +++ b/Doc/tutorial/controlflow.rst @@ -395,9 +395,11 @@ Several other key features of this statement: from enum import Enum class Color(Enum): - RED = 0 - GREEN = 1 - BLUE = 2 + RED = 'red' + GREEN = 'green' + BLUE = 'blue' + + color = Color(input("Enter your choice of 'red', 'blue' or 'green': ")) match color: case Color.RED: From webhook-mailer at python.org Tue Dec 14 11:46:39 2021 From: webhook-mailer at python.org (vsajip) Date: Tue, 14 Dec 2021 16:46:39 -0000 Subject: [Python-checkins] bpo-46063: Add 'delay=True' to file handler initialization. (GH-30103) Message-ID: https://github.com/python/cpython/commit/850aefc2c651110a784cd5478af9774b1f6287a3 commit: 850aefc2c651110a784cd5478af9774b1f6287a3 branch: main author: Vinay Sajip committer: vsajip date: 2021-12-14T16:46:07Z summary: bpo-46063: Add 'delay=True' to file handler initialization. (GH-30103) files: M Lib/test/test_logging.py diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index c85d26e4bab69..e61ccdf86bdea 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -5451,7 +5451,8 @@ def test_compute_files_to_delete(self): p = os.path.join(wd, '%s.log' % prefix) rotator = logging.handlers.TimedRotatingFileHandler(p, when='s', interval=5, - backupCount=7) + backupCount=7, + delay=True) rotators.append(rotator) if prefix.startswith('a.b'): for t in times: From webhook-mailer at python.org Tue Dec 14 11:48:30 2021 From: webhook-mailer at python.org (iritkatriel) Date: Tue, 14 Dec 2021 16:48:30 -0000 Subject: [Python-checkins] bpo-45292: [PEP-654] add except* (GH-29581) Message-ID: https://github.com/python/cpython/commit/d60457a6673cf0263213c2f2be02c633ec2e2038 commit: d60457a6673cf0263213c2f2be02c633ec2e2038 branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-12-14T16:48:15Z summary: bpo-45292: [PEP-654] add except* (GH-29581) files: A Lib/test/test_except_star.py A Misc/NEWS.d/next/Core and Builtins/2021-11-22-13-05-32.bpo-45292.pfEouJ.rst M Doc/library/ast.rst M Doc/library/dis.rst M Doc/whatsnew/3.11.rst M Grammar/python.gram M Include/internal/pycore_ast.h M Include/internal/pycore_ast_state.h M Include/internal/pycore_pyerrors.h M Include/opcode.h M Lib/ast.py M Lib/importlib/_bootstrap_external.py M Lib/opcode.py M Lib/test/test_ast.py M Lib/test/test_compile.py M Lib/test/test_dis.py M Lib/test/test_exception_group.py M Lib/test/test_exception_variations.py M Lib/test/test_exceptions.py M Lib/test/test_grammar.py M Lib/test/test_syntax.py M Lib/test/test_sys_settrace.py M Lib/test/test_unparse.py M Objects/exceptions.c M Objects/frameobject.c M Parser/Python.asdl M Parser/parser.c M Python/Python-ast.c M Python/ast.c M Python/ast_opt.c M Python/ceval.c M Python/compile.c M Python/opcode_targets.h M Python/symtable.c diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst index e29b5e88d71d4..6486ed4f21696 100644 --- a/Doc/library/ast.rst +++ b/Doc/library/ast.rst @@ -1167,6 +1167,37 @@ Control flow type_ignores=[]) +.. class:: TryStar(body, handlers, orelse, finalbody) + + ``try`` blocks which are followed by ``except*`` clauses. The attributes are the + same as for :class:`Try` but the :class:`ExceptHandler` nodes in ``handlers`` + are interpreted as ``except*`` blocks rather then ``except``. + + .. doctest:: + + >>> print(ast.dump(ast.parse(""" + ... try: + ... ... + ... except* Exception: + ... ... + ... """), indent=4)) + Module( + body=[ + TryStar( + body=[ + Expr( + value=Constant(value=Ellipsis))], + handlers=[ + ExceptHandler( + type=Name(id='Exception', ctx=Load()), + body=[ + Expr( + value=Constant(value=Ellipsis))])], + orelse=[], + finalbody=[])], + type_ignores=[]) + + .. class:: ExceptHandler(type, name, body) A single ``except`` clause. ``type`` is the exception type it will match, diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 9665e8dbf6cfc..7ac5a9b1f5454 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -872,8 +872,10 @@ All of the following opcodes use their arguments. .. versionadded:: 3.1 + .. opcode:: JUMP_IF_NOT_EXC_MATCH (target) + Performs exception matching for ``except``. Tests whether the second value on the stack is an exception matching TOS, and jumps if it is not. Pops one value from the stack. @@ -883,6 +885,30 @@ All of the following opcodes use their arguments. This opcode no longer pops the active exception. +.. opcode:: JUMP_IF_NOT_EG_MATCH (target) + + Performs exception matching for ``except*``. Applies ``split(TOS)`` on + the exception group representing TOS1. Jumps if no match is found. + + Pops one item from the stack. If a match was found, pops the 3 items representing + the exception and pushes the 3 items representing the non-matching part of + the exception group, followed by the 3 items representing the matching part. + In other words, in case of a match it pops 4 items and pushes 6. + + .. versionadded:: 3.11 + + +.. opcode:: PREP_RERAISE_STAR + + Combines the raised and reraised exceptions list from TOS, into an exception + group to propagate from a try-except* block. Uses the original exception + group from TOS1 to reconstruct the structure of reraised exceptions. Pops + two items from the stack and pushes a triplet representing the exception to + reraise or three ``None`` if there isn't one. + + .. versionadded:: 3.11 + + .. opcode:: JUMP_IF_TRUE_OR_POP (target) If TOS is true, sets the bytecode counter to *target* and leaves TOS on the diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 8d1f4eba36eb2..793075c4b6173 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -65,6 +65,8 @@ Summary -- Release highlights .. PEP-sized items next. +PEP-654: Exception Groups and ``except*``. +(Contributed by Irit Katriel in :issue:`45292`.) New Features ============ diff --git a/Grammar/python.gram b/Grammar/python.gram index 2c696a6a085ed..c989823e3091c 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -403,6 +403,8 @@ try_stmt[stmt_ty]: | invalid_try_stmt | 'try' &&':' b=block f=finally_block { _PyAST_Try(b, NULL, NULL, f, EXTRA) } | 'try' &&':' b=block ex[asdl_excepthandler_seq*]=except_block+ el=[else_block] f=[finally_block] { _PyAST_Try(b, ex, el, f, EXTRA) } + | 'try' &&':' b=block ex[asdl_excepthandler_seq*]=except_star_block+ el=[else_block] f=[finally_block] { _PyAST_TryStar(b, ex, el, f, EXTRA) } + # Except statement # ---------------- @@ -413,6 +415,11 @@ except_block[excepthandler_ty]: _PyAST_ExceptHandler(e, (t) ? ((expr_ty) t)->v.Name.id : NULL, b, EXTRA) } | 'except' ':' b=block { _PyAST_ExceptHandler(NULL, NULL, b, EXTRA) } | invalid_except_stmt +except_star_block[excepthandler_ty]: + | invalid_except_star_stmt_indent + | 'except' '*' e=expression t=['as' z=NAME { z }] ':' b=block { + _PyAST_ExceptHandler(e, (t) ? ((expr_ty) t)->v.Name.id : NULL, b, EXTRA) } + | invalid_except_stmt finally_block[asdl_stmt_seq*]: | invalid_finally_stmt | 'finally' &&':' a=block { a } @@ -1192,11 +1199,14 @@ invalid_try_stmt: | a='try' ':' NEWLINE !INDENT { RAISE_INDENTATION_ERROR("expected an indented block after 'try' statement on line %d", a->lineno) } | 'try' ':' block !('except' | 'finally') { RAISE_SYNTAX_ERROR("expected 'except' or 'finally' block") } + | 'try' ':' block* ((except_block+ except_star_block) | (except_star_block+ except_block)) block* { + RAISE_SYNTAX_ERROR("cannot have both 'except' and 'except*' on the same 'try'") } invalid_except_stmt: - | 'except' a=expression ',' expressions ['as' NAME ] ':' { + | 'except' '*'? a=expression ',' expressions ['as' NAME ] ':' { RAISE_SYNTAX_ERROR_STARTING_FROM(a, "multiple exception types must be parenthesized") } - | a='except' expression ['as' NAME ] NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") } + | a='except' '*'? expression ['as' NAME ] NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") } | a='except' NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") } + | a='except' '*' (NEWLINE | ':') { RAISE_SYNTAX_ERROR("expected one or more exception types") } invalid_finally_stmt: | a='finally' ':' NEWLINE !INDENT { RAISE_INDENTATION_ERROR("expected an indented block after 'finally' statement on line %d", a->lineno) } @@ -1204,6 +1214,9 @@ invalid_except_stmt_indent: | a='except' expression ['as' NAME ] ':' NEWLINE !INDENT { RAISE_INDENTATION_ERROR("expected an indented block after 'except' statement on line %d", a->lineno) } | a='except' ':' NEWLINE !INDENT { RAISE_SYNTAX_ERROR("expected an indented block after except statement on line %d", a->lineno) } +invalid_except_star_stmt_indent: + | a='except' '*' expression ['as' NAME ] ':' NEWLINE !INDENT { + RAISE_INDENTATION_ERROR("expected an indented block after 'except*' statement on line %d", a->lineno) } invalid_match_stmt: | "match" subject_expr !':' { CHECK_VERSION(void*, 10, "Pattern matching is", RAISE_SYNTAX_ERROR("expected ':'") ) } | a="match" subject=subject_expr ':' NEWLINE !INDENT { diff --git a/Include/internal/pycore_ast.h b/Include/internal/pycore_ast.h index ebb6a90087bb5..36277efe9c5ca 100644 --- a/Include/internal/pycore_ast.h +++ b/Include/internal/pycore_ast.h @@ -179,9 +179,9 @@ enum _stmt_kind {FunctionDef_kind=1, AsyncFunctionDef_kind=2, ClassDef_kind=3, AugAssign_kind=7, AnnAssign_kind=8, For_kind=9, AsyncFor_kind=10, While_kind=11, If_kind=12, With_kind=13, AsyncWith_kind=14, Match_kind=15, Raise_kind=16, Try_kind=17, - Assert_kind=18, Import_kind=19, ImportFrom_kind=20, - Global_kind=21, Nonlocal_kind=22, Expr_kind=23, Pass_kind=24, - Break_kind=25, Continue_kind=26}; + TryStar_kind=18, Assert_kind=19, Import_kind=20, + ImportFrom_kind=21, Global_kind=22, Nonlocal_kind=23, + Expr_kind=24, Pass_kind=25, Break_kind=26, Continue_kind=27}; struct _stmt { enum _stmt_kind kind; union { @@ -295,6 +295,13 @@ struct _stmt { asdl_stmt_seq *finalbody; } Try; + struct { + asdl_stmt_seq *body; + asdl_excepthandler_seq *handlers; + asdl_stmt_seq *orelse; + asdl_stmt_seq *finalbody; + } TryStar; + struct { expr_ty test; expr_ty msg; @@ -688,6 +695,10 @@ stmt_ty _PyAST_Try(asdl_stmt_seq * body, asdl_excepthandler_seq * handlers, asdl_stmt_seq * orelse, asdl_stmt_seq * finalbody, int lineno, int col_offset, int end_lineno, int end_col_offset, PyArena *arena); +stmt_ty _PyAST_TryStar(asdl_stmt_seq * body, asdl_excepthandler_seq * handlers, + asdl_stmt_seq * orelse, asdl_stmt_seq * finalbody, int + lineno, int col_offset, int end_lineno, int + end_col_offset, PyArena *arena); stmt_ty _PyAST_Assert(expr_ty test, expr_ty msg, int lineno, int col_offset, int end_lineno, int end_col_offset, PyArena *arena); stmt_ty _PyAST_Import(asdl_alias_seq * names, int lineno, int col_offset, int diff --git a/Include/internal/pycore_ast_state.h b/Include/internal/pycore_ast_state.h index 882cd09c00628..da78bba3b69bd 100644 --- a/Include/internal/pycore_ast_state.h +++ b/Include/internal/pycore_ast_state.h @@ -132,6 +132,7 @@ struct ast_state { PyObject *Sub_singleton; PyObject *Sub_type; PyObject *Subscript_type; + PyObject *TryStar_type; PyObject *Try_type; PyObject *Tuple_type; PyObject *TypeIgnore_type; diff --git a/Include/internal/pycore_pyerrors.h b/Include/internal/pycore_pyerrors.h index 3134afeb86490..5e8d2025dfaf0 100644 --- a/Include/internal/pycore_pyerrors.h +++ b/Include/internal/pycore_pyerrors.h @@ -92,6 +92,14 @@ PyAPI_FUNC(PyObject *) _PyErr_FormatFromCauseTstate( const char *format, ...); +PyAPI_FUNC(PyObject *) _PyExc_CreateExceptionGroup( + const char *msg, + PyObject *excs); + +PyAPI_FUNC(PyObject *) _PyExc_ExceptionGroupProjection( + PyObject *left, + PyObject *right); + PyAPI_FUNC(int) _PyErr_CheckSignalsTstate(PyThreadState *tstate); PyAPI_FUNC(void) _Py_DumpExtensionModules(int fd, PyInterpreterState *interp); diff --git a/Include/opcode.h b/Include/opcode.h index f22f7e94f6190..1341a8abad4d7 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -45,6 +45,7 @@ extern "C" { #define IMPORT_STAR 84 #define SETUP_ANNOTATIONS 85 #define YIELD_VALUE 86 +#define PREP_RERAISE_STAR 88 #define POP_EXCEPT 89 #define HAVE_ARGUMENT 90 #define STORE_NAME 90 @@ -83,6 +84,7 @@ extern "C" { #define LOAD_FAST 124 #define STORE_FAST 125 #define DELETE_FAST 126 +#define JUMP_IF_NOT_EG_MATCH 127 #define GEN_START 129 #define RAISE_VARARGS 130 #define CALL_FUNCTION 131 @@ -161,7 +163,7 @@ extern "C" { #define STORE_FAST__LOAD_FAST 80 #define LOAD_FAST__LOAD_CONST 81 #define LOAD_CONST__LOAD_FAST 87 -#define STORE_FAST__STORE_FAST 88 +#define STORE_FAST__STORE_FAST 123 #define DO_TRACING 255 #ifdef NEED_OPCODE_JUMP_TABLES static uint32_t _PyOpcode_RelativeJump[8] = { @@ -178,7 +180,7 @@ static uint32_t _PyOpcode_Jump[8] = { 0U, 0U, 536870912U, - 34586624U, + 2182070272U, 0U, 0U, 0U, diff --git a/Lib/ast.py b/Lib/ast.py index 400d7c45146da..625738ad681af 100644 --- a/Lib/ast.py +++ b/Lib/ast.py @@ -683,6 +683,7 @@ def __init__(self, *, _avoid_backslashes=False): self._type_ignores = {} self._indent = 0 self._avoid_backslashes = _avoid_backslashes + self._in_try_star = False def interleave(self, inter, f, seq): """Call f on each item in seq, calling inter() in between.""" @@ -953,7 +954,7 @@ def visit_Raise(self, node): self.write(" from ") self.traverse(node.cause) - def visit_Try(self, node): + def do_visit_try(self, node): self.fill("try") with self.block(): self.traverse(node.body) @@ -968,8 +969,24 @@ def visit_Try(self, node): with self.block(): self.traverse(node.finalbody) + def visit_Try(self, node): + prev_in_try_star = self._in_try_star + try: + self._in_try_star = False + self.do_visit_try(node) + finally: + self._in_try_star = prev_in_try_star + + def visit_TryStar(self, node): + prev_in_try_star = self._in_try_star + try: + self._in_try_star = True + self.do_visit_try(node) + finally: + self._in_try_star = prev_in_try_star + def visit_ExceptHandler(self, node): - self.fill("except") + self.fill("except*" if self._in_try_star else "except") if node.type: self.write(" ") self.traverse(node.type) diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 6970e9f0a94d4..6e7ea7b378143 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -371,6 +371,7 @@ def _write_atomic(path, data, mode=0o666): # Python 3.11a3 3464 (bpo-45636: Merge numeric BINARY_*/INPLACE_* into # BINARY_OP) # Python 3.11a3 3465 (Add COPY_FREE_VARS opcode) +# Python 3.11a3 3466 (bpo-45292: PEP-654 except*) # # MAGIC must change whenever the bytecode emitted by the compiler may no @@ -380,7 +381,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 = (3465).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3466).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c _PYCACHE = '__pycache__' diff --git a/Lib/opcode.py b/Lib/opcode.py index e5889bca4c161..299216d3c8799 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -103,6 +103,7 @@ def jabs_op(name, op): def_op('SETUP_ANNOTATIONS', 85) def_op('YIELD_VALUE', 86) +def_op('PREP_RERAISE_STAR', 88) def_op('POP_EXCEPT', 89) HAVE_ARGUMENT = 90 # Opcodes from here have an argument: @@ -150,6 +151,8 @@ def jabs_op(name, op): def_op('DELETE_FAST', 126) # Local variable number haslocal.append(126) +jabs_op('JUMP_IF_NOT_EG_MATCH', 127) + def_op('GEN_START', 129) # Kind of generator/coroutine def_op('RAISE_VARARGS', 130) # Number of raise arguments (1, 2, or 3) def_op('CALL_FUNCTION', 131) # #args diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index e630677f79684..314b360c58ba9 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -86,6 +86,8 @@ def to_tuple(t): "try:\n pass\nexcept Exception:\n pass", # TryFinally "try:\n pass\nfinally:\n pass", + # TryStarExcept + "try:\n pass\nexcept* Exception:\n pass", # Assert "assert v", # Import @@ -1310,6 +1312,26 @@ def test_try(self): t = ast.Try([p], e, [p], [ast.Expr(ast.Name("x", ast.Store()))]) self.stmt(t, "must have Load context") + def test_try_star(self): + p = ast.Pass() + t = ast.TryStar([], [], [], [p]) + self.stmt(t, "empty body on TryStar") + t = ast.TryStar([ast.Expr(ast.Name("x", ast.Store()))], [], [], [p]) + self.stmt(t, "must have Load context") + t = ast.TryStar([p], [], [], []) + self.stmt(t, "TryStar has neither except handlers nor finalbody") + t = ast.TryStar([p], [], [p], [p]) + self.stmt(t, "TryStar has orelse but no except handlers") + t = ast.TryStar([p], [ast.ExceptHandler(None, "x", [])], [], []) + self.stmt(t, "empty body on ExceptHandler") + e = [ast.ExceptHandler(ast.Name("x", ast.Store()), "y", [p])] + self.stmt(ast.TryStar([p], e, [], []), "must have Load context") + e = [ast.ExceptHandler(None, "x", [p])] + t = ast.TryStar([p], e, [ast.Expr(ast.Name("x", ast.Store()))], [p]) + self.stmt(t, "must have Load context") + t = ast.TryStar([p], e, [p], [ast.Expr(ast.Name("x", ast.Store()))]) + self.stmt(t, "must have Load context") + def test_assert(self): self.stmt(ast.Assert(ast.Name("x", ast.Store()), None), "must have Load context") @@ -2316,6 +2338,7 @@ def main(): ('Module', [('Raise', (1, 0, 1, 25), ('Call', (1, 6, 1, 25), ('Name', (1, 6, 1, 15), 'Exception', ('Load',)), [('Constant', (1, 16, 1, 24), 'string', None)], []), None)], []), ('Module', [('Try', (1, 0, 4, 6), [('Pass', (2, 2, 2, 6))], [('ExceptHandler', (3, 0, 4, 6), ('Name', (3, 7, 3, 16), 'Exception', ('Load',)), None, [('Pass', (4, 2, 4, 6))])], [], [])], []), ('Module', [('Try', (1, 0, 4, 6), [('Pass', (2, 2, 2, 6))], [], [], [('Pass', (4, 2, 4, 6))])], []), +('Module', [('TryStar', (1, 0, 4, 6), [('Pass', (2, 2, 2, 6))], [('ExceptHandler', (3, 0, 4, 6), ('Name', (3, 8, 3, 17), 'Exception', ('Load',)), None, [('Pass', (4, 2, 4, 6))])], [], [])], []), ('Module', [('Assert', (1, 0, 1, 8), ('Name', (1, 7, 1, 8), 'v', ('Load',)), None)], []), ('Module', [('Import', (1, 0, 1, 10), [('alias', (1, 7, 1, 10), 'sys', None)])], []), ('Module', [('ImportFrom', (1, 0, 1, 17), 'sys', [('alias', (1, 16, 1, 17), 'v', None)], 0)], []), diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index f4ed6c706da66..5bd7b06530691 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -1263,6 +1263,39 @@ def test_try_except_as(self): """ self.check_stack_size(snippet) + def test_try_except_star_qualified(self): + snippet = """ + try: + a + except* ImportError: + b + else: + c + """ + self.check_stack_size(snippet) + + def test_try_except_star_as(self): + snippet = """ + try: + a + except* ImportError as e: + b + else: + c + """ + self.check_stack_size(snippet) + + def test_try_except_star_finally(self): + snippet = """ + try: + a + except* A: + b + finally: + c + """ + self.check_stack_size(snippet) + def test_try_finally(self): snippet = """ try: diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index dd328f072e45d..e821e001ad880 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -1119,7 +1119,7 @@ def _prepare_test_cases(): Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=132, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=134, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=136, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=33, argval=206, argrepr='to 206', offset=138, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=32, argval=204, argrepr='to 204', offset=138, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=140, starts_line=22, is_jump_target=True, positions=None), Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=142, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=144, starts_line=25, is_jump_target=True, positions=None), @@ -1134,7 +1134,7 @@ def _prepare_test_cases(): Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=162, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='CALL_FUNCTION', opcode=131, arg=3, argval=3, argrepr='', offset=164, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=166, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=25, argval=220, argrepr='to 220', offset=168, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=11, argval=192, argrepr='to 192', offset=168, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=170, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=172, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=90, argval=180, argrepr='to 180', offset=174, starts_line=None, is_jump_target=False, positions=None), @@ -1146,34 +1146,26 @@ def _prepare_test_cases(): Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=186, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=188, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=190, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=192, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=194, 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=196, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=198, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=200, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=202, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=204, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=206, starts_line=23, is_jump_target=True, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=208, 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=210, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=212, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=214, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=216, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=218, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=220, starts_line=25, is_jump_target=True, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=222, 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=224, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=226, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=228, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=230, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=232, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=234, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=236, starts_line=None, 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=238, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=240, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=242, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=244, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=246, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=192, starts_line=28, is_jump_target=True, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=194, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=196, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=198, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=200, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=202, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=204, starts_line=23, is_jump_target=True, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=206, 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=208, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=210, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=212, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=214, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=216, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=218, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=220, starts_line=None, 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=222, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=224, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=226, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=228, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=230, starts_line=None, is_jump_target=False, positions=None), ] # One last piece of inspect fodder to check the default line number handling diff --git a/Lib/test/test_except_star.py b/Lib/test/test_except_star.py new file mode 100644 index 0000000000000..b03de9c1de32e --- /dev/null +++ b/Lib/test/test_except_star.py @@ -0,0 +1,976 @@ +import sys +import unittest +import textwrap + +class TestInvalidExceptStar(unittest.TestCase): + def test_mixed_except_and_except_star_is_syntax_error(self): + errors = [ + "try: pass\nexcept ValueError: pass\nexcept* TypeError: pass\n", + "try: pass\nexcept* ValueError: pass\nexcept TypeError: pass\n", + "try: pass\nexcept ValueError as e: pass\nexcept* TypeError: pass\n", + "try: pass\nexcept* ValueError as e: pass\nexcept TypeError: pass\n", + "try: pass\nexcept ValueError: pass\nexcept* TypeError as e: pass\n", + "try: pass\nexcept* ValueError: pass\nexcept TypeError as e: pass\n", + "try: pass\nexcept ValueError: pass\nexcept*: pass\n", + "try: pass\nexcept* ValueError: pass\nexcept: pass\n", + ] + + for err in errors: + with self.assertRaises(SyntaxError): + compile(err, "", "exec") + + def test_except_star_ExceptionGroup_is_runtime_error_single(self): + with self.assertRaises(TypeError): + try: + raise OSError("blah") + except* ExceptionGroup as e: + pass + + def test_except_star_ExceptionGroup_is_runtime_error_tuple(self): + with self.assertRaises(TypeError): + try: + raise ExceptionGroup("eg", [ValueError(42)]) + except* (TypeError, ExceptionGroup): + pass + + def test_except_star_invalid_exception_type(self): + with self.assertRaises(TypeError): + try: + raise ValueError + except* 42: + pass + + with self.assertRaises(TypeError): + try: + raise ValueError + except* (ValueError, 42): + pass + + +class TestBreakContinueReturnInExceptStarBlock(unittest.TestCase): + MSG = (r"'break', 'continue' and 'return'" + r" cannot appear in an except\* block") + + def check_invalid(self, src): + with self.assertRaisesRegex(SyntaxError, self.MSG): + compile(textwrap.dedent(src), "", "exec") + + def test_break_in_except_star(self): + self.check_invalid( + """ + try: + raise ValueError + except* Exception as e: + break + """) + + self.check_invalid( + """ + for i in range(5): + try: + pass + except* Exception as e: + if i == 2: + break + """) + + self.check_invalid( + """ + for i in range(5): + try: + pass + except* Exception as e: + if i == 2: + break + finally: + return 0 + """) + + + def test_continue_in_except_star_block_invalid(self): + self.check_invalid( + """ + for i in range(5): + try: + raise ValueError + except* Exception as e: + continue + """) + + self.check_invalid( + """ + for i in range(5): + try: + pass + except* Exception as e: + if i == 2: + continue + """) + + self.check_invalid( + """ + for i in range(5): + try: + pass + except* Exception as e: + if i == 2: + continue + finally: + return 0 + """) + + def test_return_in_except_star_block_invalid(self): + self.check_invalid( + """ + def f(): + try: + raise ValueError + except* Exception as e: + return 42 + """) + + self.check_invalid( + """ + def f(): + try: + pass + except* Exception as e: + return 42 + finally: + finished = True + """) + + def test_break_continue_in_except_star_block_valid(self): + try: + raise ValueError(42) + except* Exception as e: + count = 0 + for i in range(5): + if i == 0: + continue + if i == 4: + break + count += 1 + + self.assertEqual(count, 3) + self.assertEqual(i, 4) + exc = e + self.assertIsInstance(exc, ExceptionGroup) + + def test_return_in_except_star_block_valid(self): + try: + raise ValueError(42) + except* Exception as e: + def f(x): + return 2*x + r = f(3) + exc = e + self.assertEqual(r, 6) + self.assertIsInstance(exc, ExceptionGroup) + + +class ExceptStarTest(unittest.TestCase): + def assertExceptionIsLike(self, exc, template): + if exc is None and template is None: + return + + if template is None: + self.fail(f"unexpected exception: {exc}") + + if exc is None: + self.fail(f"expected an exception like {template!r}, got None") + + if not isinstance(exc, ExceptionGroup): + self.assertEqual(exc.__class__, template.__class__) + self.assertEqual(exc.args[0], template.args[0]) + else: + self.assertEqual(exc.message, template.message) + self.assertEqual(len(exc.exceptions), len(template.exceptions)) + for e, t in zip(exc.exceptions, template.exceptions): + self.assertExceptionIsLike(e, t) + + def assertMetadataEqual(self, e1, e2): + if e1 is None or e2 is None: + self.assertTrue(e1 is None and e2 is None) + else: + self.assertEqual(e1.__context__, e2.__context__) + self.assertEqual(e1.__cause__, e2.__cause__) + self.assertEqual(e1.__traceback__, e2.__traceback__) + + def assertMetadataNotEqual(self, e1, e2): + if e1 is None or e2 is None: + self.assertNotEqual(e1, e2) + else: + return not (e1.__context__ == e2.__context__ + and e1.__cause__ == e2.__cause__ + and e1.__traceback__ == e2.__traceback__) + + +class TestExceptStarSplitSemantics(ExceptStarTest): + def doSplitTestNamed(self, exc, T, match_template, rest_template): + initial_exc_info = sys.exc_info() + exc_info = match = rest = None + try: + try: + raise exc + except* T as e: + exc_info = sys.exc_info() + match = e + except BaseException as e: + rest = e + + if match_template: + self.assertEqual(exc_info[1], match) + else: + self.assertIsNone(exc_info) + self.assertExceptionIsLike(match, match_template) + self.assertExceptionIsLike(rest, rest_template) + self.assertEqual(sys.exc_info(), initial_exc_info) + + def doSplitTestUnnamed(self, exc, T, match_template, rest_template): + initial_exc_info = sys.exc_info() + exc_info = match = rest = None + try: + try: + raise exc + except* T: + exc_info = sys.exc_info() + match = sys.exc_info()[1] + else: + if rest_template: + self.fail("Exception not raised") + except BaseException as e: + rest = e + self.assertExceptionIsLike(match, match_template) + if match_template: + self.assertEqual(exc_info[0], type(match_template)) + self.assertExceptionIsLike(rest, rest_template) + self.assertEqual(sys.exc_info(), initial_exc_info) + + def doSplitTestInExceptHandler(self, exc, T, match_template, rest_template): + try: + raise ExceptionGroup('eg', [TypeError(1), ValueError(2)]) + except Exception: + self.doSplitTestNamed(exc, T, match_template, rest_template) + self.doSplitTestUnnamed(exc, T, match_template, rest_template) + + def doSplitTestInExceptStarHandler(self, exc, T, match_template, rest_template): + try: + raise ExceptionGroup('eg', [TypeError(1), ValueError(2)]) + except* Exception: + self.doSplitTestNamed(exc, T, match_template, rest_template) + self.doSplitTestUnnamed(exc, T, match_template, rest_template) + + def doSplitTest(self, exc, T, match_template, rest_template): + self.doSplitTestNamed(exc, T, match_template, rest_template) + self.doSplitTestUnnamed(exc, T, match_template, rest_template) + self.doSplitTestInExceptHandler(exc, T, match_template, rest_template) + self.doSplitTestInExceptStarHandler(exc, T, match_template, rest_template) + + def test_no_match_single_type(self): + self.doSplitTest( + ExceptionGroup("test1", [ValueError("V"), TypeError("T")]), + SyntaxError, + None, + ExceptionGroup("test1", [ValueError("V"), TypeError("T")])) + + def test_match_single_type(self): + self.doSplitTest( + ExceptionGroup("test2", [ValueError("V1"), ValueError("V2")]), + ValueError, + ExceptionGroup("test2", [ValueError("V1"), ValueError("V2")]), + None) + + def test_match_single_type_partial_match(self): + self.doSplitTest( + ExceptionGroup( + "test3", + [ValueError("V1"), OSError("OS"), ValueError("V2")]), + ValueError, + ExceptionGroup("test3", [ValueError("V1"), ValueError("V2")]), + ExceptionGroup("test3", [OSError("OS")])) + + def test_match_single_type_nested(self): + self.doSplitTest( + ExceptionGroup( + "g1", [ + ValueError("V1"), + OSError("OS1"), + ExceptionGroup( + "g2", [ + OSError("OS2"), + ValueError("V2"), + TypeError("T")])]), + ValueError, + ExceptionGroup( + "g1", [ + ValueError("V1"), + ExceptionGroup("g2", [ValueError("V2")])]), + ExceptionGroup("g1", [ + OSError("OS1"), + ExceptionGroup("g2", [ + OSError("OS2"), TypeError("T")])])) + + def test_match_type_tuple_nested(self): + self.doSplitTest( + ExceptionGroup( + "h1", [ + ValueError("V1"), + OSError("OS1"), + ExceptionGroup( + "h2", [OSError("OS2"), ValueError("V2"), TypeError("T")])]), + (ValueError, TypeError), + ExceptionGroup( + "h1", [ + ValueError("V1"), + ExceptionGroup("h2", [ValueError("V2"), TypeError("T")])]), + ExceptionGroup( + "h1", [ + OSError("OS1"), + ExceptionGroup("h2", [OSError("OS2")])])) + + def test_empty_groups_removed(self): + self.doSplitTest( + ExceptionGroup( + "eg", [ + ExceptionGroup("i1", [ValueError("V1")]), + ExceptionGroup("i2", [ValueError("V2"), TypeError("T1")]), + ExceptionGroup("i3", [TypeError("T2")])]), + TypeError, + ExceptionGroup("eg", [ + ExceptionGroup("i2", [TypeError("T1")]), + ExceptionGroup("i3", [TypeError("T2")])]), + ExceptionGroup("eg", [ + ExceptionGroup("i1", [ValueError("V1")]), + ExceptionGroup("i2", [ValueError("V2")])])) + + def test_singleton_groups_are_kept(self): + self.doSplitTest( + ExceptionGroup("j1", [ + ExceptionGroup("j2", [ + ExceptionGroup("j3", [ValueError("V1")]), + ExceptionGroup("j4", [TypeError("T")])])]), + TypeError, + ExceptionGroup( + "j1", + [ExceptionGroup("j2", [ExceptionGroup("j4", [TypeError("T")])])]), + ExceptionGroup( + "j1", + [ExceptionGroup("j2", [ExceptionGroup("j3", [ValueError("V1")])])])) + + def test_naked_exception_matched_wrapped1(self): + self.doSplitTest( + ValueError("V"), + ValueError, + ExceptionGroup("", [ValueError("V")]), + None) + + def test_naked_exception_matched_wrapped2(self): + self.doSplitTest( + ValueError("V"), + Exception, + ExceptionGroup("", [ValueError("V")]), + None) + + def test_exception_group_except_star_Exception_not_wrapped(self): + self.doSplitTest( + ExceptionGroup("eg", [ValueError("V")]), + Exception, + ExceptionGroup("eg", [ValueError("V")]), + None) + + def test_plain_exception_not_matched(self): + self.doSplitTest( + ValueError("V"), + TypeError, + None, + ValueError("V")) + + def test_match__supertype(self): + self.doSplitTest( + ExceptionGroup("st", [BlockingIOError("io"), TypeError("T")]), + OSError, + ExceptionGroup("st", [BlockingIOError("io")]), + ExceptionGroup("st", [TypeError("T")])) + + def test_multiple_matches_named(self): + try: + raise ExceptionGroup("mmn", [OSError("os"), BlockingIOError("io")]) + except* BlockingIOError as e: + self.assertExceptionIsLike(e, + ExceptionGroup("mmn", [BlockingIOError("io")])) + except* OSError as e: + self.assertExceptionIsLike(e, + ExceptionGroup("mmn", [OSError("os")])) + else: + self.fail("Exception not raised") + + def test_multiple_matches_unnamed(self): + try: + raise ExceptionGroup("mmu", [OSError("os"), BlockingIOError("io")]) + except* BlockingIOError: + e = sys.exc_info()[1] + self.assertExceptionIsLike(e, + ExceptionGroup("mmu", [BlockingIOError("io")])) + except* OSError: + e = sys.exc_info()[1] + self.assertExceptionIsLike(e, + ExceptionGroup("mmu", [OSError("os")])) + else: + self.fail("Exception not raised") + + def test_first_match_wins_named(self): + try: + raise ExceptionGroup("fst", [BlockingIOError("io")]) + except* OSError as e: + self.assertExceptionIsLike(e, + ExceptionGroup("fst", [BlockingIOError("io")])) + except* BlockingIOError: + self.fail("Should have been matched as OSError") + else: + self.fail("Exception not raised") + + def test_first_match_wins_unnamed(self): + try: + raise ExceptionGroup("fstu", [BlockingIOError("io")]) + except* OSError: + e = sys.exc_info()[1] + self.assertExceptionIsLike(e, + ExceptionGroup("fstu", [BlockingIOError("io")])) + except* BlockingIOError: + pass + else: + self.fail("Exception not raised") + + def test_nested_except_stars(self): + try: + raise ExceptionGroup("n", [BlockingIOError("io")]) + except* BlockingIOError: + try: + raise ExceptionGroup("n", [ValueError("io")]) + except* ValueError: + pass + else: + self.fail("Exception not raised") + e = sys.exc_info()[1] + self.assertExceptionIsLike(e, + ExceptionGroup("n", [BlockingIOError("io")])) + else: + self.fail("Exception not raised") + + def test_nested_in_loop(self): + for _ in range(2): + try: + raise ExceptionGroup("nl", [BlockingIOError("io")]) + except* BlockingIOError: + pass + else: + self.fail("Exception not raised") + + +class TestExceptStarReraise(ExceptStarTest): + def test_reraise_all_named(self): + try: + try: + raise ExceptionGroup( + "eg", [TypeError(1), ValueError(2), OSError(3)]) + except* TypeError as e: + raise + except* ValueError as e: + raise + # OSError not handled + except ExceptionGroup as e: + exc = e + + self.assertExceptionIsLike( + exc, + ExceptionGroup("eg", [TypeError(1), ValueError(2), OSError(3)])) + + def test_reraise_all_unnamed(self): + try: + try: + raise ExceptionGroup( + "eg", [TypeError(1), ValueError(2), OSError(3)]) + except* TypeError: + raise + except* ValueError: + raise + # OSError not handled + except ExceptionGroup as e: + exc = e + + self.assertExceptionIsLike( + exc, + ExceptionGroup("eg", [TypeError(1), ValueError(2), OSError(3)])) + + def test_reraise_some_handle_all_named(self): + try: + try: + raise ExceptionGroup( + "eg", [TypeError(1), ValueError(2), OSError(3)]) + except* TypeError as e: + raise + except* ValueError as e: + pass + # OSError not handled + except ExceptionGroup as e: + exc = e + + self.assertExceptionIsLike( + exc, ExceptionGroup("eg", [TypeError(1), OSError(3)])) + + def test_reraise_partial_handle_all_unnamed(self): + try: + try: + raise ExceptionGroup( + "eg", [TypeError(1), ValueError(2)]) + except* TypeError: + raise + except* ValueError: + pass + except ExceptionGroup as e: + exc = e + + self.assertExceptionIsLike( + exc, ExceptionGroup("eg", [TypeError(1)])) + + def test_reraise_partial_handle_some_named(self): + try: + try: + raise ExceptionGroup( + "eg", [TypeError(1), ValueError(2), OSError(3)]) + except* TypeError as e: + raise + except* ValueError as e: + pass + # OSError not handled + except ExceptionGroup as e: + exc = e + + self.assertExceptionIsLike( + exc, ExceptionGroup("eg", [TypeError(1), OSError(3)])) + + def test_reraise_partial_handle_some_unnamed(self): + try: + try: + raise ExceptionGroup( + "eg", [TypeError(1), ValueError(2), OSError(3)]) + except* TypeError: + raise + except* ValueError: + pass + except ExceptionGroup as e: + exc = e + + self.assertExceptionIsLike( + exc, ExceptionGroup("eg", [TypeError(1), OSError(3)])) + + def test_reraise_plain_exception_named(self): + try: + try: + raise ValueError(42) + except* ValueError as e: + raise + except ExceptionGroup as e: + exc = e + + self.assertExceptionIsLike( + exc, ExceptionGroup("", [ValueError(42)])) + + def test_reraise_plain_exception_unnamed(self): + try: + try: + raise ValueError(42) + except* ValueError: + raise + except ExceptionGroup as e: + exc = e + + self.assertExceptionIsLike( + exc, ExceptionGroup("", [ValueError(42)])) + + +class TestExceptStarRaise(ExceptStarTest): + def test_raise_named(self): + orig = ExceptionGroup("eg", [ValueError(1), OSError(2)]) + try: + try: + raise orig + except* OSError as e: + raise TypeError(3) + except ExceptionGroup as e: + exc = e + + self.assertExceptionIsLike( + exc, + ExceptionGroup( + "", [TypeError(3), ExceptionGroup("eg", [ValueError(1)])])) + + self.assertExceptionIsLike( + exc.exceptions[0].__context__, + ExceptionGroup("eg", [OSError(2)])) + + self.assertMetadataNotEqual(orig, exc) + self.assertMetadataEqual(orig, exc.exceptions[0].__context__) + + def test_raise_unnamed(self): + orig = ExceptionGroup("eg", [ValueError(1), OSError(2)]) + try: + try: + raise orig + except* OSError: + raise TypeError(3) + except ExceptionGroup as e: + exc = e + + self.assertExceptionIsLike( + exc, + ExceptionGroup( + "", [TypeError(3), ExceptionGroup("eg", [ValueError(1)])])) + + self.assertExceptionIsLike( + exc.exceptions[0].__context__, + ExceptionGroup("eg", [OSError(2)])) + + self.assertMetadataNotEqual(orig, exc) + self.assertMetadataEqual(orig, exc.exceptions[0].__context__) + + def test_raise_handle_all_raise_one_named(self): + orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)]) + try: + try: + raise orig + except* (TypeError, ValueError) as e: + raise SyntaxError(3) + except BaseException as e: + exc = e + + self.assertExceptionIsLike( + exc, ExceptionGroup("", [SyntaxError(3)])) + + self.assertExceptionIsLike( + exc.exceptions[0].__context__, + ExceptionGroup("eg", [TypeError(1), ValueError(2)])) + + self.assertMetadataNotEqual(orig, exc) + self.assertMetadataEqual(orig, exc.exceptions[0].__context__) + + def test_raise_handle_all_raise_one_unnamed(self): + orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)]) + try: + try: + raise orig + except* (TypeError, ValueError) as e: + raise SyntaxError(3) + except ExceptionGroup as e: + exc = e + + self.assertExceptionIsLike( + exc, ExceptionGroup("", [SyntaxError(3)])) + + self.assertExceptionIsLike( + exc.exceptions[0].__context__, + ExceptionGroup("eg", [TypeError(1), ValueError(2)])) + + self.assertMetadataNotEqual(orig, exc) + self.assertMetadataEqual(orig, exc.exceptions[0].__context__) + + def test_raise_handle_all_raise_two_named(self): + orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)]) + try: + try: + raise orig + except* TypeError as e: + raise SyntaxError(3) + except* ValueError as e: + raise SyntaxError(4) + except ExceptionGroup as e: + exc = e + + self.assertExceptionIsLike( + exc, ExceptionGroup("", [SyntaxError(3), SyntaxError(4)])) + + self.assertExceptionIsLike( + exc.exceptions[0].__context__, + ExceptionGroup("eg", [TypeError(1)])) + + self.assertExceptionIsLike( + exc.exceptions[1].__context__, + ExceptionGroup("eg", [ValueError(2)])) + + self.assertMetadataNotEqual(orig, exc) + self.assertMetadataEqual(orig, exc.exceptions[0].__context__) + self.assertMetadataEqual(orig, exc.exceptions[1].__context__) + + def test_raise_handle_all_raise_two_unnamed(self): + orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)]) + try: + try: + raise orig + except* TypeError: + raise SyntaxError(3) + except* ValueError: + raise SyntaxError(4) + except ExceptionGroup as e: + exc = e + + self.assertExceptionIsLike( + exc, ExceptionGroup("", [SyntaxError(3), SyntaxError(4)])) + + self.assertExceptionIsLike( + exc.exceptions[0].__context__, + ExceptionGroup("eg", [TypeError(1)])) + + self.assertExceptionIsLike( + exc.exceptions[1].__context__, + ExceptionGroup("eg", [ValueError(2)])) + + self.assertMetadataNotEqual(orig, exc) + self.assertMetadataEqual(orig, exc.exceptions[0].__context__) + self.assertMetadataEqual(orig, exc.exceptions[1].__context__) + + +class TestExceptStarRaiseFrom(ExceptStarTest): + def test_raise_named(self): + orig = ExceptionGroup("eg", [ValueError(1), OSError(2)]) + try: + try: + raise orig + except* OSError as e: + raise TypeError(3) from e + except ExceptionGroup as e: + exc = e + + self.assertExceptionIsLike( + exc, + ExceptionGroup( + "", [TypeError(3), ExceptionGroup("eg", [ValueError(1)])])) + + self.assertExceptionIsLike( + exc.exceptions[0].__context__, + ExceptionGroup("eg", [OSError(2)])) + + self.assertExceptionIsLike( + exc.exceptions[0].__cause__, + ExceptionGroup("eg", [OSError(2)])) + + self.assertMetadataNotEqual(orig, exc) + self.assertMetadataEqual(orig, exc.exceptions[0].__context__) + self.assertMetadataEqual(orig, exc.exceptions[0].__cause__) + self.assertMetadataNotEqual(orig, exc.exceptions[1].__context__) + self.assertMetadataNotEqual(orig, exc.exceptions[1].__cause__) + + def test_raise_unnamed(self): + orig = ExceptionGroup("eg", [ValueError(1), OSError(2)]) + try: + try: + raise orig + except* OSError: + e = sys.exc_info()[1] + raise TypeError(3) from e + except ExceptionGroup as e: + exc = e + + self.assertExceptionIsLike( + exc, + ExceptionGroup( + "", [TypeError(3), ExceptionGroup("eg", [ValueError(1)])])) + + self.assertExceptionIsLike( + exc.exceptions[0].__context__, + ExceptionGroup("eg", [OSError(2)])) + + self.assertExceptionIsLike( + exc.exceptions[0].__cause__, + ExceptionGroup("eg", [OSError(2)])) + + self.assertMetadataNotEqual(orig, exc) + self.assertMetadataEqual(orig, exc.exceptions[0].__context__) + self.assertMetadataEqual(orig, exc.exceptions[0].__cause__) + self.assertMetadataNotEqual(orig, exc.exceptions[1].__context__) + self.assertMetadataNotEqual(orig, exc.exceptions[1].__cause__) + + def test_raise_handle_all_raise_one_named(self): + orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)]) + try: + try: + raise orig + except* (TypeError, ValueError) as e: + raise SyntaxError(3) from e + except BaseException as e: + exc = e + + self.assertExceptionIsLike( + exc, ExceptionGroup("", [SyntaxError(3)])) + + self.assertExceptionIsLike( + exc.exceptions[0].__context__, + ExceptionGroup("eg", [TypeError(1), ValueError(2)])) + + self.assertExceptionIsLike( + exc.exceptions[0].__cause__, + ExceptionGroup("eg", [TypeError(1), ValueError(2)])) + + self.assertMetadataNotEqual(orig, exc) + self.assertMetadataEqual(orig, exc.exceptions[0].__context__) + self.assertMetadataEqual(orig, exc.exceptions[0].__cause__) + + def test_raise_handle_all_raise_one_unnamed(self): + orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)]) + try: + try: + raise orig + except* (TypeError, ValueError) as e: + e = sys.exc_info()[1] + raise SyntaxError(3) from e + except ExceptionGroup as e: + exc = e + + self.assertExceptionIsLike( + exc, ExceptionGroup("", [SyntaxError(3)])) + + self.assertExceptionIsLike( + exc.exceptions[0].__context__, + ExceptionGroup("eg", [TypeError(1), ValueError(2)])) + + self.assertExceptionIsLike( + exc.exceptions[0].__cause__, + ExceptionGroup("eg", [TypeError(1), ValueError(2)])) + + self.assertMetadataNotEqual(orig, exc) + self.assertMetadataEqual(orig, exc.exceptions[0].__context__) + self.assertMetadataEqual(orig, exc.exceptions[0].__cause__) + + def test_raise_handle_all_raise_two_named(self): + orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)]) + try: + try: + raise orig + except* TypeError as e: + raise SyntaxError(3) from e + except* ValueError as e: + raise SyntaxError(4) from e + except ExceptionGroup as e: + exc = e + + self.assertExceptionIsLike( + exc, ExceptionGroup("", [SyntaxError(3), SyntaxError(4)])) + + self.assertExceptionIsLike( + exc.exceptions[0].__context__, + ExceptionGroup("eg", [TypeError(1)])) + + self.assertExceptionIsLike( + exc.exceptions[0].__cause__, + ExceptionGroup("eg", [TypeError(1)])) + + self.assertExceptionIsLike( + exc.exceptions[1].__context__, + ExceptionGroup("eg", [ValueError(2)])) + + self.assertExceptionIsLike( + exc.exceptions[1].__cause__, + ExceptionGroup("eg", [ValueError(2)])) + + self.assertMetadataNotEqual(orig, exc) + self.assertMetadataEqual(orig, exc.exceptions[0].__context__) + self.assertMetadataEqual(orig, exc.exceptions[0].__cause__) + + def test_raise_handle_all_raise_two_unnamed(self): + orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)]) + try: + try: + raise orig + except* TypeError: + e = sys.exc_info()[1] + raise SyntaxError(3) from e + except* ValueError: + e = sys.exc_info()[1] + raise SyntaxError(4) from e + except ExceptionGroup as e: + exc = e + + self.assertExceptionIsLike( + exc, ExceptionGroup("", [SyntaxError(3), SyntaxError(4)])) + + self.assertExceptionIsLike( + exc.exceptions[0].__context__, + ExceptionGroup("eg", [TypeError(1)])) + + self.assertExceptionIsLike( + exc.exceptions[0].__cause__, + ExceptionGroup("eg", [TypeError(1)])) + + self.assertExceptionIsLike( + exc.exceptions[1].__context__, + ExceptionGroup("eg", [ValueError(2)])) + + self.assertExceptionIsLike( + exc.exceptions[1].__cause__, + ExceptionGroup("eg", [ValueError(2)])) + + self.assertMetadataNotEqual(orig, exc) + self.assertMetadataEqual(orig, exc.exceptions[0].__context__) + self.assertMetadataEqual(orig, exc.exceptions[0].__cause__) + self.assertMetadataEqual(orig, exc.exceptions[1].__context__) + self.assertMetadataEqual(orig, exc.exceptions[1].__cause__) + + +class TestExceptStarExceptionGroupSubclass(ExceptStarTest): + def test_except_star_EG_subclass(self): + class EG(ExceptionGroup): + def __new__(cls, message, excs, code): + obj = super().__new__(cls, message, excs) + obj.code = code + return obj + + def derive(self, excs): + return EG(self.message, excs, self.code) + + try: + try: + try: + try: + raise TypeError(2) + except TypeError as te: + raise EG("nested", [te], 101) from None + except EG as nested: + try: + raise ValueError(1) + except ValueError as ve: + raise EG("eg", [ve, nested], 42) + except* ValueError as eg: + veg = eg + except EG as eg: + teg = eg + + self.assertIsInstance(veg, EG) + self.assertIsInstance(teg, EG) + self.assertIsInstance(teg.exceptions[0], EG) + self.assertMetadataEqual(veg, teg) + self.assertEqual(veg.code, 42) + self.assertEqual(teg.code, 42) + self.assertEqual(teg.exceptions[0].code, 101) + + +class TestExceptStarCleanup(ExceptStarTest): + def test_exc_info_restored(self): + try: + try: + raise ValueError(42) + except: + try: + raise TypeError(int) + except* Exception: + pass + 1/0 + except Exception as e: + exc = e + + self.assertExceptionIsLike(exc, ZeroDivisionError('division by zero')) + self.assertExceptionIsLike(exc.__context__, ValueError(42)) + self.assertEqual(sys.exc_info(), (None, None, None)) + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_exception_group.py b/Lib/test/test_exception_group.py index 62ec1ee248de5..c793c45e7241a 100644 --- a/Lib/test/test_exception_group.py +++ b/Lib/test/test_exception_group.py @@ -211,7 +211,8 @@ def setUp(self): def test_basics_subgroup_split__bad_arg_type(self): bad_args = ["bad arg", OSError('instance not type'), - [OSError('instance not type')],] + [OSError, TypeError], + (OSError, 42)] for arg in bad_args: with self.assertRaises(TypeError): self.eg.subgroup(arg) diff --git a/Lib/test/test_exception_variations.py b/Lib/test/test_exception_variations.py index d874b0e3d10a8..aabac6d27701f 100644 --- a/Lib/test/test_exception_variations.py +++ b/Lib/test/test_exception_variations.py @@ -172,5 +172,283 @@ def test_nested_else(self): self.assertTrue(hit_finally) self.assertTrue(hit_except) + +class ExceptStarTestCases(unittest.TestCase): + def test_try_except_else_finally(self): + hit_except = False + hit_else = False + hit_finally = False + + try: + raise Exception('nyaa!') + except* BaseException: + hit_except = True + else: + hit_else = True + finally: + hit_finally = True + + self.assertTrue(hit_except) + self.assertTrue(hit_finally) + self.assertFalse(hit_else) + + def test_try_except_else_finally_no_exception(self): + hit_except = False + hit_else = False + hit_finally = False + + try: + pass + except* BaseException: + hit_except = True + else: + hit_else = True + finally: + hit_finally = True + + self.assertFalse(hit_except) + self.assertTrue(hit_finally) + self.assertTrue(hit_else) + + def test_try_except_finally(self): + hit_except = False + hit_finally = False + + try: + raise Exception('yarr!') + except* BaseException: + hit_except = True + finally: + hit_finally = True + + self.assertTrue(hit_except) + self.assertTrue(hit_finally) + + def test_try_except_finally_no_exception(self): + hit_except = False + hit_finally = False + + try: + pass + except* BaseException: + hit_except = True + finally: + hit_finally = True + + self.assertFalse(hit_except) + self.assertTrue(hit_finally) + + def test_try_except(self): + hit_except = False + + try: + raise Exception('ahoy!') + except* BaseException: + hit_except = True + + self.assertTrue(hit_except) + + def test_try_except_no_exception(self): + hit_except = False + + try: + pass + except* BaseException: + hit_except = True + + self.assertFalse(hit_except) + + def test_try_except_else(self): + hit_except = False + hit_else = False + + try: + raise Exception('foo!') + except* BaseException: + hit_except = True + else: + hit_else = True + + self.assertFalse(hit_else) + self.assertTrue(hit_except) + + def test_try_except_else_no_exception(self): + hit_except = False + hit_else = False + + try: + pass + except* BaseException: + hit_except = True + else: + hit_else = True + + self.assertFalse(hit_except) + self.assertTrue(hit_else) + + def test_try_finally_no_exception(self): + hit_finally = False + + try: + pass + finally: + hit_finally = True + + self.assertTrue(hit_finally) + + def test_nested(self): + hit_finally = False + hit_inner_except = False + hit_inner_finally = False + + try: + try: + raise Exception('inner exception') + except* BaseException: + hit_inner_except = True + finally: + hit_inner_finally = True + finally: + hit_finally = True + + self.assertTrue(hit_inner_except) + self.assertTrue(hit_inner_finally) + self.assertTrue(hit_finally) + + def test_nested_else(self): + hit_else = False + hit_finally = False + hit_except = False + hit_inner_except = False + hit_inner_else = False + + try: + try: + pass + except* BaseException: + hit_inner_except = True + else: + hit_inner_else = True + + raise Exception('outer exception') + except* BaseException: + hit_except = True + else: + hit_else = True + finally: + hit_finally = True + + self.assertFalse(hit_inner_except) + self.assertTrue(hit_inner_else) + self.assertFalse(hit_else) + self.assertTrue(hit_finally) + self.assertTrue(hit_except) + + def test_nested_mixed1(self): + hit_except = False + hit_finally = False + hit_inner_except = False + hit_inner_finally = False + + try: + try: + raise Exception('inner exception') + except* BaseException: + hit_inner_except = True + finally: + hit_inner_finally = True + except: + hit_except = True + finally: + hit_finally = True + + self.assertTrue(hit_inner_except) + self.assertTrue(hit_inner_finally) + self.assertFalse(hit_except) + self.assertTrue(hit_finally) + + def test_nested_mixed2(self): + hit_except = False + hit_finally = False + hit_inner_except = False + hit_inner_finally = False + + try: + try: + raise Exception('inner exception') + except: + hit_inner_except = True + finally: + hit_inner_finally = True + except* BaseException: + hit_except = True + finally: + hit_finally = True + + self.assertTrue(hit_inner_except) + self.assertTrue(hit_inner_finally) + self.assertFalse(hit_except) + self.assertTrue(hit_finally) + + + def test_nested_else_mixed1(self): + hit_else = False + hit_finally = False + hit_except = False + hit_inner_except = False + hit_inner_else = False + + try: + try: + pass + except* BaseException: + hit_inner_except = True + else: + hit_inner_else = True + + raise Exception('outer exception') + except: + hit_except = True + else: + hit_else = True + finally: + hit_finally = True + + self.assertFalse(hit_inner_except) + self.assertTrue(hit_inner_else) + self.assertFalse(hit_else) + self.assertTrue(hit_finally) + self.assertTrue(hit_except) + + def test_nested_else_mixed2(self): + hit_else = False + hit_finally = False + hit_except = False + hit_inner_except = False + hit_inner_else = False + + try: + try: + pass + except: + hit_inner_except = True + else: + hit_inner_else = True + + raise Exception('outer exception') + except* BaseException: + hit_except = True + else: + hit_else = True + finally: + hit_finally = True + + self.assertFalse(hit_inner_except) + self.assertTrue(hit_inner_else) + self.assertFalse(hit_else) + self.assertTrue(hit_finally) + self.assertTrue(hit_except) + + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index ffcb5e1ff5ad1..3e7808c449955 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -241,6 +241,8 @@ def testSyntaxErrorOffset(self): check('def f():\n continue', 2, 3) check('def f():\n break', 2, 3) check('try:\n pass\nexcept:\n pass\nexcept ValueError:\n pass', 3, 1) + check('try:\n pass\nexcept*:\n pass', 3, 8) + check('try:\n pass\nexcept*:\n pass\nexcept* ValueError:\n pass', 3, 8) # Errors thrown by tokenizer.c check('(0x+1)', 1, 3) diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py index b6c457465609a..a2460add4c9ee 100644 --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -1419,6 +1419,30 @@ def test_try(self): compile("try:\n pass\nexcept Exception as a.b:\n pass", "?", "exec") compile("try:\n pass\nexcept Exception as a[b]:\n pass", "?", "exec") + def test_try_star(self): + ### try_stmt: 'try': suite (except_star_clause : suite) + ['else' ':' suite] + ### except_star_clause: 'except*' expr ['as' NAME] + try: + 1/0 + except* ZeroDivisionError: + pass + else: + pass + try: 1/0 + except* EOFError: pass + except* ZeroDivisionError as msg: pass + else: pass + try: 1/0 + except* (EOFError, TypeError, ZeroDivisionError): pass + try: 1/0 + except* (EOFError, TypeError, ZeroDivisionError) as msg: pass + try: pass + finally: pass + with self.assertRaises(SyntaxError): + compile("try:\n pass\nexcept* Exception as a.b:\n pass", "?", "exec") + compile("try:\n pass\nexcept* Exception as a[b]:\n pass", "?", "exec") + compile("try:\n pass\nexcept*:\n pass", "?", "exec") + def test_suite(self): # simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT if 1: pass diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index fc3c62954a29b..6286529d2734e 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -955,6 +955,48 @@ Traceback (most recent call last): SyntaxError: expected 'except' or 'finally' block +Custom error message for try block mixing except and except* + + >>> try: + ... pass + ... except TypeError: + ... pass + ... except* ValueError: + ... pass + Traceback (most recent call last): + SyntaxError: cannot have both 'except' and 'except*' on the same 'try' + + >>> try: + ... pass + ... except* TypeError: + ... pass + ... except ValueError: + ... pass + Traceback (most recent call last): + SyntaxError: cannot have both 'except' and 'except*' on the same 'try' + + >>> try: + ... pass + ... except TypeError: + ... pass + ... except TypeError: + ... pass + ... except* ValueError: + ... pass + Traceback (most recent call last): + SyntaxError: cannot have both 'except' and 'except*' on the same 'try' + + >>> try: + ... pass + ... except* TypeError: + ... pass + ... except* TypeError: + ... pass + ... except ValueError: + ... pass + Traceback (most recent call last): + SyntaxError: cannot have both 'except' and 'except*' on the same 'try' + Ensure that early = are not matched by the parser as invalid comparisons >>> f(2, 4, x=34); 1 $ 2 Traceback (most recent call last): @@ -1068,6 +1110,13 @@ Traceback (most recent call last): IndentationError: expected an indented block after 'except' statement on line 3 + >>> try: + ... something() + ... except* A: + ... pass + Traceback (most recent call last): + IndentationError: expected an indented block after 'except*' statement on line 3 + >>> try: ... something() ... except A: @@ -1077,6 +1126,15 @@ Traceback (most recent call last): IndentationError: expected an indented block after 'finally' statement on line 5 + >>> try: + ... something() + ... except* A: + ... pass + ... finally: + ... pass + Traceback (most recent call last): + IndentationError: expected an indented block after 'finally' statement on line 5 + >>> with A: ... pass Traceback (most recent call last): @@ -1180,6 +1238,48 @@ SyntaxError: multiple exception types must be parenthesized + >>> try: + ... pass + ... except* A, B: + ... pass + Traceback (most recent call last): + SyntaxError: multiple exception types must be parenthesized + + >>> try: + ... pass + ... except* A, B, C: + ... pass + Traceback (most recent call last): + SyntaxError: multiple exception types must be parenthesized + + >>> try: + ... pass + ... except* A, B, C as blech: + ... pass + Traceback (most recent call last): + SyntaxError: multiple exception types must be parenthesized + + >>> try: + ... pass + ... except* A, B, C as blech: + ... pass + ... finally: + ... pass + Traceback (most recent call last): + SyntaxError: multiple exception types must be parenthesized + +Custom exception for 'except*' without an exception type + + >>> try: + ... pass + ... except* A as a: + ... pass + ... except*: + ... pass + Traceback (most recent call last): + SyntaxError: expected one or more exception types + + >>> f(a=23, a=234) Traceback (most recent call last): ... diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py index 15c33a28ff2ac..dc2aef1545b0c 100644 --- a/Lib/test/test_sys_settrace.py +++ b/Lib/test/test_sys_settrace.py @@ -1213,6 +1213,181 @@ def func(): (5, 'line'), (5, 'return')]) + def test_try_except_star_no_exception(self): + + def func(): + try: + 2 + except* Exception: + 4 + else: + 6 + finally: + 8 + + self.run_and_compare(func, + [(0, 'call'), + (1, 'line'), + (2, 'line'), + (6, 'line'), + (8, 'line'), + (8, 'return')]) + + def test_try_except_star_named_no_exception(self): + + def func(): + try: + 2 + except* Exception as e: + 4 + else: + 6 + finally: + 8 + + self.run_and_compare(func, + [(0, 'call'), + (1, 'line'), + (2, 'line'), + (6, 'line'), + (8, 'line'), + (8, 'return')]) + + def test_try_except_star_exception_caught(self): + + def func(): + try: + raise ValueError(2) + except* ValueError: + 4 + else: + 6 + finally: + 8 + + self.run_and_compare(func, + [(0, 'call'), + (1, 'line'), + (2, 'line'), + (2, 'exception'), + (3, 'line'), + (4, 'line'), + (8, 'line'), + (8, 'return')]) + + def test_try_except_star_named_exception_caught(self): + + def func(): + try: + raise ValueError(2) + except* ValueError as e: + 4 + else: + 6 + finally: + 8 + + self.run_and_compare(func, + [(0, 'call'), + (1, 'line'), + (2, 'line'), + (2, 'exception'), + (3, 'line'), + (4, 'line'), + (8, 'line'), + (8, 'return')]) + + def test_try_except_star_exception_not_caught(self): + + def func(): + try: + try: + raise ValueError(3) + except* TypeError: + 5 + except ValueError: + 7 + + self.run_and_compare(func, + [(0, 'call'), + (1, 'line'), + (2, 'line'), + (3, 'line'), + (3, 'exception'), + (4, 'line'), + (6, 'line'), + (7, 'line'), + (7, 'return')]) + + def test_try_except_star_named_exception_not_caught(self): + + def func(): + try: + try: + raise ValueError(3) + except* TypeError as e: + 5 + except ValueError: + 7 + + self.run_and_compare(func, + [(0, 'call'), + (1, 'line'), + (2, 'line'), + (3, 'line'), + (3, 'exception'), + (4, 'line'), + (6, 'line'), + (7, 'line'), + (7, 'return')]) + + def test_try_except_star_nested(self): + + def func(): + try: + try: + raise ExceptionGroup( + 'eg', + [ValueError(5), TypeError('bad type')]) + except* TypeError as e: + 7 + except* OSError: + 9 + except* ValueError: + raise + except* ValueError: + try: + raise TypeError(14) + except* OSError: + 16 + except* TypeError as e: + 18 + return 0 + + self.run_and_compare(func, + [(0, 'call'), + (1, 'line'), + (2, 'line'), + (3, 'line'), + (4, 'line'), + (5, 'line'), + (3, 'line'), + (3, 'exception'), + (6, 'line'), + (7, 'line'), + (8, 'line'), + (10, 'line'), + (11, 'line'), + (12, 'line'), + (13, 'line'), + (14, 'line'), + (14, 'exception'), + (15, 'line'), + (17, 'line'), + (18, 'line'), + (19, 'line'), + (19, 'return')]) + class SkipLineEventsTraceTestCase(TraceTestCase): """Repeat the trace tests, but with per-line events skipped""" diff --git a/Lib/test/test_unparse.py b/Lib/test/test_unparse.py index d8ba487328b39..f5be13aa94a64 100644 --- a/Lib/test/test_unparse.py +++ b/Lib/test/test_unparse.py @@ -93,6 +93,19 @@ class Foo: pass suite5 """ +try_except_star_finally = """\ +try: + suite1 +except* ex1: + suite2 +except* ex2: + suite3 +else: + suite4 +finally: + suite5 +""" + with_simple = """\ with f(): suite1 @@ -304,6 +317,9 @@ def test_elifs(self): def test_try_except_finally(self): self.check_ast_roundtrip(try_except_finally) + def test_try_except_star_finally(self): + self.check_ast_roundtrip(try_except_star_finally) + def test_starred_assignment(self): self.check_ast_roundtrip("a, *b, c = seq") self.check_ast_roundtrip("a, (*b, c) = seq") diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-22-13-05-32.bpo-45292.pfEouJ.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-22-13-05-32.bpo-45292.pfEouJ.rst new file mode 100644 index 0000000000000..2cc7f39d46480 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-22-13-05-32.bpo-45292.pfEouJ.rst @@ -0,0 +1 @@ +Complete the :pep:`654` implementation: add ``except*``. \ No newline at end of file diff --git a/Objects/exceptions.c b/Objects/exceptions.c index 134015752560d..1db49d949b5c0 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -773,6 +773,23 @@ BaseExceptionGroup_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; } +PyObject * +_PyExc_CreateExceptionGroup(const char *msg_str, PyObject *excs) +{ + PyObject *msg = PyUnicode_FromString(msg_str); + if (!msg) { + return NULL; + } + PyObject *args = PyTuple_Pack(2, msg, excs); + Py_DECREF(msg); + if (!args) { + return NULL; + } + PyObject *result = PyObject_CallObject(PyExc_BaseExceptionGroup, args); + Py_DECREF(args); + return result; +} + static int BaseExceptionGroup_init(PyBaseExceptionGroupObject *self, PyObject *args, PyObject *kwds) @@ -878,7 +895,7 @@ exceptiongroup_subset( if (tb) { int res = PyException_SetTraceback(eg, tb); Py_DECREF(tb); - if (res == -1) { + if (res < 0) { goto error; } } @@ -896,26 +913,41 @@ typedef enum { EXCEPTION_GROUP_MATCH_BY_TYPE = 0, /* A PyFunction returning True for matching exceptions */ EXCEPTION_GROUP_MATCH_BY_PREDICATE = 1, - /* An instance or container thereof, checked with equality - * This matcher type is only used internally by the - * interpreter, it is not exposed to python code */ + /* A set of leaf exceptions to include in the result. + * This matcher type is used internally by the interpreter + * to construct reraised exceptions. + */ EXCEPTION_GROUP_MATCH_INSTANCES = 2 } _exceptiongroup_split_matcher_type; static int get_matcher_type(PyObject *value, - _exceptiongroup_split_matcher_type *type) + _exceptiongroup_split_matcher_type *type) { - /* the python API supports only BY_TYPE and BY_PREDICATE */ - if (PyExceptionClass_Check(value) || - PyTuple_CheckExact(value)) { + assert(value); + + if (PyFunction_Check(value)) { + *type = EXCEPTION_GROUP_MATCH_BY_PREDICATE; + return 0; + } + + if (PyExceptionClass_Check(value)) { *type = EXCEPTION_GROUP_MATCH_BY_TYPE; return 0; } - if (PyFunction_Check(value)) { - *type = EXCEPTION_GROUP_MATCH_BY_PREDICATE; + + if (PyTuple_CheckExact(value)) { + Py_ssize_t n = PyTuple_GET_SIZE(value); + for (Py_ssize_t i=0; imatch) == -1) { + if (exceptiongroup_subset(eg, match_list, &result->match) < 0) { goto done; } if (construct_rest) { assert(PyList_CheckExact(rest_list)); - if (exceptiongroup_subset(eg, rest_list, &result->rest) == -1) { + if (exceptiongroup_subset(eg, rest_list, &result->rest) < 0) { Py_CLEAR(result->match); goto done; } @@ -1061,7 +1094,7 @@ exceptiongroup_split_recursive(PyObject *exc, done: Py_DECREF(match_list); Py_XDECREF(rest_list); - if (retval == -1) { + if (retval < 0) { Py_CLEAR(result->match); Py_CLEAR(result->rest); } @@ -1077,7 +1110,7 @@ BaseExceptionGroup_split(PyObject *self, PyObject *args) } _exceptiongroup_split_matcher_type matcher_type; - if (get_matcher_type(matcher_value, &matcher_type) == -1) { + if (get_matcher_type(matcher_value, &matcher_type) < 0) { return NULL; } @@ -1085,7 +1118,7 @@ BaseExceptionGroup_split(PyObject *self, PyObject *args) bool construct_rest = true; if (exceptiongroup_split_recursive( self, matcher_type, matcher_value, - construct_rest, &split_result) == -1) { + construct_rest, &split_result) < 0) { return NULL; } @@ -1108,7 +1141,7 @@ BaseExceptionGroup_subgroup(PyObject *self, PyObject *args) } _exceptiongroup_split_matcher_type matcher_type; - if (get_matcher_type(matcher_value, &matcher_type) == -1) { + if (get_matcher_type(matcher_value, &matcher_type) < 0) { return NULL; } @@ -1116,7 +1149,7 @@ BaseExceptionGroup_subgroup(PyObject *self, PyObject *args) bool construct_rest = false; if (exceptiongroup_split_recursive( self, matcher_type, matcher_value, - construct_rest, &split_result) == -1) { + construct_rest, &split_result) < 0) { return NULL; } @@ -1128,6 +1161,85 @@ BaseExceptionGroup_subgroup(PyObject *self, PyObject *args) return result; } +static int +collect_exception_group_leaves(PyObject *exc, PyObject *leaves) +{ + if (Py_IsNone(exc)) { + return 0; + } + + assert(PyExceptionInstance_Check(exc)); + assert(PySet_Check(leaves)); + + /* Add all leaf exceptions in exc to the leaves set */ + + if (!_PyBaseExceptionGroup_Check(exc)) { + if (PySet_Add(leaves, exc) < 0) { + return -1; + } + return 0; + } + PyBaseExceptionGroupObject *eg = _PyBaseExceptionGroupObject_cast(exc); + Py_ssize_t num_excs = PyTuple_GET_SIZE(eg->excs); + /* recursive calls */ + for (Py_ssize_t i = 0; i < num_excs; i++) { + PyObject *e = PyTuple_GET_ITEM(eg->excs, i); + if (Py_EnterRecursiveCall(" in collect_exception_group_leaves")) { + return -1; + } + int res = collect_exception_group_leaves(e, leaves); + Py_LeaveRecursiveCall(); + if (res < 0) { + return -1; + } + } + return 0; +} + +/* This function is used by the interpreter to construct reraised + * exception groups. It takes an exception group eg and a list + * of exception groups keep and returns the sub-exception group + * of eg which contains all leaf exceptions that are contained + * in any exception group in keep. + */ +PyObject * +_PyExc_ExceptionGroupProjection(PyObject *eg, PyObject *keep) +{ + assert(_PyBaseExceptionGroup_Check(eg)); + assert(PyList_CheckExact(keep)); + + PyObject *leaves = PySet_New(NULL); + if (!leaves) { + return NULL; + } + + Py_ssize_t n = PyList_GET_SIZE(keep); + for (Py_ssize_t i = 0; i < n; i++) { + PyObject *e = PyList_GET_ITEM(keep, i); + assert(e != NULL); + assert(_PyBaseExceptionGroup_Check(e)); + if (collect_exception_group_leaves(e, leaves) < 0) { + Py_DECREF(leaves); + return NULL; + } + } + + _exceptiongroup_split_result split_result; + bool construct_rest = false; + int err = exceptiongroup_split_recursive( + eg, EXCEPTION_GROUP_MATCH_INSTANCES, leaves, + construct_rest, &split_result); + Py_DECREF(leaves); + if (err < 0) { + return NULL; + } + + PyObject *result = split_result.match ? + split_result.match : Py_NewRef(Py_None); + assert(split_result.rest == NULL); + return result; +} + static PyMemberDef BaseExceptionGroup_members[] = { {"message", T_OBJECT, offsetof(PyBaseExceptionGroupObject, msg), READONLY, PyDoc_STR("exception message")}, diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 2197e07bc0610..82931b6e85f07 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -207,6 +207,7 @@ mark_stacks(PyCodeObject *code_obj, int len) case POP_JUMP_IF_FALSE: case POP_JUMP_IF_TRUE: case JUMP_IF_NOT_EXC_MATCH: + case JUMP_IF_NOT_EG_MATCH: { int64_t target_stack; int j = get_arg(code, i); @@ -214,7 +215,9 @@ mark_stacks(PyCodeObject *code_obj, int len) if (stacks[j] == UNINITIALIZED && j < i) { todo = 1; } - if (opcode == JUMP_IF_NOT_EXC_MATCH) { + if (opcode == JUMP_IF_NOT_EXC_MATCH || + opcode == JUMP_IF_NOT_EG_MATCH) + { next_stack = pop_value(pop_value(next_stack)); target_stack = next_stack; } diff --git a/Parser/Python.asdl b/Parser/Python.asdl index 85225fc88c5a5..4a61bda701b47 100644 --- a/Parser/Python.asdl +++ b/Parser/Python.asdl @@ -40,6 +40,7 @@ module Python | Raise(expr? exc, expr? cause) | Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody) + | TryStar(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody) | Assert(expr test, expr? msg) | Import(alias* names) diff --git a/Parser/parser.c b/Parser/parser.c index b139e55705250..4d576aa781542 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -11,39 +11,39 @@ static KeywordToken *reserved_keywords[] = { (KeywordToken[]) {{NULL, -1}}, (KeywordToken[]) {{NULL, -1}}, (KeywordToken[]) { - {"if", 627}, - {"as", 625}, - {"in", 634}, - {"or", 571}, - {"is", 579}, + {"if", 634}, + {"as", 632}, + {"in", 641}, + {"or", 574}, + {"is", 582}, {NULL, -1}, }, (KeywordToken[]) { - {"del", 600}, - {"def", 635}, - {"for", 633}, - {"try", 612}, - {"and", 572}, - {"not", 578}, + {"del", 603}, + {"def", 642}, + {"for", 640}, + {"try", 618}, + {"and", 575}, + {"not", 581}, {NULL, -1}, }, (KeywordToken[]) { - {"from", 569}, + {"from", 572}, {"pass", 504}, - {"with", 609}, - {"elif", 629}, - {"else", 630}, - {"None", 598}, - {"True", 597}, + {"with", 612}, + {"elif", 636}, + {"else", 637}, + {"None", 601}, + {"True", 600}, {NULL, -1}, }, (KeywordToken[]) { {"raise", 522}, - {"yield", 570}, + {"yield", 573}, {"break", 508}, - {"class", 636}, - {"while", 632}, - {"False", 599}, + {"class", 643}, + {"while", 639}, + {"False", 602}, {NULL, -1}, }, (KeywordToken[]) { @@ -51,12 +51,12 @@ static KeywordToken *reserved_keywords[] = { {"import", 531}, {"assert", 526}, {"global", 523}, - {"except", 623}, - {"lambda", 583}, + {"except", 629}, + {"lambda", 586}, {NULL, -1}, }, (KeywordToken[]) { - {"finally", 620}, + {"finally", 625}, {NULL, -1}, }, (KeywordToken[]) { @@ -128,381 +128,394 @@ static char *soft_keywords[] = { #define with_item_type 1054 #define try_stmt_type 1055 #define except_block_type 1056 -#define finally_block_type 1057 -#define match_stmt_type 1058 -#define subject_expr_type 1059 -#define case_block_type 1060 -#define guard_type 1061 -#define patterns_type 1062 -#define pattern_type 1063 -#define as_pattern_type 1064 -#define or_pattern_type 1065 -#define closed_pattern_type 1066 -#define literal_pattern_type 1067 -#define literal_expr_type 1068 -#define complex_number_type 1069 -#define signed_number_type 1070 -#define signed_real_number_type 1071 -#define real_number_type 1072 -#define imaginary_number_type 1073 -#define capture_pattern_type 1074 -#define pattern_capture_target_type 1075 -#define wildcard_pattern_type 1076 -#define value_pattern_type 1077 -#define attr_type 1078 // Left-recursive -#define name_or_attr_type 1079 // Left-recursive -#define group_pattern_type 1080 -#define sequence_pattern_type 1081 -#define open_sequence_pattern_type 1082 -#define maybe_sequence_pattern_type 1083 -#define maybe_star_pattern_type 1084 -#define star_pattern_type 1085 -#define mapping_pattern_type 1086 -#define items_pattern_type 1087 -#define key_value_pattern_type 1088 -#define double_star_pattern_type 1089 -#define class_pattern_type 1090 -#define positional_patterns_type 1091 -#define keyword_patterns_type 1092 -#define keyword_pattern_type 1093 -#define expressions_type 1094 -#define expression_type 1095 -#define yield_expr_type 1096 -#define star_expressions_type 1097 -#define star_expression_type 1098 -#define star_named_expressions_type 1099 -#define star_named_expression_type 1100 -#define assignment_expression_type 1101 -#define named_expression_type 1102 -#define disjunction_type 1103 -#define conjunction_type 1104 -#define inversion_type 1105 -#define comparison_type 1106 -#define compare_op_bitwise_or_pair_type 1107 -#define eq_bitwise_or_type 1108 -#define noteq_bitwise_or_type 1109 -#define lte_bitwise_or_type 1110 -#define lt_bitwise_or_type 1111 -#define gte_bitwise_or_type 1112 -#define gt_bitwise_or_type 1113 -#define notin_bitwise_or_type 1114 -#define in_bitwise_or_type 1115 -#define isnot_bitwise_or_type 1116 -#define is_bitwise_or_type 1117 -#define bitwise_or_type 1118 // Left-recursive -#define bitwise_xor_type 1119 // Left-recursive -#define bitwise_and_type 1120 // Left-recursive -#define shift_expr_type 1121 // Left-recursive -#define sum_type 1122 // Left-recursive -#define term_type 1123 // Left-recursive -#define factor_type 1124 -#define power_type 1125 -#define await_primary_type 1126 -#define primary_type 1127 // Left-recursive -#define slices_type 1128 -#define slice_type 1129 -#define atom_type 1130 -#define group_type 1131 -#define lambdef_type 1132 -#define lambda_params_type 1133 -#define lambda_parameters_type 1134 -#define lambda_slash_no_default_type 1135 -#define lambda_slash_with_default_type 1136 -#define lambda_star_etc_type 1137 -#define lambda_kwds_type 1138 -#define lambda_param_no_default_type 1139 -#define lambda_param_with_default_type 1140 -#define lambda_param_maybe_default_type 1141 -#define lambda_param_type 1142 -#define strings_type 1143 -#define list_type 1144 -#define tuple_type 1145 -#define set_type 1146 -#define dict_type 1147 -#define double_starred_kvpairs_type 1148 -#define double_starred_kvpair_type 1149 -#define kvpair_type 1150 -#define for_if_clauses_type 1151 -#define for_if_clause_type 1152 -#define listcomp_type 1153 -#define setcomp_type 1154 -#define genexp_type 1155 -#define dictcomp_type 1156 -#define arguments_type 1157 -#define args_type 1158 -#define kwargs_type 1159 -#define starred_expression_type 1160 -#define kwarg_or_starred_type 1161 -#define kwarg_or_double_starred_type 1162 -#define star_targets_type 1163 -#define star_targets_list_seq_type 1164 -#define star_targets_tuple_seq_type 1165 -#define star_target_type 1166 -#define target_with_star_atom_type 1167 -#define star_atom_type 1168 -#define single_target_type 1169 -#define single_subscript_attribute_target_type 1170 -#define t_primary_type 1171 // Left-recursive -#define t_lookahead_type 1172 -#define del_targets_type 1173 -#define del_target_type 1174 -#define del_t_atom_type 1175 -#define type_expressions_type 1176 -#define func_type_comment_type 1177 -#define invalid_arguments_type 1178 -#define invalid_kwarg_type 1179 -#define expression_without_invalid_type 1180 -#define invalid_legacy_expression_type 1181 -#define invalid_expression_type 1182 -#define invalid_named_expression_type 1183 -#define invalid_assignment_type 1184 -#define invalid_ann_assign_target_type 1185 -#define invalid_del_stmt_type 1186 -#define invalid_block_type 1187 -#define invalid_comprehension_type 1188 -#define invalid_dict_comprehension_type 1189 -#define invalid_parameters_type 1190 -#define invalid_parameters_helper_type 1191 -#define invalid_lambda_parameters_type 1192 -#define invalid_lambda_parameters_helper_type 1193 -#define invalid_star_etc_type 1194 -#define invalid_lambda_star_etc_type 1195 -#define invalid_double_type_comments_type 1196 -#define invalid_with_item_type 1197 -#define invalid_for_target_type 1198 -#define invalid_group_type 1199 -#define invalid_import_from_targets_type 1200 -#define invalid_with_stmt_type 1201 -#define invalid_with_stmt_indent_type 1202 -#define invalid_try_stmt_type 1203 -#define invalid_except_stmt_type 1204 -#define invalid_finally_stmt_type 1205 -#define invalid_except_stmt_indent_type 1206 -#define invalid_match_stmt_type 1207 -#define invalid_case_block_type 1208 -#define invalid_as_pattern_type 1209 -#define invalid_class_pattern_type 1210 -#define invalid_class_argument_pattern_type 1211 -#define invalid_if_stmt_type 1212 -#define invalid_elif_stmt_type 1213 -#define invalid_else_stmt_type 1214 -#define invalid_while_stmt_type 1215 -#define invalid_for_stmt_type 1216 -#define invalid_def_raw_type 1217 -#define invalid_class_def_raw_type 1218 -#define invalid_double_starred_kvpairs_type 1219 -#define invalid_kvpair_type 1220 -#define _loop0_1_type 1221 -#define _loop0_2_type 1222 -#define _loop1_3_type 1223 -#define _loop0_5_type 1224 -#define _gather_4_type 1225 -#define _tmp_6_type 1226 -#define _tmp_7_type 1227 -#define _tmp_8_type 1228 -#define _tmp_9_type 1229 -#define _tmp_10_type 1230 -#define _tmp_11_type 1231 -#define _tmp_12_type 1232 -#define _tmp_13_type 1233 -#define _loop1_14_type 1234 -#define _tmp_15_type 1235 -#define _tmp_16_type 1236 -#define _tmp_17_type 1237 -#define _loop0_19_type 1238 -#define _gather_18_type 1239 -#define _loop0_21_type 1240 -#define _gather_20_type 1241 -#define _tmp_22_type 1242 -#define _tmp_23_type 1243 -#define _loop0_24_type 1244 -#define _loop1_25_type 1245 -#define _loop0_27_type 1246 -#define _gather_26_type 1247 -#define _tmp_28_type 1248 -#define _loop0_30_type 1249 -#define _gather_29_type 1250 -#define _tmp_31_type 1251 -#define _loop1_32_type 1252 -#define _tmp_33_type 1253 -#define _tmp_34_type 1254 -#define _tmp_35_type 1255 -#define _loop0_36_type 1256 -#define _loop0_37_type 1257 -#define _loop0_38_type 1258 -#define _loop1_39_type 1259 -#define _loop0_40_type 1260 -#define _loop1_41_type 1261 -#define _loop1_42_type 1262 -#define _loop1_43_type 1263 -#define _loop0_44_type 1264 -#define _loop1_45_type 1265 -#define _loop0_46_type 1266 -#define _loop1_47_type 1267 -#define _loop0_48_type 1268 -#define _loop1_49_type 1269 -#define _loop0_51_type 1270 -#define _gather_50_type 1271 -#define _loop0_53_type 1272 -#define _gather_52_type 1273 -#define _loop0_55_type 1274 -#define _gather_54_type 1275 -#define _loop0_57_type 1276 -#define _gather_56_type 1277 -#define _tmp_58_type 1278 -#define _loop1_59_type 1279 -#define _tmp_60_type 1280 -#define _loop1_61_type 1281 -#define _loop0_63_type 1282 -#define _gather_62_type 1283 -#define _tmp_64_type 1284 -#define _tmp_65_type 1285 -#define _tmp_66_type 1286 -#define _tmp_67_type 1287 -#define _loop0_69_type 1288 -#define _gather_68_type 1289 -#define _loop0_71_type 1290 -#define _gather_70_type 1291 -#define _tmp_72_type 1292 -#define _loop0_74_type 1293 -#define _gather_73_type 1294 -#define _loop0_76_type 1295 -#define _gather_75_type 1296 -#define _loop1_77_type 1297 -#define _loop1_78_type 1298 -#define _loop0_80_type 1299 -#define _gather_79_type 1300 -#define _loop1_81_type 1301 -#define _loop1_82_type 1302 -#define _loop1_83_type 1303 -#define _tmp_84_type 1304 -#define _loop0_86_type 1305 -#define _gather_85_type 1306 -#define _tmp_87_type 1307 -#define _tmp_88_type 1308 -#define _tmp_89_type 1309 -#define _tmp_90_type 1310 -#define _tmp_91_type 1311 -#define _loop0_92_type 1312 -#define _loop0_93_type 1313 -#define _loop0_94_type 1314 -#define _loop1_95_type 1315 -#define _loop0_96_type 1316 -#define _loop1_97_type 1317 -#define _loop1_98_type 1318 -#define _loop1_99_type 1319 -#define _loop0_100_type 1320 -#define _loop1_101_type 1321 -#define _loop0_102_type 1322 -#define _loop1_103_type 1323 -#define _loop0_104_type 1324 -#define _loop1_105_type 1325 -#define _loop1_106_type 1326 -#define _tmp_107_type 1327 -#define _loop0_109_type 1328 -#define _gather_108_type 1329 -#define _loop1_110_type 1330 -#define _loop0_111_type 1331 -#define _loop0_112_type 1332 -#define _tmp_113_type 1333 -#define _loop0_115_type 1334 -#define _gather_114_type 1335 -#define _tmp_116_type 1336 -#define _loop0_118_type 1337 -#define _gather_117_type 1338 -#define _loop0_120_type 1339 -#define _gather_119_type 1340 -#define _loop0_122_type 1341 -#define _gather_121_type 1342 -#define _loop0_124_type 1343 -#define _gather_123_type 1344 -#define _loop0_125_type 1345 -#define _loop0_127_type 1346 -#define _gather_126_type 1347 -#define _loop1_128_type 1348 -#define _tmp_129_type 1349 -#define _loop0_131_type 1350 -#define _gather_130_type 1351 -#define _loop0_133_type 1352 -#define _gather_132_type 1353 -#define _loop0_135_type 1354 -#define _gather_134_type 1355 -#define _loop0_137_type 1356 -#define _gather_136_type 1357 -#define _loop0_139_type 1358 -#define _gather_138_type 1359 -#define _tmp_140_type 1360 -#define _tmp_141_type 1361 -#define _tmp_142_type 1362 -#define _tmp_143_type 1363 -#define _tmp_144_type 1364 -#define _tmp_145_type 1365 -#define _tmp_146_type 1366 -#define _tmp_147_type 1367 -#define _tmp_148_type 1368 -#define _loop0_149_type 1369 -#define _loop0_150_type 1370 -#define _loop0_151_type 1371 -#define _tmp_152_type 1372 -#define _tmp_153_type 1373 -#define _tmp_154_type 1374 -#define _tmp_155_type 1375 -#define _loop0_156_type 1376 -#define _loop0_157_type 1377 -#define _loop1_158_type 1378 -#define _loop1_159_type 1379 -#define _loop0_160_type 1380 -#define _loop0_161_type 1381 -#define _loop0_163_type 1382 -#define _gather_162_type 1383 -#define _loop1_164_type 1384 -#define _tmp_165_type 1385 -#define _tmp_166_type 1386 -#define _tmp_167_type 1387 -#define _loop0_169_type 1388 -#define _gather_168_type 1389 -#define _loop0_171_type 1390 -#define _gather_170_type 1391 -#define _loop0_173_type 1392 -#define _gather_172_type 1393 -#define _loop0_175_type 1394 -#define _gather_174_type 1395 -#define _tmp_176_type 1396 -#define _tmp_177_type 1397 -#define _tmp_178_type 1398 -#define _tmp_179_type 1399 -#define _tmp_180_type 1400 -#define _tmp_181_type 1401 -#define _tmp_182_type 1402 -#define _loop0_184_type 1403 -#define _gather_183_type 1404 -#define _tmp_185_type 1405 -#define _tmp_186_type 1406 -#define _tmp_187_type 1407 -#define _tmp_188_type 1408 -#define _tmp_189_type 1409 -#define _tmp_190_type 1410 -#define _tmp_191_type 1411 -#define _tmp_192_type 1412 -#define _tmp_193_type 1413 -#define _tmp_194_type 1414 -#define _tmp_195_type 1415 -#define _tmp_196_type 1416 -#define _tmp_197_type 1417 -#define _tmp_198_type 1418 -#define _tmp_199_type 1419 -#define _tmp_200_type 1420 -#define _tmp_201_type 1421 -#define _tmp_202_type 1422 -#define _tmp_203_type 1423 -#define _tmp_204_type 1424 -#define _tmp_205_type 1425 -#define _tmp_206_type 1426 -#define _tmp_207_type 1427 -#define _tmp_208_type 1428 -#define _tmp_209_type 1429 -#define _tmp_210_type 1430 -#define _tmp_211_type 1431 +#define except_star_block_type 1057 +#define finally_block_type 1058 +#define match_stmt_type 1059 +#define subject_expr_type 1060 +#define case_block_type 1061 +#define guard_type 1062 +#define patterns_type 1063 +#define pattern_type 1064 +#define as_pattern_type 1065 +#define or_pattern_type 1066 +#define closed_pattern_type 1067 +#define literal_pattern_type 1068 +#define literal_expr_type 1069 +#define complex_number_type 1070 +#define signed_number_type 1071 +#define signed_real_number_type 1072 +#define real_number_type 1073 +#define imaginary_number_type 1074 +#define capture_pattern_type 1075 +#define pattern_capture_target_type 1076 +#define wildcard_pattern_type 1077 +#define value_pattern_type 1078 +#define attr_type 1079 // Left-recursive +#define name_or_attr_type 1080 // Left-recursive +#define group_pattern_type 1081 +#define sequence_pattern_type 1082 +#define open_sequence_pattern_type 1083 +#define maybe_sequence_pattern_type 1084 +#define maybe_star_pattern_type 1085 +#define star_pattern_type 1086 +#define mapping_pattern_type 1087 +#define items_pattern_type 1088 +#define key_value_pattern_type 1089 +#define double_star_pattern_type 1090 +#define class_pattern_type 1091 +#define positional_patterns_type 1092 +#define keyword_patterns_type 1093 +#define keyword_pattern_type 1094 +#define expressions_type 1095 +#define expression_type 1096 +#define yield_expr_type 1097 +#define star_expressions_type 1098 +#define star_expression_type 1099 +#define star_named_expressions_type 1100 +#define star_named_expression_type 1101 +#define assignment_expression_type 1102 +#define named_expression_type 1103 +#define disjunction_type 1104 +#define conjunction_type 1105 +#define inversion_type 1106 +#define comparison_type 1107 +#define compare_op_bitwise_or_pair_type 1108 +#define eq_bitwise_or_type 1109 +#define noteq_bitwise_or_type 1110 +#define lte_bitwise_or_type 1111 +#define lt_bitwise_or_type 1112 +#define gte_bitwise_or_type 1113 +#define gt_bitwise_or_type 1114 +#define notin_bitwise_or_type 1115 +#define in_bitwise_or_type 1116 +#define isnot_bitwise_or_type 1117 +#define is_bitwise_or_type 1118 +#define bitwise_or_type 1119 // Left-recursive +#define bitwise_xor_type 1120 // Left-recursive +#define bitwise_and_type 1121 // Left-recursive +#define shift_expr_type 1122 // Left-recursive +#define sum_type 1123 // Left-recursive +#define term_type 1124 // Left-recursive +#define factor_type 1125 +#define power_type 1126 +#define await_primary_type 1127 +#define primary_type 1128 // Left-recursive +#define slices_type 1129 +#define slice_type 1130 +#define atom_type 1131 +#define group_type 1132 +#define lambdef_type 1133 +#define lambda_params_type 1134 +#define lambda_parameters_type 1135 +#define lambda_slash_no_default_type 1136 +#define lambda_slash_with_default_type 1137 +#define lambda_star_etc_type 1138 +#define lambda_kwds_type 1139 +#define lambda_param_no_default_type 1140 +#define lambda_param_with_default_type 1141 +#define lambda_param_maybe_default_type 1142 +#define lambda_param_type 1143 +#define strings_type 1144 +#define list_type 1145 +#define tuple_type 1146 +#define set_type 1147 +#define dict_type 1148 +#define double_starred_kvpairs_type 1149 +#define double_starred_kvpair_type 1150 +#define kvpair_type 1151 +#define for_if_clauses_type 1152 +#define for_if_clause_type 1153 +#define listcomp_type 1154 +#define setcomp_type 1155 +#define genexp_type 1156 +#define dictcomp_type 1157 +#define arguments_type 1158 +#define args_type 1159 +#define kwargs_type 1160 +#define starred_expression_type 1161 +#define kwarg_or_starred_type 1162 +#define kwarg_or_double_starred_type 1163 +#define star_targets_type 1164 +#define star_targets_list_seq_type 1165 +#define star_targets_tuple_seq_type 1166 +#define star_target_type 1167 +#define target_with_star_atom_type 1168 +#define star_atom_type 1169 +#define single_target_type 1170 +#define single_subscript_attribute_target_type 1171 +#define t_primary_type 1172 // Left-recursive +#define t_lookahead_type 1173 +#define del_targets_type 1174 +#define del_target_type 1175 +#define del_t_atom_type 1176 +#define type_expressions_type 1177 +#define func_type_comment_type 1178 +#define invalid_arguments_type 1179 +#define invalid_kwarg_type 1180 +#define expression_without_invalid_type 1181 +#define invalid_legacy_expression_type 1182 +#define invalid_expression_type 1183 +#define invalid_named_expression_type 1184 +#define invalid_assignment_type 1185 +#define invalid_ann_assign_target_type 1186 +#define invalid_del_stmt_type 1187 +#define invalid_block_type 1188 +#define invalid_comprehension_type 1189 +#define invalid_dict_comprehension_type 1190 +#define invalid_parameters_type 1191 +#define invalid_parameters_helper_type 1192 +#define invalid_lambda_parameters_type 1193 +#define invalid_lambda_parameters_helper_type 1194 +#define invalid_star_etc_type 1195 +#define invalid_lambda_star_etc_type 1196 +#define invalid_double_type_comments_type 1197 +#define invalid_with_item_type 1198 +#define invalid_for_target_type 1199 +#define invalid_group_type 1200 +#define invalid_import_from_targets_type 1201 +#define invalid_with_stmt_type 1202 +#define invalid_with_stmt_indent_type 1203 +#define invalid_try_stmt_type 1204 +#define invalid_except_stmt_type 1205 +#define invalid_finally_stmt_type 1206 +#define invalid_except_stmt_indent_type 1207 +#define invalid_except_star_stmt_indent_type 1208 +#define invalid_match_stmt_type 1209 +#define invalid_case_block_type 1210 +#define invalid_as_pattern_type 1211 +#define invalid_class_pattern_type 1212 +#define invalid_class_argument_pattern_type 1213 +#define invalid_if_stmt_type 1214 +#define invalid_elif_stmt_type 1215 +#define invalid_else_stmt_type 1216 +#define invalid_while_stmt_type 1217 +#define invalid_for_stmt_type 1218 +#define invalid_def_raw_type 1219 +#define invalid_class_def_raw_type 1220 +#define invalid_double_starred_kvpairs_type 1221 +#define invalid_kvpair_type 1222 +#define _loop0_1_type 1223 +#define _loop0_2_type 1224 +#define _loop1_3_type 1225 +#define _loop0_5_type 1226 +#define _gather_4_type 1227 +#define _tmp_6_type 1228 +#define _tmp_7_type 1229 +#define _tmp_8_type 1230 +#define _tmp_9_type 1231 +#define _tmp_10_type 1232 +#define _tmp_11_type 1233 +#define _tmp_12_type 1234 +#define _tmp_13_type 1235 +#define _loop1_14_type 1236 +#define _tmp_15_type 1237 +#define _tmp_16_type 1238 +#define _tmp_17_type 1239 +#define _loop0_19_type 1240 +#define _gather_18_type 1241 +#define _loop0_21_type 1242 +#define _gather_20_type 1243 +#define _tmp_22_type 1244 +#define _tmp_23_type 1245 +#define _loop0_24_type 1246 +#define _loop1_25_type 1247 +#define _loop0_27_type 1248 +#define _gather_26_type 1249 +#define _tmp_28_type 1250 +#define _loop0_30_type 1251 +#define _gather_29_type 1252 +#define _tmp_31_type 1253 +#define _loop1_32_type 1254 +#define _tmp_33_type 1255 +#define _tmp_34_type 1256 +#define _tmp_35_type 1257 +#define _loop0_36_type 1258 +#define _loop0_37_type 1259 +#define _loop0_38_type 1260 +#define _loop1_39_type 1261 +#define _loop0_40_type 1262 +#define _loop1_41_type 1263 +#define _loop1_42_type 1264 +#define _loop1_43_type 1265 +#define _loop0_44_type 1266 +#define _loop1_45_type 1267 +#define _loop0_46_type 1268 +#define _loop1_47_type 1269 +#define _loop0_48_type 1270 +#define _loop1_49_type 1271 +#define _loop0_51_type 1272 +#define _gather_50_type 1273 +#define _loop0_53_type 1274 +#define _gather_52_type 1275 +#define _loop0_55_type 1276 +#define _gather_54_type 1277 +#define _loop0_57_type 1278 +#define _gather_56_type 1279 +#define _tmp_58_type 1280 +#define _loop1_59_type 1281 +#define _loop1_60_type 1282 +#define _tmp_61_type 1283 +#define _tmp_62_type 1284 +#define _loop1_63_type 1285 +#define _loop0_65_type 1286 +#define _gather_64_type 1287 +#define _tmp_66_type 1288 +#define _tmp_67_type 1289 +#define _tmp_68_type 1290 +#define _tmp_69_type 1291 +#define _loop0_71_type 1292 +#define _gather_70_type 1293 +#define _loop0_73_type 1294 +#define _gather_72_type 1295 +#define _tmp_74_type 1296 +#define _loop0_76_type 1297 +#define _gather_75_type 1298 +#define _loop0_78_type 1299 +#define _gather_77_type 1300 +#define _loop1_79_type 1301 +#define _loop1_80_type 1302 +#define _loop0_82_type 1303 +#define _gather_81_type 1304 +#define _loop1_83_type 1305 +#define _loop1_84_type 1306 +#define _loop1_85_type 1307 +#define _tmp_86_type 1308 +#define _loop0_88_type 1309 +#define _gather_87_type 1310 +#define _tmp_89_type 1311 +#define _tmp_90_type 1312 +#define _tmp_91_type 1313 +#define _tmp_92_type 1314 +#define _tmp_93_type 1315 +#define _loop0_94_type 1316 +#define _loop0_95_type 1317 +#define _loop0_96_type 1318 +#define _loop1_97_type 1319 +#define _loop0_98_type 1320 +#define _loop1_99_type 1321 +#define _loop1_100_type 1322 +#define _loop1_101_type 1323 +#define _loop0_102_type 1324 +#define _loop1_103_type 1325 +#define _loop0_104_type 1326 +#define _loop1_105_type 1327 +#define _loop0_106_type 1328 +#define _loop1_107_type 1329 +#define _loop1_108_type 1330 +#define _tmp_109_type 1331 +#define _loop0_111_type 1332 +#define _gather_110_type 1333 +#define _loop1_112_type 1334 +#define _loop0_113_type 1335 +#define _loop0_114_type 1336 +#define _tmp_115_type 1337 +#define _loop0_117_type 1338 +#define _gather_116_type 1339 +#define _tmp_118_type 1340 +#define _loop0_120_type 1341 +#define _gather_119_type 1342 +#define _loop0_122_type 1343 +#define _gather_121_type 1344 +#define _loop0_124_type 1345 +#define _gather_123_type 1346 +#define _loop0_126_type 1347 +#define _gather_125_type 1348 +#define _loop0_127_type 1349 +#define _loop0_129_type 1350 +#define _gather_128_type 1351 +#define _loop1_130_type 1352 +#define _tmp_131_type 1353 +#define _loop0_133_type 1354 +#define _gather_132_type 1355 +#define _loop0_135_type 1356 +#define _gather_134_type 1357 +#define _loop0_137_type 1358 +#define _gather_136_type 1359 +#define _loop0_139_type 1360 +#define _gather_138_type 1361 +#define _loop0_141_type 1362 +#define _gather_140_type 1363 +#define _tmp_142_type 1364 +#define _tmp_143_type 1365 +#define _tmp_144_type 1366 +#define _tmp_145_type 1367 +#define _tmp_146_type 1368 +#define _tmp_147_type 1369 +#define _tmp_148_type 1370 +#define _tmp_149_type 1371 +#define _tmp_150_type 1372 +#define _loop0_151_type 1373 +#define _loop0_152_type 1374 +#define _loop0_153_type 1375 +#define _tmp_154_type 1376 +#define _tmp_155_type 1377 +#define _tmp_156_type 1378 +#define _tmp_157_type 1379 +#define _loop0_158_type 1380 +#define _loop0_159_type 1381 +#define _loop1_160_type 1382 +#define _loop1_161_type 1383 +#define _loop0_162_type 1384 +#define _loop0_163_type 1385 +#define _loop0_165_type 1386 +#define _gather_164_type 1387 +#define _loop1_166_type 1388 +#define _tmp_167_type 1389 +#define _tmp_168_type 1390 +#define _tmp_169_type 1391 +#define _loop0_171_type 1392 +#define _gather_170_type 1393 +#define _loop0_173_type 1394 +#define _gather_172_type 1395 +#define _loop0_175_type 1396 +#define _gather_174_type 1397 +#define _loop0_177_type 1398 +#define _gather_176_type 1399 +#define _tmp_178_type 1400 +#define _loop0_179_type 1401 +#define _tmp_180_type 1402 +#define _loop0_181_type 1403 +#define _tmp_182_type 1404 +#define _tmp_183_type 1405 +#define _tmp_184_type 1406 +#define _tmp_185_type 1407 +#define _tmp_186_type 1408 +#define _tmp_187_type 1409 +#define _tmp_188_type 1410 +#define _tmp_189_type 1411 +#define _loop0_191_type 1412 +#define _gather_190_type 1413 +#define _tmp_192_type 1414 +#define _tmp_193_type 1415 +#define _tmp_194_type 1416 +#define _tmp_195_type 1417 +#define _tmp_196_type 1418 +#define _tmp_197_type 1419 +#define _tmp_198_type 1420 +#define _tmp_199_type 1421 +#define _tmp_200_type 1422 +#define _tmp_201_type 1423 +#define _tmp_202_type 1424 +#define _tmp_203_type 1425 +#define _tmp_204_type 1426 +#define _tmp_205_type 1427 +#define _tmp_206_type 1428 +#define _tmp_207_type 1429 +#define _tmp_208_type 1430 +#define _tmp_209_type 1431 +#define _tmp_210_type 1432 +#define _tmp_211_type 1433 +#define _tmp_212_type 1434 +#define _tmp_213_type 1435 +#define _tmp_214_type 1436 +#define _tmp_215_type 1437 +#define _tmp_216_type 1438 +#define _tmp_217_type 1439 +#define _tmp_218_type 1440 +#define _tmp_219_type 1441 +#define _tmp_220_type 1442 +#define _loop1_221_type 1443 +#define _loop1_222_type 1444 static mod_ty file_rule(Parser *p); static mod_ty interactive_rule(Parser *p); @@ -561,6 +574,7 @@ static stmt_ty with_stmt_rule(Parser *p); static withitem_ty with_item_rule(Parser *p); static stmt_ty try_stmt_rule(Parser *p); static excepthandler_ty except_block_rule(Parser *p); +static excepthandler_ty except_star_block_rule(Parser *p); static asdl_stmt_seq* finally_block_rule(Parser *p); static stmt_ty match_stmt_rule(Parser *p); static expr_ty subject_expr_rule(Parser *p); @@ -711,6 +725,7 @@ static void *invalid_try_stmt_rule(Parser *p); static void *invalid_except_stmt_rule(Parser *p); static void *invalid_finally_stmt_rule(Parser *p); static void *invalid_except_stmt_indent_rule(Parser *p); +static void *invalid_except_star_stmt_indent_rule(Parser *p); static void *invalid_match_stmt_rule(Parser *p); static void *invalid_case_block_rule(Parser *p); static void *invalid_as_pattern_rule(Parser *p); @@ -784,78 +799,78 @@ static asdl_seq *_loop0_57_rule(Parser *p); static asdl_seq *_gather_56_rule(Parser *p); static void *_tmp_58_rule(Parser *p); static asdl_seq *_loop1_59_rule(Parser *p); -static void *_tmp_60_rule(Parser *p); -static asdl_seq *_loop1_61_rule(Parser *p); -static asdl_seq *_loop0_63_rule(Parser *p); -static asdl_seq *_gather_62_rule(Parser *p); -static void *_tmp_64_rule(Parser *p); -static void *_tmp_65_rule(Parser *p); +static asdl_seq *_loop1_60_rule(Parser *p); +static void *_tmp_61_rule(Parser *p); +static void *_tmp_62_rule(Parser *p); +static asdl_seq *_loop1_63_rule(Parser *p); +static asdl_seq *_loop0_65_rule(Parser *p); +static asdl_seq *_gather_64_rule(Parser *p); static void *_tmp_66_rule(Parser *p); static void *_tmp_67_rule(Parser *p); -static asdl_seq *_loop0_69_rule(Parser *p); -static asdl_seq *_gather_68_rule(Parser *p); +static void *_tmp_68_rule(Parser *p); +static void *_tmp_69_rule(Parser *p); static asdl_seq *_loop0_71_rule(Parser *p); static asdl_seq *_gather_70_rule(Parser *p); -static void *_tmp_72_rule(Parser *p); -static asdl_seq *_loop0_74_rule(Parser *p); -static asdl_seq *_gather_73_rule(Parser *p); +static asdl_seq *_loop0_73_rule(Parser *p); +static asdl_seq *_gather_72_rule(Parser *p); +static void *_tmp_74_rule(Parser *p); static asdl_seq *_loop0_76_rule(Parser *p); static asdl_seq *_gather_75_rule(Parser *p); -static asdl_seq *_loop1_77_rule(Parser *p); -static asdl_seq *_loop1_78_rule(Parser *p); -static asdl_seq *_loop0_80_rule(Parser *p); -static asdl_seq *_gather_79_rule(Parser *p); -static asdl_seq *_loop1_81_rule(Parser *p); -static asdl_seq *_loop1_82_rule(Parser *p); +static asdl_seq *_loop0_78_rule(Parser *p); +static asdl_seq *_gather_77_rule(Parser *p); +static asdl_seq *_loop1_79_rule(Parser *p); +static asdl_seq *_loop1_80_rule(Parser *p); +static asdl_seq *_loop0_82_rule(Parser *p); +static asdl_seq *_gather_81_rule(Parser *p); static asdl_seq *_loop1_83_rule(Parser *p); -static void *_tmp_84_rule(Parser *p); -static asdl_seq *_loop0_86_rule(Parser *p); -static asdl_seq *_gather_85_rule(Parser *p); -static void *_tmp_87_rule(Parser *p); -static void *_tmp_88_rule(Parser *p); +static asdl_seq *_loop1_84_rule(Parser *p); +static asdl_seq *_loop1_85_rule(Parser *p); +static void *_tmp_86_rule(Parser *p); +static asdl_seq *_loop0_88_rule(Parser *p); +static asdl_seq *_gather_87_rule(Parser *p); static void *_tmp_89_rule(Parser *p); static void *_tmp_90_rule(Parser *p); static void *_tmp_91_rule(Parser *p); -static asdl_seq *_loop0_92_rule(Parser *p); -static asdl_seq *_loop0_93_rule(Parser *p); +static void *_tmp_92_rule(Parser *p); +static void *_tmp_93_rule(Parser *p); static asdl_seq *_loop0_94_rule(Parser *p); -static asdl_seq *_loop1_95_rule(Parser *p); +static asdl_seq *_loop0_95_rule(Parser *p); static asdl_seq *_loop0_96_rule(Parser *p); static asdl_seq *_loop1_97_rule(Parser *p); -static asdl_seq *_loop1_98_rule(Parser *p); +static asdl_seq *_loop0_98_rule(Parser *p); static asdl_seq *_loop1_99_rule(Parser *p); -static asdl_seq *_loop0_100_rule(Parser *p); +static asdl_seq *_loop1_100_rule(Parser *p); static asdl_seq *_loop1_101_rule(Parser *p); static asdl_seq *_loop0_102_rule(Parser *p); static asdl_seq *_loop1_103_rule(Parser *p); static asdl_seq *_loop0_104_rule(Parser *p); static asdl_seq *_loop1_105_rule(Parser *p); -static asdl_seq *_loop1_106_rule(Parser *p); -static void *_tmp_107_rule(Parser *p); -static asdl_seq *_loop0_109_rule(Parser *p); -static asdl_seq *_gather_108_rule(Parser *p); -static asdl_seq *_loop1_110_rule(Parser *p); +static asdl_seq *_loop0_106_rule(Parser *p); +static asdl_seq *_loop1_107_rule(Parser *p); +static asdl_seq *_loop1_108_rule(Parser *p); +static void *_tmp_109_rule(Parser *p); static asdl_seq *_loop0_111_rule(Parser *p); -static asdl_seq *_loop0_112_rule(Parser *p); -static void *_tmp_113_rule(Parser *p); -static asdl_seq *_loop0_115_rule(Parser *p); -static asdl_seq *_gather_114_rule(Parser *p); -static void *_tmp_116_rule(Parser *p); -static asdl_seq *_loop0_118_rule(Parser *p); -static asdl_seq *_gather_117_rule(Parser *p); +static asdl_seq *_gather_110_rule(Parser *p); +static asdl_seq *_loop1_112_rule(Parser *p); +static asdl_seq *_loop0_113_rule(Parser *p); +static asdl_seq *_loop0_114_rule(Parser *p); +static void *_tmp_115_rule(Parser *p); +static asdl_seq *_loop0_117_rule(Parser *p); +static asdl_seq *_gather_116_rule(Parser *p); +static void *_tmp_118_rule(Parser *p); static asdl_seq *_loop0_120_rule(Parser *p); static asdl_seq *_gather_119_rule(Parser *p); static asdl_seq *_loop0_122_rule(Parser *p); static asdl_seq *_gather_121_rule(Parser *p); static asdl_seq *_loop0_124_rule(Parser *p); static asdl_seq *_gather_123_rule(Parser *p); -static asdl_seq *_loop0_125_rule(Parser *p); +static asdl_seq *_loop0_126_rule(Parser *p); +static asdl_seq *_gather_125_rule(Parser *p); static asdl_seq *_loop0_127_rule(Parser *p); -static asdl_seq *_gather_126_rule(Parser *p); -static asdl_seq *_loop1_128_rule(Parser *p); -static void *_tmp_129_rule(Parser *p); -static asdl_seq *_loop0_131_rule(Parser *p); -static asdl_seq *_gather_130_rule(Parser *p); +static asdl_seq *_loop0_129_rule(Parser *p); +static asdl_seq *_gather_128_rule(Parser *p); +static asdl_seq *_loop1_130_rule(Parser *p); +static void *_tmp_131_rule(Parser *p); static asdl_seq *_loop0_133_rule(Parser *p); static asdl_seq *_gather_132_rule(Parser *p); static asdl_seq *_loop0_135_rule(Parser *p); @@ -864,8 +879,8 @@ static asdl_seq *_loop0_137_rule(Parser *p); static asdl_seq *_gather_136_rule(Parser *p); static asdl_seq *_loop0_139_rule(Parser *p); static asdl_seq *_gather_138_rule(Parser *p); -static void *_tmp_140_rule(Parser *p); -static void *_tmp_141_rule(Parser *p); +static asdl_seq *_loop0_141_rule(Parser *p); +static asdl_seq *_gather_140_rule(Parser *p); static void *_tmp_142_rule(Parser *p); static void *_tmp_143_rule(Parser *p); static void *_tmp_144_rule(Parser *p); @@ -873,49 +888,49 @@ static void *_tmp_145_rule(Parser *p); static void *_tmp_146_rule(Parser *p); static void *_tmp_147_rule(Parser *p); static void *_tmp_148_rule(Parser *p); -static asdl_seq *_loop0_149_rule(Parser *p); -static asdl_seq *_loop0_150_rule(Parser *p); +static void *_tmp_149_rule(Parser *p); +static void *_tmp_150_rule(Parser *p); static asdl_seq *_loop0_151_rule(Parser *p); -static void *_tmp_152_rule(Parser *p); -static void *_tmp_153_rule(Parser *p); +static asdl_seq *_loop0_152_rule(Parser *p); +static asdl_seq *_loop0_153_rule(Parser *p); static void *_tmp_154_rule(Parser *p); static void *_tmp_155_rule(Parser *p); -static asdl_seq *_loop0_156_rule(Parser *p); -static asdl_seq *_loop0_157_rule(Parser *p); -static asdl_seq *_loop1_158_rule(Parser *p); -static asdl_seq *_loop1_159_rule(Parser *p); -static asdl_seq *_loop0_160_rule(Parser *p); -static asdl_seq *_loop0_161_rule(Parser *p); +static void *_tmp_156_rule(Parser *p); +static void *_tmp_157_rule(Parser *p); +static asdl_seq *_loop0_158_rule(Parser *p); +static asdl_seq *_loop0_159_rule(Parser *p); +static asdl_seq *_loop1_160_rule(Parser *p); +static asdl_seq *_loop1_161_rule(Parser *p); +static asdl_seq *_loop0_162_rule(Parser *p); static asdl_seq *_loop0_163_rule(Parser *p); -static asdl_seq *_gather_162_rule(Parser *p); -static asdl_seq *_loop1_164_rule(Parser *p); -static void *_tmp_165_rule(Parser *p); -static void *_tmp_166_rule(Parser *p); +static asdl_seq *_loop0_165_rule(Parser *p); +static asdl_seq *_gather_164_rule(Parser *p); +static asdl_seq *_loop1_166_rule(Parser *p); static void *_tmp_167_rule(Parser *p); -static asdl_seq *_loop0_169_rule(Parser *p); -static asdl_seq *_gather_168_rule(Parser *p); +static void *_tmp_168_rule(Parser *p); +static void *_tmp_169_rule(Parser *p); static asdl_seq *_loop0_171_rule(Parser *p); static asdl_seq *_gather_170_rule(Parser *p); static asdl_seq *_loop0_173_rule(Parser *p); static asdl_seq *_gather_172_rule(Parser *p); static asdl_seq *_loop0_175_rule(Parser *p); static asdl_seq *_gather_174_rule(Parser *p); -static void *_tmp_176_rule(Parser *p); -static void *_tmp_177_rule(Parser *p); +static asdl_seq *_loop0_177_rule(Parser *p); +static asdl_seq *_gather_176_rule(Parser *p); static void *_tmp_178_rule(Parser *p); -static void *_tmp_179_rule(Parser *p); +static asdl_seq *_loop0_179_rule(Parser *p); static void *_tmp_180_rule(Parser *p); -static void *_tmp_181_rule(Parser *p); +static asdl_seq *_loop0_181_rule(Parser *p); static void *_tmp_182_rule(Parser *p); -static asdl_seq *_loop0_184_rule(Parser *p); -static asdl_seq *_gather_183_rule(Parser *p); +static void *_tmp_183_rule(Parser *p); +static void *_tmp_184_rule(Parser *p); static void *_tmp_185_rule(Parser *p); static void *_tmp_186_rule(Parser *p); static void *_tmp_187_rule(Parser *p); static void *_tmp_188_rule(Parser *p); static void *_tmp_189_rule(Parser *p); -static void *_tmp_190_rule(Parser *p); -static void *_tmp_191_rule(Parser *p); +static asdl_seq *_loop0_191_rule(Parser *p); +static asdl_seq *_gather_190_rule(Parser *p); static void *_tmp_192_rule(Parser *p); static void *_tmp_193_rule(Parser *p); static void *_tmp_194_rule(Parser *p); @@ -936,6 +951,17 @@ static void *_tmp_208_rule(Parser *p); static void *_tmp_209_rule(Parser *p); static void *_tmp_210_rule(Parser *p); static void *_tmp_211_rule(Parser *p); +static void *_tmp_212_rule(Parser *p); +static void *_tmp_213_rule(Parser *p); +static void *_tmp_214_rule(Parser *p); +static void *_tmp_215_rule(Parser *p); +static void *_tmp_216_rule(Parser *p); +static void *_tmp_217_rule(Parser *p); +static void *_tmp_218_rule(Parser *p); +static void *_tmp_219_rule(Parser *p); +static void *_tmp_220_rule(Parser *p); +static asdl_seq *_loop1_221_rule(Parser *p); +static asdl_seq *_loop1_222_rule(Parser *p); // file: statements? $ @@ -1670,7 +1696,7 @@ simple_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'del' del_stmt")); stmt_ty del_stmt_var; if ( - _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 600) // token='del' + _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 603) // token='del' && (del_stmt_var = del_stmt_rule(p)) // del_stmt ) @@ -1691,7 +1717,7 @@ simple_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'yield' yield_stmt")); stmt_ty yield_stmt_var; if ( - _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 570) // token='yield' + _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 573) // token='yield' && (yield_stmt_var = yield_stmt_rule(p)) // yield_stmt ) @@ -1888,7 +1914,7 @@ compound_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'if' if_stmt")); stmt_ty if_stmt_var; if ( - _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 627) // token='if' + _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 634) // token='if' && (if_stmt_var = if_stmt_rule(p)) // if_stmt ) @@ -1972,7 +1998,7 @@ compound_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'try' try_stmt")); stmt_ty try_stmt_var; if ( - _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 612) // token='try' + _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 618) // token='try' && (try_stmt_var = try_stmt_rule(p)) // try_stmt ) @@ -1993,7 +2019,7 @@ compound_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'while' while_stmt")); stmt_ty while_stmt_var; if ( - _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 632) // token='while' + _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 639) // token='while' && (while_stmt_var = while_stmt_rule(p)) // while_stmt ) @@ -2962,7 +2988,7 @@ del_stmt_rule(Parser *p) Token * _keyword; asdl_expr_seq* a; if ( - (_keyword = _PyPegen_expect_token(p, 600)) // token='del' + (_keyword = _PyPegen_expect_token(p, 603)) // token='del' && (a = del_targets_rule(p)) // del_targets && @@ -3291,7 +3317,7 @@ import_from_rule(Parser *p) expr_ty b; asdl_alias_seq* c; if ( - (_keyword = _PyPegen_expect_token(p, 569)) // token='from' + (_keyword = _PyPegen_expect_token(p, 572)) // token='from' && (a = _loop0_24_rule(p)) // (('.' | '...'))* && @@ -3335,7 +3361,7 @@ import_from_rule(Parser *p) asdl_seq * a; asdl_alias_seq* b; if ( - (_keyword = _PyPegen_expect_token(p, 569)) // token='from' + (_keyword = _PyPegen_expect_token(p, 572)) // token='from' && (a = _loop1_25_rule(p)) // (('.' | '...'))+ && @@ -4063,7 +4089,7 @@ class_def_raw_rule(Parser *p) void *b; asdl_stmt_seq* c; if ( - (_keyword = _PyPegen_expect_token(p, 636)) // token='class' + (_keyword = _PyPegen_expect_token(p, 643)) // token='class' && (a = _PyPegen_name_token(p)) // NAME && @@ -4223,7 +4249,7 @@ function_def_raw_rule(Parser *p) void *params; void *tc; if ( - (_keyword = _PyPegen_expect_token(p, 635)) // token='def' + (_keyword = _PyPegen_expect_token(p, 642)) // token='def' && (n = _PyPegen_name_token(p)) // NAME && @@ -4283,7 +4309,7 @@ function_def_raw_rule(Parser *p) if ( (async_var = _PyPegen_expect_token(p, ASYNC)) // token='ASYNC' && - (_keyword = _PyPegen_expect_token(p, 635)) // token='def' + (_keyword = _PyPegen_expect_token(p, 642)) // token='def' && (n = _PyPegen_name_token(p)) // NAME && @@ -5331,7 +5357,7 @@ if_stmt_rule(Parser *p) asdl_stmt_seq* b; stmt_ty c; if ( - (_keyword = _PyPegen_expect_token(p, 627)) // token='if' + (_keyword = _PyPegen_expect_token(p, 634)) // token='if' && (a = named_expression_rule(p)) // named_expression && @@ -5376,7 +5402,7 @@ if_stmt_rule(Parser *p) asdl_stmt_seq* b; void *c; if ( - (_keyword = _PyPegen_expect_token(p, 627)) // token='if' + (_keyword = _PyPegen_expect_token(p, 634)) // token='if' && (a = named_expression_rule(p)) // named_expression && @@ -5469,7 +5495,7 @@ elif_stmt_rule(Parser *p) asdl_stmt_seq* b; stmt_ty c; if ( - (_keyword = _PyPegen_expect_token(p, 629)) // token='elif' + (_keyword = _PyPegen_expect_token(p, 636)) // token='elif' && (a = named_expression_rule(p)) // named_expression && @@ -5514,7 +5540,7 @@ elif_stmt_rule(Parser *p) asdl_stmt_seq* b; void *c; if ( - (_keyword = _PyPegen_expect_token(p, 629)) // token='elif' + (_keyword = _PyPegen_expect_token(p, 636)) // token='elif' && (a = named_expression_rule(p)) // named_expression && @@ -5593,7 +5619,7 @@ else_block_rule(Parser *p) Token * _literal; asdl_stmt_seq* b; if ( - (_keyword = _PyPegen_expect_token(p, 630)) // token='else' + (_keyword = _PyPegen_expect_token(p, 637)) // token='else' && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && @@ -5670,7 +5696,7 @@ while_stmt_rule(Parser *p) asdl_stmt_seq* b; void *c; if ( - (_keyword = _PyPegen_expect_token(p, 632)) // token='while' + (_keyword = _PyPegen_expect_token(p, 639)) // token='while' && (a = named_expression_rule(p)) // named_expression && @@ -5768,11 +5794,11 @@ for_stmt_rule(Parser *p) expr_ty t; void *tc; if ( - (_keyword = _PyPegen_expect_token(p, 633)) // token='for' + (_keyword = _PyPegen_expect_token(p, 640)) // token='for' && (t = star_targets_rule(p)) // star_targets && - (_keyword_1 = _PyPegen_expect_token(p, 634)) // token='in' + (_keyword_1 = _PyPegen_expect_token(p, 641)) // token='in' && (_cut_var = 1) && @@ -5832,11 +5858,11 @@ for_stmt_rule(Parser *p) if ( (async_var = _PyPegen_expect_token(p, ASYNC)) // token='ASYNC' && - (_keyword = _PyPegen_expect_token(p, 633)) // token='for' + (_keyword = _PyPegen_expect_token(p, 640)) // token='for' && (t = star_targets_rule(p)) // star_targets && - (_keyword_1 = _PyPegen_expect_token(p, 634)) // token='in' + (_keyword_1 = _PyPegen_expect_token(p, 641)) // token='in' && (_cut_var = 1) && @@ -5962,7 +5988,7 @@ with_stmt_rule(Parser *p) asdl_withitem_seq* a; asdl_stmt_seq* b; if ( - (_keyword = _PyPegen_expect_token(p, 609)) // token='with' + (_keyword = _PyPegen_expect_token(p, 612)) // token='with' && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && @@ -6011,7 +6037,7 @@ with_stmt_rule(Parser *p) asdl_stmt_seq* b; void *tc; if ( - (_keyword = _PyPegen_expect_token(p, 609)) // token='with' + (_keyword = _PyPegen_expect_token(p, 612)) // token='with' && (a = (asdl_withitem_seq*)_gather_52_rule(p)) // ','.with_item+ && @@ -6062,7 +6088,7 @@ with_stmt_rule(Parser *p) if ( (async_var = _PyPegen_expect_token(p, ASYNC)) // token='ASYNC' && - (_keyword = _PyPegen_expect_token(p, 609)) // token='with' + (_keyword = _PyPegen_expect_token(p, 612)) // token='with' && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && @@ -6114,7 +6140,7 @@ with_stmt_rule(Parser *p) if ( (async_var = _PyPegen_expect_token(p, ASYNC)) // token='ASYNC' && - (_keyword = _PyPegen_expect_token(p, 609)) // token='with' + (_keyword = _PyPegen_expect_token(p, 612)) // token='with' && (a = (asdl_withitem_seq*)_gather_56_rule(p)) // ','.with_item+ && @@ -6198,7 +6224,7 @@ with_item_rule(Parser *p) if ( (e = expression_rule(p)) // expression && - (_keyword = _PyPegen_expect_token(p, 625)) // token='as' + (_keyword = _PyPegen_expect_token(p, 632)) // token='as' && (t = star_target_rule(p)) // star_target && @@ -6271,6 +6297,7 @@ with_item_rule(Parser *p) // | invalid_try_stmt // | 'try' &&':' block finally_block // | 'try' &&':' block except_block+ else_block? finally_block? +// | 'try' &&':' block except_star_block+ else_block? finally_block? static stmt_ty try_stmt_rule(Parser *p) { @@ -6320,7 +6347,7 @@ try_stmt_rule(Parser *p) asdl_stmt_seq* b; asdl_stmt_seq* f; if ( - (_keyword = _PyPegen_expect_token(p, 612)) // token='try' + (_keyword = _PyPegen_expect_token(p, 618)) // token='try' && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && @@ -6364,7 +6391,7 @@ try_stmt_rule(Parser *p) asdl_excepthandler_seq* ex; void *f; if ( - (_keyword = _PyPegen_expect_token(p, 612)) // token='try' + (_keyword = _PyPegen_expect_token(p, 618)) // token='try' && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && @@ -6399,6 +6426,54 @@ try_stmt_rule(Parser *p) D(fprintf(stderr, "%*c%s try_stmt[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'try' &&':' block except_block+ else_block? finally_block?")); } + { // 'try' &&':' block except_star_block+ else_block? finally_block? + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> try_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'try' &&':' block except_star_block+ else_block? finally_block?")); + Token * _keyword; + Token * _literal; + asdl_stmt_seq* b; + void *el; + asdl_excepthandler_seq* ex; + void *f; + if ( + (_keyword = _PyPegen_expect_token(p, 618)) // token='try' + && + (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' + && + (b = block_rule(p)) // block + && + (ex = (asdl_excepthandler_seq*)_loop1_60_rule(p)) // except_star_block+ + && + (el = else_block_rule(p), !p->error_indicator) // else_block? + && + (f = finally_block_rule(p), !p->error_indicator) // finally_block? + ) + { + D(fprintf(stderr, "%*c+ try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' &&':' block except_star_block+ else_block? finally_block?")); + Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); + if (_token == NULL) { + D(p->level--); + return NULL; + } + int _end_lineno = _token->end_lineno; + UNUSED(_end_lineno); // Only used by EXTRA macro + int _end_col_offset = _token->end_col_offset; + UNUSED(_end_col_offset); // Only used by EXTRA macro + _res = _PyAST_TryStar ( b , ex , el , f , EXTRA ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + D(p->level--); + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s try_stmt[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'try' &&':' block except_star_block+ else_block? finally_block?")); + } _res = NULL; done: D(p->level--); @@ -6460,11 +6535,11 @@ except_block_rule(Parser *p) expr_ty e; void *t; if ( - (_keyword = _PyPegen_expect_token(p, 623)) // token='except' + (_keyword = _PyPegen_expect_token(p, 629)) // token='except' && (e = expression_rule(p)) // expression && - (t = _tmp_60_rule(p), !p->error_indicator) // ['as' NAME] + (t = _tmp_61_rule(p), !p->error_indicator) // ['as' NAME] && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -6503,7 +6578,7 @@ except_block_rule(Parser *p) Token * _literal; asdl_stmt_seq* b; if ( - (_keyword = _PyPegen_expect_token(p, 623)) // token='except' + (_keyword = _PyPegen_expect_token(p, 629)) // token='except' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -6557,6 +6632,121 @@ except_block_rule(Parser *p) return _res; } +// except_star_block: +// | invalid_except_star_stmt_indent +// | 'except' '*' expression ['as' NAME] ':' block +// | invalid_except_stmt +static excepthandler_ty +except_star_block_rule(Parser *p) +{ + D(p->level++); + if (p->error_indicator) { + D(p->level--); + return NULL; + } + excepthandler_ty _res = NULL; + int _mark = p->mark; + if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { + p->error_indicator = 1; + D(p->level--); + return NULL; + } + int _start_lineno = p->tokens[_mark]->lineno; + UNUSED(_start_lineno); // Only used by EXTRA macro + int _start_col_offset = p->tokens[_mark]->col_offset; + UNUSED(_start_col_offset); // Only used by EXTRA macro + if (p->call_invalid_rules) { // invalid_except_star_stmt_indent + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> except_star_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_except_star_stmt_indent")); + void *invalid_except_star_stmt_indent_var; + if ( + (invalid_except_star_stmt_indent_var = invalid_except_star_stmt_indent_rule(p)) // invalid_except_star_stmt_indent + ) + { + D(fprintf(stderr, "%*c+ except_star_block[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "invalid_except_star_stmt_indent")); + _res = invalid_except_star_stmt_indent_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s except_star_block[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_except_star_stmt_indent")); + } + { // 'except' '*' expression ['as' NAME] ':' block + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> except_star_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' '*' expression ['as' NAME] ':' block")); + Token * _keyword; + Token * _literal; + Token * _literal_1; + asdl_stmt_seq* b; + expr_ty e; + void *t; + if ( + (_keyword = _PyPegen_expect_token(p, 629)) // token='except' + && + (_literal = _PyPegen_expect_token(p, 16)) // token='*' + && + (e = expression_rule(p)) // expression + && + (t = _tmp_62_rule(p), !p->error_indicator) // ['as' NAME] + && + (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' + && + (b = block_rule(p)) // block + ) + { + D(fprintf(stderr, "%*c+ except_star_block[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' '*' expression ['as' NAME] ':' block")); + Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); + if (_token == NULL) { + D(p->level--); + return NULL; + } + int _end_lineno = _token->end_lineno; + UNUSED(_end_lineno); // Only used by EXTRA macro + int _end_col_offset = _token->end_col_offset; + UNUSED(_end_col_offset); // Only used by EXTRA macro + _res = _PyAST_ExceptHandler ( e , ( t ) ? ( ( expr_ty ) t ) -> v . Name . id : NULL , b , EXTRA ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + D(p->level--); + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s except_star_block[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'except' '*' expression ['as' NAME] ':' block")); + } + if (p->call_invalid_rules) { // invalid_except_stmt + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> except_star_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_except_stmt")); + void *invalid_except_stmt_var; + if ( + (invalid_except_stmt_var = invalid_except_stmt_rule(p)) // invalid_except_stmt + ) + { + D(fprintf(stderr, "%*c+ except_star_block[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "invalid_except_stmt")); + _res = invalid_except_stmt_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s except_star_block[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_except_stmt")); + } + _res = NULL; + done: + D(p->level--); + return _res; +} + // finally_block: invalid_finally_stmt | 'finally' &&':' block static asdl_stmt_seq* finally_block_rule(Parser *p) @@ -6597,7 +6787,7 @@ finally_block_rule(Parser *p) Token * _literal; asdl_stmt_seq* a; if ( - (_keyword = _PyPegen_expect_token(p, 620)) // token='finally' + (_keyword = _PyPegen_expect_token(p, 625)) // token='finally' && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && @@ -6669,7 +6859,7 @@ match_stmt_rule(Parser *p) && (indent_var = _PyPegen_expect_token(p, INDENT)) // token='INDENT' && - (cases = (asdl_match_case_seq*)_loop1_61_rule(p)) // case_block+ + (cases = (asdl_match_case_seq*)_loop1_63_rule(p)) // case_block+ && (dedent_var = _PyPegen_expect_token(p, DEDENT)) // token='DEDENT' ) @@ -6897,7 +7087,7 @@ guard_rule(Parser *p) Token * _keyword; expr_ty guard; if ( - (_keyword = _PyPegen_expect_token(p, 627)) // token='if' + (_keyword = _PyPegen_expect_token(p, 634)) // token='if' && (guard = named_expression_rule(p)) // named_expression ) @@ -7086,7 +7276,7 @@ as_pattern_rule(Parser *p) if ( (pattern = or_pattern_rule(p)) // or_pattern && - (_keyword = _PyPegen_expect_token(p, 625)) // token='as' + (_keyword = _PyPegen_expect_token(p, 632)) // token='as' && (target = pattern_capture_target_rule(p)) // pattern_capture_target ) @@ -7166,7 +7356,7 @@ or_pattern_rule(Parser *p) D(fprintf(stderr, "%*c> or_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'|'.closed_pattern+")); asdl_pattern_seq* patterns; if ( - (patterns = (asdl_pattern_seq*)_gather_62_rule(p)) // '|'.closed_pattern+ + (patterns = (asdl_pattern_seq*)_gather_64_rule(p)) // '|'.closed_pattern+ ) { D(fprintf(stderr, "%*c+ or_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'|'.closed_pattern+")); @@ -7410,7 +7600,7 @@ literal_pattern_rule(Parser *p) if ( (value = signed_number_rule(p)) // signed_number && - _PyPegen_lookahead(0, _tmp_64_rule, p) + _PyPegen_lookahead(0, _tmp_66_rule, p) ) { D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "signed_number !('+' | '-')")); @@ -7509,7 +7699,7 @@ literal_pattern_rule(Parser *p) D(fprintf(stderr, "%*c> literal_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 598)) // token='None' + (_keyword = _PyPegen_expect_token(p, 601)) // token='None' ) { D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); @@ -7542,7 +7732,7 @@ literal_pattern_rule(Parser *p) D(fprintf(stderr, "%*c> literal_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 597)) // token='True' + (_keyword = _PyPegen_expect_token(p, 600)) // token='True' ) { D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); @@ -7575,7 +7765,7 @@ literal_pattern_rule(Parser *p) D(fprintf(stderr, "%*c> literal_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 599)) // token='False' + (_keyword = _PyPegen_expect_token(p, 602)) // token='False' ) { D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); @@ -7642,7 +7832,7 @@ literal_expr_rule(Parser *p) if ( (signed_number_var = signed_number_rule(p)) // signed_number && - _PyPegen_lookahead(0, _tmp_65_rule, p) + _PyPegen_lookahead(0, _tmp_67_rule, p) ) { D(fprintf(stderr, "%*c+ literal_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "signed_number !('+' | '-')")); @@ -7699,7 +7889,7 @@ literal_expr_rule(Parser *p) D(fprintf(stderr, "%*c> literal_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 598)) // token='None' + (_keyword = _PyPegen_expect_token(p, 601)) // token='None' ) { D(fprintf(stderr, "%*c+ literal_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); @@ -7732,7 +7922,7 @@ literal_expr_rule(Parser *p) D(fprintf(stderr, "%*c> literal_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 597)) // token='True' + (_keyword = _PyPegen_expect_token(p, 600)) // token='True' ) { D(fprintf(stderr, "%*c+ literal_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); @@ -7765,7 +7955,7 @@ literal_expr_rule(Parser *p) D(fprintf(stderr, "%*c> literal_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 599)) // token='False' + (_keyword = _PyPegen_expect_token(p, 602)) // token='False' ) { D(fprintf(stderr, "%*c+ literal_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); @@ -8228,7 +8418,7 @@ pattern_capture_target_rule(Parser *p) && (name = _PyPegen_name_token(p)) // NAME && - _PyPegen_lookahead(0, _tmp_66_rule, p) + _PyPegen_lookahead(0, _tmp_68_rule, p) ) { D(fprintf(stderr, "%*c+ pattern_capture_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!\"_\" NAME !('.' | '(' | '=')")); @@ -8339,7 +8529,7 @@ value_pattern_rule(Parser *p) if ( (attr = attr_rule(p)) // attr && - _PyPegen_lookahead(0, _tmp_67_rule, p) + _PyPegen_lookahead(0, _tmp_69_rule, p) ) { D(fprintf(stderr, "%*c+ value_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "attr !('.' | '(' | '=')")); @@ -8744,7 +8934,7 @@ maybe_sequence_pattern_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_seq * patterns; if ( - (patterns = _gather_68_rule(p)) // ','.maybe_star_pattern+ + (patterns = _gather_70_rule(p)) // ','.maybe_star_pattern+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -9139,13 +9329,13 @@ items_pattern_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> items_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.key_value_pattern+")); - asdl_seq * _gather_70_var; + asdl_seq * _gather_72_var; if ( - (_gather_70_var = _gather_70_rule(p)) // ','.key_value_pattern+ + (_gather_72_var = _gather_72_rule(p)) // ','.key_value_pattern+ ) { D(fprintf(stderr, "%*c+ items_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.key_value_pattern+")); - _res = _gather_70_var; + _res = _gather_72_var; goto done; } p->mark = _mark; @@ -9179,7 +9369,7 @@ key_value_pattern_rule(Parser *p) void *key; pattern_ty pattern; if ( - (key = _tmp_72_rule(p)) // literal_expr | attr + (key = _tmp_74_rule(p)) // literal_expr | attr && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -9501,7 +9691,7 @@ positional_patterns_rule(Parser *p) D(fprintf(stderr, "%*c> positional_patterns[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.pattern+")); asdl_pattern_seq* args; if ( - (args = (asdl_pattern_seq*)_gather_73_rule(p)) // ','.pattern+ + (args = (asdl_pattern_seq*)_gather_75_rule(p)) // ','.pattern+ ) { D(fprintf(stderr, "%*c+ positional_patterns[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.pattern+")); @@ -9540,13 +9730,13 @@ keyword_patterns_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> keyword_patterns[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.keyword_pattern+")); - asdl_seq * _gather_75_var; + asdl_seq * _gather_77_var; if ( - (_gather_75_var = _gather_75_rule(p)) // ','.keyword_pattern+ + (_gather_77_var = _gather_77_rule(p)) // ','.keyword_pattern+ ) { D(fprintf(stderr, "%*c+ keyword_patterns[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.keyword_pattern+")); - _res = _gather_75_var; + _res = _gather_77_var; goto done; } p->mark = _mark; @@ -9639,7 +9829,7 @@ expressions_rule(Parser *p) if ( (a = expression_rule(p)) // expression && - (b = _loop1_77_rule(p)) // ((',' expression))+ + (b = _loop1_79_rule(p)) // ((',' expression))+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -9808,11 +9998,11 @@ expression_rule(Parser *p) if ( (a = disjunction_rule(p)) // disjunction && - (_keyword = _PyPegen_expect_token(p, 627)) // token='if' + (_keyword = _PyPegen_expect_token(p, 634)) // token='if' && (b = disjunction_rule(p)) // disjunction && - (_keyword_1 = _PyPegen_expect_token(p, 630)) // token='else' + (_keyword_1 = _PyPegen_expect_token(p, 637)) // token='else' && (c = expression_rule(p)) // expression ) @@ -9914,9 +10104,9 @@ yield_expr_rule(Parser *p) Token * _keyword_1; expr_ty a; if ( - (_keyword = _PyPegen_expect_token(p, 570)) // token='yield' + (_keyword = _PyPegen_expect_token(p, 573)) // token='yield' && - (_keyword_1 = _PyPegen_expect_token(p, 569)) // token='from' + (_keyword_1 = _PyPegen_expect_token(p, 572)) // token='from' && (a = expression_rule(p)) // expression ) @@ -9952,7 +10142,7 @@ yield_expr_rule(Parser *p) Token * _keyword; void *a; if ( - (_keyword = _PyPegen_expect_token(p, 570)) // token='yield' + (_keyword = _PyPegen_expect_token(p, 573)) // token='yield' && (a = star_expressions_rule(p), !p->error_indicator) // star_expressions? ) @@ -10021,7 +10211,7 @@ star_expressions_rule(Parser *p) if ( (a = star_expression_rule(p)) // star_expression && - (b = _loop1_78_rule(p)) // ((',' star_expression))+ + (b = _loop1_80_rule(p)) // ((',' star_expression))+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -10216,7 +10406,7 @@ star_named_expressions_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_gather_79_rule(p)) // ','.star_named_expression+ + (a = (asdl_expr_seq*)_gather_81_rule(p)) // ','.star_named_expression+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -10504,7 +10694,7 @@ disjunction_rule(Parser *p) if ( (a = conjunction_rule(p)) // conjunction && - (b = _loop1_81_rule(p)) // (('or' conjunction))+ + (b = _loop1_83_rule(p)) // (('or' conjunction))+ ) { D(fprintf(stderr, "%*c+ disjunction[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "conjunction (('or' conjunction))+")); @@ -10590,7 +10780,7 @@ conjunction_rule(Parser *p) if ( (a = inversion_rule(p)) // inversion && - (b = _loop1_82_rule(p)) // (('and' inversion))+ + (b = _loop1_84_rule(p)) // (('and' inversion))+ ) { D(fprintf(stderr, "%*c+ conjunction[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "inversion (('and' inversion))+")); @@ -10674,7 +10864,7 @@ inversion_rule(Parser *p) Token * _keyword; expr_ty a; if ( - (_keyword = _PyPegen_expect_token(p, 578)) // token='not' + (_keyword = _PyPegen_expect_token(p, 581)) // token='not' && (a = inversion_rule(p)) // inversion ) @@ -10758,7 +10948,7 @@ comparison_rule(Parser *p) if ( (a = bitwise_or_rule(p)) // bitwise_or && - (b = _loop1_83_rule(p)) // compare_op_bitwise_or_pair+ + (b = _loop1_85_rule(p)) // compare_op_bitwise_or_pair+ ) { D(fprintf(stderr, "%*c+ comparison[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_or compare_op_bitwise_or_pair+")); @@ -11086,10 +11276,10 @@ noteq_bitwise_or_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> noteq_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('!=') bitwise_or")); - void *_tmp_84_var; + void *_tmp_86_var; expr_ty a; if ( - (_tmp_84_var = _tmp_84_rule(p)) // '!=' + (_tmp_86_var = _tmp_86_rule(p)) // '!=' && (a = bitwise_or_rule(p)) // bitwise_or ) @@ -11310,9 +11500,9 @@ notin_bitwise_or_rule(Parser *p) Token * _keyword_1; expr_ty a; if ( - (_keyword = _PyPegen_expect_token(p, 578)) // token='not' + (_keyword = _PyPegen_expect_token(p, 581)) // token='not' && - (_keyword_1 = _PyPegen_expect_token(p, 634)) // token='in' + (_keyword_1 = _PyPegen_expect_token(p, 641)) // token='in' && (a = bitwise_or_rule(p)) // bitwise_or ) @@ -11356,7 +11546,7 @@ in_bitwise_or_rule(Parser *p) Token * _keyword; expr_ty a; if ( - (_keyword = _PyPegen_expect_token(p, 634)) // token='in' + (_keyword = _PyPegen_expect_token(p, 641)) // token='in' && (a = bitwise_or_rule(p)) // bitwise_or ) @@ -11401,9 +11591,9 @@ isnot_bitwise_or_rule(Parser *p) Token * _keyword_1; expr_ty a; if ( - (_keyword = _PyPegen_expect_token(p, 579)) // token='is' + (_keyword = _PyPegen_expect_token(p, 582)) // token='is' && - (_keyword_1 = _PyPegen_expect_token(p, 578)) // token='not' + (_keyword_1 = _PyPegen_expect_token(p, 581)) // token='not' && (a = bitwise_or_rule(p)) // bitwise_or ) @@ -11447,7 +11637,7 @@ is_bitwise_or_rule(Parser *p) Token * _keyword; expr_ty a; if ( - (_keyword = _PyPegen_expect_token(p, 579)) // token='is' + (_keyword = _PyPegen_expect_token(p, 582)) // token='is' && (a = bitwise_or_rule(p)) // bitwise_or ) @@ -13046,7 +13236,7 @@ slices_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_gather_85_rule(p)) // ','.slice+ + (a = (asdl_expr_seq*)_gather_87_rule(p)) // ','.slice+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -13116,7 +13306,7 @@ slice_rule(Parser *p) && (b = expression_rule(p), !p->error_indicator) // expression? && - (c = _tmp_87_rule(p), !p->error_indicator) // [':' expression?] + (c = _tmp_89_rule(p), !p->error_indicator) // [':' expression?] ) { D(fprintf(stderr, "%*c+ slice[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression? ':' expression? [':' expression?]")); @@ -13228,7 +13418,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 597)) // token='True' + (_keyword = _PyPegen_expect_token(p, 600)) // token='True' ) { D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); @@ -13261,7 +13451,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 599)) // token='False' + (_keyword = _PyPegen_expect_token(p, 602)) // token='False' ) { D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); @@ -13294,7 +13484,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 598)) // token='None' + (_keyword = _PyPegen_expect_token(p, 601)) // token='None' ) { D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); @@ -13365,15 +13555,15 @@ atom_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'(' (tuple | group | genexp)")); - void *_tmp_88_var; + void *_tmp_90_var; if ( _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 7) // token='(' && - (_tmp_88_var = _tmp_88_rule(p)) // tuple | group | genexp + (_tmp_90_var = _tmp_90_rule(p)) // tuple | group | genexp ) { D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "&'(' (tuple | group | genexp)")); - _res = _tmp_88_var; + _res = _tmp_90_var; goto done; } p->mark = _mark; @@ -13386,15 +13576,15 @@ atom_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'[' (list | listcomp)")); - void *_tmp_89_var; + void *_tmp_91_var; if ( _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 9) // token='[' && - (_tmp_89_var = _tmp_89_rule(p)) // list | listcomp + (_tmp_91_var = _tmp_91_rule(p)) // list | listcomp ) { D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "&'[' (list | listcomp)")); - _res = _tmp_89_var; + _res = _tmp_91_var; goto done; } p->mark = _mark; @@ -13407,15 +13597,15 @@ atom_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'{' (dict | set | dictcomp | setcomp)")); - void *_tmp_90_var; + void *_tmp_92_var; if ( _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 25) // token='{' && - (_tmp_90_var = _tmp_90_rule(p)) // dict | set | dictcomp | setcomp + (_tmp_92_var = _tmp_92_rule(p)) // dict | set | dictcomp | setcomp ) { D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "&'{' (dict | set | dictcomp | setcomp)")); - _res = _tmp_90_var; + _res = _tmp_92_var; goto done; } p->mark = _mark; @@ -13484,7 +13674,7 @@ group_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (a = _tmp_91_rule(p)) // yield_expr | named_expression + (a = _tmp_93_rule(p)) // yield_expr | named_expression && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) @@ -13558,7 +13748,7 @@ lambdef_rule(Parser *p) void *a; expr_ty b; if ( - (_keyword = _PyPegen_expect_token(p, 583)) // token='lambda' + (_keyword = _PyPegen_expect_token(p, 586)) // token='lambda' && (a = lambda_params_rule(p), !p->error_indicator) // lambda_params? && @@ -13679,9 +13869,9 @@ lambda_parameters_rule(Parser *p) if ( (a = lambda_slash_no_default_rule(p)) // lambda_slash_no_default && - (b = (asdl_arg_seq*)_loop0_92_rule(p)) // lambda_param_no_default* + (b = (asdl_arg_seq*)_loop0_94_rule(p)) // lambda_param_no_default* && - (c = _loop0_93_rule(p)) // lambda_param_with_default* + (c = _loop0_95_rule(p)) // lambda_param_with_default* && (d = lambda_star_etc_rule(p), !p->error_indicator) // lambda_star_etc? ) @@ -13711,7 +13901,7 @@ lambda_parameters_rule(Parser *p) if ( (a = lambda_slash_with_default_rule(p)) // lambda_slash_with_default && - (b = _loop0_94_rule(p)) // lambda_param_with_default* + (b = _loop0_96_rule(p)) // lambda_param_with_default* && (c = lambda_star_etc_rule(p), !p->error_indicator) // lambda_star_etc? ) @@ -13739,9 +13929,9 @@ lambda_parameters_rule(Parser *p) asdl_seq * b; void *c; if ( - (a = (asdl_arg_seq*)_loop1_95_rule(p)) // lambda_param_no_default+ + (a = (asdl_arg_seq*)_loop1_97_rule(p)) // lambda_param_no_default+ && - (b = _loop0_96_rule(p)) // lambda_param_with_default* + (b = _loop0_98_rule(p)) // lambda_param_with_default* && (c = lambda_star_etc_rule(p), !p->error_indicator) // lambda_star_etc? ) @@ -13768,7 +13958,7 @@ lambda_parameters_rule(Parser *p) asdl_seq * a; void *b; if ( - (a = _loop1_97_rule(p)) // lambda_param_with_default+ + (a = _loop1_99_rule(p)) // lambda_param_with_default+ && (b = lambda_star_etc_rule(p), !p->error_indicator) // lambda_star_etc? ) @@ -13839,7 +14029,7 @@ lambda_slash_no_default_rule(Parser *p) Token * _literal_1; asdl_arg_seq* a; if ( - (a = (asdl_arg_seq*)_loop1_98_rule(p)) // lambda_param_no_default+ + (a = (asdl_arg_seq*)_loop1_100_rule(p)) // lambda_param_no_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -13868,7 +14058,7 @@ lambda_slash_no_default_rule(Parser *p) Token * _literal; asdl_arg_seq* a; if ( - (a = (asdl_arg_seq*)_loop1_99_rule(p)) // lambda_param_no_default+ + (a = (asdl_arg_seq*)_loop1_101_rule(p)) // lambda_param_no_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -13918,9 +14108,9 @@ lambda_slash_with_default_rule(Parser *p) asdl_seq * a; asdl_seq * b; if ( - (a = _loop0_100_rule(p)) // lambda_param_no_default* + (a = _loop0_102_rule(p)) // lambda_param_no_default* && - (b = _loop1_101_rule(p)) // lambda_param_with_default+ + (b = _loop1_103_rule(p)) // lambda_param_with_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -13950,9 +14140,9 @@ lambda_slash_with_default_rule(Parser *p) asdl_seq * a; asdl_seq * b; if ( - (a = _loop0_102_rule(p)) // lambda_param_no_default* + (a = _loop0_104_rule(p)) // lambda_param_no_default* && - (b = _loop1_103_rule(p)) // lambda_param_with_default+ + (b = _loop1_105_rule(p)) // lambda_param_with_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -14008,7 +14198,7 @@ lambda_star_etc_rule(Parser *p) && (a = lambda_param_no_default_rule(p)) // lambda_param_no_default && - (b = _loop0_104_rule(p)) // lambda_param_maybe_default* + (b = _loop0_106_rule(p)) // lambda_param_maybe_default* && (c = lambda_kwds_rule(p), !p->error_indicator) // lambda_kwds? ) @@ -14041,7 +14231,7 @@ lambda_star_etc_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 12)) // token=',' && - (b = _loop1_105_rule(p)) // lambda_param_maybe_default+ + (b = _loop1_107_rule(p)) // lambda_param_maybe_default+ && (c = lambda_kwds_rule(p), !p->error_indicator) // lambda_kwds? ) @@ -14456,7 +14646,7 @@ strings_rule(Parser *p) D(fprintf(stderr, "%*c> strings[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "STRING+")); asdl_seq * a; if ( - (a = _loop1_106_rule(p)) // STRING+ + (a = _loop1_108_rule(p)) // STRING+ ) { D(fprintf(stderr, "%*c+ strings[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "STRING+")); @@ -14576,7 +14766,7 @@ tuple_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (a = _tmp_107_rule(p), !p->error_indicator) // [star_named_expression ',' star_named_expressions?] + (a = _tmp_109_rule(p), !p->error_indicator) // [star_named_expression ',' star_named_expressions?] && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) @@ -14785,7 +14975,7 @@ double_starred_kvpairs_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_seq * a; if ( - (a = _gather_108_rule(p)) // ','.double_starred_kvpair+ + (a = _gather_110_rule(p)) // ','.double_starred_kvpair+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -14938,7 +15128,7 @@ for_if_clauses_rule(Parser *p) D(fprintf(stderr, "%*c> for_if_clauses[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "for_if_clause+")); asdl_comprehension_seq* a; if ( - (a = (asdl_comprehension_seq*)_loop1_110_rule(p)) // for_if_clause+ + (a = (asdl_comprehension_seq*)_loop1_112_rule(p)) // for_if_clause+ ) { D(fprintf(stderr, "%*c+ for_if_clauses[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "for_if_clause+")); @@ -14990,17 +15180,17 @@ for_if_clause_rule(Parser *p) if ( (async_var = _PyPegen_expect_token(p, ASYNC)) // token='ASYNC' && - (_keyword = _PyPegen_expect_token(p, 633)) // token='for' + (_keyword = _PyPegen_expect_token(p, 640)) // token='for' && (a = star_targets_rule(p)) // star_targets && - (_keyword_1 = _PyPegen_expect_token(p, 634)) // token='in' + (_keyword_1 = _PyPegen_expect_token(p, 641)) // token='in' && (_cut_var = 1) && (b = disjunction_rule(p)) // disjunction && - (c = (asdl_expr_seq*)_loop0_111_rule(p)) // (('if' disjunction))* + (c = (asdl_expr_seq*)_loop0_113_rule(p)) // (('if' disjunction))* ) { D(fprintf(stderr, "%*c+ for_if_clause[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC 'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); @@ -15033,17 +15223,17 @@ for_if_clause_rule(Parser *p) expr_ty b; asdl_expr_seq* c; if ( - (_keyword = _PyPegen_expect_token(p, 633)) // token='for' + (_keyword = _PyPegen_expect_token(p, 640)) // token='for' && (a = star_targets_rule(p)) // star_targets && - (_keyword_1 = _PyPegen_expect_token(p, 634)) // token='in' + (_keyword_1 = _PyPegen_expect_token(p, 641)) // token='in' && (_cut_var = 1) && (b = disjunction_rule(p)) // disjunction && - (c = (asdl_expr_seq*)_loop0_112_rule(p)) // (('if' disjunction))* + (c = (asdl_expr_seq*)_loop0_114_rule(p)) // (('if' disjunction))* ) { D(fprintf(stderr, "%*c+ for_if_clause[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); @@ -15297,7 +15487,7 @@ genexp_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (a = _tmp_113_rule(p)) // assignment_expression | expression !':=' + (a = _tmp_115_rule(p)) // assignment_expression | expression !':=' && (b = for_if_clauses_rule(p)) // for_if_clauses && @@ -15540,9 +15730,9 @@ args_rule(Parser *p) asdl_expr_seq* a; void *b; if ( - (a = (asdl_expr_seq*)_gather_114_rule(p)) // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ + (a = (asdl_expr_seq*)_gather_116_rule(p)) // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ && - (b = _tmp_116_rule(p), !p->error_indicator) // [',' kwargs] + (b = _tmp_118_rule(p), !p->error_indicator) // [',' kwargs] ) { D(fprintf(stderr, "%*c+ args[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ [',' kwargs]")); @@ -15630,11 +15820,11 @@ kwargs_rule(Parser *p) asdl_seq * a; asdl_seq * b; if ( - (a = _gather_117_rule(p)) // ','.kwarg_or_starred+ + (a = _gather_119_rule(p)) // ','.kwarg_or_starred+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (b = _gather_119_rule(p)) // ','.kwarg_or_double_starred+ + (b = _gather_121_rule(p)) // ','.kwarg_or_double_starred+ ) { D(fprintf(stderr, "%*c+ kwargs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+ ',' ','.kwarg_or_double_starred+")); @@ -15656,13 +15846,13 @@ kwargs_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> kwargs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+")); - asdl_seq * _gather_121_var; + asdl_seq * _gather_123_var; if ( - (_gather_121_var = _gather_121_rule(p)) // ','.kwarg_or_starred+ + (_gather_123_var = _gather_123_rule(p)) // ','.kwarg_or_starred+ ) { D(fprintf(stderr, "%*c+ kwargs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+")); - _res = _gather_121_var; + _res = _gather_123_var; goto done; } p->mark = _mark; @@ -15675,13 +15865,13 @@ kwargs_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> kwargs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_double_starred+")); - asdl_seq * _gather_123_var; + asdl_seq * _gather_125_var; if ( - (_gather_123_var = _gather_123_rule(p)) // ','.kwarg_or_double_starred+ + (_gather_125_var = _gather_125_rule(p)) // ','.kwarg_or_double_starred+ ) { D(fprintf(stderr, "%*c+ kwargs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_double_starred+")); - _res = _gather_123_var; + _res = _gather_125_var; goto done; } p->mark = _mark; @@ -16043,7 +16233,7 @@ star_targets_rule(Parser *p) if ( (a = star_target_rule(p)) // star_target && - (b = _loop0_125_rule(p)) // ((',' star_target))* + (b = _loop0_127_rule(p)) // ((',' star_target))* && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -16097,7 +16287,7 @@ star_targets_list_seq_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_gather_126_rule(p)) // ','.star_target+ + (a = (asdl_expr_seq*)_gather_128_rule(p)) // ','.star_target+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -16145,7 +16335,7 @@ star_targets_tuple_seq_rule(Parser *p) if ( (a = star_target_rule(p)) // star_target && - (b = _loop1_128_rule(p)) // ((',' star_target))+ + (b = _loop1_130_rule(p)) // ((',' star_target))+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -16231,7 +16421,7 @@ star_target_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (a = _tmp_129_rule(p)) // !'*' star_target + (a = _tmp_131_rule(p)) // !'*' star_target ) { D(fprintf(stderr, "%*c+ star_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (!'*' star_target)")); @@ -17138,7 +17328,7 @@ del_targets_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_gather_130_rule(p)) // ','.del_target+ + (a = (asdl_expr_seq*)_gather_132_rule(p)) // ','.del_target+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -17490,7 +17680,7 @@ type_expressions_rule(Parser *p) expr_ty b; expr_ty c; if ( - (a = _gather_132_rule(p)) // ','.expression+ + (a = _gather_134_rule(p)) // ','.expression+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && @@ -17529,7 +17719,7 @@ type_expressions_rule(Parser *p) asdl_seq * a; expr_ty b; if ( - (a = _gather_134_rule(p)) // ','.expression+ + (a = _gather_136_rule(p)) // ','.expression+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && @@ -17562,7 +17752,7 @@ type_expressions_rule(Parser *p) asdl_seq * a; expr_ty b; if ( - (a = _gather_136_rule(p)) // ','.expression+ + (a = _gather_138_rule(p)) // ','.expression+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && @@ -17682,7 +17872,7 @@ type_expressions_rule(Parser *p) D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.expression+")); asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_gather_138_rule(p)) // ','.expression+ + (a = (asdl_expr_seq*)_gather_140_rule(p)) // ','.expression+ ) { D(fprintf(stderr, "%*c+ type_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.expression+")); @@ -17731,7 +17921,7 @@ func_type_comment_rule(Parser *p) && (t = _PyPegen_expect_token(p, TYPE_COMMENT)) // token='TYPE_COMMENT' && - _PyPegen_lookahead(1, _tmp_140_rule, p) + _PyPegen_lookahead(1, _tmp_142_rule, p) ) { D(fprintf(stderr, "%*c+ func_type_comment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE TYPE_COMMENT &(NEWLINE INDENT)")); @@ -17856,7 +18046,7 @@ invalid_arguments_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_opt_var = _tmp_141_rule(p), !p->error_indicator) // [args | expression for_if_clauses] + (_opt_var = _tmp_143_rule(p), !p->error_indicator) // [args | expression for_if_clauses] ) { D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses ',' [args | expression for_if_clauses]")); @@ -18024,7 +18214,7 @@ invalid_kwarg_rule(Parser *p) Token* a; Token * b; if ( - (a = (Token*)_tmp_142_rule(p)) // 'True' | 'False' | 'None' + (a = (Token*)_tmp_144_rule(p)) // 'True' | 'False' | 'None' && (b = _PyPegen_expect_token(p, 22)) // token='=' ) @@ -18084,7 +18274,7 @@ invalid_kwarg_rule(Parser *p) expr_ty a; Token * b; if ( - _PyPegen_lookahead(0, _tmp_143_rule, p) + _PyPegen_lookahead(0, _tmp_145_rule, p) && (a = expression_rule(p)) // expression && @@ -18147,11 +18337,11 @@ expression_without_invalid_rule(Parser *p) if ( (a = disjunction_rule(p)) // disjunction && - (_keyword = _PyPegen_expect_token(p, 627)) // token='if' + (_keyword = _PyPegen_expect_token(p, 634)) // token='if' && (b = disjunction_rule(p)) // disjunction && - (_keyword_1 = _PyPegen_expect_token(p, 630)) // token='else' + (_keyword_1 = _PyPegen_expect_token(p, 637)) // token='else' && (c = expression_rule(p)) // expression ) @@ -18290,7 +18480,7 @@ invalid_expression_rule(Parser *p) expr_ty a; expr_ty b; if ( - _PyPegen_lookahead(0, _tmp_144_rule, p) + _PyPegen_lookahead(0, _tmp_146_rule, p) && (a = disjunction_rule(p)) // disjunction && @@ -18322,11 +18512,11 @@ invalid_expression_rule(Parser *p) if ( (a = disjunction_rule(p)) // disjunction && - (_keyword = _PyPegen_expect_token(p, 627)) // token='if' + (_keyword = _PyPegen_expect_token(p, 634)) // token='if' && (b = disjunction_rule(p)) // disjunction && - _PyPegen_lookahead(0, _tmp_145_rule, p) + _PyPegen_lookahead(0, _tmp_147_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction !('else' | ':')")); @@ -18408,7 +18598,7 @@ invalid_named_expression_rule(Parser *p) && (b = bitwise_or_rule(p)) // bitwise_or && - _PyPegen_lookahead(0, _tmp_146_rule, p) + _PyPegen_lookahead(0, _tmp_148_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' bitwise_or !('=' | ':=')")); @@ -18434,7 +18624,7 @@ invalid_named_expression_rule(Parser *p) Token * b; expr_ty bitwise_or_var; if ( - _PyPegen_lookahead(0, _tmp_147_rule, p) + _PyPegen_lookahead(0, _tmp_149_rule, p) && (a = bitwise_or_rule(p)) // bitwise_or && @@ -18442,7 +18632,7 @@ invalid_named_expression_rule(Parser *p) && (bitwise_or_var = bitwise_or_rule(p)) // bitwise_or && - _PyPegen_lookahead(0, _tmp_148_rule, p) + _PyPegen_lookahead(0, _tmp_150_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!(list | tuple | genexp | 'True' | 'None' | 'False') bitwise_or '=' bitwise_or !('=' | ':=')")); @@ -18519,7 +18709,7 @@ invalid_assignment_rule(Parser *p) D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions* ':' expression")); Token * _literal; Token * _literal_1; - asdl_seq * _loop0_149_var; + asdl_seq * _loop0_151_var; expr_ty a; expr_ty expression_var; if ( @@ -18527,7 +18717,7 @@ invalid_assignment_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_loop0_149_var = _loop0_149_rule(p)) // star_named_expressions* + (_loop0_151_var = _loop0_151_rule(p)) // star_named_expressions* && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -18584,10 +18774,10 @@ invalid_assignment_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* star_expressions '='")); Token * _literal; - asdl_seq * _loop0_150_var; + asdl_seq * _loop0_152_var; expr_ty a; if ( - (_loop0_150_var = _loop0_150_rule(p)) // ((star_targets '='))* + (_loop0_152_var = _loop0_152_rule(p)) // ((star_targets '='))* && (a = star_expressions_rule(p)) // star_expressions && @@ -18614,10 +18804,10 @@ invalid_assignment_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* yield_expr '='")); Token * _literal; - asdl_seq * _loop0_151_var; + asdl_seq * _loop0_153_var; expr_ty a; if ( - (_loop0_151_var = _loop0_151_rule(p)) // ((star_targets '='))* + (_loop0_153_var = _loop0_153_rule(p)) // ((star_targets '='))* && (a = yield_expr_rule(p)) // yield_expr && @@ -18643,7 +18833,7 @@ invalid_assignment_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions augassign (yield_expr | star_expressions)")); - void *_tmp_152_var; + void *_tmp_154_var; expr_ty a; AugOperator* augassign_var; if ( @@ -18651,7 +18841,7 @@ invalid_assignment_rule(Parser *p) && (augassign_var = augassign_rule(p)) // augassign && - (_tmp_152_var = _tmp_152_rule(p)) // yield_expr | star_expressions + (_tmp_154_var = _tmp_154_rule(p)) // yield_expr | star_expressions ) { D(fprintf(stderr, "%*c+ invalid_assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions augassign (yield_expr | star_expressions)")); @@ -18778,7 +18968,7 @@ invalid_del_stmt_rule(Parser *p) Token * _keyword; expr_ty a; if ( - (_keyword = _PyPegen_expect_token(p, 600)) // token='del' + (_keyword = _PyPegen_expect_token(p, 603)) // token='del' && (a = star_expressions_rule(p)) // star_expressions ) @@ -18865,11 +19055,11 @@ invalid_comprehension_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '(' | '{') starred_expression for_if_clauses")); - void *_tmp_153_var; + void *_tmp_155_var; expr_ty a; asdl_comprehension_seq* for_if_clauses_var; if ( - (_tmp_153_var = _tmp_153_rule(p)) // '[' | '(' | '{' + (_tmp_155_var = _tmp_155_rule(p)) // '[' | '(' | '{' && (a = starred_expression_rule(p)) // starred_expression && @@ -18896,12 +19086,12 @@ invalid_comprehension_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '{') star_named_expression ',' star_named_expressions for_if_clauses")); Token * _literal; - void *_tmp_154_var; + void *_tmp_156_var; expr_ty a; asdl_expr_seq* b; asdl_comprehension_seq* for_if_clauses_var; if ( - (_tmp_154_var = _tmp_154_rule(p)) // '[' | '{' + (_tmp_156_var = _tmp_156_rule(p)) // '[' | '{' && (a = star_named_expression_rule(p)) // star_named_expression && @@ -18931,12 +19121,12 @@ invalid_comprehension_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '{') star_named_expression ',' for_if_clauses")); - void *_tmp_155_var; + void *_tmp_157_var; expr_ty a; Token * b; asdl_comprehension_seq* for_if_clauses_var; if ( - (_tmp_155_var = _tmp_155_rule(p)) // '[' | '{' + (_tmp_157_var = _tmp_157_rule(p)) // '[' | '{' && (a = star_named_expression_rule(p)) // star_named_expression && @@ -19036,11 +19226,11 @@ invalid_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default* invalid_parameters_helper param_no_default")); - asdl_seq * _loop0_156_var; + asdl_seq * _loop0_158_var; arg_ty a; void *invalid_parameters_helper_var; if ( - (_loop0_156_var = _loop0_156_rule(p)) // param_no_default* + (_loop0_158_var = _loop0_158_rule(p)) // param_no_default* && (invalid_parameters_helper_var = invalid_parameters_helper_rule(p)) // invalid_parameters_helper && @@ -19066,18 +19256,18 @@ invalid_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default* '(' param_no_default+ ','? ')'")); - asdl_seq * _loop0_157_var; - asdl_seq * _loop1_158_var; + asdl_seq * _loop0_159_var; + asdl_seq * _loop1_160_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings Token * a; Token * b; if ( - (_loop0_157_var = _loop0_157_rule(p)) // param_no_default* + (_loop0_159_var = _loop0_159_rule(p)) // param_no_default* && (a = _PyPegen_expect_token(p, 7)) // token='(' && - (_loop1_158_var = _loop1_158_rule(p)) // param_no_default+ + (_loop1_160_var = _loop1_160_rule(p)) // param_no_default+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -19144,13 +19334,13 @@ invalid_parameters_helper_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default+")); - asdl_seq * _loop1_159_var; + asdl_seq * _loop1_161_var; if ( - (_loop1_159_var = _loop1_159_rule(p)) // param_with_default+ + (_loop1_161_var = _loop1_161_rule(p)) // param_with_default+ ) { D(fprintf(stderr, "%*c+ invalid_parameters_helper[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_with_default+")); - _res = _loop1_159_var; + _res = _loop1_161_var; goto done; } p->mark = _mark; @@ -19182,11 +19372,11 @@ invalid_lambda_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* invalid_lambda_parameters_helper lambda_param_no_default")); - asdl_seq * _loop0_160_var; + asdl_seq * _loop0_162_var; arg_ty a; void *invalid_lambda_parameters_helper_var; if ( - (_loop0_160_var = _loop0_160_rule(p)) // lambda_param_no_default* + (_loop0_162_var = _loop0_162_rule(p)) // lambda_param_no_default* && (invalid_lambda_parameters_helper_var = invalid_lambda_parameters_helper_rule(p)) // invalid_lambda_parameters_helper && @@ -19212,18 +19402,18 @@ invalid_lambda_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* '(' ','.lambda_param+ ','? ')'")); - asdl_seq * _gather_162_var; - asdl_seq * _loop0_161_var; + asdl_seq * _gather_164_var; + asdl_seq * _loop0_163_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings Token * a; Token * b; if ( - (_loop0_161_var = _loop0_161_rule(p)) // lambda_param_no_default* + (_loop0_163_var = _loop0_163_rule(p)) // lambda_param_no_default* && (a = _PyPegen_expect_token(p, 7)) // token='(' && - (_gather_162_var = _gather_162_rule(p)) // ','.lambda_param+ + (_gather_164_var = _gather_164_rule(p)) // ','.lambda_param+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -19292,13 +19482,13 @@ invalid_lambda_parameters_helper_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+")); - asdl_seq * _loop1_164_var; + asdl_seq * _loop1_166_var; if ( - (_loop1_164_var = _loop1_164_rule(p)) // lambda_param_with_default+ + (_loop1_166_var = _loop1_166_rule(p)) // lambda_param_with_default+ ) { D(fprintf(stderr, "%*c+ invalid_lambda_parameters_helper[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+")); - _res = _loop1_164_var; + _res = _loop1_166_var; goto done; } p->mark = _mark; @@ -19328,12 +19518,12 @@ invalid_star_etc_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))")); - void *_tmp_165_var; + void *_tmp_167_var; Token * a; if ( (a = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_165_var = _tmp_165_rule(p)) // ')' | ',' (')' | '**') + (_tmp_167_var = _tmp_167_rule(p)) // ')' | ',' (')' | '**') ) { D(fprintf(stderr, "%*c+ invalid_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))")); @@ -19403,11 +19593,11 @@ invalid_lambda_star_etc_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))")); Token * _literal; - void *_tmp_166_var; + void *_tmp_168_var; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_166_var = _tmp_166_rule(p)) // ':' | ',' (':' | '**') + (_tmp_168_var = _tmp_168_rule(p)) // ':' | ',' (':' | '**') ) { D(fprintf(stderr, "%*c+ invalid_lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))")); @@ -19505,11 +19695,11 @@ invalid_with_item_rule(Parser *p) if ( (expression_var = expression_rule(p)) // expression && - (_keyword = _PyPegen_expect_token(p, 625)) // token='as' + (_keyword = _PyPegen_expect_token(p, 632)) // token='as' && (a = expression_rule(p)) // expression && - _PyPegen_lookahead(1, _tmp_167_rule, p) + _PyPegen_lookahead(1, _tmp_169_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_with_item[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression 'as' expression &(',' | ')' | ':')")); @@ -19555,7 +19745,7 @@ invalid_for_target_rule(Parser *p) if ( (_opt_var = _PyPegen_expect_token(p, ASYNC), !p->error_indicator) // ASYNC? && - (_keyword = _PyPegen_expect_token(p, 633)) // token='for' + (_keyword = _PyPegen_expect_token(p, 640)) // token='for' && (a = star_expressions_rule(p)) // star_expressions ) @@ -19725,7 +19915,7 @@ invalid_with_stmt_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' ','.(expression ['as' star_target])+ &&':'")); - asdl_seq * _gather_168_var; + asdl_seq * _gather_170_var; Token * _keyword; Token * _literal; void *_opt_var; @@ -19733,15 +19923,15 @@ invalid_with_stmt_rule(Parser *p) if ( (_opt_var = _PyPegen_expect_token(p, ASYNC), !p->error_indicator) // ASYNC? && - (_keyword = _PyPegen_expect_token(p, 609)) // token='with' + (_keyword = _PyPegen_expect_token(p, 612)) // token='with' && - (_gather_168_var = _gather_168_rule(p)) // ','.(expression ['as' star_target])+ + (_gather_170_var = _gather_170_rule(p)) // ','.(expression ['as' star_target])+ && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' ) { D(fprintf(stderr, "%*c+ invalid_with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' ','.(expression ['as' star_target])+ &&':'")); - _res = _PyPegen_dummy_name(p, _opt_var, _keyword, _gather_168_var, _literal); + _res = _PyPegen_dummy_name(p, _opt_var, _keyword, _gather_170_var, _literal); goto done; } p->mark = _mark; @@ -19754,7 +19944,7 @@ invalid_with_stmt_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' &&':'")); - asdl_seq * _gather_170_var; + asdl_seq * _gather_172_var; Token * _keyword; Token * _literal; Token * _literal_1; @@ -19766,11 +19956,11 @@ invalid_with_stmt_rule(Parser *p) if ( (_opt_var = _PyPegen_expect_token(p, ASYNC), !p->error_indicator) // ASYNC? && - (_keyword = _PyPegen_expect_token(p, 609)) // token='with' + (_keyword = _PyPegen_expect_token(p, 612)) // token='with' && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (_gather_170_var = _gather_170_rule(p)) // ','.(expressions ['as' star_target])+ + (_gather_172_var = _gather_172_rule(p)) // ','.(expressions ['as' star_target])+ && (_opt_var_1 = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -19780,7 +19970,7 @@ invalid_with_stmt_rule(Parser *p) ) { D(fprintf(stderr, "%*c+ invalid_with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' &&':'")); - _res = _PyPegen_dummy_name(p, _opt_var, _keyword, _literal, _gather_170_var, _opt_var_1, _literal_1, _literal_2); + _res = _PyPegen_dummy_name(p, _opt_var, _keyword, _literal, _gather_172_var, _opt_var_1, _literal_1, _literal_2); goto done; } p->mark = _mark; @@ -19812,7 +20002,7 @@ invalid_with_stmt_indent_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' ','.(expression ['as' star_target])+ ':' NEWLINE !INDENT")); - asdl_seq * _gather_172_var; + asdl_seq * _gather_174_var; Token * _literal; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings @@ -19821,9 +20011,9 @@ invalid_with_stmt_indent_rule(Parser *p) if ( (_opt_var = _PyPegen_expect_token(p, ASYNC), !p->error_indicator) // ASYNC? && - (a = _PyPegen_expect_token(p, 609)) // token='with' + (a = _PyPegen_expect_token(p, 612)) // token='with' && - (_gather_172_var = _gather_172_rule(p)) // ','.(expression ['as' star_target])+ + (_gather_174_var = _gather_174_rule(p)) // ','.(expression ['as' star_target])+ && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -19851,7 +20041,7 @@ invalid_with_stmt_indent_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' ':' NEWLINE !INDENT")); - asdl_seq * _gather_174_var; + asdl_seq * _gather_176_var; Token * _literal; Token * _literal_1; Token * _literal_2; @@ -19864,11 +20054,11 @@ invalid_with_stmt_indent_rule(Parser *p) if ( (_opt_var = _PyPegen_expect_token(p, ASYNC), !p->error_indicator) // ASYNC? && - (a = _PyPegen_expect_token(p, 609)) // token='with' + (a = _PyPegen_expect_token(p, 612)) // token='with' && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (_gather_174_var = _gather_174_rule(p)) // ','.(expressions ['as' star_target])+ + (_gather_176_var = _gather_176_rule(p)) // ','.(expressions ['as' star_target])+ && (_opt_var_1 = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -19900,7 +20090,10 @@ invalid_with_stmt_indent_rule(Parser *p) return _res; } -// invalid_try_stmt: 'try' ':' NEWLINE !INDENT | 'try' ':' block !('except' | 'finally') +// invalid_try_stmt: +// | 'try' ':' NEWLINE !INDENT +// | 'try' ':' block !('except' | 'finally') +// | 'try' ':' block* ((except_block+ except_star_block) | (except_star_block+ except_block)) block* static void * invalid_try_stmt_rule(Parser *p) { @@ -19921,7 +20114,7 @@ invalid_try_stmt_rule(Parser *p) Token * a; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 612)) // token='try' + (a = _PyPegen_expect_token(p, 618)) // token='try' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -19953,13 +20146,13 @@ invalid_try_stmt_rule(Parser *p) Token * _literal; asdl_stmt_seq* block_var; if ( - (_keyword = _PyPegen_expect_token(p, 612)) // token='try' + (_keyword = _PyPegen_expect_token(p, 618)) // token='try' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && (block_var = block_rule(p)) // block && - _PyPegen_lookahead(0, _tmp_176_rule, p) + _PyPegen_lookahead(0, _tmp_178_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' ':' block !('except' | 'finally')")); @@ -19975,6 +20168,42 @@ invalid_try_stmt_rule(Parser *p) D(fprintf(stderr, "%*c%s invalid_try_stmt[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'try' ':' block !('except' | 'finally')")); } + { // 'try' ':' block* ((except_block+ except_star_block) | (except_star_block+ except_block)) block* + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> invalid_try_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'try' ':' block* ((except_block+ except_star_block) | (except_star_block+ except_block)) block*")); + Token * _keyword; + Token * _literal; + asdl_seq * _loop0_179_var; + asdl_seq * _loop0_181_var; + void *_tmp_180_var; + if ( + (_keyword = _PyPegen_expect_token(p, 618)) // token='try' + && + (_literal = _PyPegen_expect_token(p, 11)) // token=':' + && + (_loop0_179_var = _loop0_179_rule(p)) // block* + && + (_tmp_180_var = _tmp_180_rule(p)) // (except_block+ except_star_block) | (except_star_block+ except_block) + && + (_loop0_181_var = _loop0_181_rule(p)) // block* + ) + { + D(fprintf(stderr, "%*c+ invalid_try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' ':' block* ((except_block+ except_star_block) | (except_star_block+ except_block)) block*")); + _res = RAISE_SYNTAX_ERROR ( "cannot have both 'except' and 'except*' on the same 'try'" ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + D(p->level--); + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s invalid_try_stmt[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'try' ':' block* ((except_block+ except_star_block) | (except_star_block+ except_block)) block*")); + } _res = NULL; done: D(p->level--); @@ -19982,9 +20211,10 @@ invalid_try_stmt_rule(Parser *p) } // invalid_except_stmt: -// | 'except' expression ',' expressions ['as' NAME] ':' -// | 'except' expression ['as' NAME] NEWLINE +// | 'except' '*'? expression ',' expressions ['as' NAME] ':' +// | 'except' '*'? expression ['as' NAME] NEWLINE // | 'except' NEWLINE +// | 'except' '*' (NEWLINE | ':') static void * invalid_except_stmt_rule(Parser *p) { @@ -19995,21 +20225,25 @@ invalid_except_stmt_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // 'except' expression ',' expressions ['as' NAME] ':' + { // 'except' '*'? expression ',' expressions ['as' NAME] ':' if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> invalid_except_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' expression ',' expressions ['as' NAME] ':'")); + D(fprintf(stderr, "%*c> invalid_except_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' '*'? expression ',' expressions ['as' NAME] ':'")); Token * _keyword; Token * _literal; Token * _literal_1; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings + void *_opt_var_1; + UNUSED(_opt_var_1); // Silence compiler warnings expr_ty a; expr_ty expressions_var; if ( - (_keyword = _PyPegen_expect_token(p, 623)) // token='except' + (_keyword = _PyPegen_expect_token(p, 629)) // token='except' + && + (_opt_var = _PyPegen_expect_token(p, 16), !p->error_indicator) // '*'? && (a = expression_rule(p)) // expression && @@ -20017,12 +20251,12 @@ invalid_except_stmt_rule(Parser *p) && (expressions_var = expressions_rule(p)) // expressions && - (_opt_var = _tmp_177_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var_1 = _tmp_182_rule(p), !p->error_indicator) // ['as' NAME] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ invalid_except_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' expression ',' expressions ['as' NAME] ':'")); + D(fprintf(stderr, "%*c+ invalid_except_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' '*'? expression ',' expressions ['as' NAME] ':'")); _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( a , "multiple exception types must be parenthesized" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -20033,30 +20267,34 @@ invalid_except_stmt_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s invalid_except_stmt[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'except' expression ',' expressions ['as' NAME] ':'")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'except' '*'? expression ',' expressions ['as' NAME] ':'")); } - { // 'except' expression ['as' NAME] NEWLINE + { // 'except' '*'? expression ['as' NAME] NEWLINE if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> invalid_except_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' expression ['as' NAME] NEWLINE")); + D(fprintf(stderr, "%*c> invalid_except_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' '*'? expression ['as' NAME] NEWLINE")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings + void *_opt_var_1; + UNUSED(_opt_var_1); // Silence compiler warnings Token * a; expr_ty expression_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 623)) // token='except' + (a = _PyPegen_expect_token(p, 629)) // token='except' + && + (_opt_var = _PyPegen_expect_token(p, 16), !p->error_indicator) // '*'? && (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_178_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var_1 = _tmp_183_rule(p), !p->error_indicator) // ['as' NAME] && (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) { - D(fprintf(stderr, "%*c+ invalid_except_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' expression ['as' NAME] NEWLINE")); + D(fprintf(stderr, "%*c+ invalid_except_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' '*'? expression ['as' NAME] NEWLINE")); _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -20067,7 +20305,7 @@ invalid_except_stmt_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s invalid_except_stmt[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'except' expression ['as' NAME] NEWLINE")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'except' '*'? expression ['as' NAME] NEWLINE")); } { // 'except' NEWLINE if (p->error_indicator) { @@ -20078,7 +20316,7 @@ invalid_except_stmt_rule(Parser *p) Token * a; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 623)) // token='except' + (a = _PyPegen_expect_token(p, 629)) // token='except' && (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) @@ -20096,6 +20334,36 @@ invalid_except_stmt_rule(Parser *p) D(fprintf(stderr, "%*c%s invalid_except_stmt[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'except' NEWLINE")); } + { // 'except' '*' (NEWLINE | ':') + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> invalid_except_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' '*' (NEWLINE | ':')")); + Token * _literal; + void *_tmp_184_var; + Token * a; + if ( + (a = _PyPegen_expect_token(p, 629)) // token='except' + && + (_literal = _PyPegen_expect_token(p, 16)) // token='*' + && + (_tmp_184_var = _tmp_184_rule(p)) // NEWLINE | ':' + ) + { + D(fprintf(stderr, "%*c+ invalid_except_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' '*' (NEWLINE | ':')")); + _res = RAISE_SYNTAX_ERROR ( "expected one or more exception types" ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + D(p->level--); + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s invalid_except_stmt[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'except' '*' (NEWLINE | ':')")); + } _res = NULL; done: D(p->level--); @@ -20123,7 +20391,7 @@ invalid_finally_stmt_rule(Parser *p) Token * a; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 620)) // token='finally' + (a = _PyPegen_expect_token(p, 625)) // token='finally' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -20177,11 +20445,11 @@ invalid_except_stmt_indent_rule(Parser *p) expr_ty expression_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 623)) // token='except' + (a = _PyPegen_expect_token(p, 629)) // token='except' && (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_179_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_185_rule(p), !p->error_indicator) // ['as' NAME] && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -20213,7 +20481,7 @@ invalid_except_stmt_indent_rule(Parser *p) Token * a; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 623)) // token='except' + (a = _PyPegen_expect_token(p, 629)) // token='except' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -20241,11 +20509,10 @@ invalid_except_stmt_indent_rule(Parser *p) return _res; } -// invalid_match_stmt: -// | "match" subject_expr !':' -// | "match" subject_expr ':' NEWLINE !INDENT +// invalid_except_star_stmt_indent: +// | 'except' '*' expression ['as' NAME] ':' NEWLINE !INDENT static void * -invalid_match_stmt_rule(Parser *p) +invalid_except_star_stmt_indent_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -20254,23 +20521,84 @@ invalid_match_stmt_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // "match" subject_expr !':' + { // 'except' '*' expression ['as' NAME] ':' NEWLINE !INDENT if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> invalid_match_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"match\" subject_expr !':'")); - expr_ty _keyword; - expr_ty subject_expr_var; + D(fprintf(stderr, "%*c> invalid_except_star_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' '*' expression ['as' NAME] ':' NEWLINE !INDENT")); + Token * _literal; + Token * _literal_1; + void *_opt_var; + UNUSED(_opt_var); // Silence compiler warnings + Token * a; + expr_ty expression_var; + Token * newline_var; if ( - (_keyword = _PyPegen_expect_soft_keyword(p, "match")) // soft_keyword='"match"' + (a = _PyPegen_expect_token(p, 629)) // token='except' && - (subject_expr_var = subject_expr_rule(p)) // subject_expr + (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 11) // token=':' + (expression_var = expression_rule(p)) // expression + && + (_opt_var = _tmp_186_rule(p), !p->error_indicator) // ['as' NAME] + && + (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' + && + (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' + && + _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, INDENT) // token=INDENT ) { - D(fprintf(stderr, "%*c+ invalid_match_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"match\" subject_expr !':'")); + D(fprintf(stderr, "%*c+ invalid_except_star_stmt_indent[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' '*' expression ['as' NAME] ':' NEWLINE !INDENT")); + _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'except*' statement on line %d" , a -> lineno ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + D(p->level--); + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s invalid_except_star_stmt_indent[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'except' '*' expression ['as' NAME] ':' NEWLINE !INDENT")); + } + _res = NULL; + done: + D(p->level--); + return _res; +} + +// invalid_match_stmt: +// | "match" subject_expr !':' +// | "match" subject_expr ':' NEWLINE !INDENT +static void * +invalid_match_stmt_rule(Parser *p) +{ + D(p->level++); + if (p->error_indicator) { + D(p->level--); + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // "match" subject_expr !':' + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> invalid_match_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"match\" subject_expr !':'")); + expr_ty _keyword; + expr_ty subject_expr_var; + if ( + (_keyword = _PyPegen_expect_soft_keyword(p, "match")) // soft_keyword='"match"' + && + (subject_expr_var = subject_expr_rule(p)) // subject_expr + && + _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 11) // token=':' + ) + { + D(fprintf(stderr, "%*c+ invalid_match_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"match\" subject_expr !':'")); _res = CHECK_VERSION ( void* , 10 , "Pattern matching is" , RAISE_SYNTAX_ERROR ( "expected ':'" ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -20438,7 +20766,7 @@ invalid_as_pattern_rule(Parser *p) if ( (or_pattern_var = or_pattern_rule(p)) // or_pattern && - (_keyword = _PyPegen_expect_token(p, 625)) // token='as' + (_keyword = _PyPegen_expect_token(p, 632)) // token='as' && (a = _PyPegen_expect_soft_keyword(p, "_")) // soft_keyword='"_"' ) @@ -20468,7 +20796,7 @@ invalid_as_pattern_rule(Parser *p) if ( (or_pattern_var = or_pattern_rule(p)) // or_pattern && - (_keyword = _PyPegen_expect_token(p, 625)) // token='as' + (_keyword = _PyPegen_expect_token(p, 632)) // token='as' && _PyPegen_lookahead_with_name(0, _PyPegen_name_token, p) && @@ -20565,7 +20893,7 @@ invalid_class_argument_pattern_rule(Parser *p) asdl_pattern_seq* a; asdl_seq* keyword_patterns_var; if ( - (_opt_var = _tmp_180_rule(p), !p->error_indicator) // [positional_patterns ','] + (_opt_var = _tmp_187_rule(p), !p->error_indicator) // [positional_patterns ','] && (keyword_patterns_var = keyword_patterns_rule(p)) // keyword_patterns && @@ -20616,7 +20944,7 @@ invalid_if_stmt_rule(Parser *p) expr_ty named_expression_var; Token * newline_var; if ( - (_keyword = _PyPegen_expect_token(p, 627)) // token='if' + (_keyword = _PyPegen_expect_token(p, 634)) // token='if' && (named_expression_var = named_expression_rule(p)) // named_expression && @@ -20647,7 +20975,7 @@ invalid_if_stmt_rule(Parser *p) expr_ty a_1; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 627)) // token='if' + (a = _PyPegen_expect_token(p, 634)) // token='if' && (a_1 = named_expression_rule(p)) // named_expression && @@ -20700,7 +21028,7 @@ invalid_elif_stmt_rule(Parser *p) expr_ty named_expression_var; Token * newline_var; if ( - (_keyword = _PyPegen_expect_token(p, 629)) // token='elif' + (_keyword = _PyPegen_expect_token(p, 636)) // token='elif' && (named_expression_var = named_expression_rule(p)) // named_expression && @@ -20731,7 +21059,7 @@ invalid_elif_stmt_rule(Parser *p) expr_ty named_expression_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 629)) // token='elif' + (a = _PyPegen_expect_token(p, 636)) // token='elif' && (named_expression_var = named_expression_rule(p)) // named_expression && @@ -20782,7 +21110,7 @@ invalid_else_stmt_rule(Parser *p) Token * a; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 630)) // token='else' + (a = _PyPegen_expect_token(p, 637)) // token='else' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -20833,7 +21161,7 @@ invalid_while_stmt_rule(Parser *p) expr_ty named_expression_var; Token * newline_var; if ( - (_keyword = _PyPegen_expect_token(p, 632)) // token='while' + (_keyword = _PyPegen_expect_token(p, 639)) // token='while' && (named_expression_var = named_expression_rule(p)) // named_expression && @@ -20864,7 +21192,7 @@ invalid_while_stmt_rule(Parser *p) expr_ty named_expression_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 632)) // token='while' + (a = _PyPegen_expect_token(p, 639)) // token='while' && (named_expression_var = named_expression_rule(p)) // named_expression && @@ -20922,11 +21250,11 @@ invalid_for_stmt_rule(Parser *p) if ( (_opt_var = _PyPegen_expect_token(p, ASYNC), !p->error_indicator) // ASYNC? && - (a = _PyPegen_expect_token(p, 633)) // token='for' + (a = _PyPegen_expect_token(p, 640)) // token='for' && (star_targets_var = star_targets_rule(p)) // star_targets && - (_keyword = _PyPegen_expect_token(p, 634)) // token='in' + (_keyword = _PyPegen_expect_token(p, 641)) // token='in' && (star_expressions_var = star_expressions_rule(p)) // star_expressions && @@ -20989,7 +21317,7 @@ invalid_def_raw_rule(Parser *p) if ( (_opt_var = _PyPegen_expect_token(p, ASYNC), !p->error_indicator) // ASYNC? && - (a = _PyPegen_expect_token(p, 635)) // token='def' + (a = _PyPegen_expect_token(p, 642)) // token='def' && (name_var = _PyPegen_name_token(p)) // NAME && @@ -20999,7 +21327,7 @@ invalid_def_raw_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' && - (_opt_var_2 = _tmp_181_rule(p), !p->error_indicator) // ['->' expression] + (_opt_var_2 = _tmp_188_rule(p), !p->error_indicator) // ['->' expression] && (_literal_2 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -21051,11 +21379,11 @@ invalid_class_def_raw_rule(Parser *p) expr_ty name_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 636)) // token='class' + (a = _PyPegen_expect_token(p, 643)) // token='class' && (name_var = _PyPegen_name_token(p)) // NAME && - (_opt_var = _tmp_182_rule(p), !p->error_indicator) // ['(' arguments? ')'] + (_opt_var = _tmp_189_rule(p), !p->error_indicator) // ['(' arguments? ')'] && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -21103,11 +21431,11 @@ invalid_double_starred_kvpairs_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_double_starred_kvpairs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ',' invalid_kvpair")); - asdl_seq * _gather_183_var; + asdl_seq * _gather_190_var; Token * _literal; void *invalid_kvpair_var; if ( - (_gather_183_var = _gather_183_rule(p)) // ','.double_starred_kvpair+ + (_gather_190_var = _gather_190_rule(p)) // ','.double_starred_kvpair+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && @@ -21115,7 +21443,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) ) { D(fprintf(stderr, "%*c+ invalid_double_starred_kvpairs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ',' invalid_kvpair")); - _res = _PyPegen_dummy_name(p, _gather_183_var, _literal, invalid_kvpair_var); + _res = _PyPegen_dummy_name(p, _gather_190_var, _literal, invalid_kvpair_var); goto done; } p->mark = _mark; @@ -21168,7 +21496,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) && (a = _PyPegen_expect_token(p, 11)) // token=':' && - _PyPegen_lookahead(1, _tmp_185_rule, p) + _PyPegen_lookahead(1, _tmp_192_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_double_starred_kvpairs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' &('}' | ',')")); @@ -21648,7 +21976,7 @@ _tmp_6_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_6[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 569)) // token='from' + (_keyword = _PyPegen_expect_token(p, 572)) // token='from' ) { D(fprintf(stderr, "%*c+ _tmp_6[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'from'")); @@ -21684,7 +22012,7 @@ _tmp_7_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_7[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'def'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 635)) // token='def' + (_keyword = _PyPegen_expect_token(p, 642)) // token='def' ) { D(fprintf(stderr, "%*c+ _tmp_7[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'def'")); @@ -21758,7 +22086,7 @@ _tmp_8_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_8[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 636)) // token='class' + (_keyword = _PyPegen_expect_token(p, 643)) // token='class' ) { D(fprintf(stderr, "%*c+ _tmp_8[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'class'")); @@ -21813,7 +22141,7 @@ _tmp_9_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_9[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'with'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 609)) // token='with' + (_keyword = _PyPegen_expect_token(p, 612)) // token='with' ) { D(fprintf(stderr, "%*c+ _tmp_9[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'with'")); @@ -21868,7 +22196,7 @@ _tmp_10_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_10[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'for'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 633)) // token='for' + (_keyword = _PyPegen_expect_token(p, 640)) // token='for' ) { D(fprintf(stderr, "%*c+ _tmp_10[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'for'")); @@ -22085,12 +22413,12 @@ _loop1_14_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_14[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_186_var; + void *_tmp_193_var; while ( - (_tmp_186_var = _tmp_186_rule(p)) // star_targets '=' + (_tmp_193_var = _tmp_193_rule(p)) // star_targets '=' ) { - _res = _tmp_186_var; + _res = _tmp_193_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -22259,7 +22587,7 @@ _tmp_17_rule(Parser *p) Token * _keyword; expr_ty z; if ( - (_keyword = _PyPegen_expect_token(p, 569)) // token='from' + (_keyword = _PyPegen_expect_token(p, 572)) // token='from' && (z = expression_rule(p)) // expression ) @@ -22637,12 +22965,12 @@ _loop0_24_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop0_24[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); - void *_tmp_187_var; + void *_tmp_194_var; while ( - (_tmp_187_var = _tmp_187_rule(p)) // '.' | '...' + (_tmp_194_var = _tmp_194_rule(p)) // '.' | '...' ) { - _res = _tmp_187_var; + _res = _tmp_194_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -22703,12 +23031,12 @@ _loop1_25_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_25[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); - void *_tmp_188_var; + void *_tmp_195_var; while ( - (_tmp_188_var = _tmp_188_rule(p)) // '.' | '...' + (_tmp_195_var = _tmp_195_rule(p)) // '.' | '...' ) { - _res = _tmp_188_var; + _res = _tmp_195_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -22881,7 +23209,7 @@ _tmp_28_rule(Parser *p) Token * _keyword; expr_ty z; if ( - (_keyword = _PyPegen_expect_token(p, 625)) // token='as' + (_keyword = _PyPegen_expect_token(p, 632)) // token='as' && (z = _PyPegen_name_token(p)) // NAME ) @@ -23039,7 +23367,7 @@ _tmp_31_rule(Parser *p) Token * _keyword; expr_ty z; if ( - (_keyword = _PyPegen_expect_token(p, 625)) // token='as' + (_keyword = _PyPegen_expect_token(p, 632)) // token='as' && (z = _PyPegen_name_token(p)) // NAME ) @@ -23090,12 +23418,12 @@ _loop1_32_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_32[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('@' named_expression NEWLINE)")); - void *_tmp_189_var; + void *_tmp_196_var; while ( - (_tmp_189_var = _tmp_189_rule(p)) // '@' named_expression NEWLINE + (_tmp_196_var = _tmp_196_rule(p)) // '@' named_expression NEWLINE ) { - _res = _tmp_189_var; + _res = _tmp_196_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -24829,9 +25157,124 @@ _loop1_59_rule(Parser *p) return _seq; } -// _tmp_60: 'as' NAME +// _loop1_60: except_star_block +static asdl_seq * +_loop1_60_rule(Parser *p) +{ + D(p->level++); + if (p->error_indicator) { + D(p->level--); + return NULL; + } + void *_res = NULL; + int _mark = p->mark; + int _start_mark = p->mark; + void **_children = PyMem_Malloc(sizeof(void *)); + if (!_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + Py_ssize_t _children_capacity = 1; + Py_ssize_t _n = 0; + { // except_star_block + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> _loop1_60[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_star_block")); + excepthandler_ty except_star_block_var; + while ( + (except_star_block_var = except_star_block_rule(p)) // except_star_block + ) + { + _res = except_star_block_var; + if (_n == _children_capacity) { + _children_capacity *= 2; + void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); + if (!_new_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + _children = _new_children; + } + _children[_n++] = _res; + _mark = p->mark; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _loop1_60[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "except_star_block")); + } + if (_n == 0 || p->error_indicator) { + PyMem_Free(_children); + D(p->level--); + return NULL; + } + asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); + if (!_seq) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); + PyMem_Free(_children); + _PyPegen_insert_memo(p, _start_mark, _loop1_60_type, _seq); + D(p->level--); + return _seq; +} + +// _tmp_61: 'as' NAME +static void * +_tmp_61_rule(Parser *p) +{ + D(p->level++); + if (p->error_indicator) { + D(p->level--); + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // 'as' NAME + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_61[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + Token * _keyword; + expr_ty z; + if ( + (_keyword = _PyPegen_expect_token(p, 632)) // token='as' + && + (z = _PyPegen_name_token(p)) // NAME + ) + { + D(fprintf(stderr, "%*c+ _tmp_61[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + _res = z; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + D(p->level--); + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_61[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); + } + _res = NULL; + done: + D(p->level--); + return _res; +} + +// _tmp_62: 'as' NAME static void * -_tmp_60_rule(Parser *p) +_tmp_62_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -24845,16 +25288,16 @@ _tmp_60_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_60[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_62[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty z; if ( - (_keyword = _PyPegen_expect_token(p, 625)) // token='as' + (_keyword = _PyPegen_expect_token(p, 632)) // token='as' && (z = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_60[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_62[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -24864,7 +25307,7 @@ _tmp_60_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_60[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_62[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -24873,9 +25316,9 @@ _tmp_60_rule(Parser *p) return _res; } -// _loop1_61: case_block +// _loop1_63: case_block static asdl_seq * -_loop1_61_rule(Parser *p) +_loop1_63_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -24899,7 +25342,7 @@ _loop1_61_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop1_61[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "case_block")); + D(fprintf(stderr, "%*c> _loop1_63[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "case_block")); match_case_ty case_block_var; while ( (case_block_var = case_block_rule(p)) // case_block @@ -24921,7 +25364,7 @@ _loop1_61_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_61[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_63[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "case_block")); } if (_n == 0 || p->error_indicator) { @@ -24939,14 +25382,14 @@ _loop1_61_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_61_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop1_63_type, _seq); D(p->level--); return _seq; } -// _loop0_63: '|' closed_pattern +// _loop0_65: '|' closed_pattern static asdl_seq * -_loop0_63_rule(Parser *p) +_loop0_65_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -24970,7 +25413,7 @@ _loop0_63_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_63[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'|' closed_pattern")); + D(fprintf(stderr, "%*c> _loop0_65[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'|' closed_pattern")); Token * _literal; pattern_ty elem; while ( @@ -25001,7 +25444,7 @@ _loop0_63_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_63[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_65[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'|' closed_pattern")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -25014,14 +25457,14 @@ _loop0_63_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_63_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_65_type, _seq); D(p->level--); return _seq; } -// _gather_62: closed_pattern _loop0_63 +// _gather_64: closed_pattern _loop0_65 static asdl_seq * -_gather_62_rule(Parser *p) +_gather_64_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -25030,27 +25473,27 @@ _gather_62_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // closed_pattern _loop0_63 + { // closed_pattern _loop0_65 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_62[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "closed_pattern _loop0_63")); + D(fprintf(stderr, "%*c> _gather_64[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "closed_pattern _loop0_65")); pattern_ty elem; asdl_seq * seq; if ( (elem = closed_pattern_rule(p)) // closed_pattern && - (seq = _loop0_63_rule(p)) // _loop0_63 + (seq = _loop0_65_rule(p)) // _loop0_65 ) { - D(fprintf(stderr, "%*c+ _gather_62[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "closed_pattern _loop0_63")); + D(fprintf(stderr, "%*c+ _gather_64[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "closed_pattern _loop0_65")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_62[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "closed_pattern _loop0_63")); + D(fprintf(stderr, "%*c%s _gather_64[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "closed_pattern _loop0_65")); } _res = NULL; done: @@ -25058,9 +25501,9 @@ _gather_62_rule(Parser *p) return _res; } -// _tmp_64: '+' | '-' +// _tmp_66: '+' | '-' static void * -_tmp_64_rule(Parser *p) +_tmp_66_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -25074,18 +25517,18 @@ _tmp_64_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_64[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); + D(fprintf(stderr, "%*c> _tmp_66[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 14)) // token='+' ) { - D(fprintf(stderr, "%*c+ _tmp_64[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+'")); + D(fprintf(stderr, "%*c+ _tmp_66[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_64[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_66[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'+'")); } { // '-' @@ -25093,18 +25536,18 @@ _tmp_64_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_64[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); + D(fprintf(stderr, "%*c> _tmp_66[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 15)) // token='-' ) { - D(fprintf(stderr, "%*c+ _tmp_64[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-'")); + D(fprintf(stderr, "%*c+ _tmp_66[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_64[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_66[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'-'")); } _res = NULL; @@ -25113,9 +25556,9 @@ _tmp_64_rule(Parser *p) return _res; } -// _tmp_65: '+' | '-' +// _tmp_67: '+' | '-' static void * -_tmp_65_rule(Parser *p) +_tmp_67_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -25129,18 +25572,18 @@ _tmp_65_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_65[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); + D(fprintf(stderr, "%*c> _tmp_67[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 14)) // token='+' ) { - D(fprintf(stderr, "%*c+ _tmp_65[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+'")); + D(fprintf(stderr, "%*c+ _tmp_67[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_65[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_67[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'+'")); } { // '-' @@ -25148,18 +25591,18 @@ _tmp_65_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_65[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); + D(fprintf(stderr, "%*c> _tmp_67[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 15)) // token='-' ) { - D(fprintf(stderr, "%*c+ _tmp_65[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-'")); + D(fprintf(stderr, "%*c+ _tmp_67[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_65[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_67[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'-'")); } _res = NULL; @@ -25168,9 +25611,9 @@ _tmp_65_rule(Parser *p) return _res; } -// _tmp_66: '.' | '(' | '=' +// _tmp_68: '.' | '(' | '=' static void * -_tmp_66_rule(Parser *p) +_tmp_68_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -25184,18 +25627,18 @@ _tmp_66_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_66[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c> _tmp_68[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 23)) // token='.' ) { - D(fprintf(stderr, "%*c+ _tmp_66[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c+ _tmp_68[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_66[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_68[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); } { // '(' @@ -25203,18 +25646,18 @@ _tmp_66_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_66[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); + D(fprintf(stderr, "%*c> _tmp_68[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' ) { - D(fprintf(stderr, "%*c+ _tmp_66[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); + D(fprintf(stderr, "%*c+ _tmp_68[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_66[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_68[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'('")); } { // '=' @@ -25222,18 +25665,18 @@ _tmp_66_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_66[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c> _tmp_68[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_66[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c+ _tmp_68[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_66[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_68[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); } _res = NULL; @@ -25242,9 +25685,9 @@ _tmp_66_rule(Parser *p) return _res; } -// _tmp_67: '.' | '(' | '=' +// _tmp_69: '.' | '(' | '=' static void * -_tmp_67_rule(Parser *p) +_tmp_69_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -25258,18 +25701,18 @@ _tmp_67_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_67[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c> _tmp_69[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 23)) // token='.' ) { - D(fprintf(stderr, "%*c+ _tmp_67[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c+ _tmp_69[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_67[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_69[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); } { // '(' @@ -25277,18 +25720,18 @@ _tmp_67_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_67[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); + D(fprintf(stderr, "%*c> _tmp_69[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' ) { - D(fprintf(stderr, "%*c+ _tmp_67[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); + D(fprintf(stderr, "%*c+ _tmp_69[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_67[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_69[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'('")); } { // '=' @@ -25296,18 +25739,18 @@ _tmp_67_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_67[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c> _tmp_69[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_67[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c+ _tmp_69[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_67[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_69[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); } _res = NULL; @@ -25316,9 +25759,9 @@ _tmp_67_rule(Parser *p) return _res; } -// _loop0_69: ',' maybe_star_pattern +// _loop0_71: ',' maybe_star_pattern static asdl_seq * -_loop0_69_rule(Parser *p) +_loop0_71_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -25342,7 +25785,7 @@ _loop0_69_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_69[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' maybe_star_pattern")); + D(fprintf(stderr, "%*c> _loop0_71[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' maybe_star_pattern")); Token * _literal; pattern_ty elem; while ( @@ -25373,7 +25816,7 @@ _loop0_69_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_69[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_71[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' maybe_star_pattern")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -25386,14 +25829,14 @@ _loop0_69_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_69_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_71_type, _seq); D(p->level--); return _seq; } -// _gather_68: maybe_star_pattern _loop0_69 +// _gather_70: maybe_star_pattern _loop0_71 static asdl_seq * -_gather_68_rule(Parser *p) +_gather_70_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -25402,27 +25845,27 @@ _gather_68_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // maybe_star_pattern _loop0_69 + { // maybe_star_pattern _loop0_71 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_68[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "maybe_star_pattern _loop0_69")); + D(fprintf(stderr, "%*c> _gather_70[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "maybe_star_pattern _loop0_71")); pattern_ty elem; asdl_seq * seq; if ( (elem = maybe_star_pattern_rule(p)) // maybe_star_pattern && - (seq = _loop0_69_rule(p)) // _loop0_69 + (seq = _loop0_71_rule(p)) // _loop0_71 ) { - D(fprintf(stderr, "%*c+ _gather_68[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "maybe_star_pattern _loop0_69")); + D(fprintf(stderr, "%*c+ _gather_70[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "maybe_star_pattern _loop0_71")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_68[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "maybe_star_pattern _loop0_69")); + D(fprintf(stderr, "%*c%s _gather_70[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "maybe_star_pattern _loop0_71")); } _res = NULL; done: @@ -25430,9 +25873,9 @@ _gather_68_rule(Parser *p) return _res; } -// _loop0_71: ',' key_value_pattern +// _loop0_73: ',' key_value_pattern static asdl_seq * -_loop0_71_rule(Parser *p) +_loop0_73_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -25456,7 +25899,7 @@ _loop0_71_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_71[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' key_value_pattern")); + D(fprintf(stderr, "%*c> _loop0_73[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' key_value_pattern")); Token * _literal; KeyPatternPair* elem; while ( @@ -25487,7 +25930,7 @@ _loop0_71_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_71[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_73[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' key_value_pattern")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -25500,14 +25943,14 @@ _loop0_71_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_71_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_73_type, _seq); D(p->level--); return _seq; } -// _gather_70: key_value_pattern _loop0_71 +// _gather_72: key_value_pattern _loop0_73 static asdl_seq * -_gather_70_rule(Parser *p) +_gather_72_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -25516,27 +25959,27 @@ _gather_70_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // key_value_pattern _loop0_71 + { // key_value_pattern _loop0_73 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_70[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "key_value_pattern _loop0_71")); + D(fprintf(stderr, "%*c> _gather_72[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "key_value_pattern _loop0_73")); KeyPatternPair* elem; asdl_seq * seq; if ( (elem = key_value_pattern_rule(p)) // key_value_pattern && - (seq = _loop0_71_rule(p)) // _loop0_71 + (seq = _loop0_73_rule(p)) // _loop0_73 ) { - D(fprintf(stderr, "%*c+ _gather_70[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "key_value_pattern _loop0_71")); + D(fprintf(stderr, "%*c+ _gather_72[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "key_value_pattern _loop0_73")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_70[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "key_value_pattern _loop0_71")); + D(fprintf(stderr, "%*c%s _gather_72[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "key_value_pattern _loop0_73")); } _res = NULL; done: @@ -25544,9 +25987,9 @@ _gather_70_rule(Parser *p) return _res; } -// _tmp_72: literal_expr | attr +// _tmp_74: literal_expr | attr static void * -_tmp_72_rule(Parser *p) +_tmp_74_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -25560,18 +26003,18 @@ _tmp_72_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_72[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "literal_expr")); + D(fprintf(stderr, "%*c> _tmp_74[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "literal_expr")); expr_ty literal_expr_var; if ( (literal_expr_var = literal_expr_rule(p)) // literal_expr ) { - D(fprintf(stderr, "%*c+ _tmp_72[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "literal_expr")); + D(fprintf(stderr, "%*c+ _tmp_74[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "literal_expr")); _res = literal_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_72[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_74[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "literal_expr")); } { // attr @@ -25579,18 +26022,18 @@ _tmp_72_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_72[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "attr")); + D(fprintf(stderr, "%*c> _tmp_74[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "attr")); expr_ty attr_var; if ( (attr_var = attr_rule(p)) // attr ) { - D(fprintf(stderr, "%*c+ _tmp_72[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "attr")); + D(fprintf(stderr, "%*c+ _tmp_74[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "attr")); _res = attr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_72[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_74[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "attr")); } _res = NULL; @@ -25599,9 +26042,9 @@ _tmp_72_rule(Parser *p) return _res; } -// _loop0_74: ',' pattern +// _loop0_76: ',' pattern static asdl_seq * -_loop0_74_rule(Parser *p) +_loop0_76_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -25625,7 +26068,7 @@ _loop0_74_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_74[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' pattern")); + D(fprintf(stderr, "%*c> _loop0_76[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' pattern")); Token * _literal; pattern_ty elem; while ( @@ -25656,7 +26099,7 @@ _loop0_74_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_74[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_76[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' pattern")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -25669,14 +26112,14 @@ _loop0_74_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_74_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_76_type, _seq); D(p->level--); return _seq; } -// _gather_73: pattern _loop0_74 +// _gather_75: pattern _loop0_76 static asdl_seq * -_gather_73_rule(Parser *p) +_gather_75_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -25685,27 +26128,27 @@ _gather_73_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // pattern _loop0_74 + { // pattern _loop0_76 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_73[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "pattern _loop0_74")); + D(fprintf(stderr, "%*c> _gather_75[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "pattern _loop0_76")); pattern_ty elem; asdl_seq * seq; if ( (elem = pattern_rule(p)) // pattern && - (seq = _loop0_74_rule(p)) // _loop0_74 + (seq = _loop0_76_rule(p)) // _loop0_76 ) { - D(fprintf(stderr, "%*c+ _gather_73[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "pattern _loop0_74")); + D(fprintf(stderr, "%*c+ _gather_75[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "pattern _loop0_76")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_73[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "pattern _loop0_74")); + D(fprintf(stderr, "%*c%s _gather_75[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "pattern _loop0_76")); } _res = NULL; done: @@ -25713,9 +26156,9 @@ _gather_73_rule(Parser *p) return _res; } -// _loop0_76: ',' keyword_pattern +// _loop0_78: ',' keyword_pattern static asdl_seq * -_loop0_76_rule(Parser *p) +_loop0_78_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -25739,7 +26182,7 @@ _loop0_76_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_76[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' keyword_pattern")); + D(fprintf(stderr, "%*c> _loop0_78[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' keyword_pattern")); Token * _literal; KeyPatternPair* elem; while ( @@ -25770,7 +26213,7 @@ _loop0_76_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_76[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_78[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' keyword_pattern")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -25783,14 +26226,14 @@ _loop0_76_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_76_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_78_type, _seq); D(p->level--); return _seq; } -// _gather_75: keyword_pattern _loop0_76 +// _gather_77: keyword_pattern _loop0_78 static asdl_seq * -_gather_75_rule(Parser *p) +_gather_77_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -25799,27 +26242,27 @@ _gather_75_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // keyword_pattern _loop0_76 + { // keyword_pattern _loop0_78 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_75[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "keyword_pattern _loop0_76")); + D(fprintf(stderr, "%*c> _gather_77[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "keyword_pattern _loop0_78")); KeyPatternPair* elem; asdl_seq * seq; if ( (elem = keyword_pattern_rule(p)) // keyword_pattern && - (seq = _loop0_76_rule(p)) // _loop0_76 + (seq = _loop0_78_rule(p)) // _loop0_78 ) { - D(fprintf(stderr, "%*c+ _gather_75[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "keyword_pattern _loop0_76")); + D(fprintf(stderr, "%*c+ _gather_77[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "keyword_pattern _loop0_78")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_75[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "keyword_pattern _loop0_76")); + D(fprintf(stderr, "%*c%s _gather_77[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "keyword_pattern _loop0_78")); } _res = NULL; done: @@ -25827,9 +26270,9 @@ _gather_75_rule(Parser *p) return _res; } -// _loop1_77: (',' expression) +// _loop1_79: (',' expression) static asdl_seq * -_loop1_77_rule(Parser *p) +_loop1_79_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -25853,13 +26296,13 @@ _loop1_77_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop1_77[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' expression)")); - void *_tmp_190_var; + D(fprintf(stderr, "%*c> _loop1_79[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' expression)")); + void *_tmp_197_var; while ( - (_tmp_190_var = _tmp_190_rule(p)) // ',' expression + (_tmp_197_var = _tmp_197_rule(p)) // ',' expression ) { - _res = _tmp_190_var; + _res = _tmp_197_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -25875,7 +26318,7 @@ _loop1_77_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_77[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_79[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' expression)")); } if (_n == 0 || p->error_indicator) { @@ -25893,14 +26336,14 @@ _loop1_77_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_77_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop1_79_type, _seq); D(p->level--); return _seq; } -// _loop1_78: (',' star_expression) +// _loop1_80: (',' star_expression) static asdl_seq * -_loop1_78_rule(Parser *p) +_loop1_80_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -25924,13 +26367,13 @@ _loop1_78_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop1_78[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_expression)")); - void *_tmp_191_var; + D(fprintf(stderr, "%*c> _loop1_80[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_expression)")); + void *_tmp_198_var; while ( - (_tmp_191_var = _tmp_191_rule(p)) // ',' star_expression + (_tmp_198_var = _tmp_198_rule(p)) // ',' star_expression ) { - _res = _tmp_191_var; + _res = _tmp_198_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -25946,7 +26389,7 @@ _loop1_78_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_78[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_80[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' star_expression)")); } if (_n == 0 || p->error_indicator) { @@ -25964,14 +26407,14 @@ _loop1_78_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_78_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop1_80_type, _seq); D(p->level--); return _seq; } -// _loop0_80: ',' star_named_expression +// _loop0_82: ',' star_named_expression static asdl_seq * -_loop0_80_rule(Parser *p) +_loop0_82_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -25995,7 +26438,7 @@ _loop0_80_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_80[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_named_expression")); + D(fprintf(stderr, "%*c> _loop0_82[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_named_expression")); Token * _literal; expr_ty elem; while ( @@ -26026,7 +26469,7 @@ _loop0_80_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_80[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_82[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_named_expression")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26039,14 +26482,14 @@ _loop0_80_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_80_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_82_type, _seq); D(p->level--); return _seq; } -// _gather_79: star_named_expression _loop0_80 +// _gather_81: star_named_expression _loop0_82 static asdl_seq * -_gather_79_rule(Parser *p) +_gather_81_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -26055,27 +26498,27 @@ _gather_79_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // star_named_expression _loop0_80 + { // star_named_expression _loop0_82 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_79[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression _loop0_80")); + D(fprintf(stderr, "%*c> _gather_81[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression _loop0_82")); expr_ty elem; asdl_seq * seq; if ( (elem = star_named_expression_rule(p)) // star_named_expression && - (seq = _loop0_80_rule(p)) // _loop0_80 + (seq = _loop0_82_rule(p)) // _loop0_82 ) { - D(fprintf(stderr, "%*c+ _gather_79[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression _loop0_80")); + D(fprintf(stderr, "%*c+ _gather_81[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression _loop0_82")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_79[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expression _loop0_80")); + D(fprintf(stderr, "%*c%s _gather_81[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expression _loop0_82")); } _res = NULL; done: @@ -26083,9 +26526,9 @@ _gather_79_rule(Parser *p) return _res; } -// _loop1_81: ('or' conjunction) +// _loop1_83: ('or' conjunction) static asdl_seq * -_loop1_81_rule(Parser *p) +_loop1_83_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -26109,13 +26552,13 @@ _loop1_81_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop1_81[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('or' conjunction)")); - void *_tmp_192_var; + D(fprintf(stderr, "%*c> _loop1_83[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('or' conjunction)")); + void *_tmp_199_var; while ( - (_tmp_192_var = _tmp_192_rule(p)) // 'or' conjunction + (_tmp_199_var = _tmp_199_rule(p)) // 'or' conjunction ) { - _res = _tmp_192_var; + _res = _tmp_199_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -26131,7 +26574,7 @@ _loop1_81_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_81[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_83[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('or' conjunction)")); } if (_n == 0 || p->error_indicator) { @@ -26149,14 +26592,14 @@ _loop1_81_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_81_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop1_83_type, _seq); D(p->level--); return _seq; } -// _loop1_82: ('and' inversion) +// _loop1_84: ('and' inversion) static asdl_seq * -_loop1_82_rule(Parser *p) +_loop1_84_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -26180,13 +26623,13 @@ _loop1_82_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop1_82[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('and' inversion)")); - void *_tmp_193_var; + D(fprintf(stderr, "%*c> _loop1_84[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('and' inversion)")); + void *_tmp_200_var; while ( - (_tmp_193_var = _tmp_193_rule(p)) // 'and' inversion + (_tmp_200_var = _tmp_200_rule(p)) // 'and' inversion ) { - _res = _tmp_193_var; + _res = _tmp_200_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -26202,7 +26645,7 @@ _loop1_82_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_82[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_84[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('and' inversion)")); } if (_n == 0 || p->error_indicator) { @@ -26220,14 +26663,14 @@ _loop1_82_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_82_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop1_84_type, _seq); D(p->level--); return _seq; } -// _loop1_83: compare_op_bitwise_or_pair +// _loop1_85: compare_op_bitwise_or_pair static asdl_seq * -_loop1_83_rule(Parser *p) +_loop1_85_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -26251,7 +26694,7 @@ _loop1_83_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop1_83[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "compare_op_bitwise_or_pair")); + D(fprintf(stderr, "%*c> _loop1_85[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "compare_op_bitwise_or_pair")); CmpopExprPair* compare_op_bitwise_or_pair_var; while ( (compare_op_bitwise_or_pair_var = compare_op_bitwise_or_pair_rule(p)) // compare_op_bitwise_or_pair @@ -26273,7 +26716,7 @@ _loop1_83_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_83[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_85[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "compare_op_bitwise_or_pair")); } if (_n == 0 || p->error_indicator) { @@ -26291,14 +26734,14 @@ _loop1_83_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_83_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop1_85_type, _seq); D(p->level--); return _seq; } -// _tmp_84: '!=' +// _tmp_86: '!=' static void * -_tmp_84_rule(Parser *p) +_tmp_86_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -26312,13 +26755,13 @@ _tmp_84_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_84[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!='")); + D(fprintf(stderr, "%*c> _tmp_86[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!='")); Token * tok; if ( (tok = _PyPegen_expect_token(p, 28)) // token='!=' ) { - D(fprintf(stderr, "%*c+ _tmp_84[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!='")); + D(fprintf(stderr, "%*c+ _tmp_86[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!='")); _res = _PyPegen_check_barry_as_flufl ( p , tok ) ? NULL : tok; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -26328,7 +26771,7 @@ _tmp_84_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_84[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_86[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!='")); } _res = NULL; @@ -26337,9 +26780,9 @@ _tmp_84_rule(Parser *p) return _res; } -// _loop0_86: ',' slice +// _loop0_88: ',' slice static asdl_seq * -_loop0_86_rule(Parser *p) +_loop0_88_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -26363,7 +26806,7 @@ _loop0_86_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_86[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' slice")); + D(fprintf(stderr, "%*c> _loop0_88[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' slice")); Token * _literal; expr_ty elem; while ( @@ -26394,7 +26837,7 @@ _loop0_86_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_86[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_88[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' slice")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26407,14 +26850,14 @@ _loop0_86_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_86_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_88_type, _seq); D(p->level--); return _seq; } -// _gather_85: slice _loop0_86 +// _gather_87: slice _loop0_88 static asdl_seq * -_gather_85_rule(Parser *p) +_gather_87_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -26423,27 +26866,27 @@ _gather_85_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // slice _loop0_86 + { // slice _loop0_88 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_85[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slice _loop0_86")); + D(fprintf(stderr, "%*c> _gather_87[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slice _loop0_88")); expr_ty elem; asdl_seq * seq; if ( (elem = slice_rule(p)) // slice && - (seq = _loop0_86_rule(p)) // _loop0_86 + (seq = _loop0_88_rule(p)) // _loop0_88 ) { - D(fprintf(stderr, "%*c+ _gather_85[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slice _loop0_86")); + D(fprintf(stderr, "%*c+ _gather_87[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slice _loop0_88")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_85[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slice _loop0_86")); + D(fprintf(stderr, "%*c%s _gather_87[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slice _loop0_88")); } _res = NULL; done: @@ -26451,9 +26894,9 @@ _gather_85_rule(Parser *p) return _res; } -// _tmp_87: ':' expression? +// _tmp_89: ':' expression? static void * -_tmp_87_rule(Parser *p) +_tmp_89_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -26467,7 +26910,7 @@ _tmp_87_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_87[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':' expression?")); + D(fprintf(stderr, "%*c> _tmp_89[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':' expression?")); Token * _literal; void *d; if ( @@ -26476,7 +26919,7 @@ _tmp_87_rule(Parser *p) (d = expression_rule(p), !p->error_indicator) // expression? ) { - D(fprintf(stderr, "%*c+ _tmp_87[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':' expression?")); + D(fprintf(stderr, "%*c+ _tmp_89[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':' expression?")); _res = d; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -26486,7 +26929,7 @@ _tmp_87_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_87[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_89[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':' expression?")); } _res = NULL; @@ -26495,9 +26938,9 @@ _tmp_87_rule(Parser *p) return _res; } -// _tmp_88: tuple | group | genexp +// _tmp_90: tuple | group | genexp static void * -_tmp_88_rule(Parser *p) +_tmp_90_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -26511,18 +26954,18 @@ _tmp_88_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_88[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); + D(fprintf(stderr, "%*c> _tmp_90[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); expr_ty tuple_var; if ( (tuple_var = tuple_rule(p)) // tuple ) { - D(fprintf(stderr, "%*c+ _tmp_88[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "tuple")); + D(fprintf(stderr, "%*c+ _tmp_90[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "tuple")); _res = tuple_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_88[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_90[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "tuple")); } { // group @@ -26530,18 +26973,18 @@ _tmp_88_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_88[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "group")); + D(fprintf(stderr, "%*c> _tmp_90[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "group")); expr_ty group_var; if ( (group_var = group_rule(p)) // group ) { - D(fprintf(stderr, "%*c+ _tmp_88[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "group")); + D(fprintf(stderr, "%*c+ _tmp_90[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "group")); _res = group_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_88[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_90[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "group")); } { // genexp @@ -26549,18 +26992,18 @@ _tmp_88_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_88[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); + D(fprintf(stderr, "%*c> _tmp_90[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); expr_ty genexp_var; if ( (genexp_var = genexp_rule(p)) // genexp ) { - D(fprintf(stderr, "%*c+ _tmp_88[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "genexp")); + D(fprintf(stderr, "%*c+ _tmp_90[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "genexp")); _res = genexp_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_88[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_90[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "genexp")); } _res = NULL; @@ -26569,9 +27012,9 @@ _tmp_88_rule(Parser *p) return _res; } -// _tmp_89: list | listcomp +// _tmp_91: list | listcomp static void * -_tmp_89_rule(Parser *p) +_tmp_91_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -26585,18 +27028,18 @@ _tmp_89_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_89[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); + D(fprintf(stderr, "%*c> _tmp_91[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); expr_ty list_var; if ( (list_var = list_rule(p)) // list ) { - D(fprintf(stderr, "%*c+ _tmp_89[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "list")); + D(fprintf(stderr, "%*c+ _tmp_91[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "list")); _res = list_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_89[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_91[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "list")); } { // listcomp @@ -26604,18 +27047,18 @@ _tmp_89_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_89[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "listcomp")); + D(fprintf(stderr, "%*c> _tmp_91[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "listcomp")); expr_ty listcomp_var; if ( (listcomp_var = listcomp_rule(p)) // listcomp ) { - D(fprintf(stderr, "%*c+ _tmp_89[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "listcomp")); + D(fprintf(stderr, "%*c+ _tmp_91[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "listcomp")); _res = listcomp_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_89[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_91[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "listcomp")); } _res = NULL; @@ -26624,9 +27067,9 @@ _tmp_89_rule(Parser *p) return _res; } -// _tmp_90: dict | set | dictcomp | setcomp +// _tmp_92: dict | set | dictcomp | setcomp static void * -_tmp_90_rule(Parser *p) +_tmp_92_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -26640,18 +27083,18 @@ _tmp_90_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_90[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dict")); + D(fprintf(stderr, "%*c> _tmp_92[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dict")); expr_ty dict_var; if ( (dict_var = dict_rule(p)) // dict ) { - D(fprintf(stderr, "%*c+ _tmp_90[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dict")); + D(fprintf(stderr, "%*c+ _tmp_92[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dict")); _res = dict_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_90[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_92[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "dict")); } { // set @@ -26659,18 +27102,18 @@ _tmp_90_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_90[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "set")); + D(fprintf(stderr, "%*c> _tmp_92[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "set")); expr_ty set_var; if ( (set_var = set_rule(p)) // set ) { - D(fprintf(stderr, "%*c+ _tmp_90[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "set")); + D(fprintf(stderr, "%*c+ _tmp_92[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "set")); _res = set_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_90[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_92[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "set")); } { // dictcomp @@ -26678,18 +27121,18 @@ _tmp_90_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_90[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dictcomp")); + D(fprintf(stderr, "%*c> _tmp_92[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dictcomp")); expr_ty dictcomp_var; if ( (dictcomp_var = dictcomp_rule(p)) // dictcomp ) { - D(fprintf(stderr, "%*c+ _tmp_90[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dictcomp")); + D(fprintf(stderr, "%*c+ _tmp_92[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dictcomp")); _res = dictcomp_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_90[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_92[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "dictcomp")); } { // setcomp @@ -26697,18 +27140,18 @@ _tmp_90_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_90[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "setcomp")); + D(fprintf(stderr, "%*c> _tmp_92[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "setcomp")); expr_ty setcomp_var; if ( (setcomp_var = setcomp_rule(p)) // setcomp ) { - D(fprintf(stderr, "%*c+ _tmp_90[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "setcomp")); + D(fprintf(stderr, "%*c+ _tmp_92[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "setcomp")); _res = setcomp_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_90[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_92[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "setcomp")); } _res = NULL; @@ -26717,9 +27160,9 @@ _tmp_90_rule(Parser *p) return _res; } -// _tmp_91: yield_expr | named_expression +// _tmp_93: yield_expr | named_expression static void * -_tmp_91_rule(Parser *p) +_tmp_93_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -26733,18 +27176,18 @@ _tmp_91_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_91[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_93[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_91[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_93[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_91[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_93[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } { // named_expression @@ -26752,18 +27195,18 @@ _tmp_91_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_91[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression")); + D(fprintf(stderr, "%*c> _tmp_93[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression")); expr_ty named_expression_var; if ( (named_expression_var = named_expression_rule(p)) // named_expression ) { - D(fprintf(stderr, "%*c+ _tmp_91[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "named_expression")); + D(fprintf(stderr, "%*c+ _tmp_93[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "named_expression")); _res = named_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_91[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_93[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "named_expression")); } _res = NULL; @@ -26772,9 +27215,9 @@ _tmp_91_rule(Parser *p) return _res; } -// _loop0_92: lambda_param_no_default +// _loop0_94: lambda_param_no_default static asdl_seq * -_loop0_92_rule(Parser *p) +_loop0_94_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -26798,7 +27241,7 @@ _loop0_92_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_92[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop0_94[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -26820,7 +27263,7 @@ _loop0_92_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_92[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_94[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26833,14 +27276,14 @@ _loop0_92_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_92_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_94_type, _seq); D(p->level--); return _seq; } -// _loop0_93: lambda_param_with_default +// _loop0_95: lambda_param_with_default static asdl_seq * -_loop0_93_rule(Parser *p) +_loop0_95_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -26864,7 +27307,7 @@ _loop0_93_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_93[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c> _loop0_95[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); NameDefaultPair* lambda_param_with_default_var; while ( (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default @@ -26886,7 +27329,7 @@ _loop0_93_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_93[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_95[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26899,14 +27342,14 @@ _loop0_93_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_93_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_95_type, _seq); D(p->level--); return _seq; } -// _loop0_94: lambda_param_with_default +// _loop0_96: lambda_param_with_default static asdl_seq * -_loop0_94_rule(Parser *p) +_loop0_96_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -26930,7 +27373,7 @@ _loop0_94_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_94[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c> _loop0_96[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); NameDefaultPair* lambda_param_with_default_var; while ( (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default @@ -26952,7 +27395,7 @@ _loop0_94_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_94[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_96[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26965,14 +27408,14 @@ _loop0_94_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_94_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_96_type, _seq); D(p->level--); return _seq; } -// _loop1_95: lambda_param_no_default +// _loop1_97: lambda_param_no_default static asdl_seq * -_loop1_95_rule(Parser *p) +_loop1_97_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -26996,7 +27439,7 @@ _loop1_95_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop1_95[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop1_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -27018,7 +27461,7 @@ _loop1_95_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_95[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_97[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } if (_n == 0 || p->error_indicator) { @@ -27036,14 +27479,14 @@ _loop1_95_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_95_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop1_97_type, _seq); D(p->level--); return _seq; } -// _loop0_96: lambda_param_with_default +// _loop0_98: lambda_param_with_default static asdl_seq * -_loop0_96_rule(Parser *p) +_loop0_98_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -27067,7 +27510,7 @@ _loop0_96_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_96[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c> _loop0_98[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); NameDefaultPair* lambda_param_with_default_var; while ( (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default @@ -27089,7 +27532,7 @@ _loop0_96_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_96[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_98[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27102,14 +27545,14 @@ _loop0_96_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_96_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_98_type, _seq); D(p->level--); return _seq; } -// _loop1_97: lambda_param_with_default +// _loop1_99: lambda_param_with_default static asdl_seq * -_loop1_97_rule(Parser *p) +_loop1_99_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -27133,7 +27576,7 @@ _loop1_97_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop1_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c> _loop1_99[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); NameDefaultPair* lambda_param_with_default_var; while ( (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default @@ -27155,7 +27598,7 @@ _loop1_97_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_97[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_99[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -27173,14 +27616,14 @@ _loop1_97_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_97_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop1_99_type, _seq); D(p->level--); return _seq; } -// _loop1_98: lambda_param_no_default +// _loop1_100: lambda_param_no_default static asdl_seq * -_loop1_98_rule(Parser *p) +_loop1_100_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -27204,7 +27647,7 @@ _loop1_98_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop1_98[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop1_100[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -27226,7 +27669,7 @@ _loop1_98_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_98[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_100[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } if (_n == 0 || p->error_indicator) { @@ -27244,14 +27687,14 @@ _loop1_98_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_98_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop1_100_type, _seq); D(p->level--); return _seq; } -// _loop1_99: lambda_param_no_default +// _loop1_101: lambda_param_no_default static asdl_seq * -_loop1_99_rule(Parser *p) +_loop1_101_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -27275,7 +27718,7 @@ _loop1_99_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop1_99[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop1_101[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -27297,7 +27740,7 @@ _loop1_99_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_99[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_101[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } if (_n == 0 || p->error_indicator) { @@ -27315,14 +27758,14 @@ _loop1_99_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_99_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop1_101_type, _seq); D(p->level--); return _seq; } -// _loop0_100: lambda_param_no_default +// _loop0_102: lambda_param_no_default static asdl_seq * -_loop0_100_rule(Parser *p) +_loop0_102_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -27346,7 +27789,7 @@ _loop0_100_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_100[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop0_102[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -27368,7 +27811,7 @@ _loop0_100_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_100[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_102[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27381,14 +27824,14 @@ _loop0_100_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_100_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_102_type, _seq); D(p->level--); return _seq; } -// _loop1_101: lambda_param_with_default +// _loop1_103: lambda_param_with_default static asdl_seq * -_loop1_101_rule(Parser *p) +_loop1_103_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -27412,7 +27855,7 @@ _loop1_101_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop1_101[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c> _loop1_103[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); NameDefaultPair* lambda_param_with_default_var; while ( (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default @@ -27434,7 +27877,7 @@ _loop1_101_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_101[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_103[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -27452,14 +27895,14 @@ _loop1_101_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_101_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop1_103_type, _seq); D(p->level--); return _seq; } -// _loop0_102: lambda_param_no_default +// _loop0_104: lambda_param_no_default static asdl_seq * -_loop0_102_rule(Parser *p) +_loop0_104_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -27483,7 +27926,7 @@ _loop0_102_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_102[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop0_104[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -27505,7 +27948,7 @@ _loop0_102_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_102[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_104[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27518,14 +27961,14 @@ _loop0_102_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_102_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_104_type, _seq); D(p->level--); return _seq; } -// _loop1_103: lambda_param_with_default +// _loop1_105: lambda_param_with_default static asdl_seq * -_loop1_103_rule(Parser *p) +_loop1_105_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -27549,7 +27992,7 @@ _loop1_103_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop1_103[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c> _loop1_105[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); NameDefaultPair* lambda_param_with_default_var; while ( (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default @@ -27571,7 +28014,7 @@ _loop1_103_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_103[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_105[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -27589,14 +28032,14 @@ _loop1_103_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_103_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop1_105_type, _seq); D(p->level--); return _seq; } -// _loop0_104: lambda_param_maybe_default +// _loop0_106: lambda_param_maybe_default static asdl_seq * -_loop0_104_rule(Parser *p) +_loop0_106_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -27620,7 +28063,7 @@ _loop0_104_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_104[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_106[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); NameDefaultPair* lambda_param_maybe_default_var; while ( (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default @@ -27642,7 +28085,7 @@ _loop0_104_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_104[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_106[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27655,14 +28098,14 @@ _loop0_104_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_104_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_106_type, _seq); D(p->level--); return _seq; } -// _loop1_105: lambda_param_maybe_default +// _loop1_107: lambda_param_maybe_default static asdl_seq * -_loop1_105_rule(Parser *p) +_loop1_107_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -27686,7 +28129,7 @@ _loop1_105_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop1_105[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); + D(fprintf(stderr, "%*c> _loop1_107[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); NameDefaultPair* lambda_param_maybe_default_var; while ( (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default @@ -27708,7 +28151,7 @@ _loop1_105_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_105[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_107[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); } if (_n == 0 || p->error_indicator) { @@ -27726,14 +28169,14 @@ _loop1_105_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_105_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop1_107_type, _seq); D(p->level--); return _seq; } -// _loop1_106: STRING +// _loop1_108: STRING static asdl_seq * -_loop1_106_rule(Parser *p) +_loop1_108_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -27757,7 +28200,7 @@ _loop1_106_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop1_106[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "STRING")); + D(fprintf(stderr, "%*c> _loop1_108[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "STRING")); expr_ty string_var; while ( (string_var = _PyPegen_string_token(p)) // STRING @@ -27779,7 +28222,7 @@ _loop1_106_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_106[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_108[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "STRING")); } if (_n == 0 || p->error_indicator) { @@ -27797,14 +28240,14 @@ _loop1_106_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_106_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop1_108_type, _seq); D(p->level--); return _seq; } -// _tmp_107: star_named_expression ',' star_named_expressions? +// _tmp_109: star_named_expression ',' star_named_expressions? static void * -_tmp_107_rule(Parser *p) +_tmp_109_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -27818,7 +28261,7 @@ _tmp_107_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_107[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?")); + D(fprintf(stderr, "%*c> _tmp_109[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?")); Token * _literal; expr_ty y; void *z; @@ -27830,7 +28273,7 @@ _tmp_107_rule(Parser *p) (z = star_named_expressions_rule(p), !p->error_indicator) // star_named_expressions? ) { - D(fprintf(stderr, "%*c+ _tmp_107[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?")); + D(fprintf(stderr, "%*c+ _tmp_109[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?")); _res = _PyPegen_seq_insert_in_front ( p , y , z ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -27840,7 +28283,7 @@ _tmp_107_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_107[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_109[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expression ',' star_named_expressions?")); } _res = NULL; @@ -27849,9 +28292,9 @@ _tmp_107_rule(Parser *p) return _res; } -// _loop0_109: ',' double_starred_kvpair +// _loop0_111: ',' double_starred_kvpair static asdl_seq * -_loop0_109_rule(Parser *p) +_loop0_111_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -27875,7 +28318,7 @@ _loop0_109_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_109[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); + D(fprintf(stderr, "%*c> _loop0_111[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); Token * _literal; KeyValuePair* elem; while ( @@ -27906,7 +28349,7 @@ _loop0_109_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_109[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_111[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' double_starred_kvpair")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27919,14 +28362,14 @@ _loop0_109_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_109_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_111_type, _seq); D(p->level--); return _seq; } -// _gather_108: double_starred_kvpair _loop0_109 +// _gather_110: double_starred_kvpair _loop0_111 static asdl_seq * -_gather_108_rule(Parser *p) +_gather_110_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -27935,27 +28378,27 @@ _gather_108_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // double_starred_kvpair _loop0_109 + { // double_starred_kvpair _loop0_111 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_108[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_109")); + D(fprintf(stderr, "%*c> _gather_110[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_111")); KeyValuePair* elem; asdl_seq * seq; if ( (elem = double_starred_kvpair_rule(p)) // double_starred_kvpair && - (seq = _loop0_109_rule(p)) // _loop0_109 + (seq = _loop0_111_rule(p)) // _loop0_111 ) { - D(fprintf(stderr, "%*c+ _gather_108[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_109")); + D(fprintf(stderr, "%*c+ _gather_110[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_111")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_108[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_109")); + D(fprintf(stderr, "%*c%s _gather_110[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_111")); } _res = NULL; done: @@ -27963,9 +28406,9 @@ _gather_108_rule(Parser *p) return _res; } -// _loop1_110: for_if_clause +// _loop1_112: for_if_clause static asdl_seq * -_loop1_110_rule(Parser *p) +_loop1_112_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -27989,7 +28432,7 @@ _loop1_110_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop1_110[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "for_if_clause")); + D(fprintf(stderr, "%*c> _loop1_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "for_if_clause")); comprehension_ty for_if_clause_var; while ( (for_if_clause_var = for_if_clause_rule(p)) // for_if_clause @@ -28011,7 +28454,7 @@ _loop1_110_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_110[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_112[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "for_if_clause")); } if (_n == 0 || p->error_indicator) { @@ -28029,14 +28472,14 @@ _loop1_110_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_110_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop1_112_type, _seq); D(p->level--); return _seq; } -// _loop0_111: ('if' disjunction) +// _loop0_113: ('if' disjunction) static asdl_seq * -_loop0_111_rule(Parser *p) +_loop0_113_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -28060,13 +28503,13 @@ _loop0_111_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_111[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); - void *_tmp_194_var; + D(fprintf(stderr, "%*c> _loop0_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); + void *_tmp_201_var; while ( - (_tmp_194_var = _tmp_194_rule(p)) // 'if' disjunction + (_tmp_201_var = _tmp_201_rule(p)) // 'if' disjunction ) { - _res = _tmp_194_var; + _res = _tmp_201_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -28082,7 +28525,7 @@ _loop0_111_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_111[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_113[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('if' disjunction)")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28095,14 +28538,14 @@ _loop0_111_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_111_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_113_type, _seq); D(p->level--); return _seq; } -// _loop0_112: ('if' disjunction) +// _loop0_114: ('if' disjunction) static asdl_seq * -_loop0_112_rule(Parser *p) +_loop0_114_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -28126,13 +28569,13 @@ _loop0_112_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); - void *_tmp_195_var; + D(fprintf(stderr, "%*c> _loop0_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); + void *_tmp_202_var; while ( - (_tmp_195_var = _tmp_195_rule(p)) // 'if' disjunction + (_tmp_202_var = _tmp_202_rule(p)) // 'if' disjunction ) { - _res = _tmp_195_var; + _res = _tmp_202_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -28148,7 +28591,7 @@ _loop0_112_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_112[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_114[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('if' disjunction)")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28161,14 +28604,14 @@ _loop0_112_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_112_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_114_type, _seq); D(p->level--); return _seq; } -// _tmp_113: assignment_expression | expression !':=' +// _tmp_115: assignment_expression | expression !':=' static void * -_tmp_113_rule(Parser *p) +_tmp_115_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -28182,18 +28625,18 @@ _tmp_113_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + D(fprintf(stderr, "%*c> _tmp_115[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); expr_ty assignment_expression_var; if ( (assignment_expression_var = assignment_expression_rule(p)) // assignment_expression ) { - D(fprintf(stderr, "%*c+ _tmp_113[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + D(fprintf(stderr, "%*c+ _tmp_115[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); _res = assignment_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_113[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_115[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment_expression")); } { // expression !':=' @@ -28201,7 +28644,7 @@ _tmp_113_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c> _tmp_115[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression @@ -28209,12 +28652,12 @@ _tmp_113_rule(Parser *p) _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 53) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_113[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c+ _tmp_115[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); _res = expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_113[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_115[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression !':='")); } _res = NULL; @@ -28223,9 +28666,9 @@ _tmp_113_rule(Parser *p) return _res; } -// _loop0_115: ',' (starred_expression | (assignment_expression | expression !':=') !'=') +// _loop0_117: ',' (starred_expression | (assignment_expression | expression !':=') !'=') static asdl_seq * -_loop0_115_rule(Parser *p) +_loop0_117_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -28249,13 +28692,13 @@ _loop0_115_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_115[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); + D(fprintf(stderr, "%*c> _loop0_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_196_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' + (elem = _tmp_203_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' ) { _res = elem; @@ -28280,7 +28723,7 @@ _loop0_115_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_115[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_117[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28293,15 +28736,15 @@ _loop0_115_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_115_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_117_type, _seq); D(p->level--); return _seq; } -// _gather_114: -// | (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_115 +// _gather_116: +// | (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_117 static asdl_seq * -_gather_114_rule(Parser *p) +_gather_116_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -28310,27 +28753,27 @@ _gather_114_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_115 + { // (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_117 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_115")); + D(fprintf(stderr, "%*c> _gather_116[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_117")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_196_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' + (elem = _tmp_203_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' && - (seq = _loop0_115_rule(p)) // _loop0_115 + (seq = _loop0_117_rule(p)) // _loop0_117 ) { - D(fprintf(stderr, "%*c+ _gather_114[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_115")); + D(fprintf(stderr, "%*c+ _gather_116[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_117")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_114[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_115")); + D(fprintf(stderr, "%*c%s _gather_116[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_117")); } _res = NULL; done: @@ -28338,9 +28781,9 @@ _gather_114_rule(Parser *p) return _res; } -// _tmp_116: ',' kwargs +// _tmp_118: ',' kwargs static void * -_tmp_116_rule(Parser *p) +_tmp_118_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -28354,7 +28797,7 @@ _tmp_116_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_116[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwargs")); + D(fprintf(stderr, "%*c> _tmp_118[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwargs")); Token * _literal; asdl_seq* k; if ( @@ -28363,7 +28806,7 @@ _tmp_116_rule(Parser *p) (k = kwargs_rule(p)) // kwargs ) { - D(fprintf(stderr, "%*c+ _tmp_116[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' kwargs")); + D(fprintf(stderr, "%*c+ _tmp_118[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' kwargs")); _res = k; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -28373,7 +28816,7 @@ _tmp_116_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_116[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_118[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwargs")); } _res = NULL; @@ -28382,9 +28825,9 @@ _tmp_116_rule(Parser *p) return _res; } -// _loop0_118: ',' kwarg_or_starred +// _loop0_120: ',' kwarg_or_starred static asdl_seq * -_loop0_118_rule(Parser *p) +_loop0_120_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -28408,7 +28851,7 @@ _loop0_118_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_118[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); + D(fprintf(stderr, "%*c> _loop0_120[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); Token * _literal; KeywordOrStarred* elem; while ( @@ -28439,7 +28882,7 @@ _loop0_118_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_118[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_120[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_starred")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28452,14 +28895,14 @@ _loop0_118_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_118_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_120_type, _seq); D(p->level--); return _seq; } -// _gather_117: kwarg_or_starred _loop0_118 +// _gather_119: kwarg_or_starred _loop0_120 static asdl_seq * -_gather_117_rule(Parser *p) +_gather_119_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -28468,27 +28911,27 @@ _gather_117_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // kwarg_or_starred _loop0_118 + { // kwarg_or_starred _loop0_120 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_118")); + D(fprintf(stderr, "%*c> _gather_119[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_120")); KeywordOrStarred* elem; asdl_seq * seq; if ( (elem = kwarg_or_starred_rule(p)) // kwarg_or_starred && - (seq = _loop0_118_rule(p)) // _loop0_118 + (seq = _loop0_120_rule(p)) // _loop0_120 ) { - D(fprintf(stderr, "%*c+ _gather_117[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_118")); + D(fprintf(stderr, "%*c+ _gather_119[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_120")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_117[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_118")); + D(fprintf(stderr, "%*c%s _gather_119[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_120")); } _res = NULL; done: @@ -28496,9 +28939,9 @@ _gather_117_rule(Parser *p) return _res; } -// _loop0_120: ',' kwarg_or_double_starred +// _loop0_122: ',' kwarg_or_double_starred static asdl_seq * -_loop0_120_rule(Parser *p) +_loop0_122_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -28522,7 +28965,7 @@ _loop0_120_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_120[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); + D(fprintf(stderr, "%*c> _loop0_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); Token * _literal; KeywordOrStarred* elem; while ( @@ -28553,7 +28996,7 @@ _loop0_120_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_120[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_122[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_double_starred")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28566,14 +29009,14 @@ _loop0_120_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_120_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_122_type, _seq); D(p->level--); return _seq; } -// _gather_119: kwarg_or_double_starred _loop0_120 +// _gather_121: kwarg_or_double_starred _loop0_122 static asdl_seq * -_gather_119_rule(Parser *p) +_gather_121_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -28582,27 +29025,27 @@ _gather_119_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // kwarg_or_double_starred _loop0_120 + { // kwarg_or_double_starred _loop0_122 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_119[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_120")); + D(fprintf(stderr, "%*c> _gather_121[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_122")); KeywordOrStarred* elem; asdl_seq * seq; if ( (elem = kwarg_or_double_starred_rule(p)) // kwarg_or_double_starred && - (seq = _loop0_120_rule(p)) // _loop0_120 + (seq = _loop0_122_rule(p)) // _loop0_122 ) { - D(fprintf(stderr, "%*c+ _gather_119[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_120")); + D(fprintf(stderr, "%*c+ _gather_121[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_122")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_119[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_120")); + D(fprintf(stderr, "%*c%s _gather_121[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_122")); } _res = NULL; done: @@ -28610,9 +29053,9 @@ _gather_119_rule(Parser *p) return _res; } -// _loop0_122: ',' kwarg_or_starred +// _loop0_124: ',' kwarg_or_starred static asdl_seq * -_loop0_122_rule(Parser *p) +_loop0_124_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -28636,7 +29079,7 @@ _loop0_122_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); + D(fprintf(stderr, "%*c> _loop0_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); Token * _literal; KeywordOrStarred* elem; while ( @@ -28667,7 +29110,7 @@ _loop0_122_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_122[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_124[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_starred")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28680,14 +29123,14 @@ _loop0_122_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_122_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_124_type, _seq); D(p->level--); return _seq; } -// _gather_121: kwarg_or_starred _loop0_122 +// _gather_123: kwarg_or_starred _loop0_124 static asdl_seq * -_gather_121_rule(Parser *p) +_gather_123_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -28696,27 +29139,27 @@ _gather_121_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // kwarg_or_starred _loop0_122 + { // kwarg_or_starred _loop0_124 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_121[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_122")); + D(fprintf(stderr, "%*c> _gather_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_124")); KeywordOrStarred* elem; asdl_seq * seq; if ( (elem = kwarg_or_starred_rule(p)) // kwarg_or_starred && - (seq = _loop0_122_rule(p)) // _loop0_122 + (seq = _loop0_124_rule(p)) // _loop0_124 ) { - D(fprintf(stderr, "%*c+ _gather_121[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_122")); + D(fprintf(stderr, "%*c+ _gather_123[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_124")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_121[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_122")); + D(fprintf(stderr, "%*c%s _gather_123[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_124")); } _res = NULL; done: @@ -28724,9 +29167,9 @@ _gather_121_rule(Parser *p) return _res; } -// _loop0_124: ',' kwarg_or_double_starred +// _loop0_126: ',' kwarg_or_double_starred static asdl_seq * -_loop0_124_rule(Parser *p) +_loop0_126_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -28750,7 +29193,7 @@ _loop0_124_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); + D(fprintf(stderr, "%*c> _loop0_126[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); Token * _literal; KeywordOrStarred* elem; while ( @@ -28781,7 +29224,7 @@ _loop0_124_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_124[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_126[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_double_starred")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28794,14 +29237,14 @@ _loop0_124_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_124_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_126_type, _seq); D(p->level--); return _seq; } -// _gather_123: kwarg_or_double_starred _loop0_124 +// _gather_125: kwarg_or_double_starred _loop0_126 static asdl_seq * -_gather_123_rule(Parser *p) +_gather_125_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -28810,27 +29253,27 @@ _gather_123_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // kwarg_or_double_starred _loop0_124 + { // kwarg_or_double_starred _loop0_126 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_124")); + D(fprintf(stderr, "%*c> _gather_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_126")); KeywordOrStarred* elem; asdl_seq * seq; if ( (elem = kwarg_or_double_starred_rule(p)) // kwarg_or_double_starred && - (seq = _loop0_124_rule(p)) // _loop0_124 + (seq = _loop0_126_rule(p)) // _loop0_126 ) { - D(fprintf(stderr, "%*c+ _gather_123[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_124")); + D(fprintf(stderr, "%*c+ _gather_125[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_126")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_123[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_124")); + D(fprintf(stderr, "%*c%s _gather_125[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_126")); } _res = NULL; done: @@ -28838,9 +29281,9 @@ _gather_123_rule(Parser *p) return _res; } -// _loop0_125: (',' star_target) +// _loop0_127: (',' star_target) static asdl_seq * -_loop0_125_rule(Parser *p) +_loop0_127_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -28864,13 +29307,13 @@ _loop0_125_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); - void *_tmp_197_var; + D(fprintf(stderr, "%*c> _loop0_127[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); + void *_tmp_204_var; while ( - (_tmp_197_var = _tmp_197_rule(p)) // ',' star_target + (_tmp_204_var = _tmp_204_rule(p)) // ',' star_target ) { - _res = _tmp_197_var; + _res = _tmp_204_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -28886,7 +29329,7 @@ _loop0_125_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_125[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_127[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' star_target)")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28899,14 +29342,14 @@ _loop0_125_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_125_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_127_type, _seq); D(p->level--); return _seq; } -// _loop0_127: ',' star_target +// _loop0_129: ',' star_target static asdl_seq * -_loop0_127_rule(Parser *p) +_loop0_129_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -28930,7 +29373,7 @@ _loop0_127_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_127[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c> _loop0_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); Token * _literal; expr_ty elem; while ( @@ -28961,7 +29404,7 @@ _loop0_127_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_127[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_129[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28974,14 +29417,14 @@ _loop0_127_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_127_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_129_type, _seq); D(p->level--); return _seq; } -// _gather_126: star_target _loop0_127 +// _gather_128: star_target _loop0_129 static asdl_seq * -_gather_126_rule(Parser *p) +_gather_128_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -28990,27 +29433,27 @@ _gather_126_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // star_target _loop0_127 + { // star_target _loop0_129 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_126[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target _loop0_127")); + D(fprintf(stderr, "%*c> _gather_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target _loop0_129")); expr_ty elem; asdl_seq * seq; if ( (elem = star_target_rule(p)) // star_target && - (seq = _loop0_127_rule(p)) // _loop0_127 + (seq = _loop0_129_rule(p)) // _loop0_129 ) { - D(fprintf(stderr, "%*c+ _gather_126[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target _loop0_127")); + D(fprintf(stderr, "%*c+ _gather_128[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target _loop0_129")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_126[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_target _loop0_127")); + D(fprintf(stderr, "%*c%s _gather_128[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_target _loop0_129")); } _res = NULL; done: @@ -29018,9 +29461,9 @@ _gather_126_rule(Parser *p) return _res; } -// _loop1_128: (',' star_target) +// _loop1_130: (',' star_target) static asdl_seq * -_loop1_128_rule(Parser *p) +_loop1_130_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29044,13 +29487,13 @@ _loop1_128_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop1_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); - void *_tmp_198_var; + D(fprintf(stderr, "%*c> _loop1_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); + void *_tmp_205_var; while ( - (_tmp_198_var = _tmp_198_rule(p)) // ',' star_target + (_tmp_205_var = _tmp_205_rule(p)) // ',' star_target ) { - _res = _tmp_198_var; + _res = _tmp_205_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -29066,7 +29509,7 @@ _loop1_128_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_128[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_130[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' star_target)")); } if (_n == 0 || p->error_indicator) { @@ -29084,14 +29527,14 @@ _loop1_128_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_128_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop1_130_type, _seq); D(p->level--); return _seq; } -// _tmp_129: !'*' star_target +// _tmp_131: !'*' star_target static void * -_tmp_129_rule(Parser *p) +_tmp_131_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29105,7 +29548,7 @@ _tmp_129_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); + D(fprintf(stderr, "%*c> _tmp_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); expr_ty star_target_var; if ( _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 16) // token='*' @@ -29113,12 +29556,12 @@ _tmp_129_rule(Parser *p) (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_129[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); + D(fprintf(stderr, "%*c+ _tmp_131[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); _res = star_target_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_129[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_131[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "!'*' star_target")); } _res = NULL; @@ -29127,9 +29570,9 @@ _tmp_129_rule(Parser *p) return _res; } -// _loop0_131: ',' del_target +// _loop0_133: ',' del_target static asdl_seq * -_loop0_131_rule(Parser *p) +_loop0_133_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29153,7 +29596,7 @@ _loop0_131_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' del_target")); + D(fprintf(stderr, "%*c> _loop0_133[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' del_target")); Token * _literal; expr_ty elem; while ( @@ -29184,7 +29627,7 @@ _loop0_131_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_131[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_133[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' del_target")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -29197,14 +29640,14 @@ _loop0_131_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_131_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_133_type, _seq); D(p->level--); return _seq; } -// _gather_130: del_target _loop0_131 +// _gather_132: del_target _loop0_133 static asdl_seq * -_gather_130_rule(Parser *p) +_gather_132_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29213,27 +29656,27 @@ _gather_130_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // del_target _loop0_131 + { // del_target _loop0_133 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "del_target _loop0_131")); + D(fprintf(stderr, "%*c> _gather_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "del_target _loop0_133")); expr_ty elem; asdl_seq * seq; if ( (elem = del_target_rule(p)) // del_target && - (seq = _loop0_131_rule(p)) // _loop0_131 + (seq = _loop0_133_rule(p)) // _loop0_133 ) { - D(fprintf(stderr, "%*c+ _gather_130[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "del_target _loop0_131")); + D(fprintf(stderr, "%*c+ _gather_132[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "del_target _loop0_133")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_130[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "del_target _loop0_131")); + D(fprintf(stderr, "%*c%s _gather_132[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "del_target _loop0_133")); } _res = NULL; done: @@ -29241,9 +29684,9 @@ _gather_130_rule(Parser *p) return _res; } -// _loop0_133: ',' expression +// _loop0_135: ',' expression static asdl_seq * -_loop0_133_rule(Parser *p) +_loop0_135_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29267,7 +29710,7 @@ _loop0_133_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_133[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _loop0_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); Token * _literal; expr_ty elem; while ( @@ -29298,7 +29741,7 @@ _loop0_133_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_133[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_135[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -29311,14 +29754,14 @@ _loop0_133_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_133_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_135_type, _seq); D(p->level--); return _seq; } -// _gather_132: expression _loop0_133 +// _gather_134: expression _loop0_135 static asdl_seq * -_gather_132_rule(Parser *p) +_gather_134_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29327,27 +29770,27 @@ _gather_132_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // expression _loop0_133 + { // expression _loop0_135 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_133")); + D(fprintf(stderr, "%*c> _gather_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_135")); expr_ty elem; asdl_seq * seq; if ( (elem = expression_rule(p)) // expression && - (seq = _loop0_133_rule(p)) // _loop0_133 + (seq = _loop0_135_rule(p)) // _loop0_135 ) { - D(fprintf(stderr, "%*c+ _gather_132[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_133")); + D(fprintf(stderr, "%*c+ _gather_134[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_135")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_132[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_133")); + D(fprintf(stderr, "%*c%s _gather_134[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_135")); } _res = NULL; done: @@ -29355,9 +29798,9 @@ _gather_132_rule(Parser *p) return _res; } -// _loop0_135: ',' expression +// _loop0_137: ',' expression static asdl_seq * -_loop0_135_rule(Parser *p) +_loop0_137_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29381,7 +29824,7 @@ _loop0_135_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _loop0_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); Token * _literal; expr_ty elem; while ( @@ -29412,7 +29855,7 @@ _loop0_135_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_135[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_137[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -29425,14 +29868,14 @@ _loop0_135_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_135_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_137_type, _seq); D(p->level--); return _seq; } -// _gather_134: expression _loop0_135 +// _gather_136: expression _loop0_137 static asdl_seq * -_gather_134_rule(Parser *p) +_gather_136_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29441,27 +29884,27 @@ _gather_134_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // expression _loop0_135 + { // expression _loop0_137 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_135")); + D(fprintf(stderr, "%*c> _gather_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_137")); expr_ty elem; asdl_seq * seq; if ( (elem = expression_rule(p)) // expression && - (seq = _loop0_135_rule(p)) // _loop0_135 + (seq = _loop0_137_rule(p)) // _loop0_137 ) { - D(fprintf(stderr, "%*c+ _gather_134[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_135")); + D(fprintf(stderr, "%*c+ _gather_136[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_137")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_134[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_135")); + D(fprintf(stderr, "%*c%s _gather_136[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_137")); } _res = NULL; done: @@ -29469,9 +29912,9 @@ _gather_134_rule(Parser *p) return _res; } -// _loop0_137: ',' expression +// _loop0_139: ',' expression static asdl_seq * -_loop0_137_rule(Parser *p) +_loop0_139_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29495,7 +29938,7 @@ _loop0_137_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _loop0_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); Token * _literal; expr_ty elem; while ( @@ -29526,7 +29969,7 @@ _loop0_137_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_137[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_139[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -29539,14 +29982,14 @@ _loop0_137_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_137_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_139_type, _seq); D(p->level--); return _seq; } -// _gather_136: expression _loop0_137 +// _gather_138: expression _loop0_139 static asdl_seq * -_gather_136_rule(Parser *p) +_gather_138_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29555,27 +29998,27 @@ _gather_136_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // expression _loop0_137 + { // expression _loop0_139 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_137")); + D(fprintf(stderr, "%*c> _gather_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_139")); expr_ty elem; asdl_seq * seq; if ( (elem = expression_rule(p)) // expression && - (seq = _loop0_137_rule(p)) // _loop0_137 + (seq = _loop0_139_rule(p)) // _loop0_139 ) { - D(fprintf(stderr, "%*c+ _gather_136[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_137")); + D(fprintf(stderr, "%*c+ _gather_138[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_139")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_136[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_137")); + D(fprintf(stderr, "%*c%s _gather_138[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_139")); } _res = NULL; done: @@ -29583,9 +30026,9 @@ _gather_136_rule(Parser *p) return _res; } -// _loop0_139: ',' expression +// _loop0_141: ',' expression static asdl_seq * -_loop0_139_rule(Parser *p) +_loop0_141_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29609,7 +30052,7 @@ _loop0_139_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _loop0_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); Token * _literal; expr_ty elem; while ( @@ -29640,7 +30083,7 @@ _loop0_139_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_139[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_141[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -29653,14 +30096,14 @@ _loop0_139_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_139_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_141_type, _seq); D(p->level--); return _seq; } -// _gather_138: expression _loop0_139 +// _gather_140: expression _loop0_141 static asdl_seq * -_gather_138_rule(Parser *p) +_gather_140_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29669,27 +30112,27 @@ _gather_138_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // expression _loop0_139 + { // expression _loop0_141 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_139")); + D(fprintf(stderr, "%*c> _gather_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_141")); expr_ty elem; asdl_seq * seq; if ( (elem = expression_rule(p)) // expression && - (seq = _loop0_139_rule(p)) // _loop0_139 + (seq = _loop0_141_rule(p)) // _loop0_141 ) { - D(fprintf(stderr, "%*c+ _gather_138[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_139")); + D(fprintf(stderr, "%*c+ _gather_140[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_141")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_138[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_139")); + D(fprintf(stderr, "%*c%s _gather_140[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_141")); } _res = NULL; done: @@ -29697,9 +30140,9 @@ _gather_138_rule(Parser *p) return _res; } -// _tmp_140: NEWLINE INDENT +// _tmp_142: NEWLINE INDENT static void * -_tmp_140_rule(Parser *p) +_tmp_142_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29713,7 +30156,7 @@ _tmp_140_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT")); + D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT")); Token * indent_var; Token * newline_var; if ( @@ -29722,12 +30165,12 @@ _tmp_140_rule(Parser *p) (indent_var = _PyPegen_expect_token(p, INDENT)) // token='INDENT' ) { - D(fprintf(stderr, "%*c+ _tmp_140[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT")); + D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT")); _res = _PyPegen_dummy_name(p, newline_var, indent_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_140[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NEWLINE INDENT")); } _res = NULL; @@ -29736,9 +30179,9 @@ _tmp_140_rule(Parser *p) return _res; } -// _tmp_141: args | expression for_if_clauses +// _tmp_143: args | expression for_if_clauses static void * -_tmp_141_rule(Parser *p) +_tmp_143_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29752,18 +30195,18 @@ _tmp_141_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args")); + D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args")); expr_ty args_var; if ( (args_var = args_rule(p)) // args ) { - D(fprintf(stderr, "%*c+ _tmp_141[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args")); + D(fprintf(stderr, "%*c+ _tmp_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args")); _res = args_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_141[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_143[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "args")); } { // expression for_if_clauses @@ -29771,7 +30214,7 @@ _tmp_141_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); + D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); expr_ty expression_var; asdl_comprehension_seq* for_if_clauses_var; if ( @@ -29780,12 +30223,12 @@ _tmp_141_rule(Parser *p) (for_if_clauses_var = for_if_clauses_rule(p)) // for_if_clauses ) { - D(fprintf(stderr, "%*c+ _tmp_141[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); + D(fprintf(stderr, "%*c+ _tmp_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); _res = _PyPegen_dummy_name(p, expression_var, for_if_clauses_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_141[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_143[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression for_if_clauses")); } _res = NULL; @@ -29794,9 +30237,9 @@ _tmp_141_rule(Parser *p) return _res; } -// _tmp_142: 'True' | 'False' | 'None' +// _tmp_144: 'True' | 'False' | 'None' static void * -_tmp_142_rule(Parser *p) +_tmp_144_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29810,18 +30253,18 @@ _tmp_142_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); + D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 597)) // token='True' + (_keyword = _PyPegen_expect_token(p, 600)) // token='True' ) { - D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); + D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'True'")); } { // 'False' @@ -29829,18 +30272,18 @@ _tmp_142_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); + D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 599)) // token='False' + (_keyword = _PyPegen_expect_token(p, 602)) // token='False' ) { - D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); + D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'False'")); } { // 'None' @@ -29848,18 +30291,18 @@ _tmp_142_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); + D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 598)) // token='None' + (_keyword = _PyPegen_expect_token(p, 601)) // token='None' ) { - D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); + D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'None'")); } _res = NULL; @@ -29868,9 +30311,9 @@ _tmp_142_rule(Parser *p) return _res; } -// _tmp_143: NAME '=' +// _tmp_145: NAME '=' static void * -_tmp_143_rule(Parser *p) +_tmp_145_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29884,7 +30327,7 @@ _tmp_143_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '='")); + D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '='")); Token * _literal; expr_ty name_var; if ( @@ -29893,12 +30336,12 @@ _tmp_143_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '='")); + D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '='")); _res = _PyPegen_dummy_name(p, name_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_143[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME '='")); } _res = NULL; @@ -29907,9 +30350,9 @@ _tmp_143_rule(Parser *p) return _res; } -// _tmp_144: NAME STRING | SOFT_KEYWORD +// _tmp_146: NAME STRING | SOFT_KEYWORD static void * -_tmp_144_rule(Parser *p) +_tmp_146_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29923,7 +30366,7 @@ _tmp_144_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME STRING")); + D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME STRING")); expr_ty name_var; expr_ty string_var; if ( @@ -29932,12 +30375,12 @@ _tmp_144_rule(Parser *p) (string_var = _PyPegen_string_token(p)) // STRING ) { - D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME STRING")); + D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME STRING")); _res = _PyPegen_dummy_name(p, name_var, string_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME STRING")); } { // SOFT_KEYWORD @@ -29945,18 +30388,18 @@ _tmp_144_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); + D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); expr_ty soft_keyword_var; if ( (soft_keyword_var = _PyPegen_soft_keyword_token(p)) // SOFT_KEYWORD ) { - D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); + D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); _res = soft_keyword_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "SOFT_KEYWORD")); } _res = NULL; @@ -29965,9 +30408,9 @@ _tmp_144_rule(Parser *p) return _res; } -// _tmp_145: 'else' | ':' +// _tmp_147: 'else' | ':' static void * -_tmp_145_rule(Parser *p) +_tmp_147_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29981,18 +30424,18 @@ _tmp_145_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else'")); + D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 630)) // token='else' + (_keyword = _PyPegen_expect_token(p, 637)) // token='else' ) { - D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else'")); + D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'else'")); } { // ':' @@ -30000,18 +30443,18 @@ _tmp_145_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } _res = NULL; @@ -30020,9 +30463,9 @@ _tmp_145_rule(Parser *p) return _res; } -// _tmp_146: '=' | ':=' +// _tmp_148: '=' | ':=' static void * -_tmp_146_rule(Parser *p) +_tmp_148_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30036,18 +30479,18 @@ _tmp_146_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); } { // ':=' @@ -30055,18 +30498,18 @@ _tmp_146_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 53)) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':='")); } _res = NULL; @@ -30075,9 +30518,9 @@ _tmp_146_rule(Parser *p) return _res; } -// _tmp_147: list | tuple | genexp | 'True' | 'None' | 'False' +// _tmp_149: list | tuple | genexp | 'True' | 'None' | 'False' static void * -_tmp_147_rule(Parser *p) +_tmp_149_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30091,18 +30534,18 @@ _tmp_147_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); + D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); expr_ty list_var; if ( (list_var = list_rule(p)) // list ) { - D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "list")); + D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "list")); _res = list_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_149[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "list")); } { // tuple @@ -30110,18 +30553,18 @@ _tmp_147_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); + D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); expr_ty tuple_var; if ( (tuple_var = tuple_rule(p)) // tuple ) { - D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "tuple")); + D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "tuple")); _res = tuple_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_149[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "tuple")); } { // genexp @@ -30129,18 +30572,18 @@ _tmp_147_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); + D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); expr_ty genexp_var; if ( (genexp_var = genexp_rule(p)) // genexp ) { - D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "genexp")); + D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "genexp")); _res = genexp_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_149[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "genexp")); } { // 'True' @@ -30148,18 +30591,18 @@ _tmp_147_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); + D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 597)) // token='True' + (_keyword = _PyPegen_expect_token(p, 600)) // token='True' ) { - D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); + D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_149[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'True'")); } { // 'None' @@ -30167,18 +30610,18 @@ _tmp_147_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); + D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 598)) // token='None' + (_keyword = _PyPegen_expect_token(p, 601)) // token='None' ) { - D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); + D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_149[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'None'")); } { // 'False' @@ -30186,18 +30629,18 @@ _tmp_147_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); + D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 599)) // token='False' + (_keyword = _PyPegen_expect_token(p, 602)) // token='False' ) { - D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); + D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_149[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'False'")); } _res = NULL; @@ -30206,9 +30649,9 @@ _tmp_147_rule(Parser *p) return _res; } -// _tmp_148: '=' | ':=' +// _tmp_150: '=' | ':=' static void * -_tmp_148_rule(Parser *p) +_tmp_150_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30222,18 +30665,18 @@ _tmp_148_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c> _tmp_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c+ _tmp_150[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_150[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); } { // ':=' @@ -30241,18 +30684,18 @@ _tmp_148_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c> _tmp_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 53)) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c+ _tmp_150[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_150[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':='")); } _res = NULL; @@ -30261,9 +30704,9 @@ _tmp_148_rule(Parser *p) return _res; } -// _loop0_149: star_named_expressions +// _loop0_151: star_named_expressions static asdl_seq * -_loop0_149_rule(Parser *p) +_loop0_151_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30287,7 +30730,7 @@ _loop0_149_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expressions")); + D(fprintf(stderr, "%*c> _loop0_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expressions")); asdl_expr_seq* star_named_expressions_var; while ( (star_named_expressions_var = star_named_expressions_rule(p)) // star_named_expressions @@ -30309,7 +30752,7 @@ _loop0_149_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_149[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_151[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expressions")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30322,14 +30765,14 @@ _loop0_149_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_149_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_151_type, _seq); D(p->level--); return _seq; } -// _loop0_150: (star_targets '=') +// _loop0_152: (star_targets '=') static asdl_seq * -_loop0_150_rule(Parser *p) +_loop0_152_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30353,13 +30796,13 @@ _loop0_150_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_199_var; + D(fprintf(stderr, "%*c> _loop0_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); + void *_tmp_206_var; while ( - (_tmp_199_var = _tmp_199_rule(p)) // star_targets '=' + (_tmp_206_var = _tmp_206_rule(p)) // star_targets '=' ) { - _res = _tmp_199_var; + _res = _tmp_206_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30375,7 +30818,7 @@ _loop0_150_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_150[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_152[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(star_targets '=')")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30388,14 +30831,14 @@ _loop0_150_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_150_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_152_type, _seq); D(p->level--); return _seq; } -// _loop0_151: (star_targets '=') +// _loop0_153: (star_targets '=') static asdl_seq * -_loop0_151_rule(Parser *p) +_loop0_153_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30419,13 +30862,13 @@ _loop0_151_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_200_var; + D(fprintf(stderr, "%*c> _loop0_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); + void *_tmp_207_var; while ( - (_tmp_200_var = _tmp_200_rule(p)) // star_targets '=' + (_tmp_207_var = _tmp_207_rule(p)) // star_targets '=' ) { - _res = _tmp_200_var; + _res = _tmp_207_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30441,7 +30884,7 @@ _loop0_151_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_151[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_153[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(star_targets '=')")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30454,14 +30897,14 @@ _loop0_151_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_151_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_153_type, _seq); D(p->level--); return _seq; } -// _tmp_152: yield_expr | star_expressions +// _tmp_154: yield_expr | star_expressions static void * -_tmp_152_rule(Parser *p) +_tmp_154_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30475,18 +30918,18 @@ _tmp_152_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } { // star_expressions @@ -30494,18 +30937,18 @@ _tmp_152_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); expr_ty star_expressions_var; if ( (star_expressions_var = star_expressions_rule(p)) // star_expressions ) { - D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); _res = star_expressions_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); } _res = NULL; @@ -30514,9 +30957,9 @@ _tmp_152_rule(Parser *p) return _res; } -// _tmp_153: '[' | '(' | '{' +// _tmp_155: '[' | '(' | '{' static void * -_tmp_153_rule(Parser *p) +_tmp_155_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30530,18 +30973,18 @@ _tmp_153_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 9)) // token='[' ) { - D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['")); } { // '(' @@ -30549,18 +30992,18 @@ _tmp_153_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); + D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' ) { - D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); + D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'('")); } { // '{' @@ -30568,18 +31011,18 @@ _tmp_153_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' ) { - D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'")); } _res = NULL; @@ -30588,9 +31031,9 @@ _tmp_153_rule(Parser *p) return _res; } -// _tmp_154: '[' | '{' +// _tmp_156: '[' | '{' static void * -_tmp_154_rule(Parser *p) +_tmp_156_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30604,18 +31047,18 @@ _tmp_154_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c> _tmp_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 9)) // token='[' ) { - D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c+ _tmp_156[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_156[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['")); } { // '{' @@ -30623,18 +31066,18 @@ _tmp_154_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c> _tmp_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' ) { - D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c+ _tmp_156[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_156[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'")); } _res = NULL; @@ -30643,9 +31086,9 @@ _tmp_154_rule(Parser *p) return _res; } -// _tmp_155: '[' | '{' +// _tmp_157: '[' | '{' static void * -_tmp_155_rule(Parser *p) +_tmp_157_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30659,18 +31102,18 @@ _tmp_155_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c> _tmp_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 9)) // token='[' ) { - D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c+ _tmp_157[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_157[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['")); } { // '{' @@ -30678,18 +31121,18 @@ _tmp_155_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c> _tmp_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' ) { - D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c+ _tmp_157[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_157[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'")); } _res = NULL; @@ -30698,9 +31141,9 @@ _tmp_155_rule(Parser *p) return _res; } -// _loop0_156: param_no_default +// _loop0_158: param_no_default static asdl_seq * -_loop0_156_rule(Parser *p) +_loop0_158_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30724,7 +31167,7 @@ _loop0_156_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _loop0_158[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; while ( (param_no_default_var = param_no_default_rule(p)) // param_no_default @@ -30746,7 +31189,7 @@ _loop0_156_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_156[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_158[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30759,14 +31202,14 @@ _loop0_156_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_156_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_158_type, _seq); D(p->level--); return _seq; } -// _loop0_157: param_no_default +// _loop0_159: param_no_default static asdl_seq * -_loop0_157_rule(Parser *p) +_loop0_159_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30790,7 +31233,7 @@ _loop0_157_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _loop0_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; while ( (param_no_default_var = param_no_default_rule(p)) // param_no_default @@ -30812,7 +31255,7 @@ _loop0_157_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_157[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_159[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30825,14 +31268,14 @@ _loop0_157_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_157_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_159_type, _seq); D(p->level--); return _seq; } -// _loop1_158: param_no_default +// _loop1_160: param_no_default static asdl_seq * -_loop1_158_rule(Parser *p) +_loop1_160_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30856,7 +31299,7 @@ _loop1_158_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop1_158[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _loop1_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; while ( (param_no_default_var = param_no_default_rule(p)) // param_no_default @@ -30878,7 +31321,7 @@ _loop1_158_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_158[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_160[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } if (_n == 0 || p->error_indicator) { @@ -30896,14 +31339,14 @@ _loop1_158_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_158_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop1_160_type, _seq); D(p->level--); return _seq; } -// _loop1_159: param_with_default +// _loop1_161: param_with_default static asdl_seq * -_loop1_159_rule(Parser *p) +_loop1_161_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30927,7 +31370,7 @@ _loop1_159_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop1_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); + D(fprintf(stderr, "%*c> _loop1_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); NameDefaultPair* param_with_default_var; while ( (param_with_default_var = param_with_default_rule(p)) // param_with_default @@ -30949,7 +31392,7 @@ _loop1_159_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_159[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_161[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -30967,14 +31410,14 @@ _loop1_159_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_159_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop1_161_type, _seq); D(p->level--); return _seq; } -// _loop0_160: lambda_param_no_default +// _loop0_162: lambda_param_no_default static asdl_seq * -_loop0_160_rule(Parser *p) +_loop0_162_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30998,7 +31441,7 @@ _loop0_160_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop0_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -31020,7 +31463,7 @@ _loop0_160_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_160[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_162[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31033,14 +31476,14 @@ _loop0_160_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_160_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_162_type, _seq); D(p->level--); return _seq; } -// _loop0_161: lambda_param_no_default +// _loop0_163: lambda_param_no_default static asdl_seq * -_loop0_161_rule(Parser *p) +_loop0_163_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31064,7 +31507,7 @@ _loop0_161_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop0_163[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -31086,7 +31529,7 @@ _loop0_161_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_161[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_163[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31099,14 +31542,14 @@ _loop0_161_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_161_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_163_type, _seq); D(p->level--); return _seq; } -// _loop0_163: ',' lambda_param +// _loop0_165: ',' lambda_param static asdl_seq * -_loop0_163_rule(Parser *p) +_loop0_165_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31130,7 +31573,7 @@ _loop0_163_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_163[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' lambda_param")); + D(fprintf(stderr, "%*c> _loop0_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' lambda_param")); Token * _literal; arg_ty elem; while ( @@ -31161,7 +31604,7 @@ _loop0_163_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_163[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_165[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' lambda_param")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31174,14 +31617,14 @@ _loop0_163_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_163_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_165_type, _seq); D(p->level--); return _seq; } -// _gather_162: lambda_param _loop0_163 +// _gather_164: lambda_param _loop0_165 static asdl_seq * -_gather_162_rule(Parser *p) +_gather_164_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31190,27 +31633,27 @@ _gather_162_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // lambda_param _loop0_163 + { // lambda_param _loop0_165 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param _loop0_163")); + D(fprintf(stderr, "%*c> _gather_164[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param _loop0_165")); arg_ty elem; asdl_seq * seq; if ( (elem = lambda_param_rule(p)) // lambda_param && - (seq = _loop0_163_rule(p)) // _loop0_163 + (seq = _loop0_165_rule(p)) // _loop0_165 ) { - D(fprintf(stderr, "%*c+ _gather_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param _loop0_163")); + D(fprintf(stderr, "%*c+ _gather_164[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param _loop0_165")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_162[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param _loop0_163")); + D(fprintf(stderr, "%*c%s _gather_164[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param _loop0_165")); } _res = NULL; done: @@ -31218,9 +31661,9 @@ _gather_162_rule(Parser *p) return _res; } -// _loop1_164: lambda_param_with_default +// _loop1_166: lambda_param_with_default static asdl_seq * -_loop1_164_rule(Parser *p) +_loop1_166_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31244,7 +31687,7 @@ _loop1_164_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop1_164[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c> _loop1_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); NameDefaultPair* lambda_param_with_default_var; while ( (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default @@ -31266,7 +31709,7 @@ _loop1_164_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_164[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_166[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -31284,14 +31727,14 @@ _loop1_164_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_164_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop1_166_type, _seq); D(p->level--); return _seq; } -// _tmp_165: ')' | ',' (')' | '**') +// _tmp_167: ')' | ',' (')' | '**') static void * -_tmp_165_rule(Parser *p) +_tmp_167_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31305,18 +31748,18 @@ _tmp_165_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_165[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_167[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_165[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_167[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // ',' (')' | '**') @@ -31324,21 +31767,21 @@ _tmp_165_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); + D(fprintf(stderr, "%*c> _tmp_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); Token * _literal; - void *_tmp_201_var; + void *_tmp_208_var; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_tmp_201_var = _tmp_201_rule(p)) // ')' | '**' + (_tmp_208_var = _tmp_208_rule(p)) // ')' | '**' ) { - D(fprintf(stderr, "%*c+ _tmp_165[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); - _res = _PyPegen_dummy_name(p, _literal, _tmp_201_var); + D(fprintf(stderr, "%*c+ _tmp_167[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); + _res = _PyPegen_dummy_name(p, _literal, _tmp_208_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_165[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_167[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (')' | '**')")); } _res = NULL; @@ -31347,9 +31790,9 @@ _tmp_165_rule(Parser *p) return _res; } -// _tmp_166: ':' | ',' (':' | '**') +// _tmp_168: ':' | ',' (':' | '**') static void * -_tmp_166_rule(Parser *p) +_tmp_168_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31363,18 +31806,18 @@ _tmp_166_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_166[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_168[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_166[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_168[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // ',' (':' | '**') @@ -31382,21 +31825,21 @@ _tmp_166_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); + D(fprintf(stderr, "%*c> _tmp_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); Token * _literal; - void *_tmp_202_var; + void *_tmp_209_var; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_tmp_202_var = _tmp_202_rule(p)) // ':' | '**' + (_tmp_209_var = _tmp_209_rule(p)) // ':' | '**' ) { - D(fprintf(stderr, "%*c+ _tmp_166[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); - _res = _PyPegen_dummy_name(p, _literal, _tmp_202_var); + D(fprintf(stderr, "%*c+ _tmp_168[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); + _res = _PyPegen_dummy_name(p, _literal, _tmp_209_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_166[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_168[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (':' | '**')")); } _res = NULL; @@ -31405,9 +31848,9 @@ _tmp_166_rule(Parser *p) return _res; } -// _tmp_167: ',' | ')' | ':' +// _tmp_169: ',' | ')' | ':' static void * -_tmp_167_rule(Parser *p) +_tmp_169_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31421,18 +31864,18 @@ _tmp_167_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_167[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_169[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_167[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_169[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } { // ')' @@ -31440,18 +31883,18 @@ _tmp_167_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_167[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_169[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_167[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_169[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // ':' @@ -31459,18 +31902,18 @@ _tmp_167_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_167[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_169[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_167[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_169[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } _res = NULL; @@ -31479,9 +31922,9 @@ _tmp_167_rule(Parser *p) return _res; } -// _loop0_169: ',' (expression ['as' star_target]) +// _loop0_171: ',' (expression ['as' star_target]) static asdl_seq * -_loop0_169_rule(Parser *p) +_loop0_171_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31505,13 +31948,13 @@ _loop0_169_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_171[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_203_rule(p)) // expression ['as' star_target] + (elem = _tmp_210_rule(p)) // expression ['as' star_target] ) { _res = elem; @@ -31536,7 +31979,7 @@ _loop0_169_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_169[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_171[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expression ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31549,14 +31992,14 @@ _loop0_169_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_169_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_171_type, _seq); D(p->level--); return _seq; } -// _gather_168: (expression ['as' star_target]) _loop0_169 +// _gather_170: (expression ['as' star_target]) _loop0_171 static asdl_seq * -_gather_168_rule(Parser *p) +_gather_170_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31565,27 +32008,27 @@ _gather_168_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expression ['as' star_target]) _loop0_169 + { // (expression ['as' star_target]) _loop0_171 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_169")); + D(fprintf(stderr, "%*c> _gather_170[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_171")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_203_rule(p)) // expression ['as' star_target] + (elem = _tmp_210_rule(p)) // expression ['as' star_target] && - (seq = _loop0_169_rule(p)) // _loop0_169 + (seq = _loop0_171_rule(p)) // _loop0_171 ) { - D(fprintf(stderr, "%*c+ _gather_168[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_169")); + D(fprintf(stderr, "%*c+ _gather_170[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_171")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_168[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_169")); + D(fprintf(stderr, "%*c%s _gather_170[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_171")); } _res = NULL; done: @@ -31593,9 +32036,9 @@ _gather_168_rule(Parser *p) return _res; } -// _loop0_171: ',' (expressions ['as' star_target]) +// _loop0_173: ',' (expressions ['as' star_target]) static asdl_seq * -_loop0_171_rule(Parser *p) +_loop0_173_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31619,13 +32062,13 @@ _loop0_171_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_171[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_173[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_204_rule(p)) // expressions ['as' star_target] + (elem = _tmp_211_rule(p)) // expressions ['as' star_target] ) { _res = elem; @@ -31650,7 +32093,7 @@ _loop0_171_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_171[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_173[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expressions ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31663,14 +32106,14 @@ _loop0_171_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_171_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_173_type, _seq); D(p->level--); return _seq; } -// _gather_170: (expressions ['as' star_target]) _loop0_171 +// _gather_172: (expressions ['as' star_target]) _loop0_173 static asdl_seq * -_gather_170_rule(Parser *p) +_gather_172_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31679,27 +32122,27 @@ _gather_170_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expressions ['as' star_target]) _loop0_171 + { // (expressions ['as' star_target]) _loop0_173 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_170[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_171")); + D(fprintf(stderr, "%*c> _gather_172[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_173")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_204_rule(p)) // expressions ['as' star_target] + (elem = _tmp_211_rule(p)) // expressions ['as' star_target] && - (seq = _loop0_171_rule(p)) // _loop0_171 + (seq = _loop0_173_rule(p)) // _loop0_173 ) { - D(fprintf(stderr, "%*c+ _gather_170[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_171")); + D(fprintf(stderr, "%*c+ _gather_172[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_173")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_170[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_171")); + D(fprintf(stderr, "%*c%s _gather_172[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_173")); } _res = NULL; done: @@ -31707,9 +32150,9 @@ _gather_170_rule(Parser *p) return _res; } -// _loop0_173: ',' (expression ['as' star_target]) +// _loop0_175: ',' (expression ['as' star_target]) static asdl_seq * -_loop0_173_rule(Parser *p) +_loop0_175_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31733,13 +32176,13 @@ _loop0_173_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_173[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_175[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_205_rule(p)) // expression ['as' star_target] + (elem = _tmp_212_rule(p)) // expression ['as' star_target] ) { _res = elem; @@ -31764,7 +32207,7 @@ _loop0_173_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_173[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_175[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expression ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31777,14 +32220,14 @@ _loop0_173_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_173_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_175_type, _seq); D(p->level--); return _seq; } -// _gather_172: (expression ['as' star_target]) _loop0_173 +// _gather_174: (expression ['as' star_target]) _loop0_175 static asdl_seq * -_gather_172_rule(Parser *p) +_gather_174_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31793,27 +32236,27 @@ _gather_172_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expression ['as' star_target]) _loop0_173 + { // (expression ['as' star_target]) _loop0_175 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_172[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_173")); + D(fprintf(stderr, "%*c> _gather_174[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_175")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_205_rule(p)) // expression ['as' star_target] + (elem = _tmp_212_rule(p)) // expression ['as' star_target] && - (seq = _loop0_173_rule(p)) // _loop0_173 + (seq = _loop0_175_rule(p)) // _loop0_175 ) { - D(fprintf(stderr, "%*c+ _gather_172[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_173")); + D(fprintf(stderr, "%*c+ _gather_174[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_175")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_172[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_173")); + D(fprintf(stderr, "%*c%s _gather_174[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_175")); } _res = NULL; done: @@ -31821,9 +32264,9 @@ _gather_172_rule(Parser *p) return _res; } -// _loop0_175: ',' (expressions ['as' star_target]) +// _loop0_177: ',' (expressions ['as' star_target]) static asdl_seq * -_loop0_175_rule(Parser *p) +_loop0_177_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31847,13 +32290,13 @@ _loop0_175_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_175[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_177[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_206_rule(p)) // expressions ['as' star_target] + (elem = _tmp_213_rule(p)) // expressions ['as' star_target] ) { _res = elem; @@ -31878,7 +32321,7 @@ _loop0_175_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_175[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_177[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expressions ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31891,14 +32334,14 @@ _loop0_175_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_175_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_177_type, _seq); D(p->level--); return _seq; } -// _gather_174: (expressions ['as' star_target]) _loop0_175 +// _gather_176: (expressions ['as' star_target]) _loop0_177 static asdl_seq * -_gather_174_rule(Parser *p) +_gather_176_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31907,27 +32350,27 @@ _gather_174_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expressions ['as' star_target]) _loop0_175 + { // (expressions ['as' star_target]) _loop0_177 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_174[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_175")); + D(fprintf(stderr, "%*c> _gather_176[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_177")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_206_rule(p)) // expressions ['as' star_target] + (elem = _tmp_213_rule(p)) // expressions ['as' star_target] && - (seq = _loop0_175_rule(p)) // _loop0_175 + (seq = _loop0_177_rule(p)) // _loop0_177 ) { - D(fprintf(stderr, "%*c+ _gather_174[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_175")); + D(fprintf(stderr, "%*c+ _gather_176[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_177")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_174[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_175")); + D(fprintf(stderr, "%*c%s _gather_176[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_177")); } _res = NULL; done: @@ -31935,9 +32378,9 @@ _gather_174_rule(Parser *p) return _res; } -// _tmp_176: 'except' | 'finally' +// _tmp_178: 'except' | 'finally' static void * -_tmp_176_rule(Parser *p) +_tmp_178_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31951,18 +32394,18 @@ _tmp_176_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_176[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except'")); + D(fprintf(stderr, "%*c> _tmp_178[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 623)) // token='except' + (_keyword = _PyPegen_expect_token(p, 629)) // token='except' ) { - D(fprintf(stderr, "%*c+ _tmp_176[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except'")); + D(fprintf(stderr, "%*c+ _tmp_178[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_176[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_178[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'except'")); } { // 'finally' @@ -31970,18 +32413,18 @@ _tmp_176_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_176[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally'")); + D(fprintf(stderr, "%*c> _tmp_178[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 620)) // token='finally' + (_keyword = _PyPegen_expect_token(p, 625)) // token='finally' ) { - D(fprintf(stderr, "%*c+ _tmp_176[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally'")); + D(fprintf(stderr, "%*c+ _tmp_178[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_176[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_178[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'finally'")); } _res = NULL; @@ -31990,48 +32433,75 @@ _tmp_176_rule(Parser *p) return _res; } -// _tmp_177: 'as' NAME -static void * -_tmp_177_rule(Parser *p) +// _loop0_179: block +static asdl_seq * +_loop0_179_rule(Parser *p) { D(p->level++); if (p->error_indicator) { D(p->level--); return NULL; } - void * _res = NULL; + void *_res = NULL; int _mark = p->mark; - { // 'as' NAME + int _start_mark = p->mark; + void **_children = PyMem_Malloc(sizeof(void *)); + if (!_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + Py_ssize_t _children_capacity = 1; + Py_ssize_t _n = 0; + { // block if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_177[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - Token * _keyword; - expr_ty name_var; - if ( - (_keyword = _PyPegen_expect_token(p, 625)) // token='as' - && - (name_var = _PyPegen_name_token(p)) // NAME + D(fprintf(stderr, "%*c> _loop0_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "block")); + asdl_stmt_seq* block_var; + while ( + (block_var = block_rule(p)) // block ) { - D(fprintf(stderr, "%*c+ _tmp_177[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - _res = _PyPegen_dummy_name(p, _keyword, name_var); - goto done; + _res = block_var; + if (_n == _children_capacity) { + _children_capacity *= 2; + void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); + if (!_new_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + _children = _new_children; + } + _children[_n++] = _res; + _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_177[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c%s _loop0_179[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "block")); } - _res = NULL; - done: + asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); + if (!_seq) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); + PyMem_Free(_children); + _PyPegen_insert_memo(p, _start_mark, _loop0_179_type, _seq); D(p->level--); - return _res; + return _seq; } -// _tmp_178: 'as' NAME +// _tmp_180: (except_block+ except_star_block) | (except_star_block+ except_block) static void * -_tmp_178_rule(Parser *p) +_tmp_180_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32040,27 +32510,43 @@ _tmp_178_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // 'as' NAME + { // (except_block+ except_star_block) if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_178[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - Token * _keyword; - expr_ty name_var; + D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(except_block+ except_star_block)")); + void *_tmp_214_var; if ( - (_keyword = _PyPegen_expect_token(p, 625)) // token='as' - && - (name_var = _PyPegen_name_token(p)) // NAME + (_tmp_214_var = _tmp_214_rule(p)) // except_block+ except_star_block ) { - D(fprintf(stderr, "%*c+ _tmp_178[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - _res = _PyPegen_dummy_name(p, _keyword, name_var); + D(fprintf(stderr, "%*c+ _tmp_180[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(except_block+ except_star_block)")); + _res = _tmp_214_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_178[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c%s _tmp_180[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(except_block+ except_star_block)")); + } + { // (except_star_block+ except_block) + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(except_star_block+ except_block)")); + void *_tmp_215_var; + if ( + (_tmp_215_var = _tmp_215_rule(p)) // except_star_block+ except_block + ) + { + D(fprintf(stderr, "%*c+ _tmp_180[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(except_star_block+ except_block)")); + _res = _tmp_215_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_180[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(except_star_block+ except_block)")); } _res = NULL; done: @@ -32068,9 +32554,75 @@ _tmp_178_rule(Parser *p) return _res; } -// _tmp_179: 'as' NAME +// _loop0_181: block +static asdl_seq * +_loop0_181_rule(Parser *p) +{ + D(p->level++); + if (p->error_indicator) { + D(p->level--); + return NULL; + } + void *_res = NULL; + int _mark = p->mark; + int _start_mark = p->mark; + void **_children = PyMem_Malloc(sizeof(void *)); + if (!_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + Py_ssize_t _children_capacity = 1; + Py_ssize_t _n = 0; + { // block + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> _loop0_181[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "block")); + asdl_stmt_seq* block_var; + while ( + (block_var = block_rule(p)) // block + ) + { + _res = block_var; + if (_n == _children_capacity) { + _children_capacity *= 2; + void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); + if (!_new_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + _children = _new_children; + } + _children[_n++] = _res; + _mark = p->mark; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _loop0_181[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "block")); + } + asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); + if (!_seq) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); + PyMem_Free(_children); + _PyPegen_insert_memo(p, _start_mark, _loop0_181_type, _seq); + D(p->level--); + return _seq; +} + +// _tmp_182: 'as' NAME static void * -_tmp_179_rule(Parser *p) +_tmp_182_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32084,21 +32636,21 @@ _tmp_179_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( - (_keyword = _PyPegen_expect_token(p, 625)) // token='as' + (_keyword = _PyPegen_expect_token(p, 632)) // token='as' && (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_179[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_182[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_179[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_182[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -32107,9 +32659,9 @@ _tmp_179_rule(Parser *p) return _res; } -// _tmp_180: positional_patterns ',' +// _tmp_183: 'as' NAME static void * -_tmp_180_rule(Parser *p) +_tmp_183_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32118,27 +32670,27 @@ _tmp_180_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // positional_patterns ',' + { // 'as' NAME if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); - Token * _literal; - asdl_pattern_seq* positional_patterns_var; + D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + Token * _keyword; + expr_ty name_var; if ( - (positional_patterns_var = positional_patterns_rule(p)) // positional_patterns + (_keyword = _PyPegen_expect_token(p, 632)) // token='as' && - (_literal = _PyPegen_expect_token(p, 12)) // token=',' + (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_180[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); - _res = _PyPegen_dummy_name(p, positional_patterns_var, _literal); + D(fprintf(stderr, "%*c+ _tmp_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_180[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "positional_patterns ','")); + D(fprintf(stderr, "%*c%s _tmp_183[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; done: @@ -32146,9 +32698,9 @@ _tmp_180_rule(Parser *p) return _res; } -// _tmp_181: '->' expression +// _tmp_184: NEWLINE | ':' static void * -_tmp_181_rule(Parser *p) +_tmp_184_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32157,27 +32709,43 @@ _tmp_181_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // '->' expression + { // NEWLINE + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_184[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); + Token * newline_var; + if ( + (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' + ) + { + D(fprintf(stderr, "%*c+ _tmp_184[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE")); + _res = newline_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_184[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NEWLINE")); + } + { // ':' if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_181[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); + D(fprintf(stderr, "%*c> _tmp_184[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; - expr_ty expression_var; if ( - (_literal = _PyPegen_expect_token(p, 51)) // token='->' - && - (expression_var = expression_rule(p)) // expression + (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_181[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression")); - _res = _PyPegen_dummy_name(p, _literal, expression_var); + D(fprintf(stderr, "%*c+ _tmp_184[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_181[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'->' expression")); + D(fprintf(stderr, "%*c%s _tmp_184[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } _res = NULL; done: @@ -32185,9 +32753,9 @@ _tmp_181_rule(Parser *p) return _res; } -// _tmp_182: '(' arguments? ')' +// _tmp_185: 'as' NAME static void * -_tmp_182_rule(Parser *p) +_tmp_185_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32196,14 +32764,170 @@ _tmp_182_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // '(' arguments? ')' + { // 'as' NAME if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); - Token * _literal; - Token * _literal_1; + D(fprintf(stderr, "%*c> _tmp_185[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + Token * _keyword; + expr_ty name_var; + if ( + (_keyword = _PyPegen_expect_token(p, 632)) // token='as' + && + (name_var = _PyPegen_name_token(p)) // NAME + ) + { + D(fprintf(stderr, "%*c+ _tmp_185[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + _res = _PyPegen_dummy_name(p, _keyword, name_var); + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_185[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); + } + _res = NULL; + done: + D(p->level--); + return _res; +} + +// _tmp_186: 'as' NAME +static void * +_tmp_186_rule(Parser *p) +{ + D(p->level++); + if (p->error_indicator) { + D(p->level--); + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // 'as' NAME + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_186[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + Token * _keyword; + expr_ty name_var; + if ( + (_keyword = _PyPegen_expect_token(p, 632)) // token='as' + && + (name_var = _PyPegen_name_token(p)) // NAME + ) + { + D(fprintf(stderr, "%*c+ _tmp_186[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + _res = _PyPegen_dummy_name(p, _keyword, name_var); + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_186[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); + } + _res = NULL; + done: + D(p->level--); + return _res; +} + +// _tmp_187: positional_patterns ',' +static void * +_tmp_187_rule(Parser *p) +{ + D(p->level++); + if (p->error_indicator) { + D(p->level--); + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // positional_patterns ',' + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_187[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); + Token * _literal; + asdl_pattern_seq* positional_patterns_var; + if ( + (positional_patterns_var = positional_patterns_rule(p)) // positional_patterns + && + (_literal = _PyPegen_expect_token(p, 12)) // token=',' + ) + { + D(fprintf(stderr, "%*c+ _tmp_187[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); + _res = _PyPegen_dummy_name(p, positional_patterns_var, _literal); + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_187[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "positional_patterns ','")); + } + _res = NULL; + done: + D(p->level--); + return _res; +} + +// _tmp_188: '->' expression +static void * +_tmp_188_rule(Parser *p) +{ + D(p->level++); + if (p->error_indicator) { + D(p->level--); + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // '->' expression + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_188[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); + Token * _literal; + expr_ty expression_var; + if ( + (_literal = _PyPegen_expect_token(p, 51)) // token='->' + && + (expression_var = expression_rule(p)) // expression + ) + { + D(fprintf(stderr, "%*c+ _tmp_188[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression")); + _res = _PyPegen_dummy_name(p, _literal, expression_var); + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_188[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'->' expression")); + } + _res = NULL; + done: + D(p->level--); + return _res; +} + +// _tmp_189: '(' arguments? ')' +static void * +_tmp_189_rule(Parser *p) +{ + D(p->level++); + if (p->error_indicator) { + D(p->level--); + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // '(' arguments? ')' + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_189[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); + Token * _literal; + Token * _literal_1; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings if ( @@ -32214,12 +32938,12 @@ _tmp_182_rule(Parser *p) (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_182[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c+ _tmp_189[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); _res = _PyPegen_dummy_name(p, _literal, _opt_var, _literal_1); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_182[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_189[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' arguments? ')'")); } _res = NULL; @@ -32228,9 +32952,9 @@ _tmp_182_rule(Parser *p) return _res; } -// _loop0_184: ',' double_starred_kvpair +// _loop0_191: ',' double_starred_kvpair static asdl_seq * -_loop0_184_rule(Parser *p) +_loop0_191_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32254,7 +32978,7 @@ _loop0_184_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_184[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); + D(fprintf(stderr, "%*c> _loop0_191[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); Token * _literal; KeyValuePair* elem; while ( @@ -32285,7 +33009,7 @@ _loop0_184_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_184[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_191[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' double_starred_kvpair")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -32298,14 +33022,14 @@ _loop0_184_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_184_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_191_type, _seq); D(p->level--); return _seq; } -// _gather_183: double_starred_kvpair _loop0_184 +// _gather_190: double_starred_kvpair _loop0_191 static asdl_seq * -_gather_183_rule(Parser *p) +_gather_190_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32314,27 +33038,27 @@ _gather_183_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // double_starred_kvpair _loop0_184 + { // double_starred_kvpair _loop0_191 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_184")); + D(fprintf(stderr, "%*c> _gather_190[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_191")); KeyValuePair* elem; asdl_seq * seq; if ( (elem = double_starred_kvpair_rule(p)) // double_starred_kvpair && - (seq = _loop0_184_rule(p)) // _loop0_184 + (seq = _loop0_191_rule(p)) // _loop0_191 ) { - D(fprintf(stderr, "%*c+ _gather_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_184")); + D(fprintf(stderr, "%*c+ _gather_190[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_191")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_183[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_184")); + D(fprintf(stderr, "%*c%s _gather_190[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_191")); } _res = NULL; done: @@ -32342,9 +33066,9 @@ _gather_183_rule(Parser *p) return _res; } -// _tmp_185: '}' | ',' +// _tmp_192: '}' | ',' static void * -_tmp_185_rule(Parser *p) +_tmp_192_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32358,18 +33082,18 @@ _tmp_185_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_185[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_192[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_185[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_192[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_185[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_192[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } { // ',' @@ -32377,18 +33101,18 @@ _tmp_185_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_185[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_192[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_185[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_192[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_185[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_192[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -32397,9 +33121,9 @@ _tmp_185_rule(Parser *p) return _res; } -// _tmp_186: star_targets '=' +// _tmp_193: star_targets '=' static void * -_tmp_186_rule(Parser *p) +_tmp_193_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32413,7 +33137,7 @@ _tmp_186_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_186[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_193[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty z; if ( @@ -32422,7 +33146,7 @@ _tmp_186_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_186[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_193[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32432,7 +33156,7 @@ _tmp_186_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_186[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_193[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; @@ -32441,9 +33165,9 @@ _tmp_186_rule(Parser *p) return _res; } -// _tmp_187: '.' | '...' +// _tmp_194: '.' | '...' static void * -_tmp_187_rule(Parser *p) +_tmp_194_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32457,18 +33181,18 @@ _tmp_187_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_187[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c> _tmp_194[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 23)) // token='.' ) { - D(fprintf(stderr, "%*c+ _tmp_187[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c+ _tmp_194[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_187[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_194[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); } { // '...' @@ -32476,18 +33200,18 @@ _tmp_187_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_187[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c> _tmp_194[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 52)) // token='...' ) { - D(fprintf(stderr, "%*c+ _tmp_187[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c+ _tmp_194[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_187[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_194[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'")); } _res = NULL; @@ -32496,9 +33220,9 @@ _tmp_187_rule(Parser *p) return _res; } -// _tmp_188: '.' | '...' +// _tmp_195: '.' | '...' static void * -_tmp_188_rule(Parser *p) +_tmp_195_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32512,18 +33236,18 @@ _tmp_188_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_188[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c> _tmp_195[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 23)) // token='.' ) { - D(fprintf(stderr, "%*c+ _tmp_188[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c+ _tmp_195[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_188[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_195[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); } { // '...' @@ -32531,18 +33255,18 @@ _tmp_188_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_188[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c> _tmp_195[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 52)) // token='...' ) { - D(fprintf(stderr, "%*c+ _tmp_188[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c+ _tmp_195[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_188[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_195[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'")); } _res = NULL; @@ -32551,9 +33275,9 @@ _tmp_188_rule(Parser *p) return _res; } -// _tmp_189: '@' named_expression NEWLINE +// _tmp_196: '@' named_expression NEWLINE static void * -_tmp_189_rule(Parser *p) +_tmp_196_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32567,7 +33291,7 @@ _tmp_189_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_189[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); + D(fprintf(stderr, "%*c> _tmp_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); Token * _literal; expr_ty f; Token * newline_var; @@ -32579,7 +33303,7 @@ _tmp_189_rule(Parser *p) (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) { - D(fprintf(stderr, "%*c+ _tmp_189[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); + D(fprintf(stderr, "%*c+ _tmp_196[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); _res = f; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32589,7 +33313,7 @@ _tmp_189_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_189[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_196[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'@' named_expression NEWLINE")); } _res = NULL; @@ -32598,9 +33322,9 @@ _tmp_189_rule(Parser *p) return _res; } -// _tmp_190: ',' expression +// _tmp_197: ',' expression static void * -_tmp_190_rule(Parser *p) +_tmp_197_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32614,7 +33338,7 @@ _tmp_190_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_190[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _tmp_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); Token * _literal; expr_ty c; if ( @@ -32623,7 +33347,7 @@ _tmp_190_rule(Parser *p) (c = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ _tmp_190[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c+ _tmp_197[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32633,7 +33357,7 @@ _tmp_190_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_190[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_197[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } _res = NULL; @@ -32642,9 +33366,9 @@ _tmp_190_rule(Parser *p) return _res; } -// _tmp_191: ',' star_expression +// _tmp_198: ',' star_expression static void * -_tmp_191_rule(Parser *p) +_tmp_198_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32658,7 +33382,7 @@ _tmp_191_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_191[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression")); + D(fprintf(stderr, "%*c> _tmp_198[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression")); Token * _literal; expr_ty c; if ( @@ -32667,7 +33391,7 @@ _tmp_191_rule(Parser *p) (c = star_expression_rule(p)) // star_expression ) { - D(fprintf(stderr, "%*c+ _tmp_191[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression")); + D(fprintf(stderr, "%*c+ _tmp_198[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32677,7 +33401,7 @@ _tmp_191_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_191[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_198[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_expression")); } _res = NULL; @@ -32686,9 +33410,9 @@ _tmp_191_rule(Parser *p) return _res; } -// _tmp_192: 'or' conjunction +// _tmp_199: 'or' conjunction static void * -_tmp_192_rule(Parser *p) +_tmp_199_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32702,16 +33426,16 @@ _tmp_192_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_192[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); + D(fprintf(stderr, "%*c> _tmp_199[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); Token * _keyword; expr_ty c; if ( - (_keyword = _PyPegen_expect_token(p, 571)) // token='or' + (_keyword = _PyPegen_expect_token(p, 574)) // token='or' && (c = conjunction_rule(p)) // conjunction ) { - D(fprintf(stderr, "%*c+ _tmp_192[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); + D(fprintf(stderr, "%*c+ _tmp_199[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32721,7 +33445,7 @@ _tmp_192_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_192[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_199[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'or' conjunction")); } _res = NULL; @@ -32730,9 +33454,9 @@ _tmp_192_rule(Parser *p) return _res; } -// _tmp_193: 'and' inversion +// _tmp_200: 'and' inversion static void * -_tmp_193_rule(Parser *p) +_tmp_200_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32746,16 +33470,16 @@ _tmp_193_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_193[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion")); + D(fprintf(stderr, "%*c> _tmp_200[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion")); Token * _keyword; expr_ty c; if ( - (_keyword = _PyPegen_expect_token(p, 572)) // token='and' + (_keyword = _PyPegen_expect_token(p, 575)) // token='and' && (c = inversion_rule(p)) // inversion ) { - D(fprintf(stderr, "%*c+ _tmp_193[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion")); + D(fprintf(stderr, "%*c+ _tmp_200[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32765,7 +33489,7 @@ _tmp_193_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_193[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_200[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'and' inversion")); } _res = NULL; @@ -32774,9 +33498,9 @@ _tmp_193_rule(Parser *p) return _res; } -// _tmp_194: 'if' disjunction +// _tmp_201: 'if' disjunction static void * -_tmp_194_rule(Parser *p) +_tmp_201_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32790,16 +33514,16 @@ _tmp_194_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_194[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); Token * _keyword; expr_ty z; if ( - (_keyword = _PyPegen_expect_token(p, 627)) // token='if' + (_keyword = _PyPegen_expect_token(p, 634)) // token='if' && (z = disjunction_rule(p)) // disjunction ) { - D(fprintf(stderr, "%*c+ _tmp_194[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32809,7 +33533,7 @@ _tmp_194_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_194[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction")); } _res = NULL; @@ -32818,9 +33542,9 @@ _tmp_194_rule(Parser *p) return _res; } -// _tmp_195: 'if' disjunction +// _tmp_202: 'if' disjunction static void * -_tmp_195_rule(Parser *p) +_tmp_202_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32834,16 +33558,16 @@ _tmp_195_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_195[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); Token * _keyword; expr_ty z; if ( - (_keyword = _PyPegen_expect_token(p, 627)) // token='if' + (_keyword = _PyPegen_expect_token(p, 634)) // token='if' && (z = disjunction_rule(p)) // disjunction ) { - D(fprintf(stderr, "%*c+ _tmp_195[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32853,7 +33577,7 @@ _tmp_195_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_195[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction")); } _res = NULL; @@ -32862,9 +33586,9 @@ _tmp_195_rule(Parser *p) return _res; } -// _tmp_196: starred_expression | (assignment_expression | expression !':=') !'=' +// _tmp_203: starred_expression | (assignment_expression | expression !':=') !'=' static void * -_tmp_196_rule(Parser *p) +_tmp_203_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32878,18 +33602,18 @@ _tmp_196_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c> _tmp_203[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); expr_ty starred_expression_var; if ( (starred_expression_var = starred_expression_rule(p)) // starred_expression ) { - D(fprintf(stderr, "%*c+ _tmp_196[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c+ _tmp_203[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); _res = starred_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_196[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_203[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression")); } { // (assignment_expression | expression !':=') !'=' @@ -32897,20 +33621,20 @@ _tmp_196_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); - void *_tmp_207_var; + D(fprintf(stderr, "%*c> _tmp_203[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); + void *_tmp_216_var; if ( - (_tmp_207_var = _tmp_207_rule(p)) // assignment_expression | expression !':=' + (_tmp_216_var = _tmp_216_rule(p)) // assignment_expression | expression !':=' && _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_196[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); - _res = _tmp_207_var; + D(fprintf(stderr, "%*c+ _tmp_203[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); + _res = _tmp_216_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_196[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_203[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(assignment_expression | expression !':=') !'='")); } _res = NULL; @@ -32919,9 +33643,9 @@ _tmp_196_rule(Parser *p) return _res; } -// _tmp_197: ',' star_target +// _tmp_204: ',' star_target static void * -_tmp_197_rule(Parser *p) +_tmp_204_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32935,7 +33659,7 @@ _tmp_197_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c> _tmp_204[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); Token * _literal; expr_ty c; if ( @@ -32944,7 +33668,7 @@ _tmp_197_rule(Parser *p) (c = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_197[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c+ _tmp_204[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32954,7 +33678,7 @@ _tmp_197_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_197[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_204[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); } _res = NULL; @@ -32963,9 +33687,9 @@ _tmp_197_rule(Parser *p) return _res; } -// _tmp_198: ',' star_target +// _tmp_205: ',' star_target static void * -_tmp_198_rule(Parser *p) +_tmp_205_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32979,7 +33703,7 @@ _tmp_198_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_198[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c> _tmp_205[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); Token * _literal; expr_ty c; if ( @@ -32988,7 +33712,7 @@ _tmp_198_rule(Parser *p) (c = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_198[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c+ _tmp_205[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32998,7 +33722,7 @@ _tmp_198_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_198[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_205[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); } _res = NULL; @@ -33007,9 +33731,9 @@ _tmp_198_rule(Parser *p) return _res; } -// _tmp_199: star_targets '=' +// _tmp_206: star_targets '=' static void * -_tmp_199_rule(Parser *p) +_tmp_206_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -33023,7 +33747,7 @@ _tmp_199_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_199[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_206[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty star_targets_var; if ( @@ -33032,12 +33756,12 @@ _tmp_199_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_199[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_206[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = _PyPegen_dummy_name(p, star_targets_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_199[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_206[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; @@ -33046,9 +33770,9 @@ _tmp_199_rule(Parser *p) return _res; } -// _tmp_200: star_targets '=' +// _tmp_207: star_targets '=' static void * -_tmp_200_rule(Parser *p) +_tmp_207_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -33062,7 +33786,7 @@ _tmp_200_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_200[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_207[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty star_targets_var; if ( @@ -33071,12 +33795,12 @@ _tmp_200_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_200[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_207[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = _PyPegen_dummy_name(p, star_targets_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_200[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_207[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; @@ -33085,9 +33809,9 @@ _tmp_200_rule(Parser *p) return _res; } -// _tmp_201: ')' | '**' +// _tmp_208: ')' | '**' static void * -_tmp_201_rule(Parser *p) +_tmp_208_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -33101,18 +33825,18 @@ _tmp_201_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_208[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_208[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_208[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // '**' @@ -33120,18 +33844,18 @@ _tmp_201_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c> _tmp_208[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c+ _tmp_208[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_208[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } _res = NULL; @@ -33140,9 +33864,9 @@ _tmp_201_rule(Parser *p) return _res; } -// _tmp_202: ':' | '**' +// _tmp_209: ':' | '**' static void * -_tmp_202_rule(Parser *p) +_tmp_209_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -33156,18 +33880,18 @@ _tmp_202_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_209[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_209[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_209[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // '**' @@ -33175,18 +33899,18 @@ _tmp_202_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c> _tmp_209[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c+ _tmp_209[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_209[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } _res = NULL; @@ -33195,9 +33919,9 @@ _tmp_202_rule(Parser *p) return _res; } -// _tmp_203: expression ['as' star_target] +// _tmp_210: expression ['as' star_target] static void * -_tmp_203_rule(Parser *p) +_tmp_210_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -33211,22 +33935,22 @@ _tmp_203_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_203[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_210[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_208_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_217_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_203[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_210[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); _res = _PyPegen_dummy_name(p, expression_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_203[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_210[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' star_target]")); } _res = NULL; @@ -33235,9 +33959,9 @@ _tmp_203_rule(Parser *p) return _res; } -// _tmp_204: expressions ['as' star_target] +// _tmp_211: expressions ['as' star_target] static void * -_tmp_204_rule(Parser *p) +_tmp_211_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -33251,22 +33975,22 @@ _tmp_204_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_204[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_211[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expressions_var; if ( (expressions_var = expressions_rule(p)) // expressions && - (_opt_var = _tmp_209_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_218_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_204[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_211[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); _res = _PyPegen_dummy_name(p, expressions_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_204[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_211[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expressions ['as' star_target]")); } _res = NULL; @@ -33275,9 +33999,9 @@ _tmp_204_rule(Parser *p) return _res; } -// _tmp_205: expression ['as' star_target] +// _tmp_212: expression ['as' star_target] static void * -_tmp_205_rule(Parser *p) +_tmp_212_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -33291,22 +34015,22 @@ _tmp_205_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_205[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_212[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_210_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_219_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_205[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_212[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); _res = _PyPegen_dummy_name(p, expression_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_205[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_212[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' star_target]")); } _res = NULL; @@ -33315,9 +34039,9 @@ _tmp_205_rule(Parser *p) return _res; } -// _tmp_206: expressions ['as' star_target] +// _tmp_213: expressions ['as' star_target] static void * -_tmp_206_rule(Parser *p) +_tmp_213_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -33331,22 +34055,22 @@ _tmp_206_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_206[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_213[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expressions_var; if ( (expressions_var = expressions_rule(p)) // expressions && - (_opt_var = _tmp_211_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_220_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_206[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_213[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); _res = _PyPegen_dummy_name(p, expressions_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_206[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_213[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expressions ['as' star_target]")); } _res = NULL; @@ -33355,9 +34079,87 @@ _tmp_206_rule(Parser *p) return _res; } -// _tmp_207: assignment_expression | expression !':=' +// _tmp_214: except_block+ except_star_block static void * -_tmp_207_rule(Parser *p) +_tmp_214_rule(Parser *p) +{ + D(p->level++); + if (p->error_indicator) { + D(p->level--); + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // except_block+ except_star_block + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_214[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_block+ except_star_block")); + asdl_seq * _loop1_221_var; + excepthandler_ty except_star_block_var; + if ( + (_loop1_221_var = _loop1_221_rule(p)) // except_block+ + && + (except_star_block_var = except_star_block_rule(p)) // except_star_block + ) + { + D(fprintf(stderr, "%*c+ _tmp_214[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "except_block+ except_star_block")); + _res = _PyPegen_dummy_name(p, _loop1_221_var, except_star_block_var); + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_214[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "except_block+ except_star_block")); + } + _res = NULL; + done: + D(p->level--); + return _res; +} + +// _tmp_215: except_star_block+ except_block +static void * +_tmp_215_rule(Parser *p) +{ + D(p->level++); + if (p->error_indicator) { + D(p->level--); + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // except_star_block+ except_block + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_215[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_star_block+ except_block")); + asdl_seq * _loop1_222_var; + excepthandler_ty except_block_var; + if ( + (_loop1_222_var = _loop1_222_rule(p)) // except_star_block+ + && + (except_block_var = except_block_rule(p)) // except_block + ) + { + D(fprintf(stderr, "%*c+ _tmp_215[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "except_star_block+ except_block")); + _res = _PyPegen_dummy_name(p, _loop1_222_var, except_block_var); + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_215[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "except_star_block+ except_block")); + } + _res = NULL; + done: + D(p->level--); + return _res; +} + +// _tmp_216: assignment_expression | expression !':=' +static void * +_tmp_216_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -33371,18 +34173,18 @@ _tmp_207_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_207[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + D(fprintf(stderr, "%*c> _tmp_216[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); expr_ty assignment_expression_var; if ( (assignment_expression_var = assignment_expression_rule(p)) // assignment_expression ) { - D(fprintf(stderr, "%*c+ _tmp_207[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + D(fprintf(stderr, "%*c+ _tmp_216[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); _res = assignment_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_207[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_216[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment_expression")); } { // expression !':=' @@ -33390,7 +34192,7 @@ _tmp_207_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_207[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c> _tmp_216[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression @@ -33398,12 +34200,12 @@ _tmp_207_rule(Parser *p) _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 53) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_207[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c+ _tmp_216[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); _res = expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_207[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_216[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression !':='")); } _res = NULL; @@ -33412,9 +34214,9 @@ _tmp_207_rule(Parser *p) return _res; } -// _tmp_208: 'as' star_target +// _tmp_217: 'as' star_target static void * -_tmp_208_rule(Parser *p) +_tmp_217_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -33428,21 +34230,21 @@ _tmp_208_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_208[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_217[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( - (_keyword = _PyPegen_expect_token(p, 625)) // token='as' + (_keyword = _PyPegen_expect_token(p, 632)) // token='as' && (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_208[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_217[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_208[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_217[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; @@ -33451,9 +34253,9 @@ _tmp_208_rule(Parser *p) return _res; } -// _tmp_209: 'as' star_target +// _tmp_218: 'as' star_target static void * -_tmp_209_rule(Parser *p) +_tmp_218_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -33467,21 +34269,21 @@ _tmp_209_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_209[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_218[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( - (_keyword = _PyPegen_expect_token(p, 625)) // token='as' + (_keyword = _PyPegen_expect_token(p, 632)) // token='as' && (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_209[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_218[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_209[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_218[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; @@ -33490,9 +34292,9 @@ _tmp_209_rule(Parser *p) return _res; } -// _tmp_210: 'as' star_target +// _tmp_219: 'as' star_target static void * -_tmp_210_rule(Parser *p) +_tmp_219_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -33506,21 +34308,21 @@ _tmp_210_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_210[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_219[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( - (_keyword = _PyPegen_expect_token(p, 625)) // token='as' + (_keyword = _PyPegen_expect_token(p, 632)) // token='as' && (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_210[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_219[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_210[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_219[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; @@ -33529,9 +34331,9 @@ _tmp_210_rule(Parser *p) return _res; } -// _tmp_211: 'as' star_target +// _tmp_220: 'as' star_target static void * -_tmp_211_rule(Parser *p) +_tmp_220_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -33545,21 +34347,21 @@ _tmp_211_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_211[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_220[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( - (_keyword = _PyPegen_expect_token(p, 625)) // token='as' + (_keyword = _PyPegen_expect_token(p, 632)) // token='as' && (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_211[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_220[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_211[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_220[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; @@ -33568,6 +34370,148 @@ _tmp_211_rule(Parser *p) return _res; } +// _loop1_221: except_block +static asdl_seq * +_loop1_221_rule(Parser *p) +{ + D(p->level++); + if (p->error_indicator) { + D(p->level--); + return NULL; + } + void *_res = NULL; + int _mark = p->mark; + int _start_mark = p->mark; + void **_children = PyMem_Malloc(sizeof(void *)); + if (!_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + Py_ssize_t _children_capacity = 1; + Py_ssize_t _n = 0; + { // except_block + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> _loop1_221[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_block")); + excepthandler_ty except_block_var; + while ( + (except_block_var = except_block_rule(p)) // except_block + ) + { + _res = except_block_var; + if (_n == _children_capacity) { + _children_capacity *= 2; + void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); + if (!_new_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + _children = _new_children; + } + _children[_n++] = _res; + _mark = p->mark; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _loop1_221[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "except_block")); + } + if (_n == 0 || p->error_indicator) { + PyMem_Free(_children); + D(p->level--); + return NULL; + } + asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); + if (!_seq) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); + PyMem_Free(_children); + _PyPegen_insert_memo(p, _start_mark, _loop1_221_type, _seq); + D(p->level--); + return _seq; +} + +// _loop1_222: except_star_block +static asdl_seq * +_loop1_222_rule(Parser *p) +{ + D(p->level++); + if (p->error_indicator) { + D(p->level--); + return NULL; + } + void *_res = NULL; + int _mark = p->mark; + int _start_mark = p->mark; + void **_children = PyMem_Malloc(sizeof(void *)); + if (!_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + Py_ssize_t _children_capacity = 1; + Py_ssize_t _n = 0; + { // except_star_block + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> _loop1_222[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_star_block")); + excepthandler_ty except_star_block_var; + while ( + (except_star_block_var = except_star_block_rule(p)) // except_star_block + ) + { + _res = except_star_block_var; + if (_n == _children_capacity) { + _children_capacity *= 2; + void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); + if (!_new_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + _children = _new_children; + } + _children[_n++] = _res; + _mark = p->mark; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _loop1_222[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "except_star_block")); + } + if (_n == 0 || p->error_indicator) { + PyMem_Free(_children); + D(p->level--); + return NULL; + } + asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); + if (!_seq) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); + PyMem_Free(_children); + _PyPegen_insert_memo(p, _start_mark, _loop1_222_type, _seq); + D(p->level--); + return _seq; +} + void * _PyPegen_parse(Parser *p) { diff --git a/Python/Python-ast.c b/Python/Python-ast.c index ce6e6a93ea70f..167018482077d 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -146,6 +146,7 @@ void _PyAST_Fini(PyInterpreterState *interp) Py_CLEAR(state->Sub_singleton); Py_CLEAR(state->Sub_type); Py_CLEAR(state->Subscript_type); + Py_CLEAR(state->TryStar_type); Py_CLEAR(state->Try_type); Py_CLEAR(state->Tuple_type); Py_CLEAR(state->TypeIgnore_type); @@ -486,6 +487,12 @@ static const char * const Try_fields[]={ "orelse", "finalbody", }; +static const char * const TryStar_fields[]={ + "body", + "handlers", + "orelse", + "finalbody", +}; static const char * const Assert_fields[]={ "test", "msg", @@ -1139,6 +1146,7 @@ init_types(struct ast_state *state) " | Match(expr subject, match_case* cases)\n" " | Raise(expr? exc, expr? cause)\n" " | Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)\n" + " | TryStar(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)\n" " | Assert(expr test, expr? msg)\n" " | Import(alias* names)\n" " | ImportFrom(identifier? module, alias* names, int? level)\n" @@ -1254,6 +1262,10 @@ init_types(struct ast_state *state) state->Try_type = make_type(state, "Try", state->stmt_type, Try_fields, 4, "Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)"); if (!state->Try_type) return 0; + state->TryStar_type = make_type(state, "TryStar", state->stmt_type, + TryStar_fields, 4, + "TryStar(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)"); + if (!state->TryStar_type) return 0; state->Assert_type = make_type(state, "Assert", state->stmt_type, Assert_fields, 2, "Assert(expr test, expr? msg)"); @@ -2379,6 +2391,28 @@ _PyAST_Try(asdl_stmt_seq * body, asdl_excepthandler_seq * handlers, return p; } +stmt_ty +_PyAST_TryStar(asdl_stmt_seq * body, asdl_excepthandler_seq * handlers, + asdl_stmt_seq * orelse, asdl_stmt_seq * finalbody, int lineno, + int col_offset, int end_lineno, int end_col_offset, PyArena + *arena) +{ + stmt_ty p; + p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p)); + if (!p) + return NULL; + p->kind = TryStar_kind; + p->v.TryStar.body = body; + p->v.TryStar.handlers = handlers; + p->v.TryStar.orelse = orelse; + p->v.TryStar.finalbody = finalbody; + p->lineno = lineno; + p->col_offset = col_offset; + p->end_lineno = end_lineno; + p->end_col_offset = end_col_offset; + return p; +} + stmt_ty _PyAST_Assert(expr_ty test, expr_ty msg, int lineno, int col_offset, int end_lineno, int end_col_offset, PyArena *arena) @@ -4049,6 +4083,34 @@ ast2obj_stmt(struct ast_state *state, void* _o) goto failed; Py_DECREF(value); break; + case TryStar_kind: + tp = (PyTypeObject *)state->TryStar_type; + result = PyType_GenericNew(tp, NULL, NULL); + if (!result) goto failed; + value = ast2obj_list(state, (asdl_seq*)o->v.TryStar.body, ast2obj_stmt); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->body, value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_list(state, (asdl_seq*)o->v.TryStar.handlers, + ast2obj_excepthandler); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->handlers, value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_list(state, (asdl_seq*)o->v.TryStar.orelse, + ast2obj_stmt); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->orelse, value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_list(state, (asdl_seq*)o->v.TryStar.finalbody, + ast2obj_stmt); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->finalbody, value) == -1) + goto failed; + Py_DECREF(value); + break; case Assert_kind: tp = (PyTypeObject *)state->Assert_type; result = PyType_GenericNew(tp, NULL, NULL); @@ -7477,6 +7539,170 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (*out == NULL) goto failed; return 0; } + tp = state->TryStar_type; + isinstance = PyObject_IsInstance(obj, tp); + if (isinstance == -1) { + return 1; + } + if (isinstance) { + asdl_stmt_seq* body; + asdl_excepthandler_seq* handlers; + asdl_stmt_seq* orelse; + asdl_stmt_seq* finalbody; + + if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) { + return 1; + } + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from TryStar"); + return 1; + } + else { + int res; + Py_ssize_t len; + Py_ssize_t i; + if (!PyList_Check(tmp)) { + PyErr_Format(PyExc_TypeError, "TryStar field \"body\" must be a list, not a %.200s", _PyType_Name(Py_TYPE(tmp))); + goto failed; + } + len = PyList_GET_SIZE(tmp); + body = _Py_asdl_stmt_seq_new(len, arena); + if (body == NULL) goto failed; + for (i = 0; i < len; i++) { + stmt_ty val; + PyObject *tmp2 = PyList_GET_ITEM(tmp, i); + Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'TryStar' node")) { + goto failed; + } + res = obj2ast_stmt(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); + Py_DECREF(tmp2); + if (res != 0) goto failed; + if (len != PyList_GET_SIZE(tmp)) { + PyErr_SetString(PyExc_RuntimeError, "TryStar field \"body\" changed size during iteration"); + goto failed; + } + asdl_seq_SET(body, i, val); + } + Py_CLEAR(tmp); + } + if (_PyObject_LookupAttr(obj, state->handlers, &tmp) < 0) { + return 1; + } + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"handlers\" missing from TryStar"); + return 1; + } + else { + int res; + Py_ssize_t len; + Py_ssize_t i; + if (!PyList_Check(tmp)) { + PyErr_Format(PyExc_TypeError, "TryStar field \"handlers\" must be a list, not a %.200s", _PyType_Name(Py_TYPE(tmp))); + goto failed; + } + len = PyList_GET_SIZE(tmp); + handlers = _Py_asdl_excepthandler_seq_new(len, arena); + if (handlers == NULL) goto failed; + for (i = 0; i < len; i++) { + excepthandler_ty val; + PyObject *tmp2 = PyList_GET_ITEM(tmp, i); + Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'TryStar' node")) { + goto failed; + } + res = obj2ast_excepthandler(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); + Py_DECREF(tmp2); + if (res != 0) goto failed; + if (len != PyList_GET_SIZE(tmp)) { + PyErr_SetString(PyExc_RuntimeError, "TryStar field \"handlers\" changed size during iteration"); + goto failed; + } + asdl_seq_SET(handlers, i, val); + } + Py_CLEAR(tmp); + } + if (_PyObject_LookupAttr(obj, state->orelse, &tmp) < 0) { + return 1; + } + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"orelse\" missing from TryStar"); + return 1; + } + else { + int res; + Py_ssize_t len; + Py_ssize_t i; + if (!PyList_Check(tmp)) { + PyErr_Format(PyExc_TypeError, "TryStar field \"orelse\" must be a list, not a %.200s", _PyType_Name(Py_TYPE(tmp))); + goto failed; + } + len = PyList_GET_SIZE(tmp); + orelse = _Py_asdl_stmt_seq_new(len, arena); + if (orelse == NULL) goto failed; + for (i = 0; i < len; i++) { + stmt_ty val; + PyObject *tmp2 = PyList_GET_ITEM(tmp, i); + Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'TryStar' node")) { + goto failed; + } + res = obj2ast_stmt(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); + Py_DECREF(tmp2); + if (res != 0) goto failed; + if (len != PyList_GET_SIZE(tmp)) { + PyErr_SetString(PyExc_RuntimeError, "TryStar field \"orelse\" changed size during iteration"); + goto failed; + } + asdl_seq_SET(orelse, i, val); + } + Py_CLEAR(tmp); + } + if (_PyObject_LookupAttr(obj, state->finalbody, &tmp) < 0) { + return 1; + } + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"finalbody\" missing from TryStar"); + return 1; + } + else { + int res; + Py_ssize_t len; + Py_ssize_t i; + if (!PyList_Check(tmp)) { + PyErr_Format(PyExc_TypeError, "TryStar field \"finalbody\" must be a list, not a %.200s", _PyType_Name(Py_TYPE(tmp))); + goto failed; + } + len = PyList_GET_SIZE(tmp); + finalbody = _Py_asdl_stmt_seq_new(len, arena); + if (finalbody == NULL) goto failed; + for (i = 0; i < len; i++) { + stmt_ty val; + PyObject *tmp2 = PyList_GET_ITEM(tmp, i); + Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'TryStar' node")) { + goto failed; + } + res = obj2ast_stmt(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); + Py_DECREF(tmp2); + if (res != 0) goto failed; + if (len != PyList_GET_SIZE(tmp)) { + PyErr_SetString(PyExc_RuntimeError, "TryStar field \"finalbody\" changed size during iteration"); + goto failed; + } + asdl_seq_SET(finalbody, i, val); + } + Py_CLEAR(tmp); + } + *out = _PyAST_TryStar(body, handlers, orelse, finalbody, lineno, + col_offset, end_lineno, end_col_offset, arena); + if (*out == NULL) goto failed; + return 0; + } tp = state->Assert_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { @@ -11687,6 +11913,9 @@ astmodule_exec(PyObject *m) if (PyModule_AddObjectRef(m, "Try", state->Try_type) < 0) { return -1; } + if (PyModule_AddObjectRef(m, "TryStar", state->TryStar_type) < 0) { + return -1; + } if (PyModule_AddObjectRef(m, "Assert", state->Assert_type) < 0) { return -1; } diff --git a/Python/ast.c b/Python/ast.c index 0c3121d3ee7b6..607281e268553 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -817,6 +817,31 @@ validate_stmt(struct validator *state, stmt_ty stmt) (!asdl_seq_LEN(stmt->v.Try.orelse) || validate_stmts(state, stmt->v.Try.orelse)); break; + case TryStar_kind: + if (!validate_body(state, stmt->v.TryStar.body, "TryStar")) + return 0; + if (!asdl_seq_LEN(stmt->v.TryStar.handlers) && + !asdl_seq_LEN(stmt->v.TryStar.finalbody)) { + PyErr_SetString(PyExc_ValueError, "TryStar has neither except handlers nor finalbody"); + return 0; + } + if (!asdl_seq_LEN(stmt->v.TryStar.handlers) && + asdl_seq_LEN(stmt->v.TryStar.orelse)) { + PyErr_SetString(PyExc_ValueError, "TryStar has orelse but no except handlers"); + return 0; + } + for (i = 0; i < asdl_seq_LEN(stmt->v.TryStar.handlers); i++) { + excepthandler_ty handler = asdl_seq_GET(stmt->v.TryStar.handlers, i); + if ((handler->v.ExceptHandler.type && + !validate_expr(state, handler->v.ExceptHandler.type, Load)) || + !validate_body(state, handler->v.ExceptHandler.body, "ExceptHandler")) + return 0; + } + ret = (!asdl_seq_LEN(stmt->v.TryStar.finalbody) || + validate_stmts(state, stmt->v.TryStar.finalbody)) && + (!asdl_seq_LEN(stmt->v.TryStar.orelse) || + validate_stmts(state, stmt->v.TryStar.orelse)); + break; case Assert_kind: ret = validate_expr(state, stmt->v.Assert.test, Load) && (!stmt->v.Assert.msg || validate_expr(state, stmt->v.Assert.msg, Load)); diff --git a/Python/ast_opt.c b/Python/ast_opt.c index 5f219c6f4bbf7..2821e69a35521 100644 --- a/Python/ast_opt.c +++ b/Python/ast_opt.c @@ -972,6 +972,12 @@ astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) CALL_SEQ(astfold_stmt, stmt, node_->v.Try.orelse); CALL_SEQ(astfold_stmt, stmt, node_->v.Try.finalbody); break; + case TryStar_kind: + CALL_SEQ(astfold_stmt, stmt, node_->v.TryStar.body); + CALL_SEQ(astfold_excepthandler, excepthandler, node_->v.TryStar.handlers); + CALL_SEQ(astfold_stmt, stmt, node_->v.TryStar.orelse); + CALL_SEQ(astfold_stmt, stmt, node_->v.TryStar.finalbody); + break; case Assert_kind: CALL(astfold_expr, expr_ty, node_->v.Assert.test); CALL_OPT(astfold_expr, expr_ty, node_->v.Assert.msg); diff --git a/Python/ceval.c b/Python/ceval.c index 4f5ccf51e9cfe..fb19f78ba14d4 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -37,6 +37,7 @@ #include "structmember.h" // struct PyMemberDef, T_OFFSET_EX #include +#include #ifdef Py_DEBUG /* For debugging the interpreter: */ @@ -95,6 +96,7 @@ static void format_exc_check_arg(PyThreadState *, PyObject *, const char *, PyOb static void format_exc_unbound(PyThreadState *tstate, PyCodeObject *co, int oparg); static int check_args_iterable(PyThreadState *, PyObject *func, PyObject *vararg); static int check_except_type_valid(PyThreadState *tstate, PyObject* right); +static int check_except_star_type_valid(PyThreadState *tstate, PyObject* right); static void format_kwargs_error(PyThreadState *, PyObject *func, PyObject *kwargs); static void format_awaitable_error(PyThreadState *, PyTypeObject *, int, int); static int get_exception_handler(PyCodeObject *, int, int*, int*, int*); @@ -1090,6 +1092,11 @@ match_class(PyThreadState *tstate, PyObject *subject, PyObject *type, static int do_raise(PyThreadState *tstate, PyObject *exc, PyObject *cause); +static PyObject *do_reraise_star(PyObject *excs, PyObject *orig); +static int exception_group_match( + PyObject *exc_type, PyObject* exc_value, PyObject *match_type, + PyObject **match, PyObject **rest); + static int unpack_iterable(PyThreadState *, PyObject *, int, int, PyObject **); #ifdef Py_DEBUG @@ -2727,6 +2734,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr type = exc_info->exc_type; value = exc_info->exc_value; traceback = exc_info->exc_traceback; + exc_info->exc_type = POP(); exc_info->exc_value = POP(); exc_info->exc_traceback = POP(); @@ -2791,6 +2799,36 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr goto exception_unwind; } + TARGET(PREP_RERAISE_STAR) { + PyObject *excs = POP(); + assert(PyList_Check(excs)); + PyObject *orig = POP(); + + PyObject *val = do_reraise_star(excs, orig); + Py_DECREF(excs); + Py_DECREF(orig); + + if (val == NULL) { + goto error; + } + + PyObject *lasti_unused = Py_NewRef(_PyLong_GetZero()); + PUSH(lasti_unused); + if (!Py_IsNone(val)) { + PyObject *tb = PyException_GetTraceback(val); + PUSH(tb ? tb : Py_NewRef(Py_None)); + PUSH(val); + PUSH(Py_NewRef(Py_TYPE(val))); + } + else { + // nothing to reraise + PUSH(Py_NewRef(Py_None)); + PUSH(val); + PUSH(Py_NewRef(Py_None)); + } + DISPATCH(); + } + TARGET(END_ASYNC_FOR) { PyObject *exc = POP(); PyObject *val = POP(); @@ -3922,6 +3960,83 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr DISPATCH(); } + TARGET(JUMP_IF_NOT_EG_MATCH) { + PyObject *match_type = POP(); + PyObject *exc_type = TOP(); + PyObject *exc_value = SECOND(); + if (check_except_star_type_valid(tstate, match_type) < 0) { + Py_DECREF(match_type); + goto error; + } + + PyObject *match = NULL, *rest = NULL; + int res = exception_group_match(exc_type, exc_value, + match_type, &match, &rest); + Py_DECREF(match_type); + if (res < 0) { + goto error; + } + + if (match == NULL || rest == NULL) { + assert(match == NULL); + assert(rest == NULL); + goto error; + } + + if (Py_IsNone(match)) { + Py_DECREF(match); + Py_XDECREF(rest); + /* no match - jump to target */ + JUMPTO(oparg); + } + else { + + /* Total or partial match - update the stack from + * [tb, val, exc] + * to + * [tb, rest, exc, tb, match, exc] + * (rest can be Py_None) + */ + + + PyObject *type = TOP(); + PyObject *val = SECOND(); + PyObject *tb = THIRD(); + + if (!Py_IsNone(rest)) { + /* tb remains the same */ + SET_TOP(Py_NewRef(Py_TYPE(rest))); + SET_SECOND(Py_NewRef(rest)); + SET_THIRD(Py_NewRef(tb)); + } + else { + SET_TOP(Py_NewRef(Py_None)); + SET_SECOND(Py_NewRef(Py_None)); + SET_THIRD(Py_NewRef(Py_None)); + } + /* Push match */ + + PUSH(Py_NewRef(tb)); + PUSH(Py_NewRef(match)); + PUSH(Py_NewRef(Py_TYPE(match))); + + // set exc_info to the current match + PyErr_SetExcInfo( + Py_NewRef(Py_TYPE(match)), + Py_NewRef(match), + Py_NewRef(tb)); + + Py_DECREF(tb); + Py_DECREF(val); + Py_DECREF(type); + + Py_DECREF(match); + Py_DECREF(rest); + } + + DISPATCH(); + } + TARGET(JUMP_IF_NOT_EXC_MATCH) { PyObject *right = POP(); ASSERT_EXC_TYPE_IS_REDUNDANT(TOP(), SECOND()); @@ -3931,17 +4046,12 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr Py_DECREF(right); goto error; } + int res = PyErr_GivenExceptionMatches(left, right); Py_DECREF(right); - if (res > 0) { - /* Exception matches -- Do nothing */; - } - else if (res == 0) { + if (res == 0) { JUMPTO(oparg); } - else { - goto error; - } DISPATCH(); } @@ -6127,6 +6237,196 @@ do_raise(PyThreadState *tstate, PyObject *exc, PyObject *cause) return 0; } +/* Logic for matching an exception in an except* clause (too + complicated for inlining). +*/ + +static int +exception_group_match(PyObject *exc_type, PyObject* exc_value, + PyObject *match_type, PyObject **match, PyObject **rest) +{ + if (Py_IsNone(exc_type)) { + assert(Py_IsNone(exc_value)); + *match = Py_NewRef(Py_None); + *rest = Py_NewRef(Py_None); + return 0; + } + assert(PyExceptionClass_Check(exc_type)); + assert(PyExceptionInstance_Check(exc_value)); + + if (PyErr_GivenExceptionMatches(exc_type, match_type)) { + /* Full match of exc itself */ + bool is_eg = _PyBaseExceptionGroup_Check(exc_value); + if (is_eg) { + *match = Py_NewRef(exc_value); + } + else { + /* naked exception - wrap it */ + PyObject *excs = PyTuple_Pack(1, exc_value); + if (excs == NULL) { + return -1; + } + PyObject *wrapped = _PyExc_CreateExceptionGroup("", excs); + Py_DECREF(excs); + if (wrapped == NULL) { + return -1; + } + *match = wrapped; + } + *rest = Py_NewRef(Py_None); + return 0; + } + + /* exc_value does not match match_type. + * Check for partial match if it's an exception group. + */ + if (_PyBaseExceptionGroup_Check(exc_value)) { + PyObject *pair = PyObject_CallMethod(exc_value, "split", "(O)", + match_type); + if (pair == NULL) { + return -1; + } + assert(PyTuple_CheckExact(pair)); + assert(PyTuple_GET_SIZE(pair) == 2); + *match = Py_NewRef(PyTuple_GET_ITEM(pair, 0)); + *rest = Py_NewRef(PyTuple_GET_ITEM(pair, 1)); + Py_DECREF(pair); + return 0; + } + /* no match */ + *match = Py_NewRef(Py_None); + *rest = Py_NewRef(Py_None); + return 0; +} + +/* Logic for the final raise/reraise of a try-except* contruct + (too complicated for inlining). +*/ + +static bool +is_same_exception_metadata(PyObject *exc1, PyObject *exc2) +{ + assert(PyExceptionInstance_Check(exc1)); + assert(PyExceptionInstance_Check(exc2)); + + PyObject *tb1 = PyException_GetTraceback(exc1); + PyObject *ctx1 = PyException_GetContext(exc1); + PyObject *cause1 = PyException_GetCause(exc1); + PyObject *tb2 = PyException_GetTraceback(exc2); + PyObject *ctx2 = PyException_GetContext(exc2); + PyObject *cause2 = PyException_GetCause(exc2); + + bool result = (Py_Is(tb1, tb2) && + Py_Is(ctx1, ctx2) && + Py_Is(cause1, cause2)); + + Py_XDECREF(tb1); + Py_XDECREF(ctx1); + Py_XDECREF(cause1); + Py_XDECREF(tb2); + Py_XDECREF(ctx2); + Py_XDECREF(cause2); + return result; +} + +/* + excs: a list of exceptions to raise/reraise + orig: the original except that was caught + + Calculates an exception group to raise. It contains + all exceptions in excs, where those that were reraised + have same nesting structure as in orig, and those that + were raised (if any) are added as siblings in a new EG. + + Returns NULL and sets an exception on failure. +*/ +static PyObject * +do_reraise_star(PyObject *excs, PyObject *orig) +{ + assert(PyList_Check(excs)); + assert(PyExceptionInstance_Check(orig)); + + Py_ssize_t numexcs = PyList_GET_SIZE(excs); + + if (numexcs == 0) { + return Py_NewRef(Py_None); + } + + if (!_PyBaseExceptionGroup_Check(orig)) { + /* a naked exception was caught and wrapped. Only one except* clause + * could have executed,so there is at most one exception to raise. + */ + + assert(numexcs == 1 || (numexcs == 2 && PyList_GET_ITEM(excs, 1) == Py_None)); + + PyObject *e = PyList_GET_ITEM(excs, 0); + assert(e != NULL); + return Py_NewRef(e); + } + + + PyObject *raised_list = PyList_New(0); + if (raised_list == NULL) { + return NULL; + } + PyObject* reraised_list = PyList_New(0); + if (reraised_list == NULL) { + Py_DECREF(raised_list); + return NULL; + } + + /* Now we are holding refs to raised_list and reraised_list */ + + PyObject *result = NULL; + + /* Split excs into raised and reraised by comparing metadata with orig */ + for (Py_ssize_t i = 0; i < numexcs; i++) { + PyObject *e = PyList_GET_ITEM(excs, i); + assert(e != NULL); + if (Py_IsNone(e)) { + continue; + } + bool is_reraise = is_same_exception_metadata(e, orig); + PyObject *append_list = is_reraise ? reraised_list : raised_list; + if (PyList_Append(append_list, e) < 0) { + goto done; + } + } + + PyObject *reraised_eg = _PyExc_ExceptionGroupProjection(orig, reraised_list); + if (reraised_eg == NULL) { + goto done; + } + + if (!Py_IsNone(reraised_eg)) { + assert(is_same_exception_metadata(reraised_eg, orig)); + } + + Py_ssize_t num_raised = PyList_GET_SIZE(raised_list); + if (num_raised == 0) { + result = reraised_eg; + } + else if (num_raised > 0) { + int res = 0; + if (!Py_IsNone(reraised_eg)) { + res = PyList_Append(raised_list, reraised_eg); + } + Py_DECREF(reraised_eg); + if (res < 0) { + goto done; + } + result = _PyExc_CreateExceptionGroup("", raised_list); + if (result == NULL) { + goto done; + } + } + +done: + Py_XDECREF(raised_list); + Py_XDECREF(reraised_list); + return result; +} + /* Iterate v argcnt times and store the results on the stack (via decreasing sp). Return 1 for success, 0 if error. @@ -7020,10 +7320,12 @@ import_all_from(PyThreadState *tstate, PyObject *locals, PyObject *v) return err; } - #define CANNOT_CATCH_MSG "catching classes that do not inherit from "\ "BaseException is not allowed" +#define CANNOT_EXCEPT_STAR_EG "catching ExceptionGroup with except* "\ + "is not allowed. Use except instead." + static int check_except_type_valid(PyThreadState *tstate, PyObject* right) { @@ -7049,6 +7351,43 @@ check_except_type_valid(PyThreadState *tstate, PyObject* right) return 0; } +static int +check_except_star_type_valid(PyThreadState *tstate, PyObject* right) +{ + if (check_except_type_valid(tstate, right) < 0) { + return -1; + } + + /* reject except *ExceptionGroup */ + + int is_subclass = 0; + if (PyTuple_Check(right)) { + Py_ssize_t length = PyTuple_GET_SIZE(right); + for (Py_ssize_t i = 0; i < length; i++) { + PyObject *exc = PyTuple_GET_ITEM(right, i); + is_subclass = PyObject_IsSubclass(exc, PyExc_BaseExceptionGroup); + if (is_subclass < 0) { + return -1; + } + if (is_subclass) { + break; + } + } + } + else { + is_subclass = PyObject_IsSubclass(right, PyExc_BaseExceptionGroup); + if (is_subclass < 0) { + return -1; + } + } + if (is_subclass) { + _PyErr_SetString(tstate, PyExc_TypeError, + CANNOT_EXCEPT_STAR_EG); + return -1; + } + return 0; +} + static int check_args_iterable(PyThreadState *tstate, PyObject *func, PyObject *args) { diff --git a/Python/compile.c b/Python/compile.c index bbdb0115be3be..00e1e016969ad 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -175,7 +175,7 @@ compiler IR. enum fblocktype { WHILE_LOOP, FOR_LOOP, TRY_EXCEPT, FINALLY_TRY, FINALLY_END, WITH, ASYNC_WITH, HANDLER_CLEANUP, POP_VALUE, EXCEPTION_HANDLER, - ASYNC_COMPREHENSION_GENERATOR }; + EXCEPTION_GROUP_HANDLER, ASYNC_COMPREHENSION_GENERATOR }; struct fblockinfo { enum fblocktype fb_type; @@ -323,6 +323,7 @@ static int compiler_call_helper(struct compiler *c, int n, asdl_expr_seq *args, asdl_keyword_seq *keywords); static int compiler_try_except(struct compiler *, stmt_ty); +static int compiler_try_star_except(struct compiler *, stmt_ty); static int compiler_set_qualname(struct compiler *); static int compiler_sync_comprehension_generator( @@ -1094,6 +1095,8 @@ stack_effect(int opcode, int oparg, int jump) return -1; case JUMP_IF_NOT_EXC_MATCH: return -1; + case JUMP_IF_NOT_EG_MATCH: + return jump > 0 ? -1 : 2; case IMPORT_NAME: return -1; case IMPORT_FROM: @@ -1131,6 +1134,8 @@ stack_effect(int opcode, int oparg, int jump) * if an exception be raised. */ return jump ? -1 + 4 : 0; + case PREP_RERAISE_STAR: + return 2; case RERAISE: return -3; case PUSH_EXC_INFO: @@ -1755,6 +1760,18 @@ find_ann(asdl_stmt_seq *stmts) find_ann(st->v.Try.finalbody) || find_ann(st->v.Try.orelse); break; + case TryStar_kind: + for (j = 0; j < asdl_seq_LEN(st->v.TryStar.handlers); j++) { + excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET( + st->v.TryStar.handlers, j); + if (find_ann(handler->v.ExceptHandler.body)) { + return 1; + } + } + res = find_ann(st->v.TryStar.body) || + find_ann(st->v.TryStar.finalbody) || + find_ann(st->v.TryStar.orelse); + break; default: res = 0; } @@ -1816,6 +1833,7 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info, switch (info->fb_type) { case WHILE_LOOP: case EXCEPTION_HANDLER: + case EXCEPTION_GROUP_HANDLER: case ASYNC_COMPREHENSION_GENERATOR: return 1; @@ -1919,6 +1937,10 @@ compiler_unwind_fblock_stack(struct compiler *c, int preserve_tos, struct fblock return 1; } struct fblockinfo *top = &c->u->u_fblock[c->u->u_nfblocks-1]; + if (top->fb_type == EXCEPTION_GROUP_HANDLER) { + return compiler_error( + c, "'break', 'continue' and 'return' cannot appear in an except* block"); + } if (loop != NULL && (top->fb_type == WHILE_LOOP || top->fb_type == FOR_LOOP)) { *loop = top; return 1; @@ -3202,6 +3224,62 @@ compiler_try_finally(struct compiler *c, stmt_ty s) return 1; } +static int +compiler_try_star_finally(struct compiler *c, stmt_ty s) +{ + basicblock *body = compiler_new_block(c); + if (body == NULL) { + return 0; + } + basicblock *end = compiler_new_block(c); + if (!end) { + return 0; + } + basicblock *exit = compiler_new_block(c); + if (!exit) { + return 0; + } + basicblock *cleanup = compiler_new_block(c); + if (!cleanup) { + return 0; + } + /* `try` block */ + ADDOP_JUMP(c, SETUP_FINALLY, end); + compiler_use_next_block(c, body); + if (!compiler_push_fblock(c, FINALLY_TRY, body, end, s->v.TryStar.finalbody)) { + return 0; + } + if (s->v.TryStar.handlers && asdl_seq_LEN(s->v.TryStar.handlers)) { + if (!compiler_try_star_except(c, s)) { + return 0; + } + } + else { + VISIT_SEQ(c, stmt, s->v.TryStar.body); + } + ADDOP_NOLINE(c, POP_BLOCK); + compiler_pop_fblock(c, FINALLY_TRY, body); + VISIT_SEQ(c, stmt, s->v.TryStar.finalbody); + ADDOP_JUMP_NOLINE(c, JUMP_FORWARD, exit); + /* `finally` block */ + compiler_use_next_block(c, end); + + UNSET_LOC(c); + ADDOP_JUMP(c, SETUP_CLEANUP, cleanup); + ADDOP(c, PUSH_EXC_INFO); + if (!compiler_push_fblock(c, FINALLY_END, end, NULL, NULL)) { + return 0; + } + VISIT_SEQ(c, stmt, s->v.TryStar.finalbody); + compiler_pop_fblock(c, FINALLY_END, end); + ADDOP_I(c, RERAISE, 0); + compiler_use_next_block(c, cleanup); + ADDOP(c, POP_EXCEPT_AND_RERAISE); + compiler_use_next_block(c, exit); + return 1; +} + + /* Code generated for "try: S except E1 as V1: S1 except E2 as V2: S2 ...": (The contents of the value stack is shown in [], with the top @@ -3360,6 +3438,253 @@ compiler_try_except(struct compiler *c, stmt_ty s) ADDOP(c, POP_EXCEPT_AND_RERAISE); compiler_use_next_block(c, orelse); VISIT_SEQ(c, stmt, s->v.Try.orelse); + ADDOP_JUMP(c, JUMP_FORWARD, end); + compiler_use_next_block(c, end); + return 1; +} + +/* + Code generated for "try: S except* E1 as V1: S1 except* E2 as V2: S2 ...": + (The contents of the value stack is shown in [], with the top + at the right; 'tb' is trace-back info, 'val' the exception instance, + and 'typ' the exception's type.) + + Value stack Label Instruction Argument + [] SETUP_FINALLY L1 + [] + [] POP_BLOCK + [] JUMP_FORWARD L0 + + [tb, val, typ] L1: DUP_TOP_TWO ) save a copy of the + [tb, val, typ, orig, typ] POP_TOP ) original raised exception + [tb, val, typ, orig] ROT_FOUR ) + [orig, tb, val, typ] BUILD_LIST ) list for raised/reraised + [orig, tb, val, typ, res] ROT_FOUR ) exceptions ("result") + + [orig, res, tb, val, typ] ) + [orig, res, tb, val, typ, E1] JUMP_IF_NOT_EXC_MATCH L2 ) only if E1 + + [orig, res, tb, rest, typ, tb, match, typ] POP + [orig, res, tb, rest, typ, tb, match] (or POP if no V1) + [orig, res, tb, rest, typ, tb] POP + + [orig, res, tb, rest, typ] SETUP_FINALLY R1 + [orig, res, tb, rest, typ] + [orig, res, tb, rest, typ] JUMP_FORWARD L2 + + [orig, res, tb, rest, typ, i, tb, v, t] R1: POP ) exception raised in except* body + [orig, res, tb, rest, typ, i, tb, v] LIST_APPEND 6 ) add it to res + [orig, res, tb, rest, typ, i, tb] POP + [orig, res, tb, rest, typ, i] POP + + [orig, res, tb, rest, typ] L2: + .............................etc....................... + + [orig, res, tb, rest, typ] Ln+1: POP ) add unhandled exception + [orig, res, tb, rest] LIST_APPEND 2 ) to res (could be None) + [orig, res, tb] POP + + [orig, res] PREP_RERAISE_STAR + [i, tb, val, typ] POP_JUMP_IF_TRUE RER + [i, tb, val, typ] POP + [i, tb, val] POP + [i, tb] POP + [i] POP + [] JUMP_FORWARD L0 + + [i, tb, val, typ] RER: POP_EXCEPT_AND_RERAISE + + [] L0: +*/ +static int +compiler_try_star_except(struct compiler *c, stmt_ty s) +{ + basicblock *body = compiler_new_block(c); + if (body == NULL) { + return 0; + } + basicblock *except = compiler_new_block(c); + if (except == NULL) { + return 0; + } + basicblock *orelse = compiler_new_block(c); + if (orelse == NULL) { + return 0; + } + basicblock *end = compiler_new_block(c); + if (end == NULL) { + return 0; + } + basicblock *cleanup = compiler_new_block(c); + if (cleanup == NULL) { + return 0; + } + basicblock *reraise_star = compiler_new_block(c); + if (reraise_star == NULL) { + return 0; + } + + ADDOP_JUMP(c, SETUP_FINALLY, except); + compiler_use_next_block(c, body); + if (!compiler_push_fblock(c, TRY_EXCEPT, body, NULL, NULL)) { + return 0; + } + VISIT_SEQ(c, stmt, s->v.TryStar.body); + compiler_pop_fblock(c, TRY_EXCEPT, body); + ADDOP_NOLINE(c, POP_BLOCK); + ADDOP_JUMP_NOLINE(c, JUMP_FORWARD, orelse); + Py_ssize_t n = asdl_seq_LEN(s->v.TryStar.handlers); + compiler_use_next_block(c, except); + + UNSET_LOC(c); + ADDOP_JUMP(c, SETUP_CLEANUP, cleanup); + ADDOP(c, PUSH_EXC_INFO); + /* Runtime will push a block here, so we need to account for that */ + if (!compiler_push_fblock(c, EXCEPTION_GROUP_HANDLER, + NULL, NULL, "except handler")) { + return 0; + } + for (Py_ssize_t i = 0; i < n; i++) { + excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET( + s->v.TryStar.handlers, i); + SET_LOC(c, handler); + except = compiler_new_block(c); + if (except == NULL) { + return 0; + } + if (i == 0) { + /* Push the original EG into the stack */ + /* + [tb, val, exc] DUP_TOP_TWO + [tb, val, exc, val, exc] POP_TOP + [tb, val, exc, val] ROT_FOUR + [val, tb, val, exc] + */ + ADDOP(c, DUP_TOP_TWO); + ADDOP(c, POP_TOP); + ADDOP(c, ROT_FOUR); + + /* create empty list for exceptions raised/reraise in the except* blocks */ + /* + [val, tb, val, exc] BUILD_LIST + [val, tb, val, exc, []] ROT_FOUR + [val, [], tb, val, exc] + */ + ADDOP_I(c, BUILD_LIST, 0); + ADDOP(c, ROT_FOUR); + } + if (handler->v.ExceptHandler.type) { + VISIT(c, expr, handler->v.ExceptHandler.type); + ADDOP_JUMP(c, JUMP_IF_NOT_EG_MATCH, except); + NEXT_BLOCK(c); + } + ADDOP(c, POP_TOP); // exc_type + + basicblock *cleanup_end = compiler_new_block(c); + if (cleanup_end == NULL) { + return 0; + } + basicblock *cleanup_body = compiler_new_block(c); + if (cleanup_body == NULL) { + return 0; + } + + if (handler->v.ExceptHandler.name) { + compiler_nameop(c, handler->v.ExceptHandler.name, Store); + } + else { + ADDOP(c, POP_TOP); // val + } + ADDOP(c, POP_TOP); // tb + + /* + try: + # body + except type as name: + try: + # body + finally: + name = None # in case body contains "del name" + del name + */ + /* second try: */ + ADDOP_JUMP(c, SETUP_CLEANUP, cleanup_end); + compiler_use_next_block(c, cleanup_body); + if (!compiler_push_fblock(c, HANDLER_CLEANUP, cleanup_body, NULL, handler->v.ExceptHandler.name)) + return 0; + + /* second # body */ + VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body); + compiler_pop_fblock(c, HANDLER_CLEANUP, cleanup_body); + /* name = None; del name; # Mark as artificial */ + UNSET_LOC(c); + ADDOP(c, POP_BLOCK); + if (handler->v.ExceptHandler.name) { + ADDOP_LOAD_CONST(c, Py_None); + compiler_nameop(c, handler->v.ExceptHandler.name, Store); + compiler_nameop(c, handler->v.ExceptHandler.name, Del); + } + ADDOP_JUMP(c, JUMP_FORWARD, except); + + /* except: */ + compiler_use_next_block(c, cleanup_end); + + /* name = None; del name; # Mark as artificial */ + UNSET_LOC(c); + + if (handler->v.ExceptHandler.name) { + ADDOP_LOAD_CONST(c, Py_None); + compiler_nameop(c, handler->v.ExceptHandler.name, Store); + compiler_nameop(c, handler->v.ExceptHandler.name, Del); + } + + /* add exception raised to the res list */ + ADDOP(c, POP_TOP); // type + ADDOP_I(c, LIST_APPEND, 6); // exc + ADDOP(c, POP_TOP); // tb + ADDOP(c, POP_TOP); // lasti + + ADDOP_JUMP(c, JUMP_ABSOLUTE, except); + compiler_use_next_block(c, except); + + if (i == n - 1) { + /* Add exc to the list (if not None it's the unhandled part of the EG) */ + ADDOP(c, POP_TOP); + ADDOP_I(c, LIST_APPEND, 2); + ADDOP(c, POP_TOP); + ADDOP_JUMP(c, JUMP_FORWARD, reraise_star); + } + } + /* Mark as artificial */ + UNSET_LOC(c); + compiler_pop_fblock(c, EXCEPTION_GROUP_HANDLER, NULL); + basicblock *reraise = compiler_new_block(c); + if (!reraise) { + return 0; + } + + compiler_use_next_block(c, reraise_star); + ADDOP(c, PREP_RERAISE_STAR); + ADDOP(c, DUP_TOP); + ADDOP_JUMP(c, POP_JUMP_IF_TRUE, reraise); + NEXT_BLOCK(c); + + /* Nothing to reraise - pop it */ + ADDOP(c, POP_TOP); + ADDOP(c, POP_TOP); + ADDOP(c, POP_TOP); + ADDOP(c, POP_TOP); + ADDOP(c, POP_BLOCK); + ADDOP(c, POP_EXCEPT); + ADDOP_JUMP(c, JUMP_FORWARD, end); + compiler_use_next_block(c, reraise); + ADDOP(c, POP_BLOCK); + ADDOP(c, POP_EXCEPT_AND_RERAISE); + compiler_use_next_block(c, cleanup); + ADDOP(c, POP_EXCEPT_AND_RERAISE); + compiler_use_next_block(c, orelse); + VISIT_SEQ(c, stmt, s->v.TryStar.orelse); + ADDOP_JUMP(c, JUMP_FORWARD, end); compiler_use_next_block(c, end); return 1; } @@ -3372,6 +3697,16 @@ compiler_try(struct compiler *c, stmt_ty s) { return compiler_try_except(c, s); } +static int +compiler_try_star(struct compiler *c, stmt_ty s) +{ + if (s->v.TryStar.finalbody && asdl_seq_LEN(s->v.TryStar.finalbody)) { + return compiler_try_star_finally(c, s); + } + else { + return compiler_try_star_except(c, s); + } +} static int compiler_import_as(struct compiler *c, identifier name, identifier asname) @@ -3634,6 +3969,8 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s) break; case Try_kind: return compiler_try(c, s); + case TryStar_kind: + return compiler_try_star(c, s); case Assert_kind: return compiler_assert(c, s); case Import_kind: diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 872a688311992..aeb9830cccc15 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -87,7 +87,7 @@ static void *opcode_targets[256] = { &&TARGET_SETUP_ANNOTATIONS, &&TARGET_YIELD_VALUE, &&TARGET_LOAD_CONST__LOAD_FAST, - &&TARGET_STORE_FAST__STORE_FAST, + &&TARGET_PREP_RERAISE_STAR, &&TARGET_POP_EXCEPT, &&TARGET_STORE_NAME, &&TARGET_DELETE_NAME, @@ -122,11 +122,11 @@ static void *opcode_targets[256] = { &&TARGET_COPY, &&TARGET_JUMP_IF_NOT_EXC_MATCH, &&TARGET_BINARY_OP, - &&_unknown_opcode, + &&TARGET_STORE_FAST__STORE_FAST, &&TARGET_LOAD_FAST, &&TARGET_STORE_FAST, &&TARGET_DELETE_FAST, - &&_unknown_opcode, + &&TARGET_JUMP_IF_NOT_EG_MATCH, &&_unknown_opcode, &&TARGET_GEN_START, &&TARGET_RAISE_VARARGS, diff --git a/Python/symtable.c b/Python/symtable.c index 7a1f0609d3542..01c6ec1318d63 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1345,6 +1345,12 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) VISIT_SEQ(st, excepthandler, s->v.Try.handlers); VISIT_SEQ(st, stmt, s->v.Try.finalbody); break; + case TryStar_kind: + VISIT_SEQ(st, stmt, s->v.TryStar.body); + VISIT_SEQ(st, stmt, s->v.TryStar.orelse); + VISIT_SEQ(st, excepthandler, s->v.TryStar.handlers); + VISIT_SEQ(st, stmt, s->v.TryStar.finalbody); + break; case Assert_kind: VISIT(st, expr, s->v.Assert.test); if (s->v.Assert.msg) From webhook-mailer at python.org Tue Dec 14 12:27:10 2021 From: webhook-mailer at python.org (vsajip) Date: Tue, 14 Dec 2021 17:27:10 -0000 Subject: [Python-checkins] [3.10] bpo-46063: Add 'delay=True' to file handler initialization. (GH-30103) (GH-30104) Message-ID: https://github.com/python/cpython/commit/908fd691f96403a3c30d85c17dd74ed1f26a60fd commit: 908fd691f96403a3c30d85c17dd74ed1f26a60fd branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: vsajip date: 2021-12-14T17:27:00Z summary: [3.10] bpo-46063: Add 'delay=True' to file handler initialization. (GH-30103) (GH-30104) files: M Lib/test/test_logging.py diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index b74f20156ffd8..40411b4488483 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -5425,7 +5425,8 @@ def test_compute_files_to_delete(self): p = os.path.join(wd, '%s.log' % prefix) rotator = logging.handlers.TimedRotatingFileHandler(p, when='s', interval=5, - backupCount=7) + backupCount=7, + delay=True) rotators.append(rotator) if prefix.startswith('a.b'): for t in times: From webhook-mailer at python.org Tue Dec 14 12:27:27 2021 From: webhook-mailer at python.org (vsajip) Date: Tue, 14 Dec 2021 17:27:27 -0000 Subject: [Python-checkins] [3.9] bpo-46063: Add 'delay=True' to file handler initialization. (GH-30103) (GH-30105) Message-ID: https://github.com/python/cpython/commit/17260e44b5ed3508e3c15f1b7ded761879e91d3e commit: 17260e44b5ed3508e3c15f1b7ded761879e91d3e branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: vsajip date: 2021-12-14T17:27:22Z summary: [3.9] bpo-46063: Add 'delay=True' to file handler initialization. (GH-30103) (GH-30105) files: M Lib/test/test_logging.py diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 858adc72b46a3..363ea29d3af2f 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -5301,7 +5301,8 @@ def test_compute_files_to_delete(self): p = os.path.join(wd, '%s.log' % prefix) rotator = logging.handlers.TimedRotatingFileHandler(p, when='s', interval=5, - backupCount=7) + backupCount=7, + delay=True) rotators.append(rotator) if prefix.startswith('a.b'): for t in times: From webhook-mailer at python.org Tue Dec 14 13:22:53 2021 From: webhook-mailer at python.org (markshannon) Date: Tue, 14 Dec 2021 18:22:53 -0000 Subject: [Python-checkins] bpo-44525: Split calls into PRECALL and CALL (GH-30011) Message-ID: https://github.com/python/cpython/commit/9f8f45144b6f0ad481e80570538cce89b414f7f9 commit: 9f8f45144b6f0ad481e80570538cce89b414f7f9 branch: main author: Mark Shannon committer: markshannon date: 2021-12-14T18:22:44Z summary: bpo-44525: Split calls into PRECALL and CALL (GH-30011) * Add 3 new opcodes for calls: PRECALL_METHOD, CALL_NO_KW, CALL_KW. * Update specialization to handle new CALL opcodes. * Specialize call to method descriptors. * Remove old CALL opcodes: CALL_FUNCTION, CALL_METHOD, CALL_METHOD_KW, CALL_FUNCTION_KW. files: A Misc/NEWS.d/next/Core and Builtins/2021-12-13-17-12-16.bpo-44525.4-FiSf.rst M Doc/library/dis.rst M Include/internal/pycore_code.h M Include/opcode.h M Lib/importlib/_bootstrap_external.py M Lib/opcode.py M Lib/test/test_compile.py M Lib/test/test_dis.py M Objects/exception_handling_notes.txt M Objects/lnotab_notes.txt M Programs/test_frozenmain.h M Python/ceval.c M Python/compile.c M Python/opcode_targets.h M Python/specialize.c diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 7ac5a9b1f5454..35d9baadf6d16 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -36,7 +36,7 @@ the following command can be used to display the disassembly of >>> dis.dis(myfunc) 2 0 LOAD_GLOBAL 0 (len) 2 LOAD_FAST 0 (alist) - 4 CALL_FUNCTION 1 + 4 CALL_NO_KW 1 6 RETURN_VALUE (The "2" is a line number). @@ -104,7 +104,7 @@ Example:: ... LOAD_GLOBAL LOAD_FAST - CALL_FUNCTION + CALL_NO_KW RETURN_VALUE @@ -616,7 +616,7 @@ iterations of the loop. .. opcode:: LOAD_BUILD_CLASS Pushes :func:`builtins.__build_class__` onto the stack. It is later called - by :opcode:`CALL_FUNCTION` to construct a class. + by :opcode:`CALL_NO_KW` to construct a class. .. opcode:: BEFORE_WITH (delta) @@ -1039,21 +1039,20 @@ All of the following opcodes use their arguments. with ``__cause__`` set to ``TOS``) -.. opcode:: CALL_FUNCTION (argc) +.. opcode:: CALL_NO_KW (argc) Calls a callable object with positional arguments. *argc* indicates the number of positional arguments. The top of the stack contains positional arguments, with the right-most argument on top. Below the arguments is a callable object to call. - ``CALL_FUNCTION`` pops all arguments and the callable object off the stack, + ``CALL_NO_KW`` pops all arguments and the callable object off the stack, calls the callable object with those arguments, and pushes the return value returned by the callable object. - .. versionchanged:: 3.6 - This opcode is used only for calls with positional arguments. + .. versionadded:: 3.11 -.. opcode:: CALL_FUNCTION_KW (argc) +.. opcode:: CALL_KW (argc) Calls a callable object with positional (if any) and keyword arguments. *argc* indicates the total number of positional and keyword arguments. @@ -1063,13 +1062,11 @@ All of the following opcodes use their arguments. in the order corresponding to the tuple. Below that are positional arguments, with the right-most parameter on top. Below the arguments is a callable object to call. - ``CALL_FUNCTION_KW`` pops all arguments and the callable object off the stack, + ``CALL_KW`` pops all arguments and the callable object off the stack, calls the callable object with those arguments, and pushes the return value returned by the callable object. - .. versionchanged:: 3.6 - Keyword arguments are packed in a tuple instead of a dictionary, - *argc* indicates the total number of arguments. + .. versionadded:: 3.11 .. opcode:: CALL_FUNCTION_EX (flags) @@ -1099,30 +1096,16 @@ All of the following opcodes use their arguments. .. versionadded:: 3.7 -.. opcode:: CALL_METHOD (argc) - - Calls a method. *argc* is the number of positional arguments. - Keyword arguments are not supported. This opcode is designed to be used - with :opcode:`LOAD_METHOD`. Positional arguments are on top of the stack. - Below them, the two items described in :opcode:`LOAD_METHOD` are on the - stack (either ``self`` and an unbound method object or ``NULL`` and an - arbitrary callable). All of them are popped and the return value is pushed. - - .. versionadded:: 3.7 - - -.. opcode:: CALL_METHOD_KW (argc) +.. opcode:: PRECALL_METHOD (argc) - Calls a method in a similar fashion as :opcode:`CALL_METHOD`, but also supports keyword arguments. - *argc* is the number of positional and keyword arguments. - This opcode is designed to be used with :opcode:`LOAD_METHOD`. TOS is a - tuple of keyword argument names. Argument values are below that. - Below them, the two items described in :opcode:`LOAD_METHOD` are on the - stack (either ``self`` and an unbound method object or ``NULL`` and an - arbitrary callable). All of them are popped from the stack and the return value is pushed. + Prefixes either :opcode:`CALL_NO_KW` or :opcode:`CALL_KW`. + This opcode is designed to be used with :opcode:`LOAD_METHOD`. + Sets internal variables, so that :opcode:`CALL_NO_KW` or :opcode:`CALL_KW` + clean up after :opcode:`LOAD_METHOD` correctly. .. versionadded:: 3.11 + .. opcode:: MAKE_FUNCTION (flags) Pushes a new function object on the stack. From bottom to top, the consumed diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index 496d52f580f1f..b0463e361718a 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -271,7 +271,7 @@ int _Py_Specialize_LoadGlobal(PyObject *globals, PyObject *builtins, _Py_CODEUNI int _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name, SpecializedCacheEntry *cache); int _Py_Specialize_BinarySubscr(PyObject *sub, PyObject *container, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache); int _Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub, _Py_CODEUNIT *instr); -int _Py_Specialize_CallFunction(PyObject *callable, _Py_CODEUNIT *instr, int nargs, SpecializedCacheEntry *cache, PyObject *builtins); +int _Py_Specialize_CallNoKw(PyObject *callable, _Py_CODEUNIT *instr, int nargs, SpecializedCacheEntry *cache, PyObject *builtins); void _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache); void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache); @@ -288,7 +288,7 @@ void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, #define COLLECT_SPECIALIZATION_STATS_DETAILED PRINT_SPECIALIZATION_STATS_DETAILED #endif -#define SPECIALIZATION_FAILURE_KINDS 20 +#define SPECIALIZATION_FAILURE_KINDS 30 #if COLLECT_SPECIALIZATION_STATS diff --git a/Include/opcode.h b/Include/opcode.h index 1341a8abad4d7..4d14081a6b618 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -87,7 +87,6 @@ extern "C" { #define JUMP_IF_NOT_EG_MATCH 127 #define GEN_START 129 #define RAISE_VARARGS 130 -#define CALL_FUNCTION 131 #define MAKE_FUNCTION 132 #define BUILD_SLICE 133 #define MAKE_CELL 135 @@ -95,7 +94,6 @@ extern "C" { #define LOAD_DEREF 137 #define STORE_DEREF 138 #define DELETE_DEREF 139 -#define CALL_FUNCTION_KW 141 #define CALL_FUNCTION_EX 142 #define EXTENDED_ARG 144 #define LIST_APPEND 145 @@ -108,12 +106,13 @@ extern "C" { #define BUILD_CONST_KEY_MAP 156 #define BUILD_STRING 157 #define LOAD_METHOD 160 -#define CALL_METHOD 161 #define LIST_EXTEND 162 #define SET_UPDATE 163 #define DICT_MERGE 164 #define DICT_UPDATE 165 -#define CALL_METHOD_KW 166 +#define PRECALL_METHOD 168 +#define CALL_NO_KW 169 +#define CALL_KW 170 #define BINARY_OP_ADAPTIVE 7 #define BINARY_OP_ADD_INT 8 #define BINARY_OP_ADD_FLOAT 13 @@ -135,35 +134,38 @@ extern "C" { #define STORE_SUBSCR_ADAPTIVE 36 #define STORE_SUBSCR_LIST_INT 38 #define STORE_SUBSCR_DICT 39 -#define CALL_FUNCTION_ADAPTIVE 40 -#define CALL_FUNCTION_BUILTIN_O 41 -#define CALL_FUNCTION_BUILTIN_FAST 42 -#define CALL_FUNCTION_LEN 43 -#define CALL_FUNCTION_ISINSTANCE 44 -#define CALL_FUNCTION_PY_SIMPLE 45 -#define JUMP_ABSOLUTE_QUICK 46 -#define LOAD_ATTR_ADAPTIVE 47 -#define LOAD_ATTR_INSTANCE_VALUE 48 -#define LOAD_ATTR_WITH_HINT 55 -#define LOAD_ATTR_SLOT 56 -#define LOAD_ATTR_MODULE 57 -#define LOAD_GLOBAL_ADAPTIVE 58 -#define LOAD_GLOBAL_MODULE 59 -#define LOAD_GLOBAL_BUILTIN 62 -#define LOAD_METHOD_ADAPTIVE 63 -#define LOAD_METHOD_CACHED 64 -#define LOAD_METHOD_CLASS 65 -#define LOAD_METHOD_MODULE 66 -#define LOAD_METHOD_NO_DICT 67 -#define STORE_ATTR_ADAPTIVE 75 -#define STORE_ATTR_INSTANCE_VALUE 76 -#define STORE_ATTR_SLOT 77 -#define STORE_ATTR_WITH_HINT 78 -#define LOAD_FAST__LOAD_FAST 79 -#define STORE_FAST__LOAD_FAST 80 -#define LOAD_FAST__LOAD_CONST 81 -#define LOAD_CONST__LOAD_FAST 87 -#define STORE_FAST__STORE_FAST 123 +#define CALL_NO_KW_ADAPTIVE 40 +#define CALL_NO_KW_BUILTIN_O 41 +#define CALL_NO_KW_BUILTIN_FAST 42 +#define CALL_NO_KW_LEN 43 +#define CALL_NO_KW_ISINSTANCE 44 +#define CALL_NO_KW_PY_SIMPLE 45 +#define CALL_NO_KW_LIST_APPEND 46 +#define CALL_NO_KW_METHOD_DESCRIPTOR_O 47 +#define CALL_NO_KW_METHOD_DESCRIPTOR_FAST 48 +#define JUMP_ABSOLUTE_QUICK 55 +#define LOAD_ATTR_ADAPTIVE 56 +#define LOAD_ATTR_INSTANCE_VALUE 57 +#define LOAD_ATTR_WITH_HINT 58 +#define LOAD_ATTR_SLOT 59 +#define LOAD_ATTR_MODULE 62 +#define LOAD_GLOBAL_ADAPTIVE 63 +#define LOAD_GLOBAL_MODULE 64 +#define LOAD_GLOBAL_BUILTIN 65 +#define LOAD_METHOD_ADAPTIVE 66 +#define LOAD_METHOD_CACHED 67 +#define LOAD_METHOD_CLASS 75 +#define LOAD_METHOD_MODULE 76 +#define LOAD_METHOD_NO_DICT 77 +#define STORE_ATTR_ADAPTIVE 78 +#define STORE_ATTR_INSTANCE_VALUE 79 +#define STORE_ATTR_SLOT 80 +#define STORE_ATTR_WITH_HINT 81 +#define LOAD_FAST__LOAD_FAST 87 +#define STORE_FAST__LOAD_FAST 123 +#define LOAD_FAST__LOAD_CONST 128 +#define LOAD_CONST__LOAD_FAST 131 +#define STORE_FAST__STORE_FAST 134 #define DO_TRACING 255 #ifdef NEED_OPCODE_JUMP_TABLES static uint32_t _PyOpcode_RelativeJump[8] = { diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 6e7ea7b378143..abd0170cac070 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -372,6 +372,7 @@ def _write_atomic(path, data, mode=0o666): # BINARY_OP) # Python 3.11a3 3465 (Add COPY_FREE_VARS opcode) # Python 3.11a3 3466 (bpo-45292: PEP-654 except*) +# Python 3.11a4 3467 (Change CALL_xxx opcodes) # # MAGIC must change whenever the bytecode emitted by the compiler may no @@ -381,7 +382,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 = (3466).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3467).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c _PYCACHE = '__pycache__' diff --git a/Lib/opcode.py b/Lib/opcode.py index 299216d3c8799..0b64686d605f9 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -155,7 +155,7 @@ def jabs_op(name, op): def_op('GEN_START', 129) # Kind of generator/coroutine def_op('RAISE_VARARGS', 130) # Number of raise arguments (1, 2, or 3) -def_op('CALL_FUNCTION', 131) # #args + def_op('MAKE_FUNCTION', 132) # Flags def_op('BUILD_SLICE', 133) # Number of items @@ -170,7 +170,6 @@ def jabs_op(name, op): def_op('DELETE_DEREF', 139) hasfree.append(139) -def_op('CALL_FUNCTION_KW', 141) # #args + #kwargs def_op('CALL_FUNCTION_EX', 142) # Flags def_op('EXTENDED_ARG', 144) @@ -189,12 +188,15 @@ def jabs_op(name, op): def_op('BUILD_STRING', 157) name_op('LOAD_METHOD', 160) -def_op('CALL_METHOD', 161) + def_op('LIST_EXTEND', 162) def_op('SET_UPDATE', 163) def_op('DICT_MERGE', 164) def_op('DICT_UPDATE', 165) -def_op('CALL_METHOD_KW', 166) + +def_op('PRECALL_METHOD', 168) +def_op('CALL_NO_KW', 169) +def_op('CALL_KW', 170) del def_op, name_op, jrel_op, jabs_op @@ -249,12 +251,15 @@ def jabs_op(name, op): "STORE_SUBSCR_ADAPTIVE", "STORE_SUBSCR_LIST_INT", "STORE_SUBSCR_DICT", - "CALL_FUNCTION_ADAPTIVE", - "CALL_FUNCTION_BUILTIN_O", - "CALL_FUNCTION_BUILTIN_FAST", - "CALL_FUNCTION_LEN", - "CALL_FUNCTION_ISINSTANCE", - "CALL_FUNCTION_PY_SIMPLE", + "CALL_NO_KW_ADAPTIVE", + "CALL_NO_KW_BUILTIN_O", + "CALL_NO_KW_BUILTIN_FAST", + "CALL_NO_KW_LEN", + "CALL_NO_KW_ISINSTANCE", + "CALL_NO_KW_PY_SIMPLE", + "CALL_NO_KW_LIST_APPEND", + "CALL_NO_KW_METHOD_DESCRIPTOR_O", + "CALL_NO_KW_METHOD_DESCRIPTOR_FAST", "JUMP_ABSOLUTE_QUICK", "LOAD_ATTR_ADAPTIVE", "LOAD_ATTR_INSTANCE_VALUE", diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index 5bd7b06530691..11615b32232e8 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -839,7 +839,7 @@ def foo(x): self.assertNotIn('LOAD_METHOD', instructions) self.assertNotIn('CALL_METHOD', instructions) self.assertIn('LOAD_ATTR', instructions) - self.assertIn('CALL_FUNCTION', instructions) + self.assertIn('CALL_NO_KW', instructions) def test_lineno_procedure_call(self): def call(): @@ -1095,7 +1095,7 @@ def test_multiline_expression(self): ) """ compiled_code, _ = self.check_positions_against_ast(snippet) - self.assertOpcodeSourcePositionIs(compiled_code, 'CALL_FUNCTION', + self.assertOpcodeSourcePositionIs(compiled_code, 'CALL_NO_KW', line=1, end_line=3, column=0, end_column=1) def test_very_long_line_end_offset(self): @@ -1105,7 +1105,7 @@ def test_very_long_line_end_offset(self): snippet = f"g('{long_string}')" compiled_code, _ = self.check_positions_against_ast(snippet) - self.assertOpcodeSourcePositionIs(compiled_code, 'CALL_FUNCTION', + self.assertOpcodeSourcePositionIs(compiled_code, 'CALL_NO_KW', line=1, end_line=1, column=None, end_column=None) def test_complex_single_line_expression(self): diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index e821e001ad880..c35f1d3ec8bd7 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -95,7 +95,7 @@ def _f(a): dis_f = """\ %3d 0 LOAD_GLOBAL 0 (print) 2 LOAD_FAST 0 (a) - 4 CALL_FUNCTION 1 + 4 CALL_NO_KW 1 6 POP_TOP %3d 8 LOAD_CONST 1 (1) @@ -107,7 +107,7 @@ def _f(a): dis_f_co_code = """\ 0 LOAD_GLOBAL 0 2 LOAD_FAST 0 - 4 CALL_FUNCTION 1 + 4 CALL_NO_KW 1 6 POP_TOP 8 LOAD_CONST 1 10 RETURN_VALUE @@ -125,7 +125,7 @@ def bug708901(): %3d 4 LOAD_CONST 2 (10) -%3d 6 CALL_FUNCTION 2 +%3d 6 CALL_NO_KW 2 8 GET_ITER >> 10 FOR_ITER 2 (to 16) 12 STORE_FAST 0 (res) @@ -152,12 +152,12 @@ def bug1333982(x=[]): 4 MAKE_FUNCTION 0 6 LOAD_FAST 0 (x) 8 GET_ITER - 10 CALL_FUNCTION 1 + 10 CALL_NO_KW 1 %3d 12 LOAD_CONST 3 (1) %3d 14 BINARY_OP 0 (+) - 16 CALL_FUNCTION 1 + 16 CALL_NO_KW 1 18 RAISE_VARARGS 1 """ % (bug1333982.__code__.co_firstlineno + 1, __file__, @@ -260,7 +260,7 @@ def bug42562(): 3 14 LOAD_NAME 3 (fun) 16 LOAD_CONST 0 (1) - 18 CALL_FUNCTION 1 + 18 CALL_NO_KW 1 20 LOAD_NAME 2 (__annotations__) 22 LOAD_CONST 2 ('y') 24 STORE_SUBSCR @@ -269,7 +269,7 @@ def bug42562(): 28 LOAD_NAME 4 (lst) 30 LOAD_NAME 3 (fun) 32 LOAD_CONST 3 (0) - 34 CALL_FUNCTION 1 + 34 CALL_NO_KW 1 36 STORE_SUBSCR 38 LOAD_NAME 1 (int) 40 POP_TOP @@ -384,12 +384,12 @@ def _tryfinallyconst(b): %3d 2 LOAD_FAST 0 (a) %3d 4 LOAD_FAST 1 (b) - 6 CALL_FUNCTION 0 + 6 CALL_NO_KW 0 8 POP_TOP 10 RETURN_VALUE >> 12 PUSH_EXC_INFO 14 LOAD_FAST 1 (b) - 16 CALL_FUNCTION 0 + 16 CALL_NO_KW 0 18 POP_TOP 20 RERAISE 0 >> 22 POP_EXCEPT_AND_RERAISE @@ -407,13 +407,13 @@ def _tryfinallyconst(b): %3d 2 NOP %3d 4 LOAD_FAST 0 (b) - 6 CALL_FUNCTION 0 + 6 CALL_NO_KW 0 8 POP_TOP 10 LOAD_CONST 1 (1) 12 RETURN_VALUE 14 PUSH_EXC_INFO 16 LOAD_FAST 0 (b) - 18 CALL_FUNCTION 0 + 18 CALL_NO_KW 0 20 POP_TOP 22 RERAISE 0 >> 24 POP_EXCEPT_AND_RERAISE @@ -468,7 +468,7 @@ def foo(x): 10 MAKE_FUNCTION 8 (closure) 12 LOAD_DEREF 1 (y) 14 GET_ITER - 16 CALL_FUNCTION 1 + 16 CALL_NO_KW 1 18 RETURN_VALUE """ % (dis_nested_0, __file__, @@ -1004,7 +1004,7 @@ def _prepare_test_cases(): Instruction(opname='BUILD_LIST', opcode=103, arg=0, argval=0, argrepr='', offset=28, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='BUILD_MAP', opcode=105, arg=0, argval=0, argrepr='', offset=30, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Hello world!', argrepr="'Hello world!'", offset=32, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=7, argval=7, argrepr='', offset=34, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_NO_KW', opcode=169, arg=7, argval=7, argrepr='', offset=34, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=36, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='f', argrepr='f', offset=38, starts_line=8, is_jump_target=False, positions=None), Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=40, starts_line=None, is_jump_target=False, positions=None), @@ -1028,7 +1028,7 @@ def _prepare_test_cases(): Instruction(opname='LOAD_DEREF', opcode=137, arg=4, argval='b', argrepr='b', offset=28, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_DEREF', opcode=137, arg=0, argval='c', argrepr='c', offset=30, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_DEREF', opcode=137, arg=1, argval='d', argrepr='d', offset=32, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=4, argval=4, argrepr='', offset=34, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_NO_KW', opcode=169, arg=4, argval=4, argrepr='', offset=34, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=36, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='inner', argrepr='inner', offset=38, starts_line=6, is_jump_target=False, positions=None), Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=40, starts_line=None, is_jump_target=False, positions=None), @@ -1043,7 +1043,7 @@ def _prepare_test_cases(): Instruction(opname='LOAD_DEREF', opcode=137, arg=5, argval='d', argrepr='d', offset=10, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='e', argrepr='e', offset=12, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_FAST', opcode=124, arg=1, argval='f', argrepr='f', offset=14, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=6, argval=6, argrepr='', offset=16, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_NO_KW', opcode=169, arg=6, argval=6, argrepr='', offset=16, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=18, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=20, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=22, starts_line=None, is_jump_target=False, positions=None), @@ -1052,13 +1052,13 @@ def _prepare_test_cases(): expected_opinfo_jumpy = [ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='range', argrepr='range', offset=0, starts_line=3, is_jump_target=False, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=10, argrepr='10', offset=2, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=4, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=4, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='GET_ITER', opcode=68, arg=None, argval=None, argrepr='', offset=6, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='FOR_ITER', opcode=93, arg=17, argval=44, argrepr='to 44', offset=8, starts_line=None, is_jump_target=True, positions=None), Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=10, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=12, starts_line=4, is_jump_target=False, positions=None), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=14, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=16, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=16, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=18, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=20, starts_line=5, is_jump_target=False, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=22, starts_line=None, is_jump_target=False, positions=None), @@ -1074,13 +1074,13 @@ def _prepare_test_cases(): Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=4, argval=8, argrepr='to 8', offset=42, starts_line=7, is_jump_target=True, positions=None), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=44, starts_line=10, is_jump_target=True, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=46, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=48, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=48, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=50, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=52, starts_line=11, is_jump_target=True, positions=None), Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=48, argval=96, argrepr='to 96', offset=54, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=56, starts_line=12, is_jump_target=True, positions=None), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=58, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=60, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=60, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=62, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=64, starts_line=13, is_jump_target=False, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=66, starts_line=None, is_jump_target=False, positions=None), @@ -1100,7 +1100,7 @@ def _prepare_test_cases(): Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=28, argval=56, argrepr='to 56', offset=94, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=96, starts_line=19, is_jump_target=True, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=98, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=100, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=100, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=102, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=104, starts_line=20, is_jump_target=True, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=106, starts_line=21, is_jump_target=False, positions=None), @@ -1116,7 +1116,7 @@ def _prepare_test_cases(): Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=126, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=128, starts_line=23, is_jump_target=False, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=130, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=132, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=132, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=134, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=136, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='JUMP_FORWARD', opcode=110, arg=32, argval=204, argrepr='to 204', offset=138, starts_line=None, is_jump_target=False, positions=None), @@ -1127,12 +1127,12 @@ def _prepare_test_cases(): Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=148, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=150, starts_line=26, is_jump_target=False, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Never reach this', argrepr="'Never reach this'", offset=152, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=154, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=154, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=156, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=158, starts_line=25, is_jump_target=False, positions=None), Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=160, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=162, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=3, argval=3, argrepr='', offset=164, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_NO_KW', opcode=169, arg=3, argval=3, argrepr='', offset=164, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=166, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='JUMP_FORWARD', opcode=110, arg=11, argval=192, argrepr='to 192', offset=168, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=170, starts_line=None, is_jump_target=False, positions=None), @@ -1148,21 +1148,21 @@ def _prepare_test_cases(): Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=190, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=192, starts_line=28, is_jump_target=True, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=194, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=196, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=196, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=198, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=200, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=202, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=204, starts_line=23, is_jump_target=True, positions=None), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=206, 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=208, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=210, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=210, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=212, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=214, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=216, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=218, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=220, starts_line=None, 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=222, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=224, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=224, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=226, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=228, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=230, starts_line=None, is_jump_target=False, positions=None), diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-13-17-12-16.bpo-44525.4-FiSf.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-13-17-12-16.bpo-44525.4-FiSf.rst new file mode 100644 index 0000000000000..d929666c9107d --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-13-17-12-16.bpo-44525.4-FiSf.rst @@ -0,0 +1,8 @@ +Replace the four call bytecode instructions which one pre-call instruction +and two call instructions. + +Removes ``CALL_FUNCTION``, ``CALL_FUNCTION_KW``, ``CALL_METHOD`` and +``CALL_METHOD_KW``. + +Adds ``CALL_NO_KW`` and ``CALL_KW`` call instructions, and +``PRECALL_METHOD`` prefix for pairing with ``LOAD_METHOD``. diff --git a/Objects/exception_handling_notes.txt b/Objects/exception_handling_notes.txt index e738c2781ad23..a136358f90c88 100644 --- a/Objects/exception_handling_notes.txt +++ b/Objects/exception_handling_notes.txt @@ -23,7 +23,7 @@ compiles as follows in 3.10: 3 2 LOAD_GLOBAL 0 (g) 4 LOAD_CONST 1 (0) - 6 CALL_FUNCTION 1 + 6 CALL_NO_KW 1 8 POP_TOP 10 POP_BLOCK 12 LOAD_CONST 0 (None) @@ -47,7 +47,7 @@ a table to determine where to jump to when an exception is raised. 3 2 LOAD_GLOBAL 0 (g) 4 LOAD_CONST 1 (0) - 6 CALL_FUNCTION 1 + 6 CALL_NO_KW 1 8 POP_TOP 10 LOAD_CONST 0 (None) 12 RETURN_VALUE @@ -68,7 +68,7 @@ ExceptionTable: (Note this code is from an early 3.11 alpha, the NOP may well have be removed before release). If an instruction raises an exception then its offset is used to find the target to jump to. -For example, the CALL_FUNCTION at offset 6, falls into the range 2 to 8. +For example, the CALL_NO_KW at offset 6, falls into the range 2 to 8. So, if g() raises an exception, then control jumps to offset 14. diff --git a/Objects/lnotab_notes.txt b/Objects/lnotab_notes.txt index e52e437c65025..362b87a86a481 100644 --- a/Objects/lnotab_notes.txt +++ b/Objects/lnotab_notes.txt @@ -188,7 +188,7 @@ which compiles to this: 3 6 LOAD_GLOBAL 0 (print) 8 LOAD_CONST 1 (1) - 10 CALL_FUNCTION 1 + 10 CALL_NO_KW 1 12 POP_TOP 4 14 BREAK_LOOP @@ -197,7 +197,7 @@ which compiles to this: 6 20 LOAD_GLOBAL 0 (print) 22 LOAD_CONST 2 (2) - 24 CALL_FUNCTION 1 + 24 CALL_NO_KW 1 26 POP_TOP >> 28 LOAD_CONST 0 (None) 30 RETURN_VALUE diff --git a/Programs/test_frozenmain.h b/Programs/test_frozenmain.h index 2c789915bf503..45ca31e1b5e95 100644 --- a/Programs/test_frozenmain.h +++ b/Programs/test_frozenmain.h @@ -2,11 +2,11 @@ unsigned char M_test_frozenmain[] = { 227,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0, 0,0,0,0,0,115,86,0,0,0,100,0,100,1,108,0, - 90,0,100,0,100,1,108,1,90,1,101,2,100,2,131,1, - 1,0,101,2,100,3,101,0,106,3,131,2,1,0,101,1, - 106,4,131,0,100,4,25,0,90,5,100,5,68,0,93,14, + 90,0,100,0,100,1,108,1,90,1,101,2,100,2,169,1, + 1,0,101,2,100,3,101,0,106,3,169,2,1,0,101,1, + 106,4,169,0,100,4,25,0,90,5,100,5,68,0,93,14, 90,6,101,2,100,6,101,6,155,0,100,7,101,5,101,6, - 25,0,155,0,157,4,131,1,1,0,113,26,100,1,83,0, + 25,0,155,0,157,4,169,1,1,0,113,26,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, diff --git a/Python/ceval.c b/Python/ceval.c index fb19f78ba14d4..6d2784894f74f 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1673,6 +1673,22 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr CFrame cframe; + /* Variables used for making calls */ + PyObject *kwnames; + int nargs; + /* + * It is only between a PRECALL_METHOD instruction and the following instruction, + * that these two values can be anything other than their defaults. */ + int postcall_shrink = 1; + int extra_args = 0; +#define RESET_STACK_ADJUST_FOR_CALLS \ + do { \ + postcall_shrink = 1; \ + extra_args = 0; \ + } while (0) +#define STACK_ADJUST_IS_RESET \ + (postcall_shrink == 1 && extra_args == 0) + /* WARNING: Because the CFrame lives on the C stack, * but can be accessed from a heap allocated object (tstate) * strict stack discipline must be maintained. @@ -1815,11 +1831,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr switch (opcode) { #endif - /* Variables used for making calls */ - PyObject *kwnames; - int nargs; - int postcall_shrink; - /* BEWARE! It is essential that any operation that fails must goto error and that all operation that succeed call DISPATCH() ! */ @@ -4319,7 +4330,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr if (iter == NULL) goto error; PREDICT(FOR_ITER); - PREDICT(CALL_FUNCTION); + PREDICT(CALL_NO_KW); DISPATCH(); } @@ -4661,7 +4672,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr DISPATCH(); } - TARGET(CALL_METHOD) { + TARGET(PRECALL_METHOD) { /* Designed to work in tamdem with LOAD_METHOD. */ /* `meth` is NULL when LOAD_METHOD thinks that it's not a method call. @@ -4689,38 +4700,26 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr make it accept the `self` as a first argument. */ int is_method = (PEEK(oparg + 2) != NULL); - oparg += is_method; - nargs = oparg; - kwnames = NULL; + extra_args = is_method; postcall_shrink = 2-is_method; - goto call_function; - } - - TARGET(CALL_METHOD_KW) { - /* Designed to work in tandem with LOAD_METHOD. Same as CALL_METHOD - but pops TOS to get a tuple of keyword names. */ - kwnames = POP(); - int is_method = (PEEK(oparg + 2) != NULL); - oparg += is_method; - nargs = oparg - (int)PyTuple_GET_SIZE(kwnames); - postcall_shrink = 2-is_method; - goto call_function; + DISPATCH(); } - TARGET(CALL_FUNCTION_KW) { + TARGET(CALL_KW) { kwnames = POP(); + oparg += extra_args; + extra_args = 0; nargs = oparg - (int)PyTuple_GET_SIZE(kwnames); - postcall_shrink = 1; goto call_function; } - TARGET(CALL_FUNCTION) { - PREDICTED(CALL_FUNCTION); - STAT_INC(CALL_FUNCTION, unquickened); + TARGET(CALL_NO_KW) { PyObject *function; - nargs = oparg; + PREDICTED(CALL_NO_KW); + STAT_INC(CALL_NO_KW, unquickened); kwnames = NULL; - postcall_shrink = 1; + oparg += extra_args; + nargs = oparg; call_function: function = PEEK(oparg + 1); if (Py_TYPE(function) == &PyMethod_Type) { @@ -4748,6 +4747,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr stack_pointer, nargs, kwnames ); STACK_SHRINK(postcall_shrink); + RESET_STACK_ADJUST_FOR_CALLS; // The frame has stolen all the arguments from the stack, // so there is no need to clean them up. Py_XDECREF(kwnames); @@ -4780,6 +4780,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr Py_DECREF(stack_pointer[i]); } STACK_SHRINK(postcall_shrink); + RESET_STACK_ADJUST_FOR_CALLS; PUSH(res); if (res == NULL) { goto error; @@ -4788,43 +4789,46 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr DISPATCH(); } - TARGET(CALL_FUNCTION_ADAPTIVE) { + TARGET(CALL_NO_KW_ADAPTIVE) { SpecializedCacheEntry *cache = GET_CACHE(); - nargs = cache->adaptive.original_oparg; + oparg = cache->adaptive.original_oparg; if (cache->adaptive.counter == 0) { next_instr--; - if (_Py_Specialize_CallFunction( + int nargs = oparg+extra_args; + if (_Py_Specialize_CallNoKw( PEEK(nargs + 1), next_instr, nargs, cache, BUILTINS()) < 0) { goto error; } DISPATCH(); } else { - STAT_INC(CALL_FUNCTION, deferred); + STAT_INC(CALL_NO_KW, deferred); cache->adaptive.counter--; - oparg = nargs; kwnames = NULL; - postcall_shrink = 1; + oparg += extra_args; + nargs = oparg; goto call_function; } } - TARGET(CALL_FUNCTION_PY_SIMPLE) { + TARGET(CALL_NO_KW_PY_SIMPLE) { SpecializedCacheEntry *caches = GET_CACHE(); _PyAdaptiveEntry *cache0 = &caches[0].adaptive; - int argcount = cache0->original_oparg; + int argcount = cache0->original_oparg + extra_args; + DEOPT_IF(argcount != cache0->index, CALL_NO_KW); _PyCallCache *cache1 = &caches[-1].call; PyObject *callable = PEEK(argcount+1); - DEOPT_IF(!PyFunction_Check(callable), CALL_FUNCTION); + DEOPT_IF(!PyFunction_Check(callable), CALL_NO_KW); PyFunctionObject *func = (PyFunctionObject *)callable; - DEOPT_IF(func->func_version != cache1->func_version, CALL_FUNCTION); + DEOPT_IF(func->func_version != cache1->func_version, CALL_NO_KW); /* PEP 523 */ - DEOPT_IF(tstate->interp->eval_frame != NULL, CALL_FUNCTION); - STAT_INC(CALL_FUNCTION, hit); + DEOPT_IF(tstate->interp->eval_frame != NULL, CALL_NO_KW); + STAT_INC(CALL_NO_KW, hit); PyCodeObject *code = (PyCodeObject *)func->func_code; size_t size = code->co_nlocalsplus + code->co_stacksize + FRAME_SPECIALS_SIZE; InterpreterFrame *new_frame = _PyThreadState_BumpFramePointer(tstate, size); if (new_frame == NULL) { + RESET_STACK_ADJUST_FOR_CALLS; goto error; } _PyFrame_InitializeSpecials(new_frame, func, @@ -4842,7 +4846,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr for (int i = argcount+deflen; i < code->co_nlocalsplus; i++) { new_frame->localsplus[i] = NULL; } - STACK_SHRINK(1); + STACK_SHRINK(postcall_shrink); + RESET_STACK_ADJUST_FOR_CALLS; Py_DECREF(func); _PyFrame_SetStackPointer(frame, stack_pointer); new_frame->previous = frame; @@ -4851,14 +4856,15 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr goto start_frame; } - TARGET(CALL_FUNCTION_BUILTIN_O) { + TARGET(CALL_NO_KW_BUILTIN_O) { assert(cframe.use_tracing == 0); + assert(STACK_ADJUST_IS_RESET); /* Builtin METH_O functions */ PyObject *callable = SECOND(); - DEOPT_IF(!PyCFunction_CheckExact(callable), CALL_FUNCTION); - DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_O, CALL_FUNCTION); - STAT_INC(CALL_FUNCTION, hit); + DEOPT_IF(!PyCFunction_CheckExact(callable), CALL_NO_KW); + DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_O, CALL_NO_KW); + STAT_INC(CALL_NO_KW, hit); PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable); // This is slower but CPython promises to check all non-vectorcall @@ -4881,18 +4887,19 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr DISPATCH(); } - TARGET(CALL_FUNCTION_BUILTIN_FAST) { + TARGET(CALL_NO_KW_BUILTIN_FAST) { assert(cframe.use_tracing == 0); + assert(STACK_ADJUST_IS_RESET); /* Builtin METH_FASTCALL functions, without keywords */ SpecializedCacheEntry *caches = GET_CACHE(); _PyAdaptiveEntry *cache0 = &caches[0].adaptive; int nargs = cache0->original_oparg; PyObject **pfunc = &PEEK(nargs + 1); PyObject *callable = *pfunc; - DEOPT_IF(!PyCFunction_CheckExact(callable), CALL_FUNCTION); + DEOPT_IF(!PyCFunction_CheckExact(callable), CALL_NO_KW); DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_FASTCALL, - CALL_FUNCTION); - STAT_INC(CALL_FUNCTION, hit); + CALL_NO_KW); + STAT_INC(CALL_NO_KW, hit); PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable); /* res = func(self, args, nargs) */ @@ -4919,16 +4926,17 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr DISPATCH(); } - TARGET(CALL_FUNCTION_LEN) { + TARGET(CALL_NO_KW_LEN) { assert(cframe.use_tracing == 0); + assert(STACK_ADJUST_IS_RESET); /* len(o) */ SpecializedCacheEntry *caches = GET_CACHE(); assert(caches[0].adaptive.original_oparg == 1); _PyObjectCache *cache1 = &caches[-1].obj; PyObject *callable = SECOND(); - DEOPT_IF(callable != cache1->obj, CALL_FUNCTION); - STAT_INC(CALL_FUNCTION, hit); + DEOPT_IF(callable != cache1->obj, CALL_NO_KW); + STAT_INC(CALL_NO_KW, hit); Py_ssize_t len_i = PyObject_Length(TOP()); if (len_i < 0) { @@ -4947,16 +4955,17 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr DISPATCH(); } - TARGET(CALL_FUNCTION_ISINSTANCE) { + TARGET(CALL_NO_KW_ISINSTANCE) { assert(cframe.use_tracing == 0); + assert(STACK_ADJUST_IS_RESET); /* isinstance(o, o2) */ SpecializedCacheEntry *caches = GET_CACHE(); assert(caches[0].adaptive.original_oparg == 2); _PyObjectCache *cache1 = &caches[-1].obj; PyObject *callable = THIRD(); - DEOPT_IF(callable != cache1->obj, CALL_FUNCTION); - STAT_INC(CALL_FUNCTION, hit); + DEOPT_IF(callable != cache1->obj, CALL_NO_KW); + STAT_INC(CALL_NO_KW, hit); int retval = PyObject_IsInstance(SECOND(), TOP()); if (retval < 0) { @@ -4976,6 +4985,97 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr DISPATCH(); } + TARGET(CALL_NO_KW_LIST_APPEND) { + assert(_Py_OPCODE(next_instr[-2]) == PRECALL_METHOD); + assert(GET_CACHE()->adaptive.original_oparg == 1); + DEOPT_IF(extra_args == 0, CALL_NO_KW); + PyObject *list = SECOND(); + DEOPT_IF(!PyList_CheckExact(list), CALL_NO_KW); + STAT_INC(CALL_NO_KW, hit); + assert(extra_args == 1); + extra_args = 0; + assert(STACK_ADJUST_IS_RESET); + PyObject *arg = TOP(); + int err = PyList_Append(list, arg); + if (err) { + goto error; + } + PyObject *callable = THIRD(); + Py_DECREF(arg); + Py_DECREF(list); + Py_INCREF(Py_None); + STACK_SHRINK(2); + SET_TOP(Py_None); + Py_DECREF(callable); + DISPATCH(); + } + + TARGET(CALL_NO_KW_METHOD_DESCRIPTOR_O) { + assert(_Py_OPCODE(next_instr[-2]) == PRECALL_METHOD); + assert(GET_CACHE()->adaptive.original_oparg == 1); + DEOPT_IF(extra_args == 0, CALL_NO_KW); + assert(extra_args == 1); + PyObject *callable = THIRD(); + DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL_NO_KW); + DEOPT_IF(((PyMethodDescrObject *)callable)->d_method->ml_flags != METH_O, CALL_NO_KW); + STAT_INC(CALL_NO_KW, hit); + assert(extra_args == 1); + extra_args = 0; + assert(STACK_ADJUST_IS_RESET); + PyCFunction cfunc = ((PyMethodDescrObject *)callable)->d_method->ml_meth; + // This is slower but CPython promises to check all non-vectorcall + // function calls. + if (_Py_EnterRecursiveCall(tstate, " while calling a Python object")) { + goto error; + } + PyObject *arg = POP(); + PyObject *self = POP(); + PyObject *res = cfunc(self, arg); + _Py_LeaveRecursiveCall(tstate); + assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); + Py_DECREF(self); + Py_DECREF(arg); + SET_TOP(res); + Py_DECREF(callable); + if (res == NULL) { + goto error; + } + DISPATCH(); + } + + TARGET(CALL_NO_KW_METHOD_DESCRIPTOR_FAST) { + assert(_Py_OPCODE(next_instr[-2]) == PRECALL_METHOD); + /* Builtin METH_FASTCALL methods, without keywords */ + SpecializedCacheEntry *caches = GET_CACHE(); + _PyAdaptiveEntry *cache0 = &caches[0].adaptive; + DEOPT_IF(extra_args == 0, CALL_NO_KW); + assert(extra_args == 1); + int nargs = cache0->original_oparg; + PyObject *callable = PEEK(nargs + 2); + DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL_NO_KW); + PyMethodDef *meth = ((PyMethodDescrObject *)callable)->d_method; + DEOPT_IF(meth->ml_flags != METH_FASTCALL, CALL_NO_KW); + STAT_INC(CALL_NO_KW, hit); + assert(extra_args == 1); + extra_args = 0; + assert(STACK_ADJUST_IS_RESET); + _PyCFunctionFast cfunc = (_PyCFunctionFast)(void(*)(void))meth->ml_meth; + PyObject *self = PEEK(nargs+1); + PyObject *res = cfunc(self, &PEEK(nargs), nargs); + assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); + /* Clear the stack of the arguments. */ + STACK_SHRINK(nargs+1); + for (int i = 0; i <= nargs; i++) { + Py_DECREF(stack_pointer[i]); + } + SET_TOP(res); + Py_DECREF(callable); + if (res == NULL) { + goto error; + } + DISPATCH(); + } + TARGET(CALL_FUNCTION_EX) { PREDICTED(CALL_FUNCTION_EX); PyObject *func, *callargs, *kwargs = NULL, *result; @@ -5289,7 +5389,7 @@ MISS_WITH_CACHE(LOAD_ATTR) MISS_WITH_CACHE(STORE_ATTR) MISS_WITH_CACHE(LOAD_GLOBAL) MISS_WITH_CACHE(LOAD_METHOD) -MISS_WITH_CACHE(CALL_FUNCTION) +MISS_WITH_CACHE(CALL_NO_KW) MISS_WITH_CACHE(BINARY_OP) MISS_WITH_CACHE(COMPARE_OP) MISS_WITH_CACHE(BINARY_SUBSCR) @@ -7509,7 +7609,7 @@ format_awaitable_error(PyThreadState *tstate, PyTypeObject *type, int prevprevop "that does not implement __await__: %.100s", type->tp_name); } - else if (prevopcode == WITH_EXCEPT_START || (prevopcode == CALL_FUNCTION && prevprevopcode == DUP_TOP)) { + else if (prevopcode == WITH_EXCEPT_START || (prevopcode == CALL_NO_KW && prevprevopcode == DUP_TOP)) { _PyErr_Format(tstate, PyExc_TypeError, "'async with' received an object from __aexit__ " "that does not implement __await__: %.100s", diff --git a/Python/compile.c b/Python/compile.c index 00e1e016969ad..afd9a629c0a9e 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1155,13 +1155,11 @@ stack_effect(int opcode, int oparg, int jump) return -oparg; /* Functions and calls */ - case CALL_FUNCTION: + case PRECALL_METHOD: + return -1; + case CALL_NO_KW: return -oparg; - case CALL_METHOD: - return -oparg-1; - case CALL_METHOD_KW: - return -oparg-2; - case CALL_FUNCTION_KW: + case CALL_KW: return -oparg-1; case CALL_FUNCTION_EX: return -1 - ((oparg & 0x01) != 0); @@ -1817,7 +1815,7 @@ compiler_call_exit_with_nones(struct compiler *c) { ADDOP_LOAD_CONST(c, Py_None); ADDOP(c, DUP_TOP); ADDOP(c, DUP_TOP); - ADDOP_I(c, CALL_FUNCTION, 3); + ADDOP_I(c, CALL_NO_KW, 3); return 1; } @@ -2166,7 +2164,7 @@ compiler_apply_decorators(struct compiler *c, asdl_expr_seq* decos) int old_end_col_offset = c->u->u_end_col_offset; for (Py_ssize_t i = asdl_seq_LEN(decos) - 1; i > -1; i--) { SET_LOC(c, (expr_ty)asdl_seq_GET(decos, i)); - ADDOP_I(c, CALL_FUNCTION, 1); + ADDOP_I(c, CALL_NO_KW, 1); } c->u->u_lineno = old_lineno; c->u->u_end_lineno = old_end_lineno; @@ -3885,7 +3883,7 @@ compiler_assert(struct compiler *c, stmt_ty s) ADDOP(c, LOAD_ASSERTION_ERROR); if (s->v.Assert.msg) { VISIT(c, expr, s->v.Assert.msg); - ADDOP_I(c, CALL_FUNCTION, 1); + ADDOP_I(c, CALL_NO_KW, 1); } ADDOP_I(c, RAISE_VARARGS, 1); compiler_use_next_block(c, end); @@ -4693,10 +4691,12 @@ maybe_optimize_method_call(struct compiler *c, expr_ty e) if (!compiler_call_simple_kw_helper(c, kwds, kwdsl)) { return 0; }; - ADDOP_I(c, CALL_METHOD_KW, argsl + kwdsl); + ADDOP_I(c, PRECALL_METHOD, argsl + kwdsl+1); + ADDOP_I(c, CALL_KW, argsl + kwdsl); } else { - ADDOP_I(c, CALL_METHOD, argsl); + ADDOP_I(c, PRECALL_METHOD, argsl); + ADDOP_I(c, CALL_NO_KW, argsl); } c->u->u_lineno = old_lineno; return 1; @@ -4763,7 +4763,8 @@ compiler_joined_str(struct compiler *c, expr_ty e) VISIT(c, expr, asdl_seq_GET(e->v.JoinedStr.values, i)); ADDOP_I(c, LIST_APPEND, 1); } - ADDOP_I(c, CALL_METHOD, 1); + ADDOP_I(c, PRECALL_METHOD, 1); + ADDOP_I(c, CALL_NO_KW, 1); } else { VISIT_SEQ(c, expr, e->v.JoinedStr.values); @@ -4935,11 +4936,11 @@ compiler_call_helper(struct compiler *c, if (!compiler_call_simple_kw_helper(c, keywords, nkwelts)) { return 0; }; - ADDOP_I(c, CALL_FUNCTION_KW, n + nelts + nkwelts); + ADDOP_I(c, CALL_KW, n + nelts + nkwelts); return 1; } else { - ADDOP_I(c, CALL_FUNCTION, n + nelts); + ADDOP_I(c, CALL_NO_KW, n + nelts); return 1; } @@ -5336,7 +5337,7 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type, ADDOP(c, GET_ITER); } - ADDOP_I(c, CALL_FUNCTION, 1); + ADDOP_I(c, CALL_NO_KW, 1); if (is_async_generator && type != COMP_GENEXP) { ADDOP(c, GET_AWAITABLE); diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index aeb9830cccc15..05bd9392d8ea9 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -39,34 +39,34 @@ static void *opcode_targets[256] = { &&TARGET_POP_EXCEPT_AND_RERAISE, &&TARGET_STORE_SUBSCR_LIST_INT, &&TARGET_STORE_SUBSCR_DICT, - &&TARGET_CALL_FUNCTION_ADAPTIVE, - &&TARGET_CALL_FUNCTION_BUILTIN_O, - &&TARGET_CALL_FUNCTION_BUILTIN_FAST, - &&TARGET_CALL_FUNCTION_LEN, - &&TARGET_CALL_FUNCTION_ISINSTANCE, - &&TARGET_CALL_FUNCTION_PY_SIMPLE, - &&TARGET_JUMP_ABSOLUTE_QUICK, - &&TARGET_LOAD_ATTR_ADAPTIVE, - &&TARGET_LOAD_ATTR_INSTANCE_VALUE, + &&TARGET_CALL_NO_KW_ADAPTIVE, + &&TARGET_CALL_NO_KW_BUILTIN_O, + &&TARGET_CALL_NO_KW_BUILTIN_FAST, + &&TARGET_CALL_NO_KW_LEN, + &&TARGET_CALL_NO_KW_ISINSTANCE, + &&TARGET_CALL_NO_KW_PY_SIMPLE, + &&TARGET_CALL_NO_KW_LIST_APPEND, + &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_O, + &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_FAST, &&TARGET_WITH_EXCEPT_START, &&TARGET_GET_AITER, &&TARGET_GET_ANEXT, &&TARGET_BEFORE_ASYNC_WITH, &&TARGET_BEFORE_WITH, &&TARGET_END_ASYNC_FOR, + &&TARGET_JUMP_ABSOLUTE_QUICK, + &&TARGET_LOAD_ATTR_ADAPTIVE, + &&TARGET_LOAD_ATTR_INSTANCE_VALUE, &&TARGET_LOAD_ATTR_WITH_HINT, &&TARGET_LOAD_ATTR_SLOT, + &&TARGET_STORE_SUBSCR, + &&TARGET_DELETE_SUBSCR, &&TARGET_LOAD_ATTR_MODULE, &&TARGET_LOAD_GLOBAL_ADAPTIVE, &&TARGET_LOAD_GLOBAL_MODULE, - &&TARGET_STORE_SUBSCR, - &&TARGET_DELETE_SUBSCR, &&TARGET_LOAD_GLOBAL_BUILTIN, &&TARGET_LOAD_METHOD_ADAPTIVE, &&TARGET_LOAD_METHOD_CACHED, - &&TARGET_LOAD_METHOD_CLASS, - &&TARGET_LOAD_METHOD_MODULE, - &&TARGET_LOAD_METHOD_NO_DICT, &&TARGET_GET_ITER, &&TARGET_GET_YIELD_FROM_ITER, &&TARGET_PRINT_EXPR, @@ -74,19 +74,19 @@ static void *opcode_targets[256] = { &&TARGET_YIELD_FROM, &&TARGET_GET_AWAITABLE, &&TARGET_LOAD_ASSERTION_ERROR, + &&TARGET_LOAD_METHOD_CLASS, + &&TARGET_LOAD_METHOD_MODULE, + &&TARGET_LOAD_METHOD_NO_DICT, &&TARGET_STORE_ATTR_ADAPTIVE, &&TARGET_STORE_ATTR_INSTANCE_VALUE, &&TARGET_STORE_ATTR_SLOT, &&TARGET_STORE_ATTR_WITH_HINT, - &&TARGET_LOAD_FAST__LOAD_FAST, - &&TARGET_STORE_FAST__LOAD_FAST, - &&TARGET_LOAD_FAST__LOAD_CONST, &&TARGET_LIST_TO_TUPLE, &&TARGET_RETURN_VALUE, &&TARGET_IMPORT_STAR, &&TARGET_SETUP_ANNOTATIONS, &&TARGET_YIELD_VALUE, - &&TARGET_LOAD_CONST__LOAD_FAST, + &&TARGET_LOAD_FAST__LOAD_FAST, &&TARGET_PREP_RERAISE_STAR, &&TARGET_POP_EXCEPT, &&TARGET_STORE_NAME, @@ -122,25 +122,25 @@ static void *opcode_targets[256] = { &&TARGET_COPY, &&TARGET_JUMP_IF_NOT_EXC_MATCH, &&TARGET_BINARY_OP, - &&TARGET_STORE_FAST__STORE_FAST, + &&TARGET_STORE_FAST__LOAD_FAST, &&TARGET_LOAD_FAST, &&TARGET_STORE_FAST, &&TARGET_DELETE_FAST, &&TARGET_JUMP_IF_NOT_EG_MATCH, - &&_unknown_opcode, + &&TARGET_LOAD_FAST__LOAD_CONST, &&TARGET_GEN_START, &&TARGET_RAISE_VARARGS, - &&TARGET_CALL_FUNCTION, + &&TARGET_LOAD_CONST__LOAD_FAST, &&TARGET_MAKE_FUNCTION, &&TARGET_BUILD_SLICE, - &&_unknown_opcode, + &&TARGET_STORE_FAST__STORE_FAST, &&TARGET_MAKE_CELL, &&TARGET_LOAD_CLOSURE, &&TARGET_LOAD_DEREF, &&TARGET_STORE_DEREF, &&TARGET_DELETE_DEREF, &&_unknown_opcode, - &&TARGET_CALL_FUNCTION_KW, + &&_unknown_opcode, &&TARGET_CALL_FUNCTION_EX, &&_unknown_opcode, &&TARGET_EXTENDED_ARG, @@ -160,16 +160,16 @@ static void *opcode_targets[256] = { &&_unknown_opcode, &&_unknown_opcode, &&TARGET_LOAD_METHOD, - &&TARGET_CALL_METHOD, + &&_unknown_opcode, &&TARGET_LIST_EXTEND, &&TARGET_SET_UPDATE, &&TARGET_DICT_MERGE, &&TARGET_DICT_UPDATE, - &&TARGET_CALL_METHOD_KW, - &&_unknown_opcode, - &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, + &&TARGET_PRECALL_METHOD, + &&TARGET_CALL_NO_KW, + &&TARGET_CALL_KW, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, diff --git a/Python/specialize.c b/Python/specialize.c index 5121845008100..bdcba46ed4d31 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -127,7 +127,7 @@ _Py_GetSpecializationStats(void) { err += add_stat_dict(stats, BINARY_SUBSCR, "binary_subscr"); err += add_stat_dict(stats, STORE_SUBSCR, "store_subscr"); err += add_stat_dict(stats, STORE_ATTR, "store_attr"); - err += add_stat_dict(stats, CALL_FUNCTION, "call_function"); + err += add_stat_dict(stats, CALL_NO_KW, "call_no_kw"); err += add_stat_dict(stats, BINARY_OP, "binary_op"); err += add_stat_dict(stats, COMPARE_OP, "compare_op"); if (err < 0) { @@ -186,7 +186,7 @@ _Py_PrintSpecializationStats(void) print_stats(out, &_specialization_stats[BINARY_SUBSCR], "binary_subscr"); print_stats(out, &_specialization_stats[STORE_SUBSCR], "store_subscr"); print_stats(out, &_specialization_stats[STORE_ATTR], "store_attr"); - print_stats(out, &_specialization_stats[CALL_FUNCTION], "call_function"); + print_stats(out, &_specialization_stats[CALL_NO_KW], "call_no_kw"); print_stats(out, &_specialization_stats[BINARY_OP], "binary_op"); print_stats(out, &_specialization_stats[COMPARE_OP], "compare_op"); if (out != stderr) { @@ -238,7 +238,7 @@ static uint8_t adaptive_opcodes[256] = { [LOAD_METHOD] = LOAD_METHOD_ADAPTIVE, [BINARY_SUBSCR] = BINARY_SUBSCR_ADAPTIVE, [STORE_SUBSCR] = STORE_SUBSCR_ADAPTIVE, - [CALL_FUNCTION] = CALL_FUNCTION_ADAPTIVE, + [CALL_NO_KW] = CALL_NO_KW_ADAPTIVE, [STORE_ATTR] = STORE_ATTR_ADAPTIVE, [BINARY_OP] = BINARY_OP_ADAPTIVE, [COMPARE_OP] = COMPARE_OP_ADAPTIVE, @@ -251,7 +251,7 @@ static uint8_t cache_requirements[256] = { [LOAD_METHOD] = 3, /* _PyAdaptiveEntry, _PyAttrCache and _PyObjectCache */ [BINARY_SUBSCR] = 2, /* _PyAdaptiveEntry, _PyObjectCache */ [STORE_SUBSCR] = 0, - [CALL_FUNCTION] = 2, /* _PyAdaptiveEntry and _PyObjectCache/_PyCallCache */ + [CALL_NO_KW] = 2, /* _PyAdaptiveEntry and _PyObjectCache/_PyCallCache */ [STORE_ATTR] = 2, /* _PyAdaptiveEntry and _PyAttrCache */ [BINARY_OP] = 1, // _PyAdaptiveEntry [COMPARE_OP] = 1, /* _PyAdaptiveEntry */ @@ -491,6 +491,8 @@ initial_counter_value(void) { #define SPEC_FAIL_PYCFUNCTION_NOARGS 16 #define SPEC_FAIL_BAD_CALL_FLAGS 17 #define SPEC_FAIL_CLASS 18 +#define SPEC_FAIL_C_METHOD_CALL 19 +#define SPEC_FAIL_METHDESCR_NON_METHOD 20 /* COMPARE_OP */ #define SPEC_FAIL_STRING_COMPARE 13 @@ -1261,7 +1263,51 @@ specialize_class_call( PyObject *callable, _Py_CODEUNIT *instr, int nargs, SpecializedCacheEntry *cache) { - SPECIALIZATION_FAIL(CALL_FUNCTION, SPEC_FAIL_CLASS); + SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_CLASS); + return -1; +} + +static PyMethodDescrObject *_list_append = NULL; +_Py_IDENTIFIER(append); + +static int +specialize_method_descriptor( + PyMethodDescrObject *descr, _Py_CODEUNIT *instr, + int nargs, SpecializedCacheEntry *cache) +{ + int oparg = cache->adaptive.original_oparg; + if (nargs - oparg != 1) { + SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_METHDESCR_NON_METHOD); + return -1; + } + if (_list_append == NULL) { + _list_append = (PyMethodDescrObject *)_PyType_LookupId(&PyList_Type, &PyId_append); + } + if (oparg == 1 && descr == _list_append) { + assert(_Py_OPCODE(instr[-1]) == PRECALL_METHOD); + *instr = _Py_MAKECODEUNIT(CALL_NO_KW_LIST_APPEND, _Py_OPARG(*instr)); + return 0; + } + + switch (descr->d_method->ml_flags & + (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O | + METH_KEYWORDS | METH_METHOD)) { + case METH_O: { + if (oparg != 1) { + SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_OUT_OF_RANGE); + return 1; + } + *instr = _Py_MAKECODEUNIT(CALL_NO_KW_METHOD_DESCRIPTOR_O, + _Py_OPARG(*instr)); + return 0; + } + case METH_FASTCALL: { + *instr = _Py_MAKECODEUNIT(CALL_NO_KW_METHOD_DESCRIPTOR_FAST, + _Py_OPARG(*instr)); + return 0; + } + } + SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_OTHER); return -1; } @@ -1274,15 +1320,19 @@ specialize_py_call( PyCodeObject *code = (PyCodeObject *)func->func_code; int kind = function_kind(code); if (kind != SIMPLE_FUNCTION) { - SPECIALIZATION_FAIL(CALL_FUNCTION, kind); + SPECIALIZATION_FAIL(CALL_NO_KW, kind); return -1; } int argcount = code->co_argcount; + if (argcount > 0xffff) { + SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_OUT_OF_RANGE); + return -1; + } int defcount = func->func_defaults == NULL ? 0 : (int)PyTuple_GET_SIZE(func->func_defaults); assert(defcount <= argcount); int min_args = argcount-defcount; if (nargs > argcount || nargs < min_args) { - SPECIALIZATION_FAIL(CALL_FUNCTION, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS); + SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS); return -1; } assert(nargs <= argcount && nargs >= min_args); @@ -1291,18 +1341,19 @@ specialize_py_call( assert(defstart >= 0 && deflen >= 0); assert(deflen == 0 || func->func_defaults != NULL); if (defstart > 0xffff || deflen > 0xffff) { - SPECIALIZATION_FAIL(CALL_FUNCTION, SPEC_FAIL_OUT_OF_RANGE); + SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_OUT_OF_RANGE); return -1; } int version = _PyFunction_GetVersionForCurrentState(func); if (version == 0) { - SPECIALIZATION_FAIL(CALL_FUNCTION, SPEC_FAIL_OUT_OF_VERSIONS); + SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_OUT_OF_VERSIONS); return -1; } + cache[0].adaptive.index = nargs; cache1->func_version = version; cache1->defaults_start = defstart; cache1->defaults_len = deflen; - *instr = _Py_MAKECODEUNIT(CALL_FUNCTION_PY_SIMPLE, _Py_OPARG(*instr)); + *instr = _Py_MAKECODEUNIT(CALL_NO_KW_PY_SIMPLE, _Py_OPARG(*instr)); return 0; } @@ -1335,6 +1386,10 @@ specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs, SpecializedCacheEntry *cache, PyObject *builtins) { _PyObjectCache *cache1 = &cache[-1].obj; + if (_Py_OPCODE(instr[-1]) == PRECALL_METHOD) { + SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_C_METHOD_CALL); + return -1; + } if (PyCFunction_GET_FUNCTION(callable) == NULL) { return 1; } @@ -1343,18 +1398,18 @@ specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs, METH_KEYWORDS | METH_METHOD)) { case METH_O: { if (nargs != 1) { - SPECIALIZATION_FAIL(CALL_FUNCTION, SPEC_FAIL_OUT_OF_RANGE); + SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_OUT_OF_RANGE); return 1; } /* len(o) */ PyObject *builtin_len = PyDict_GetItemString(builtins, "len"); if (callable == builtin_len) { cache1->obj = builtin_len; // borrowed - *instr = _Py_MAKECODEUNIT(CALL_FUNCTION_LEN, + *instr = _Py_MAKECODEUNIT(CALL_NO_KW_LEN, _Py_OPARG(*instr)); return 0; } - *instr = _Py_MAKECODEUNIT(CALL_FUNCTION_BUILTIN_O, + *instr = _Py_MAKECODEUNIT(CALL_NO_KW_BUILTIN_O, _Py_OPARG(*instr)); return 0; } @@ -1365,17 +1420,17 @@ specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs, builtins, "isinstance"); if (callable == builtin_isinstance) { cache1->obj = builtin_isinstance; // borrowed - *instr = _Py_MAKECODEUNIT(CALL_FUNCTION_ISINSTANCE, + *instr = _Py_MAKECODEUNIT(CALL_NO_KW_ISINSTANCE, _Py_OPARG(*instr)); return 0; } } - *instr = _Py_MAKECODEUNIT(CALL_FUNCTION_BUILTIN_FAST, + *instr = _Py_MAKECODEUNIT(CALL_NO_KW_BUILTIN_FAST, _Py_OPARG(*instr)); return 0; } default: - SPECIALIZATION_FAIL(CALL_FUNCTION, + SPECIALIZATION_FAIL(CALL_NO_KW, builtin_call_fail_kind(PyCFunction_GET_FLAGS(callable))); return 1; } @@ -1406,7 +1461,7 @@ call_fail_kind(PyObject *callable) - Specialize calling classes. */ int -_Py_Specialize_CallFunction( +_Py_Specialize_CallNoKw( PyObject *callable, _Py_CODEUNIT *instr, int nargs, SpecializedCacheEntry *cache, PyObject *builtins) @@ -1421,18 +1476,22 @@ _Py_Specialize_CallFunction( else if (PyType_Check(callable)) { fail = specialize_class_call(callable, instr, nargs, cache); } + else if (Py_IS_TYPE(callable, &PyMethodDescr_Type)) { + fail = specialize_method_descriptor( + (PyMethodDescrObject *)callable, instr, nargs, cache); + } else { - SPECIALIZATION_FAIL(CALL_FUNCTION, call_fail_kind(callable)); + SPECIALIZATION_FAIL(CALL_NO_KW, call_fail_kind(callable)); fail = -1; } _PyAdaptiveEntry *cache0 = &cache->adaptive; if (fail) { - STAT_INC(CALL_FUNCTION, specialization_failure); + STAT_INC(CALL_NO_KW, specialization_failure); assert(!PyErr_Occurred()); cache_backoff(cache0); } else { - STAT_INC(CALL_FUNCTION, specialization_success); + STAT_INC(CALL_NO_KW, specialization_success); assert(!PyErr_Occurred()); cache0->counter = initial_counter_value(); } From webhook-mailer at python.org Tue Dec 14 18:41:09 2021 From: webhook-mailer at python.org (markshannon) Date: Tue, 14 Dec 2021 23:41:09 -0000 Subject: [Python-checkins] Document new call opcodes for 3.11 (GH-30107) Message-ID: https://github.com/python/cpython/commit/f54fee7f37563fbd569596cf94aad023ac6c3179 commit: f54fee7f37563fbd569596cf94aad023ac6c3179 branch: main author: Mark Shannon committer: markshannon date: 2021-12-14T23:40:44Z summary: Document new call opcodes for 3.11 (GH-30107) files: M Doc/whatsnew/3.11.rst diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 793075c4b6173..3005d1d43f25b 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -373,9 +373,11 @@ CPython bytecode changes * Replaced all numeric ``BINARY_*`` and ``INPLACE_*`` instructions with a single :opcode:`BINARY_OP` implementation. -* Added a new :opcode:`CALL_METHOD_KW` opcode. Calls a method in a similar - fashion as :opcode:`CALL_METHOD`, but also supports keyword arguments. Works - in tandem with :opcode:`LOAD_METHOD`. +* Replaced the three call instructions: :opcode:`CALL_FUNCTION`, + :opcode:`CALL_FUNCTION_KW` and :opcode:`CALL_METHOD` with + :opcode:`CALL_NO_KW`, :opcode:`CALL_KW` and :opcode:`PRECALL_METHOD`. + This decouples the argument shifting for methods from the handling of + keyword arguments and allows better specialization of calls. * Removed ``COPY_DICT_WITHOUT_KEYS``. From webhook-mailer at python.org Wed Dec 15 05:08:38 2021 From: webhook-mailer at python.org (iritkatriel) Date: Wed, 15 Dec 2021 10:08:38 -0000 Subject: [Python-checkins] =?utf-8?q?bpo-26952=3A_=5Bargparse=5D_clearer_?= =?utf-8?q?error_when_formatting_an_empty_mutually=E2=80=A6_=28GH-30099=29?= Message-ID: https://github.com/python/cpython/commit/86de99588db3beff964137f4fe27dd1077a09b35 commit: 86de99588db3beff964137f4fe27dd1077a09b35 branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-12-15T10:08:26Z summary: bpo-26952: [argparse] clearer error when formatting an empty mutually? (GH-30099) files: A Misc/NEWS.d/next/Library/2021-12-14-13-18-45.bpo-26952.hjhISq.rst M Lib/argparse.py M Lib/test/test_argparse.py diff --git a/Lib/argparse.py b/Lib/argparse.py index b44fa4f0f65c3..8a81801ba9236 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -392,6 +392,9 @@ def _format_actions_usage(self, actions, groups): group_actions = set() inserts = {} for group in groups: + if not group._group_actions: + raise ValueError(f'empty group {group}') + try: start = actions.index(group._group_actions[0]) except ValueError: diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index f3edde3de8eef..eb37d4d365d24 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -2601,6 +2601,13 @@ def test_help(self): ''' self.assertEqual(parser.format_help(), textwrap.dedent(expected)) + def test_empty_group(self): + # See issue 26952 + parser = argparse.ArgumentParser() + group = parser.add_mutually_exclusive_group() + with self.assertRaises(ValueError): + parser.parse_args(['-h']) + class MEMixin(object): def test_failures_when_not_required(self): diff --git a/Misc/NEWS.d/next/Library/2021-12-14-13-18-45.bpo-26952.hjhISq.rst b/Misc/NEWS.d/next/Library/2021-12-14-13-18-45.bpo-26952.hjhISq.rst new file mode 100644 index 0000000000000..379dbb55c7ca8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-14-13-18-45.bpo-26952.hjhISq.rst @@ -0,0 +1 @@ +:mod:`argparse` raises :exc:`ValueError` with clear message when trying to render usage for an empty mutually-exclusive group. Previously it raised a cryptic :exc:`IndexError`. \ No newline at end of file From webhook-mailer at python.org Wed Dec 15 05:30:23 2021 From: webhook-mailer at python.org (markshannon) Date: Wed, 15 Dec 2021 10:30:23 -0000 Subject: [Python-checkins] bpo-46039: Split yield from in two (GH-30035) Message-ID: https://github.com/python/cpython/commit/0b50a4f0cdee41a18fb4ba6e75569f9cfaceb39e commit: 0b50a4f0cdee41a18fb4ba6e75569f9cfaceb39e branch: main author: Mark Shannon committer: markshannon date: 2021-12-15T10:30:09Z summary: bpo-46039: Split yield from in two (GH-30035) * Split YIELD_FROM opcode into SEND and JUMP_ABSOLUTE. * Remove YIELD_FROM opcode. files: A Misc/NEWS.d/next/Core and Builtins/2021-12-13-17-01-13.bpo-46039.TrCBbF.rst M Include/internal/pycore_frame.h M Include/opcode.h M Lib/importlib/_bootstrap_external.py M Lib/opcode.py M Objects/frameobject.c M Objects/genobject.c M Python/ceval.c M Python/compile.c M Python/opcode_targets.h diff --git a/Include/internal/pycore_frame.h b/Include/internal/pycore_frame.h index a55877b55fb8a..883bef199ba59 100644 --- a/Include/internal/pycore_frame.h +++ b/Include/internal/pycore_frame.h @@ -66,6 +66,7 @@ static inline PyObject **_PyFrame_Stackbase(InterpreterFrame *f) { static inline PyObject *_PyFrame_StackPeek(InterpreterFrame *f) { assert(f->stacktop > f->f_code->co_nlocalsplus); + assert(f->localsplus[f->stacktop-1] != NULL); return f->localsplus[f->stacktop-1]; } diff --git a/Include/opcode.h b/Include/opcode.h index 4d14081a6b618..bdabffd983871 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -37,7 +37,6 @@ extern "C" { #define GET_YIELD_FROM_ITER 69 #define PRINT_EXPR 70 #define LOAD_BUILD_CLASS 71 -#define YIELD_FROM 72 #define GET_AWAITABLE 73 #define LOAD_ASSERTION_ERROR 74 #define LIST_TO_TUPLE 82 @@ -81,6 +80,7 @@ extern "C" { #define COPY 120 #define JUMP_IF_NOT_EXC_MATCH 121 #define BINARY_OP 122 +#define SEND 123 #define LOAD_FAST 124 #define STORE_FAST 125 #define DELETE_FAST 126 @@ -154,15 +154,15 @@ extern "C" { #define LOAD_GLOBAL_BUILTIN 65 #define LOAD_METHOD_ADAPTIVE 66 #define LOAD_METHOD_CACHED 67 -#define LOAD_METHOD_CLASS 75 -#define LOAD_METHOD_MODULE 76 -#define LOAD_METHOD_NO_DICT 77 -#define STORE_ATTR_ADAPTIVE 78 -#define STORE_ATTR_INSTANCE_VALUE 79 -#define STORE_ATTR_SLOT 80 -#define STORE_ATTR_WITH_HINT 81 -#define LOAD_FAST__LOAD_FAST 87 -#define STORE_FAST__LOAD_FAST 123 +#define LOAD_METHOD_CLASS 72 +#define LOAD_METHOD_MODULE 75 +#define LOAD_METHOD_NO_DICT 76 +#define STORE_ATTR_ADAPTIVE 77 +#define STORE_ATTR_INSTANCE_VALUE 78 +#define STORE_ATTR_SLOT 79 +#define STORE_ATTR_WITH_HINT 80 +#define LOAD_FAST__LOAD_FAST 81 +#define STORE_FAST__LOAD_FAST 87 #define LOAD_FAST__LOAD_CONST 128 #define LOAD_CONST__LOAD_FAST 131 #define STORE_FAST__STORE_FAST 134 @@ -172,7 +172,7 @@ static uint32_t _PyOpcode_RelativeJump[8] = { 0U, 0U, 536870912U, - 16384U, + 134234112U, 0U, 0U, 0U, @@ -182,7 +182,7 @@ static uint32_t _PyOpcode_Jump[8] = { 0U, 0U, 536870912U, - 2182070272U, + 2316288000U, 0U, 0U, 0U, diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index abd0170cac070..0c1078accc819 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -373,6 +373,7 @@ def _write_atomic(path, data, mode=0o666): # Python 3.11a3 3465 (Add COPY_FREE_VARS opcode) # Python 3.11a3 3466 (bpo-45292: PEP-654 except*) # Python 3.11a4 3467 (Change CALL_xxx opcodes) +# Python 3.11a4 3468 (Add SEND opcode) # # MAGIC must change whenever the bytecode emitted by the compiler may no @@ -382,7 +383,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 = (3467).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3468).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c _PYCACHE = '__pycache__' diff --git a/Lib/opcode.py b/Lib/opcode.py index 0b64686d605f9..cb16ef78313fb 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -93,7 +93,7 @@ def jabs_op(name, op): def_op('GET_YIELD_FROM_ITER', 69) def_op('PRINT_EXPR', 70) def_op('LOAD_BUILD_CLASS', 71) -def_op('YIELD_FROM', 72) + def_op('GET_AWAITABLE', 73) def_op('LOAD_ASSERTION_ERROR', 74) @@ -143,7 +143,7 @@ def jabs_op(name, op): def_op('COPY', 120) jabs_op('JUMP_IF_NOT_EXC_MATCH', 121) def_op('BINARY_OP', 122) - +jrel_op('SEND', 123) # Number of bytes to skip def_op('LOAD_FAST', 124) # Local variable number haslocal.append(124) def_op('STORE_FAST', 125) # Local variable number diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-13-17-01-13.bpo-46039.TrCBbF.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-13-17-01-13.bpo-46039.TrCBbF.rst new file mode 100644 index 0000000000000..18bdc34d21c6b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-13-17-01-13.bpo-46039.TrCBbF.rst @@ -0,0 +1,2 @@ +Remove the ``YIELD_FROM`` instruction and replace it with the ``SEND`` +instruction which performs the same operation, but without the loop. diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 82931b6e85f07..fc62713aa241a 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -249,7 +249,13 @@ mark_stacks(PyCodeObject *code_obj, int len) next_stack = pop_value(pop_value(pop_value(next_stack))); stacks[i+1] = next_stack; break; - + case SEND: + j = get_arg(code, i) + i + 1; + assert(j < len); + assert(stacks[j] == UNINITIALIZED || stacks[j] == pop_value(next_stack)); + stacks[j] = pop_value(next_stack); + stacks[i+1] = next_stack; + break; case JUMP_FORWARD: j = get_arg(code, i) + i + 1; assert(j < len); diff --git a/Objects/genobject.c b/Objects/genobject.c index 1b08b43ac22e9..24a4e94bfc7a2 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -10,7 +10,7 @@ #include "pycore_frame.h" // InterpreterFrame #include "frameobject.h" // PyFrameObject #include "structmember.h" // PyMemberDef -#include "opcode.h" // YIELD_FROM +#include "opcode.h" // SEND static PyObject *gen_close(PyGenObject *, PyObject *); static PyObject *async_gen_asend_new(PyAsyncGenObject *, PyObject *); @@ -356,14 +356,14 @@ _PyGen_yf(PyGenObject *gen) unsigned char *code = (unsigned char *)PyBytes_AS_STRING(bytecode); if (frame->f_lasti < 0) { - /* Return immediately if the frame didn't start yet. YIELD_FROM + /* Return immediately if the frame didn't start yet. SEND always come after LOAD_CONST: a code object should not start - with YIELD_FROM */ - assert(code[0] != YIELD_FROM); + with SEND */ + assert(code[0] != SEND); return NULL; } - if (code[(frame->f_lasti+1)*sizeof(_Py_CODEUNIT)] != YIELD_FROM) + if (code[frame->f_lasti*sizeof(_Py_CODEUNIT)] != SEND || frame->stacktop < 0) return NULL; yf = _PyFrame_StackPeek(frame); Py_INCREF(yf); @@ -486,9 +486,13 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, ret = _PyFrame_StackPop((InterpreterFrame *)gen->gi_iframe); assert(ret == yf); Py_DECREF(ret); - /* Termination repetition of YIELD_FROM */ + /* Termination repetition of SEND loop */ assert(frame->f_lasti >= 0); - frame->f_lasti += 1; + PyObject *bytecode = gen->gi_code->co_code; + unsigned char *code = (unsigned char *)PyBytes_AS_STRING(bytecode); + assert(code[frame->f_lasti*sizeof(_Py_CODEUNIT)] == SEND); + int jump = code[frame->f_lasti*sizeof(_Py_CODEUNIT)+1]; + frame->f_lasti += jump; if (_PyGen_FetchStopIterationValue(&val) == 0) { ret = gen_send(gen, val); Py_DECREF(val); diff --git a/Python/ceval.c b/Python/ceval.c index 6d2784894f74f..79324330d264c 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1798,7 +1798,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr if (_Py_atomic_load_relaxed(eval_breaker)) { opcode = _Py_OPCODE(*next_instr); if (opcode != BEFORE_ASYNC_WITH && - opcode != YIELD_FROM) { + opcode != SEND && + _Py_OPCODE(next_instr[-1]) != SEND) { /* Few cases where we skip running signal handlers and other pending calls: - If we're about to enter the 'with:'. It will prevent @@ -2642,8 +2643,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr DISPATCH(); } - TARGET(YIELD_FROM) { + TARGET(SEND) { assert(frame->depth == 0); + assert(STACK_LEVEL() >= 2); PyObject *v = POP(); PyObject *receiver = TOP(); PySendResult gen_status; @@ -2680,17 +2682,13 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr } if (gen_status == PYGEN_RETURN) { assert (retval != NULL); - Py_DECREF(receiver); SET_TOP(retval); - retval = NULL; + JUMPBY(oparg); DISPATCH(); } assert (gen_status == PYGEN_NEXT); - /* receiver remains on stack, retval is value to be yielded */ - /* and repeat... */ - assert(frame->f_lasti > 0); - frame->f_lasti -= 1; + assert (retval != NULL); frame->f_state = FRAME_SUSPENDED; _PyFrame_SetStackPointer(frame, stack_pointer); TRACE_FUNCTION_EXIT(); @@ -6770,8 +6768,11 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj, return -1; } if (line != -1 && f->f_trace_lines) { - /* Trace backward edges or if line number has changed */ - if (frame->f_lasti < instr_prev || line != lastline) { + /* Trace backward edges (except in 'yield from') or if line number has changed */ + int trace = line != lastline || + (frame->f_lasti < instr_prev && + _Py_OPCODE(frame->f_code->co_firstinstr[frame->f_lasti]) != SEND); + if (trace) { result = call_trace(func, obj, tstate, frame, PyTrace_LINE, Py_None); } } diff --git a/Python/compile.c b/Python/compile.c index afd9a629c0a9e..6179ad980aade 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1045,8 +1045,6 @@ stack_effect(int opcode, int oparg, int jump) return 0; case YIELD_VALUE: return 0; - case YIELD_FROM: - return -1; case POP_BLOCK: return 0; case POP_EXCEPT: @@ -1065,7 +1063,8 @@ stack_effect(int opcode, int oparg, int jump) case FOR_ITER: /* -1 at end of iterator, 1 if continue iterating. */ return jump > 0 ? -1 : 1; - + case SEND: + return jump > 0 ? -1 : 0; case STORE_ATTR: return -2; case DELETE_ATTR: @@ -1667,6 +1666,9 @@ compiler_addop_j_noline(struct compiler *c, int opcode, basicblock *b) the ASDL name to synthesize the name of the C type and the visit function. */ +#define ADD_YIELD_FROM(C) \ + RETURN_IF_FALSE(compiler_add_yield_from((C))) + #define VISIT(C, TYPE, V) {\ if (!compiler_visit_ ## TYPE((C), (V))) \ return 0; \ @@ -1819,6 +1821,24 @@ compiler_call_exit_with_nones(struct compiler *c) { return 1; } +static int +compiler_add_yield_from(struct compiler *c) +{ + basicblock *start, *jump, *exit; + start = compiler_new_block(c); + jump = compiler_new_block(c); + exit = compiler_new_block(c); + if (start == NULL || jump == NULL || exit == NULL) { + return 0; + } + compiler_use_next_block(c, start); + ADDOP_JUMP(c, SEND, exit); + compiler_use_next_block(c, jump); + ADDOP_JUMP(c, JUMP_ABSOLUTE, start); + compiler_use_next_block(c, exit); + return 1; +} + /* Unwind a frame block. If preserve_tos is true, the TOS before * popping the blocks will be restored afterwards, unless another * return, break or continue is found. In which case, the TOS will @@ -1893,7 +1913,7 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info, if (info->fb_type == ASYNC_WITH) { ADDOP(c, GET_AWAITABLE); ADDOP_LOAD_CONST(c, Py_None); - ADDOP(c, YIELD_FROM); + ADD_YIELD_FROM(c); } ADDOP(c, POP_TOP); /* The exit block should appear to execute after the @@ -3006,7 +3026,7 @@ compiler_async_for(struct compiler *c, stmt_ty s) ADDOP_JUMP(c, SETUP_FINALLY, except); ADDOP(c, GET_ANEXT); ADDOP_LOAD_CONST(c, Py_None); - ADDOP(c, YIELD_FROM); + ADD_YIELD_FROM(c); ADDOP(c, POP_BLOCK); /* for SETUP_FINALLY */ /* Success block for __anext__ */ @@ -5192,7 +5212,7 @@ compiler_async_comprehension_generator(struct compiler *c, ADDOP_JUMP(c, SETUP_FINALLY, except); ADDOP(c, GET_ANEXT); ADDOP_LOAD_CONST(c, Py_None); - ADDOP(c, YIELD_FROM); + ADD_YIELD_FROM(c); ADDOP(c, POP_BLOCK); VISIT(c, expr, gen->target); @@ -5342,7 +5362,7 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type, if (is_async_generator && type != COMP_GENEXP) { ADDOP(c, GET_AWAITABLE); ADDOP_LOAD_CONST(c, Py_None); - ADDOP(c, YIELD_FROM); + ADD_YIELD_FROM(c); } return 1; @@ -5493,7 +5513,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos) ADDOP(c, BEFORE_ASYNC_WITH); ADDOP(c, GET_AWAITABLE); ADDOP_LOAD_CONST(c, Py_None); - ADDOP(c, YIELD_FROM); + ADD_YIELD_FROM(c); ADDOP_JUMP(c, SETUP_WITH, final); @@ -5530,7 +5550,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos) return 0; ADDOP(c, GET_AWAITABLE); ADDOP_LOAD_CONST(c, Py_None); - ADDOP(c, YIELD_FROM); + ADD_YIELD_FROM(c); ADDOP(c, POP_TOP); @@ -5544,7 +5564,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos) ADDOP(c, WITH_EXCEPT_START); ADDOP(c, GET_AWAITABLE); ADDOP_LOAD_CONST(c, Py_None); - ADDOP(c, YIELD_FROM); + ADD_YIELD_FROM(c); compiler_with_except_finish(c, cleanup); compiler_use_next_block(c, exit); @@ -5701,7 +5721,7 @@ compiler_visit_expr1(struct compiler *c, expr_ty e) VISIT(c, expr, e->v.YieldFrom.value); ADDOP(c, GET_YIELD_FROM_ITER); ADDOP_LOAD_CONST(c, Py_None); - ADDOP(c, YIELD_FROM); + ADD_YIELD_FROM(c); break; case Await_kind: if (!IS_TOP_LEVEL_AWAIT(c)){ @@ -5718,7 +5738,7 @@ compiler_visit_expr1(struct compiler *c, expr_ty e) VISIT(c, expr, e->v.Await.value); ADDOP(c, GET_AWAITABLE); ADDOP_LOAD_CONST(c, Py_None); - ADDOP(c, YIELD_FROM); + ADD_YIELD_FROM(c); break; case Compare_kind: return compiler_compare(c, e); @@ -7544,10 +7564,13 @@ normalize_jumps(struct assembler *a) continue; } struct instr *last = &b->b_instr[b->b_iused-1]; - if (last->i_opcode == JUMP_ABSOLUTE && - last->i_target->b_visited == 0 - ) { - last->i_opcode = JUMP_FORWARD; + if (last->i_opcode == JUMP_ABSOLUTE) { + if (last->i_target->b_visited == 0) { + last->i_opcode = JUMP_FORWARD; + } + else if (b->b_iused >= 2 && b->b_instr[b->b_iused-2].i_opcode == SEND) { + last->i_opcode = JUMP_ABSOLUTE_QUICK; + } } } } diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 05bd9392d8ea9..3b2e99d5a32a3 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -71,22 +71,22 @@ static void *opcode_targets[256] = { &&TARGET_GET_YIELD_FROM_ITER, &&TARGET_PRINT_EXPR, &&TARGET_LOAD_BUILD_CLASS, - &&TARGET_YIELD_FROM, + &&TARGET_LOAD_METHOD_CLASS, &&TARGET_GET_AWAITABLE, &&TARGET_LOAD_ASSERTION_ERROR, - &&TARGET_LOAD_METHOD_CLASS, &&TARGET_LOAD_METHOD_MODULE, &&TARGET_LOAD_METHOD_NO_DICT, &&TARGET_STORE_ATTR_ADAPTIVE, &&TARGET_STORE_ATTR_INSTANCE_VALUE, &&TARGET_STORE_ATTR_SLOT, &&TARGET_STORE_ATTR_WITH_HINT, + &&TARGET_LOAD_FAST__LOAD_FAST, &&TARGET_LIST_TO_TUPLE, &&TARGET_RETURN_VALUE, &&TARGET_IMPORT_STAR, &&TARGET_SETUP_ANNOTATIONS, &&TARGET_YIELD_VALUE, - &&TARGET_LOAD_FAST__LOAD_FAST, + &&TARGET_STORE_FAST__LOAD_FAST, &&TARGET_PREP_RERAISE_STAR, &&TARGET_POP_EXCEPT, &&TARGET_STORE_NAME, @@ -122,7 +122,7 @@ static void *opcode_targets[256] = { &&TARGET_COPY, &&TARGET_JUMP_IF_NOT_EXC_MATCH, &&TARGET_BINARY_OP, - &&TARGET_STORE_FAST__LOAD_FAST, + &&TARGET_SEND, &&TARGET_LOAD_FAST, &&TARGET_STORE_FAST, &&TARGET_DELETE_FAST, From webhook-mailer at python.org Wed Dec 15 06:24:45 2021 From: webhook-mailer at python.org (miss-islington) Date: Wed, 15 Dec 2021 11:24:45 -0000 Subject: [Python-checkins] Add Positional only arguments forward slash (/) to sorted() function in Built-in Functions document (GH-30113) Message-ID: https://github.com/python/cpython/commit/f025ae63dccf96c4a1d781a6438bd9ed1502f0a1 commit: f025ae63dccf96c4a1d781a6438bd9ed1502f0a1 branch: main author: Vivek Vashist committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-15T03:24:38-08:00 summary: Add Positional only arguments forward slash (/) to sorted() function in Built-in Functions document (GH-30113) sorted() function is missing forward slash (/) in Built-in Functions documentation page. Automerge-Triggered-By: GH:asvetlov files: M Doc/library/functions.rst diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index ebcd6c801d70e..059a058d5888c 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1571,7 +1571,7 @@ are always available. They are listed here in alphabetical order. :func:`itertools.islice` for an alternate version that returns an iterator. -.. function:: sorted(iterable, *, key=None, reverse=False) +.. function:: sorted(iterable, /, *, key=None, reverse=False) Return a new sorted list from the items in *iterable*. From webhook-mailer at python.org Wed Dec 15 07:20:26 2021 From: webhook-mailer at python.org (iritkatriel) Date: Wed, 15 Dec 2021 12:20:26 -0000 Subject: [Python-checkins] =?utf-8?q?bpo-26952=3A_=5Bargparse=5D_clearer_?= =?utf-8?q?error_when_formatting_an_empty_mutually=E2=80=A6_=28GH-30099=29?= =?utf-8?q?_=28GH-30114=29?= Message-ID: https://github.com/python/cpython/commit/8e4c96295bd78ae5f70b908e5dbac0da7c4c21bd commit: 8e4c96295bd78ae5f70b908e5dbac0da7c4c21bd branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-12-15T12:20:04Z summary: bpo-26952: [argparse] clearer error when formatting an empty mutually? (GH-30099) (GH-30114) (cherry picked from commit 86de99588db3beff964137f4fe27dd1077a09b35) Co-authored-by: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> files: A Misc/NEWS.d/next/Library/2021-12-14-13-18-45.bpo-26952.hjhISq.rst M Lib/argparse.py M Lib/test/test_argparse.py diff --git a/Lib/argparse.py b/Lib/argparse.py index 9eed24c2a2a76..b2db312b8fdfd 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -392,6 +392,9 @@ def _format_actions_usage(self, actions, groups): group_actions = set() inserts = {} for group in groups: + if not group._group_actions: + raise ValueError(f'empty group {group}') + try: start = actions.index(group._group_actions[0]) except ValueError: diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index ec49b2acbbb85..c96a540a8b315 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -2582,6 +2582,13 @@ def test_help(self): ''' self.assertEqual(parser.format_help(), textwrap.dedent(expected)) + def test_empty_group(self): + # See issue 26952 + parser = argparse.ArgumentParser() + group = parser.add_mutually_exclusive_group() + with self.assertRaises(ValueError): + parser.parse_args(['-h']) + class MEMixin(object): def test_failures_when_not_required(self): diff --git a/Misc/NEWS.d/next/Library/2021-12-14-13-18-45.bpo-26952.hjhISq.rst b/Misc/NEWS.d/next/Library/2021-12-14-13-18-45.bpo-26952.hjhISq.rst new file mode 100644 index 0000000000000..379dbb55c7ca8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-14-13-18-45.bpo-26952.hjhISq.rst @@ -0,0 +1 @@ +:mod:`argparse` raises :exc:`ValueError` with clear message when trying to render usage for an empty mutually-exclusive group. Previously it raised a cryptic :exc:`IndexError`. \ No newline at end of file From webhook-mailer at python.org Wed Dec 15 07:24:54 2021 From: webhook-mailer at python.org (iritkatriel) Date: Wed, 15 Dec 2021 12:24:54 -0000 Subject: [Python-checkins] =?utf-8?q?bpo-26952=3A_=5Bargparse=5D_clearer_?= =?utf-8?q?error_when_formatting_an_empty_mutually=E2=80=A6_=28GH-30099=29?= =?utf-8?q?_=28GH-30115=29?= Message-ID: https://github.com/python/cpython/commit/f0b274d2e21e6c7c1c0f56464070108f9bd00d20 commit: f0b274d2e21e6c7c1c0f56464070108f9bd00d20 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-12-15T12:24:48Z summary: bpo-26952: [argparse] clearer error when formatting an empty mutually? (GH-30099) (GH-30115) (cherry picked from commit 86de99588db3beff964137f4fe27dd1077a09b35) Co-authored-by: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> files: A Misc/NEWS.d/next/Library/2021-12-14-13-18-45.bpo-26952.hjhISq.rst M Lib/argparse.py M Lib/test/test_argparse.py diff --git a/Lib/argparse.py b/Lib/argparse.py index 7c28547f3e522..40569437ac62b 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -392,6 +392,9 @@ def _format_actions_usage(self, actions, groups): group_actions = set() inserts = {} for group in groups: + if not group._group_actions: + raise ValueError(f'empty group {group}') + try: start = actions.index(group._group_actions[0]) except ValueError: diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index d79ac5a4651d9..043a9cf93f771 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -2582,6 +2582,13 @@ def test_help(self): ''' self.assertEqual(parser.format_help(), textwrap.dedent(expected)) + def test_empty_group(self): + # See issue 26952 + parser = argparse.ArgumentParser() + group = parser.add_mutually_exclusive_group() + with self.assertRaises(ValueError): + parser.parse_args(['-h']) + class MEMixin(object): def test_failures_when_not_required(self): diff --git a/Misc/NEWS.d/next/Library/2021-12-14-13-18-45.bpo-26952.hjhISq.rst b/Misc/NEWS.d/next/Library/2021-12-14-13-18-45.bpo-26952.hjhISq.rst new file mode 100644 index 0000000000000..379dbb55c7ca8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-14-13-18-45.bpo-26952.hjhISq.rst @@ -0,0 +1 @@ +:mod:`argparse` raises :exc:`ValueError` with clear message when trying to render usage for an empty mutually-exclusive group. Previously it raised a cryptic :exc:`IndexError`. \ No newline at end of file From webhook-mailer at python.org Wed Dec 15 07:59:18 2021 From: webhook-mailer at python.org (miss-islington) Date: Wed, 15 Dec 2021 12:59:18 -0000 Subject: [Python-checkins] Add Positional only arguments forward slash (/) to sorted() function in Built-in Functions document (GH-30113) Message-ID: https://github.com/python/cpython/commit/c8044777cf8c4e9bf05d1ab69fd4005089709147 commit: c8044777cf8c4e9bf05d1ab69fd4005089709147 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-15T04:59:01-08:00 summary: Add Positional only arguments forward slash (/) to sorted() function in Built-in Functions document (GH-30113) sorted() function is missing forward slash (/) in Built-in Functions documentation page. Automerge-Triggered-By: GH:asvetlov (cherry picked from commit f025ae63dccf96c4a1d781a6438bd9ed1502f0a1) Co-authored-by: Vivek Vashist files: M Doc/library/functions.rst diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index a117d30c0b0d5..9a9c87e32013c 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1582,7 +1582,7 @@ are always available. They are listed here in alphabetical order. :func:`itertools.islice` for an alternate version that returns an iterator. -.. function:: sorted(iterable, *, key=None, reverse=False) +.. function:: sorted(iterable, /, *, key=None, reverse=False) Return a new sorted list from the items in *iterable*. From webhook-mailer at python.org Wed Dec 15 08:00:08 2021 From: webhook-mailer at python.org (miss-islington) Date: Wed, 15 Dec 2021 13:00:08 -0000 Subject: [Python-checkins] Add Positional only arguments forward slash (/) to sorted() function in Built-in Functions document (GH-30113) Message-ID: https://github.com/python/cpython/commit/86f9ae53da0b8ccba63750ef0ac313f9f931fc0c commit: 86f9ae53da0b8ccba63750ef0ac313f9f931fc0c branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-15T05:00:03-08:00 summary: Add Positional only arguments forward slash (/) to sorted() function in Built-in Functions document (GH-30113) sorted() function is missing forward slash (/) in Built-in Functions documentation page. Automerge-Triggered-By: GH:asvetlov (cherry picked from commit f025ae63dccf96c4a1d781a6438bd9ed1502f0a1) Co-authored-by: Vivek Vashist files: M Doc/library/functions.rst diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 4aa900c547714..8df557e47a16e 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1527,7 +1527,7 @@ are always available. They are listed here in alphabetical order. :func:`itertools.islice` for an alternate version that returns an iterator. -.. function:: sorted(iterable, *, key=None, reverse=False) +.. function:: sorted(iterable, /, *, key=None, reverse=False) Return a new sorted list from the items in *iterable*. From webhook-mailer at python.org Wed Dec 15 10:03:47 2021 From: webhook-mailer at python.org (markshannon) Date: Wed, 15 Dec 2021 15:03:47 -0000 Subject: [Python-checkins] bpo-44525: Specialize for calls to type and other builtin classes with 1 argument. (GH-29942) Message-ID: https://github.com/python/cpython/commit/3a60bfef49b3324660a615a8e6d10710e5f669d9 commit: 3a60bfef49b3324660a615a8e6d10710e5f669d9 branch: main author: Mark Shannon committer: markshannon date: 2021-12-15T15:03:42Z summary: bpo-44525: Specialize for calls to type and other builtin classes with 1 argument. (GH-29942) files: A Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-04-21.bpo-44525.6OWCgr.rst M Include/opcode.h M Lib/opcode.py M Python/ceval.c M Python/opcode_targets.h M Python/specialize.c diff --git a/Include/opcode.h b/Include/opcode.h index bdabffd983871..05565267941fd 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -142,30 +142,32 @@ extern "C" { #define CALL_NO_KW_PY_SIMPLE 45 #define CALL_NO_KW_LIST_APPEND 46 #define CALL_NO_KW_METHOD_DESCRIPTOR_O 47 -#define CALL_NO_KW_METHOD_DESCRIPTOR_FAST 48 -#define JUMP_ABSOLUTE_QUICK 55 -#define LOAD_ATTR_ADAPTIVE 56 -#define LOAD_ATTR_INSTANCE_VALUE 57 -#define LOAD_ATTR_WITH_HINT 58 -#define LOAD_ATTR_SLOT 59 -#define LOAD_ATTR_MODULE 62 -#define LOAD_GLOBAL_ADAPTIVE 63 -#define LOAD_GLOBAL_MODULE 64 -#define LOAD_GLOBAL_BUILTIN 65 -#define LOAD_METHOD_ADAPTIVE 66 -#define LOAD_METHOD_CACHED 67 -#define LOAD_METHOD_CLASS 72 -#define LOAD_METHOD_MODULE 75 -#define LOAD_METHOD_NO_DICT 76 -#define STORE_ATTR_ADAPTIVE 77 -#define STORE_ATTR_INSTANCE_VALUE 78 -#define STORE_ATTR_SLOT 79 -#define STORE_ATTR_WITH_HINT 80 -#define LOAD_FAST__LOAD_FAST 81 -#define STORE_FAST__LOAD_FAST 87 -#define LOAD_FAST__LOAD_CONST 128 -#define LOAD_CONST__LOAD_FAST 131 -#define STORE_FAST__STORE_FAST 134 +#define CALL_NO_KW_TYPE_1 48 +#define CALL_NO_KW_BUILTIN_CLASS_1 55 +#define CALL_NO_KW_METHOD_DESCRIPTOR_FAST 56 +#define JUMP_ABSOLUTE_QUICK 57 +#define LOAD_ATTR_ADAPTIVE 58 +#define LOAD_ATTR_INSTANCE_VALUE 59 +#define LOAD_ATTR_WITH_HINT 62 +#define LOAD_ATTR_SLOT 63 +#define LOAD_ATTR_MODULE 64 +#define LOAD_GLOBAL_ADAPTIVE 65 +#define LOAD_GLOBAL_MODULE 66 +#define LOAD_GLOBAL_BUILTIN 67 +#define LOAD_METHOD_ADAPTIVE 72 +#define LOAD_METHOD_CACHED 75 +#define LOAD_METHOD_CLASS 76 +#define LOAD_METHOD_MODULE 77 +#define LOAD_METHOD_NO_DICT 78 +#define STORE_ATTR_ADAPTIVE 79 +#define STORE_ATTR_INSTANCE_VALUE 80 +#define STORE_ATTR_SLOT 81 +#define STORE_ATTR_WITH_HINT 87 +#define LOAD_FAST__LOAD_FAST 128 +#define STORE_FAST__LOAD_FAST 131 +#define LOAD_FAST__LOAD_CONST 134 +#define LOAD_CONST__LOAD_FAST 140 +#define STORE_FAST__STORE_FAST 141 #define DO_TRACING 255 #ifdef NEED_OPCODE_JUMP_TABLES static uint32_t _PyOpcode_RelativeJump[8] = { diff --git a/Lib/opcode.py b/Lib/opcode.py index cb16ef78313fb..7b69988f91315 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -259,6 +259,8 @@ def jabs_op(name, op): "CALL_NO_KW_PY_SIMPLE", "CALL_NO_KW_LIST_APPEND", "CALL_NO_KW_METHOD_DESCRIPTOR_O", + "CALL_NO_KW_TYPE_1", + "CALL_NO_KW_BUILTIN_CLASS_1", "CALL_NO_KW_METHOD_DESCRIPTOR_FAST", "JUMP_ABSOLUTE_QUICK", "LOAD_ATTR_ADAPTIVE", diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-04-21.bpo-44525.6OWCgr.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-04-21.bpo-44525.6OWCgr.rst new file mode 100644 index 0000000000000..8e1533f477e3d --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-04-21.bpo-44525.6OWCgr.rst @@ -0,0 +1,3 @@ +Specialize the CALL_FUNCTION instruction for calls to builtin types with a +single argument. Speeds up ``range(x)``, ``list(x)``, and specifically +``type(obj)``. diff --git a/Python/ceval.c b/Python/ceval.c index 79324330d264c..b9444b22138f0 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4854,6 +4854,41 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr goto start_frame; } + TARGET(CALL_NO_KW_TYPE_1) { + assert(STACK_ADJUST_IS_RESET); + assert(GET_CACHE()->adaptive.original_oparg == 1); + PyObject *obj = TOP(); + PyObject *callable = SECOND(); + DEOPT_IF(callable != (PyObject *)&PyType_Type, CALL_NO_KW); + PyObject *res = Py_NewRef(Py_TYPE(obj)); + STACK_SHRINK(1); + Py_DECREF(callable); + Py_DECREF(obj); + SET_TOP(res); + DISPATCH(); + } + + TARGET(CALL_NO_KW_BUILTIN_CLASS_1) { + assert(STACK_ADJUST_IS_RESET); + SpecializedCacheEntry *caches = GET_CACHE(); + _PyAdaptiveEntry *cache0 = &caches[0].adaptive; + assert(cache0->original_oparg == 1); + PyObject *callable = SECOND(); + PyObject *arg = TOP(); + DEOPT_IF(!PyType_Check(callable), CALL_NO_KW); + PyTypeObject *tp = (PyTypeObject *)callable; + DEOPT_IF(tp->tp_version_tag != cache0->version, CALL_NO_KW); + STACK_SHRINK(1); + PyObject *res = tp->tp_vectorcall((PyObject *)tp, stack_pointer, 1, NULL); + SET_TOP(res); + Py_DECREF(tp); + Py_DECREF(arg); + if (res == NULL) { + goto error; + } + DISPATCH(); + } + TARGET(CALL_NO_KW_BUILTIN_O) { assert(cframe.use_tracing == 0); assert(STACK_ADJUST_IS_RESET); diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 3b2e99d5a32a3..3ee0b9c7a904c 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -47,46 +47,46 @@ static void *opcode_targets[256] = { &&TARGET_CALL_NO_KW_PY_SIMPLE, &&TARGET_CALL_NO_KW_LIST_APPEND, &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_O, - &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_FAST, + &&TARGET_CALL_NO_KW_TYPE_1, &&TARGET_WITH_EXCEPT_START, &&TARGET_GET_AITER, &&TARGET_GET_ANEXT, &&TARGET_BEFORE_ASYNC_WITH, &&TARGET_BEFORE_WITH, &&TARGET_END_ASYNC_FOR, + &&TARGET_CALL_NO_KW_BUILTIN_CLASS_1, + &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_FAST, &&TARGET_JUMP_ABSOLUTE_QUICK, &&TARGET_LOAD_ATTR_ADAPTIVE, &&TARGET_LOAD_ATTR_INSTANCE_VALUE, - &&TARGET_LOAD_ATTR_WITH_HINT, - &&TARGET_LOAD_ATTR_SLOT, &&TARGET_STORE_SUBSCR, &&TARGET_DELETE_SUBSCR, + &&TARGET_LOAD_ATTR_WITH_HINT, + &&TARGET_LOAD_ATTR_SLOT, &&TARGET_LOAD_ATTR_MODULE, &&TARGET_LOAD_GLOBAL_ADAPTIVE, &&TARGET_LOAD_GLOBAL_MODULE, &&TARGET_LOAD_GLOBAL_BUILTIN, - &&TARGET_LOAD_METHOD_ADAPTIVE, - &&TARGET_LOAD_METHOD_CACHED, &&TARGET_GET_ITER, &&TARGET_GET_YIELD_FROM_ITER, &&TARGET_PRINT_EXPR, &&TARGET_LOAD_BUILD_CLASS, - &&TARGET_LOAD_METHOD_CLASS, + &&TARGET_LOAD_METHOD_ADAPTIVE, &&TARGET_GET_AWAITABLE, &&TARGET_LOAD_ASSERTION_ERROR, + &&TARGET_LOAD_METHOD_CACHED, + &&TARGET_LOAD_METHOD_CLASS, &&TARGET_LOAD_METHOD_MODULE, &&TARGET_LOAD_METHOD_NO_DICT, &&TARGET_STORE_ATTR_ADAPTIVE, &&TARGET_STORE_ATTR_INSTANCE_VALUE, &&TARGET_STORE_ATTR_SLOT, - &&TARGET_STORE_ATTR_WITH_HINT, - &&TARGET_LOAD_FAST__LOAD_FAST, &&TARGET_LIST_TO_TUPLE, &&TARGET_RETURN_VALUE, &&TARGET_IMPORT_STAR, &&TARGET_SETUP_ANNOTATIONS, &&TARGET_YIELD_VALUE, - &&TARGET_STORE_FAST__LOAD_FAST, + &&TARGET_STORE_ATTR_WITH_HINT, &&TARGET_PREP_RERAISE_STAR, &&TARGET_POP_EXCEPT, &&TARGET_STORE_NAME, @@ -127,20 +127,20 @@ static void *opcode_targets[256] = { &&TARGET_STORE_FAST, &&TARGET_DELETE_FAST, &&TARGET_JUMP_IF_NOT_EG_MATCH, - &&TARGET_LOAD_FAST__LOAD_CONST, + &&TARGET_LOAD_FAST__LOAD_FAST, &&TARGET_GEN_START, &&TARGET_RAISE_VARARGS, - &&TARGET_LOAD_CONST__LOAD_FAST, + &&TARGET_STORE_FAST__LOAD_FAST, &&TARGET_MAKE_FUNCTION, &&TARGET_BUILD_SLICE, - &&TARGET_STORE_FAST__STORE_FAST, + &&TARGET_LOAD_FAST__LOAD_CONST, &&TARGET_MAKE_CELL, &&TARGET_LOAD_CLOSURE, &&TARGET_LOAD_DEREF, &&TARGET_STORE_DEREF, &&TARGET_DELETE_DEREF, - &&_unknown_opcode, - &&_unknown_opcode, + &&TARGET_LOAD_CONST__LOAD_FAST, + &&TARGET_STORE_FAST__STORE_FAST, &&TARGET_CALL_FUNCTION_EX, &&_unknown_opcode, &&TARGET_EXTENDED_ARG, diff --git a/Python/specialize.c b/Python/specialize.c index bdcba46ed4d31..5cf327df475c7 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -491,8 +491,10 @@ initial_counter_value(void) { #define SPEC_FAIL_PYCFUNCTION_NOARGS 16 #define SPEC_FAIL_BAD_CALL_FLAGS 17 #define SPEC_FAIL_CLASS 18 -#define SPEC_FAIL_C_METHOD_CALL 19 -#define SPEC_FAIL_METHDESCR_NON_METHOD 20 +#define SPEC_FAIL_PYTHON_CLASS 19 +#define SPEC_FAIL_C_METHOD_CALL 20 +#define SPEC_FAIL_METHDESCR_NON_METHOD 21 +#define SPEC_FAIL_METHOD_CALL_CLASS 22 /* COMPARE_OP */ #define SPEC_FAIL_STRING_COMPARE 13 @@ -1263,6 +1265,27 @@ specialize_class_call( PyObject *callable, _Py_CODEUNIT *instr, int nargs, SpecializedCacheEntry *cache) { + assert(PyType_Check(callable)); + PyTypeObject *tp = (PyTypeObject *)callable; + if (_Py_OPCODE(instr[-1]) == PRECALL_METHOD) { + SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_METHOD_CALL_CLASS); + return -1; + } + if (tp->tp_new == PyBaseObject_Type.tp_new) { + SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_PYTHON_CLASS); + return -1; + } + if (nargs == 1) { + if (tp == &PyType_Type) { + *instr = _Py_MAKECODEUNIT(CALL_NO_KW_TYPE_1, _Py_OPARG(*instr)); + return 0; + } + if ((tp->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) && tp->tp_vectorcall != NULL) { + cache->adaptive.version = tp->tp_version_tag; + *instr = _Py_MAKECODEUNIT(CALL_NO_KW_BUILTIN_CLASS_1, _Py_OPARG(*instr)); + return 0; + } + } SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_CLASS); return -1; } From webhook-mailer at python.org Wed Dec 15 10:32:42 2021 From: webhook-mailer at python.org (markshannon) Date: Wed, 15 Dec 2021 15:32:42 -0000 Subject: [Python-checkins] bpo-46072: Add --with-pystats configure option to simplify gathering of VM stats (GH-30116) Message-ID: https://github.com/python/cpython/commit/342b93f9f28746abb7b221a61d5a9b26ccbb395a commit: 342b93f9f28746abb7b221a61d5a9b26ccbb395a branch: main author: Mark Shannon committer: markshannon date: 2021-12-15T15:32:32Z summary: bpo-46072: Add --with-pystats configure option to simplify gathering of VM stats (GH-30116) * Simplify specialization stats collection macros. * Add --enable-pystats option to configure. * Update specialization summary script to handle larger number of kinds files: A Misc/NEWS.d/next/Build/2021-12-15-10-37-44.bpo-46072.GgeAU3.rst M Include/internal/pycore_code.h M Modules/_opcode.c M Python/ceval.c M Python/specialize.c M Tools/scripts/summarize_specialization_stats.py M configure M configure.ac M pyconfig.h.in diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index b0463e361718a..e9b1ad406496a 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -276,22 +276,11 @@ void _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache); void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache); -#define PRINT_SPECIALIZATION_STATS 0 -#define PRINT_SPECIALIZATION_STATS_DETAILED 0 -#define PRINT_SPECIALIZATION_STATS_TO_FILE 0 -#ifdef Py_DEBUG -#define COLLECT_SPECIALIZATION_STATS 1 -#define COLLECT_SPECIALIZATION_STATS_DETAILED 1 -#else -#define COLLECT_SPECIALIZATION_STATS PRINT_SPECIALIZATION_STATS -#define COLLECT_SPECIALIZATION_STATS_DETAILED PRINT_SPECIALIZATION_STATS_DETAILED -#endif +#ifdef Py_STATS #define SPECIALIZATION_FAILURE_KINDS 30 -#if COLLECT_SPECIALIZATION_STATS - typedef struct _stats { uint64_t specialization_success; uint64_t specialization_failure; @@ -300,15 +289,13 @@ typedef struct _stats { uint64_t miss; uint64_t deopt; uint64_t unquickened; -#if COLLECT_SPECIALIZATION_STATS_DETAILED uint64_t specialization_failure_kinds[SPECIALIZATION_FAILURE_KINDS]; -#endif } SpecializationStats; extern SpecializationStats _specialization_stats[256]; #define STAT_INC(opname, name) _specialization_stats[opname].name++ #define STAT_DEC(opname, name) _specialization_stats[opname].name-- -void _Py_PrintSpecializationStats(void); +void _Py_PrintSpecializationStats(int to_file); PyAPI_FUNC(PyObject*) _Py_GetSpecializationStats(void); diff --git a/Misc/NEWS.d/next/Build/2021-12-15-10-37-44.bpo-46072.GgeAU3.rst b/Misc/NEWS.d/next/Build/2021-12-15-10-37-44.bpo-46072.GgeAU3.rst new file mode 100644 index 0000000000000..9cc8b6c82de41 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-12-15-10-37-44.bpo-46072.GgeAU3.rst @@ -0,0 +1,2 @@ +Add a --with-pystats configure option to turn on internal statistics +gathering. diff --git a/Modules/_opcode.c b/Modules/_opcode.c index 39e3066955951..4812716c67271 100644 --- a/Modules/_opcode.c +++ b/Modules/_opcode.c @@ -85,7 +85,7 @@ static PyObject * _opcode_get_specialization_stats_impl(PyObject *module) /*[clinic end generated code: output=fcbc32fdfbec5c17 input=e1f60db68d8ce5f6]*/ { -#if COLLECT_SPECIALIZATION_STATS +#ifdef Py_STATS return _Py_GetSpecializationStats(); #else Py_RETURN_NONE; diff --git a/Python/ceval.c b/Python/ceval.c index b9444b22138f0..87d6a2288e0dd 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -349,8 +349,8 @@ PyEval_InitThreads(void) void _PyEval_Fini(void) { -#if PRINT_SPECIALIZATION_STATS - _Py_PrintSpecializationStats(); +#ifdef Py_STATS + _Py_PrintSpecializationStats(1); #endif } diff --git a/Python/specialize.c b/Python/specialize.c index 5cf327df475c7..7d4387b1639a5 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -39,7 +39,7 @@ */ Py_ssize_t _Py_QuickenedCount = 0; -#if COLLECT_SPECIALIZATION_STATS +#ifdef Py_STATS SpecializationStats _specialization_stats[256] = { 0 }; #define ADD_STAT_TO_DICT(res, field) \ @@ -71,7 +71,6 @@ stats_to_dict(SpecializationStats *stats) ADD_STAT_TO_DICT(res, miss); ADD_STAT_TO_DICT(res, deopt); ADD_STAT_TO_DICT(res, unquickened); -#if COLLECT_SPECIALIZATION_STATS_DETAILED PyObject *failure_kinds = PyTuple_New(SPECIALIZATION_FAILURE_KINDS); if (failure_kinds == NULL) { Py_DECREF(res); @@ -92,7 +91,6 @@ stats_to_dict(SpecializationStats *stats) return NULL; } Py_DECREF(failure_kinds); -#endif return res; } #undef ADD_STAT_TO_DICT @@ -113,7 +111,7 @@ add_stat_dict( return err; } -#if COLLECT_SPECIALIZATION_STATS +#ifdef Py_STATS PyObject* _Py_GetSpecializationStats(void) { PyObject *stats = PyDict_New(); @@ -151,35 +149,34 @@ print_stats(FILE *out, SpecializationStats *stats, const char *name) PRINT_STAT(name, miss); PRINT_STAT(name, deopt); PRINT_STAT(name, unquickened); -#if PRINT_SPECIALIZATION_STATS_DETAILED for (int i = 0; i < SPECIALIZATION_FAILURE_KINDS; i++) { fprintf(out, " %s.specialization_failure_kinds[%d] : %" PRIu64 "\n", name, i, stats->specialization_failure_kinds[i]); } -#endif } #undef PRINT_STAT void -_Py_PrintSpecializationStats(void) +_Py_PrintSpecializationStats(int to_file) { FILE *out = stderr; -#if PRINT_SPECIALIZATION_STATS_TO_FILE - /* Write to a file instead of stderr. */ + if (to_file) { + /* Write to a file instead of stderr. */ # ifdef MS_WINDOWS - const char *dirname = "c:\\temp\\py_stats\\"; + const char *dirname = "c:\\temp\\py_stats\\"; # else - const char *dirname = "/tmp/py_stats/"; + const char *dirname = "/tmp/py_stats/"; # endif - char buf[48]; - sprintf(buf, "%s%u_%u.txt", dirname, (unsigned)clock(), (unsigned)rand()); - FILE *fout = fopen(buf, "w"); - if (fout) { - out = fout; - } -#else - fprintf(out, "Specialization stats:\n"); -#endif + char buf[48]; + sprintf(buf, "%s%u_%u.txt", dirname, (unsigned)clock(), (unsigned)rand()); + FILE *fout = fopen(buf, "w"); + if (fout) { + out = fout; + } + } + else { + fprintf(out, "Specialization stats:\n"); + } print_stats(out, &_specialization_stats[LOAD_ATTR], "load_attr"); print_stats(out, &_specialization_stats[LOAD_GLOBAL], "load_global"); print_stats(out, &_specialization_stats[LOAD_METHOD], "load_method"); @@ -194,7 +191,7 @@ _Py_PrintSpecializationStats(void) } } -#if COLLECT_SPECIALIZATION_STATS_DETAILED +#ifdef Py_STATS #define SPECIALIZATION_FAIL(opcode, kind) _specialization_stats[opcode].specialization_failure_kinds[kind]++ @@ -860,7 +857,7 @@ _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name, S } -#if COLLECT_SPECIALIZATION_STATS_DETAILED +#ifdef Py_STATS static int load_method_fail_kind(DesciptorClassification kind) { @@ -1086,7 +1083,7 @@ _Py_Specialize_LoadGlobal( return 0; } -#if COLLECT_SPECIALIZATION_STATS_DETAILED +#ifdef Py_STATS static int binary_subscr_fail_kind(PyTypeObject *container_type, PyObject *sub) { @@ -1380,7 +1377,7 @@ specialize_py_call( return 0; } -#if COLLECT_SPECIALIZATION_STATS_DETAILED +#ifdef Py_STATS static int builtin_call_fail_kind(int ml_flags) { @@ -1459,7 +1456,7 @@ specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs, } } -#if COLLECT_SPECIALIZATION_STATS_DETAILED +#ifdef Py_STATS static int call_fail_kind(PyObject *callable) { diff --git a/Tools/scripts/summarize_specialization_stats.py b/Tools/scripts/summarize_specialization_stats.py index cc3ef85933c02..15b1887415e44 100644 --- a/Tools/scripts/summarize_specialization_stats.py +++ b/Tools/scripts/summarize_specialization_stats.py @@ -24,7 +24,7 @@ def print_stats(name, family_stats): for key in ("specialization_success", "specialization_failure"): print(f" {key}:{family_stats[key]:>12}") total_failures = family_stats["specialization_failure"] - failure_kinds = [ 0 ] * 20 + failure_kinds = [ 0 ] * 30 for key in family_stats: if not key.startswith("specialization_failure_kind"): continue diff --git a/configure b/configure index 583e7d1fe3b32..1ede29989d948 100755 --- a/configure +++ b/configure @@ -1006,6 +1006,7 @@ enable_shared enable_profiling with_pydebug with_trace_refs +enable_pystats with_assertions enable_optimizations with_lto @@ -1713,6 +1714,7 @@ Optional Features: no) --enable-profiling enable C-level code profiling with gprof (default is no) + --enable-pystats enable internal statistics gathering (default is no) --enable-optimizations enable expensive, stable optimizations (PGO, etc.) (default is no) --enable-loadable-sqlite-extensions @@ -6913,6 +6915,29 @@ then $as_echo "#define Py_TRACE_REFS 1" >>confdefs.h +fi + + +# Check for --enable-pystats +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --enable-pystats" >&5 +$as_echo_n "checking for --enable-pystats... " >&6; } +# Check whether --enable-pystats was given. +if test "${enable_pystats+set}" = set; then : + enableval=$enable_pystats; +else + enable_pystats=no + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_pystats" >&5 +$as_echo "$enable_pystats" >&6; } + +if test "x$enable_pystats" = xyes; then : + + +$as_echo "#define Py_STATS 1" >>confdefs.h + + fi # Check for --with-assertions. diff --git a/configure.ac b/configure.ac index 5256a61289e22..86404bcadeaba 100644 --- a/configure.ac +++ b/configure.ac @@ -1387,6 +1387,21 @@ then AC_DEFINE(Py_TRACE_REFS, 1, [Define if you want to enable tracing references for debugging purpose]) fi + +# Check for --enable-pystats +AC_MSG_CHECKING([for --enable-pystats]) +AC_ARG_ENABLE([pystats], + [AS_HELP_STRING( + [--enable-pystats], + [enable internal statistics gathering (default is no)])],, + [enable_pystats=no] +) +AC_MSG_RESULT([$enable_pystats]) + +AS_VAR_IF([enable_pystats], [yes], [ + AC_DEFINE([Py_STATS], [1], [Define if you want to enable internal statistics gathering.]) +]) + # Check for --with-assertions. # This allows enabling assertions without Py_DEBUG. assertions='false' @@ -6323,7 +6338,7 @@ AC_DEFUN([PY_STDLIB_MOD], [ ]) dnl Define simple stdlib extension module -dnl Always enable unless the module is listed in py_stdlib_not_available +dnl Always enable unless the module is listed in py_stdlib_not_available dnl PY_STDLIB_MOD_SIMPLE([NAME], [CFLAGS], [LDFLAGS]) dnl cflags and ldflags are optional AC_DEFUN([PY_STDLIB_MOD_SIMPLE], [ diff --git a/pyconfig.h.in b/pyconfig.h.in index efad243d0af8a..e6e81654699d8 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -1496,6 +1496,9 @@ SipHash13: 3, externally defined: 0 */ #undef Py_HASH_ALGORITHM +/* Define if you want to enable internal statistics gathering. */ +#undef Py_STATS + /* Define if you want to enable tracing references for debugging purpose */ #undef Py_TRACE_REFS From webhook-mailer at python.org Wed Dec 15 11:35:31 2021 From: webhook-mailer at python.org (corona10) Date: Wed, 15 Dec 2021 16:35:31 -0000 Subject: [Python-checkins] Remove spaces in empty lines (GH-30121) Message-ID: https://github.com/python/cpython/commit/f62420c3d3f5d87f2b57e54b2a98682bc835f7b6 commit: f62420c3d3f5d87f2b57e54b2a98682bc835f7b6 branch: main author: AN Long committer: corona10 date: 2021-12-16T01:35:21+09:00 summary: Remove spaces in empty lines (GH-30121) files: M Lib/inspect.py M Lib/test/test_getpath.py M Lib/test/test_inspect.py diff --git a/Lib/inspect.py b/Lib/inspect.py index 746f6e4f9f9f0..5d33f0d445fb9 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -32,7 +32,7 @@ __author__ = ('Ka-Ping Yee ', 'Yury Selivanov ') - + __all__ = [ "ArgInfo", "Arguments", @@ -131,7 +131,7 @@ "walktree", ] - + import abc import ast import dis @@ -591,7 +591,7 @@ def getmembers_static(object, predicate=None): without triggering dynamic lookup via the descriptor protocol, __getattr__ or __getattribute__. Optionally, only return members that satisfy a given predicate. - + Note: this function may not be able to retrieve all members that getmembers can fetch (like dynamically created attributes) and may find members that getmembers can't (like descriptors diff --git a/Lib/test/test_getpath.py b/Lib/test/test_getpath.py index 3fb1b280031c8..232b680528435 100644 --- a/Lib/test/test_getpath.py +++ b/Lib/test/test_getpath.py @@ -534,7 +534,7 @@ def test_symlink_buildpath_macos(self): VERSION_MINOR=8, # of testing PYWINVER=None, EXE_SUFFIX=None, - + ENV_PATH="", ENV_PYTHONHOME="", ENV_PYTHONEXECUTABLE="", diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index c25256dfa26fd..56168817a27f2 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -109,7 +109,7 @@ def istest(self, predicate, exp): def test__all__(self): support.check__all__(self, inspect, not_exported=("k", "v", "mod_dict", "modulesbyfile")) - + def generator_function_example(self): for i in range(2): yield i From webhook-mailer at python.org Thu Dec 16 04:12:32 2021 From: webhook-mailer at python.org (iritkatriel) Date: Thu, 16 Dec 2021 09:12:32 -0000 Subject: [Python-checkins] bpo-28816: [doc] clarify that zipimport invokes importers only for python files (GH-30060) Message-ID: https://github.com/python/cpython/commit/a951c95a13c3555ac8fb1c8ee615ba3930ccc6f7 commit: a951c95a13c3555ac8fb1c8ee615ba3930ccc6f7 branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-12-16T09:12:24Z summary: bpo-28816: [doc] clarify that zipimport invokes importers only for python files (GH-30060) files: M Doc/library/zipimport.rst diff --git a/Doc/library/zipimport.rst b/Doc/library/zipimport.rst index cd7030fed0173..fe1adcae163c2 100644 --- a/Doc/library/zipimport.rst +++ b/Doc/library/zipimport.rst @@ -23,8 +23,8 @@ and a path within the archive can be specified to only import from a subdirectory. For example, the path :file:`example.zip/lib/` would only import from the :file:`lib/` subdirectory within the archive. -Any files may be present in the ZIP archive, but only files :file:`.py` and -:file:`.pyc` are available for import. ZIP import of dynamic modules +Any files may be present in the ZIP archive, but importers are only invoked for +:file:`.py` and :file:`.pyc` files. ZIP import of dynamic modules (:file:`.pyd`, :file:`.so`) is disallowed. Note that if an archive only contains :file:`.py` files, Python will not attempt to modify the archive by adding the corresponding :file:`.pyc` file, meaning that if a ZIP archive From webhook-mailer at python.org Thu Dec 16 05:40:23 2021 From: webhook-mailer at python.org (Fidget-Spinner) Date: Thu, 16 Dec 2021 10:40:23 -0000 Subject: [Python-checkins] Fix the output of built-in iter() function example in Iterators (Section 9.8) of The Python Tutorial (GH-30110) Message-ID: https://github.com/python/cpython/commit/c5d18a5014f649368b5a4bca94e9ec7d2908b481 commit: c5d18a5014f649368b5a4bca94e9ec7d2908b481 branch: main author: Vivek Vashist committer: Fidget-Spinner <28750310+Fidget-Spinner at users.noreply.github.com> date: 2021-12-16T18:40:12+08:00 summary: Fix the output of built-in iter() function example in Iterators (Section 9.8) of The Python Tutorial (GH-30110) Updated the output for it=iter(s) from to files: M Doc/tutorial/classes.rst diff --git a/Doc/tutorial/classes.rst b/Doc/tutorial/classes.rst index 0d780e3ba8964..f44cb0b4e905a 100644 --- a/Doc/tutorial/classes.rst +++ b/Doc/tutorial/classes.rst @@ -797,7 +797,7 @@ using the :func:`next` built-in function; this example shows how it all works:: >>> s = 'abc' >>> it = iter(s) >>> it - + >>> next(it) 'a' >>> next(it) From webhook-mailer at python.org Thu Dec 16 06:01:24 2021 From: webhook-mailer at python.org (miss-islington) Date: Thu, 16 Dec 2021 11:01:24 -0000 Subject: [Python-checkins] Fix the output of built-in iter() function example in Iterators (Section 9.8) of The Python Tutorial (GH-30110) Message-ID: https://github.com/python/cpython/commit/fb5d314da8f74e624f1ba30389f8ec305e2553a4 commit: fb5d314da8f74e624f1ba30389f8ec305e2553a4 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-16T03:00:58-08:00 summary: Fix the output of built-in iter() function example in Iterators (Section 9.8) of The Python Tutorial (GH-30110) Updated the output for it=iter(s) from to (cherry picked from commit c5d18a5014f649368b5a4bca94e9ec7d2908b481) Co-authored-by: Vivek Vashist files: M Doc/tutorial/classes.rst diff --git a/Doc/tutorial/classes.rst b/Doc/tutorial/classes.rst index 0d780e3ba8964..f44cb0b4e905a 100644 --- a/Doc/tutorial/classes.rst +++ b/Doc/tutorial/classes.rst @@ -797,7 +797,7 @@ using the :func:`next` built-in function; this example shows how it all works:: >>> s = 'abc' >>> it = iter(s) >>> it - + >>> next(it) 'a' >>> next(it) From webhook-mailer at python.org Thu Dec 16 06:05:01 2021 From: webhook-mailer at python.org (miss-islington) Date: Thu, 16 Dec 2021 11:05:01 -0000 Subject: [Python-checkins] Fix the output of built-in iter() function example in Iterators (Section 9.8) of The Python Tutorial (GH-30110) Message-ID: https://github.com/python/cpython/commit/309614f1f78923b0875f24640ab5345a4eb8c76d commit: 309614f1f78923b0875f24640ab5345a4eb8c76d branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-16T03:04:53-08:00 summary: Fix the output of built-in iter() function example in Iterators (Section 9.8) of The Python Tutorial (GH-30110) Updated the output for it=iter(s) from to (cherry picked from commit c5d18a5014f649368b5a4bca94e9ec7d2908b481) Co-authored-by: Vivek Vashist files: M Doc/tutorial/classes.rst diff --git a/Doc/tutorial/classes.rst b/Doc/tutorial/classes.rst index 0d780e3ba8964..f44cb0b4e905a 100644 --- a/Doc/tutorial/classes.rst +++ b/Doc/tutorial/classes.rst @@ -797,7 +797,7 @@ using the :func:`next` built-in function; this example shows how it all works:: >>> s = 'abc' >>> it = iter(s) >>> it - + >>> next(it) 'a' >>> next(it) From webhook-mailer at python.org Thu Dec 16 06:08:36 2021 From: webhook-mailer at python.org (markshannon) Date: Thu, 16 Dec 2021 11:08:36 -0000 Subject: [Python-checkins] bpo-45829: Check `__getitem__`'s version for overflow before specializing (GH-30129) Message-ID: https://github.com/python/cpython/commit/62a8a0c5223f750e22ee381d3cfbdb718cf1cc93 commit: 62a8a0c5223f750e22ee381d3cfbdb718cf1cc93 branch: main author: Brandt Bucher committer: markshannon date: 2021-12-16T11:08:20Z summary: bpo-45829: Check `__getitem__`'s version for overflow before specializing (GH-30129) * Check __getitem__'s version for overflow. * Use SPEC_FAIL_OUT_OF_VERSIONS instead files: M Python/specialize.c diff --git a/Python/specialize.c b/Python/specialize.c index 7d4387b1639a5..730e2f045ebe5 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -1187,7 +1187,7 @@ _Py_Specialize_BinarySubscr( assert(cls->tp_version_tag != 0); cache0->version = cls->tp_version_tag; int version = _PyFunction_GetVersionForCurrentState(func); - if (version == 0) { + if (version == 0 || version != (uint16_t)version) { SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_OUT_OF_VERSIONS); goto fail; } From webhook-mailer at python.org Thu Dec 16 07:23:30 2021 From: webhook-mailer at python.org (iritkatriel) Date: Thu, 16 Dec 2021 12:23:30 -0000 Subject: [Python-checkins] bpo-28816: [doc] clarify that zipimport invokes importers only for python files (GH-30060) (GH-30134) Message-ID: https://github.com/python/cpython/commit/4c1effaaee472cc67f3186411a3df4f39af3d71a commit: 4c1effaaee472cc67f3186411a3df4f39af3d71a branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-12-16T12:23:17Z summary: bpo-28816: [doc] clarify that zipimport invokes importers only for python files (GH-30060) (GH-30134) (cherry picked from commit a951c95a13c3555ac8fb1c8ee615ba3930ccc6f7) Co-authored-by: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> files: M Doc/library/zipimport.rst diff --git a/Doc/library/zipimport.rst b/Doc/library/zipimport.rst index 8ac3fb16bdb90d..a3a24ec3c84ac6 100644 --- a/Doc/library/zipimport.rst +++ b/Doc/library/zipimport.rst @@ -23,8 +23,8 @@ and a path within the archive can be specified to only import from a subdirectory. For example, the path :file:`example.zip/lib/` would only import from the :file:`lib/` subdirectory within the archive. -Any files may be present in the ZIP archive, but only files :file:`.py` and -:file:`.pyc` are available for import. ZIP import of dynamic modules +Any files may be present in the ZIP archive, but importers are only invoked for +:file:`.py` and :file:`.pyc` files. ZIP import of dynamic modules (:file:`.pyd`, :file:`.so`) is disallowed. Note that if an archive only contains :file:`.py` files, Python will not attempt to modify the archive by adding the corresponding :file:`.pyc` file, meaning that if a ZIP archive From webhook-mailer at python.org Thu Dec 16 07:23:46 2021 From: webhook-mailer at python.org (iritkatriel) Date: Thu, 16 Dec 2021 12:23:46 -0000 Subject: [Python-checkins] bpo-28816: [doc] clarify that zipimport invokes importers only for python files (GH-30060) (GH-30133) Message-ID: https://github.com/python/cpython/commit/0194bbbee6a12264e93d3217c774e226f0a1737d commit: 0194bbbee6a12264e93d3217c774e226f0a1737d branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-12-16T12:23:41Z summary: bpo-28816: [doc] clarify that zipimport invokes importers only for python files (GH-30060) (GH-30133) (cherry picked from commit a951c95a13c3555ac8fb1c8ee615ba3930ccc6f7) Co-authored-by: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> files: M Doc/library/zipimport.rst diff --git a/Doc/library/zipimport.rst b/Doc/library/zipimport.rst index cd7030fed01732..fe1adcae163c23 100644 --- a/Doc/library/zipimport.rst +++ b/Doc/library/zipimport.rst @@ -23,8 +23,8 @@ and a path within the archive can be specified to only import from a subdirectory. For example, the path :file:`example.zip/lib/` would only import from the :file:`lib/` subdirectory within the archive. -Any files may be present in the ZIP archive, but only files :file:`.py` and -:file:`.pyc` are available for import. ZIP import of dynamic modules +Any files may be present in the ZIP archive, but importers are only invoked for +:file:`.py` and :file:`.pyc` files. ZIP import of dynamic modules (:file:`.pyd`, :file:`.so`) is disallowed. Note that if an archive only contains :file:`.py` files, Python will not attempt to modify the archive by adding the corresponding :file:`.pyc` file, meaning that if a ZIP archive From webhook-mailer at python.org Thu Dec 16 08:41:07 2021 From: webhook-mailer at python.org (markshannon) Date: Thu, 16 Dec 2021 13:41:07 -0000 Subject: [Python-checkins] bpo-46072: Document --enable-stats option. (GH-30139) Message-ID: https://github.com/python/cpython/commit/4506bbede1644e985991884964b43afa7ee6f609 commit: 4506bbede1644e985991884964b43afa7ee6f609 branch: main author: Mark Shannon committer: markshannon date: 2021-12-16T13:40:54Z summary: bpo-46072: Document --enable-stats option. (GH-30139) files: A Tools/scripts/summarize_stats.py D Tools/scripts/summarize_specialization_stats.py M Doc/using/configure.rst diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index b2a2936db738b..771ad3cf18d97 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -131,6 +131,17 @@ General Options .. versionadded:: 3.11 +.. cmdoption:: --enable-pystats + + Turn on internal statistics gathering. + + The statistics will be dumped to a arbitrary (probably unique) file in + ``/tmp/py_stats/``, or ``C:\temp\py_stats\`` on Windows. + + Use ``Tools//summarize_stats.py`` to read the stats. + + .. versionadded:: 3.11 + Install Options --------------- diff --git a/Tools/scripts/summarize_specialization_stats.py b/Tools/scripts/summarize_stats.py similarity index 100% rename from Tools/scripts/summarize_specialization_stats.py rename to Tools/scripts/summarize_stats.py From webhook-mailer at python.org Thu Dec 16 09:30:36 2021 From: webhook-mailer at python.org (Fidget-Spinner) Date: Thu, 16 Dec 2021 14:30:36 -0000 Subject: [Python-checkins] bpo-45755: [typing] Reveal class attributes of generic in generic aliases in `dir()` (GH-29962) Message-ID: https://github.com/python/cpython/commit/d6e13747161d7b634b47d2d3d212ed3be4a21fab commit: d6e13747161d7b634b47d2d3d212ed3be4a21fab branch: main author: Ken Jin <28750310+Fidget-Spinner at users.noreply.github.com> committer: Fidget-Spinner <28750310+Fidget-Spinner at users.noreply.github.com> date: 2021-12-16T22:29:59+08:00 summary: bpo-45755: [typing] Reveal class attributes of generic in generic aliases in `dir()` (GH-29962) files: A Misc/NEWS.d/next/Library/2021-12-07-21-55-22.bpo-45755.bRqKGa.rst M Lib/test/test_typing.py M Lib/typing.py diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 90d6bea59f899..a94d77d4edf4b 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -5040,6 +5040,17 @@ def test_special_attrs2(self): loaded = pickle.loads(s) self.assertIs(SpecialAttrsP, loaded) + def test_genericalias_dir(self): + class Foo(Generic[T]): + def bar(self): + pass + baz = 3 + # The class attributes of the original class should be visible even + # in dir() of the GenericAlias. See bpo-45755. + self.assertIn('bar', dir(Foo[int])) + self.assertIn('baz', dir(Foo[int])) + + class AllTests(BaseTestCase): """Tests for __all__.""" diff --git a/Lib/typing.py b/Lib/typing.py index bdd19cadb471a..ae1dd5c2d7689 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -991,6 +991,9 @@ def __subclasscheck__(self, cls): raise TypeError("Subscripted generics cannot be used with" " class and instance checks") + def __dir__(self): + return list(set(super().__dir__() + + [attr for attr in dir(self.__origin__) if not _is_dunder(attr)])) # Special typing constructs Union, Optional, Generic, Callable and Tuple # use three special attributes for internal bookkeeping of generic types: diff --git a/Misc/NEWS.d/next/Library/2021-12-07-21-55-22.bpo-45755.bRqKGa.rst b/Misc/NEWS.d/next/Library/2021-12-07-21-55-22.bpo-45755.bRqKGa.rst new file mode 100644 index 0000000000000..e5201b0dfde2d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-07-21-55-22.bpo-45755.bRqKGa.rst @@ -0,0 +1,3 @@ +:mod:`typing` generic aliases now reveal the class attributes of the +original generic class when passed to ``dir()``. This was the behavior up to +Python 3.6, but was changed in 3.7-3.9. From webhook-mailer at python.org Thu Dec 16 10:31:22 2021 From: webhook-mailer at python.org (iritkatriel) Date: Thu, 16 Dec 2021 15:31:22 -0000 Subject: [Python-checkins] bpo-22047: [argparse] deprecate nested argument groups and mutually exclusive groups (GH-30098) Message-ID: https://github.com/python/cpython/commit/30322c497e0b8d978f7a0de95985aac9c5daf1ac commit: 30322c497e0b8d978f7a0de95985aac9c5daf1ac branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-12-16T15:31:08Z summary: bpo-22047: [argparse] deprecate nested argument groups and mutually exclusive groups (GH-30098) files: A Misc/NEWS.d/next/Library/2021-12-15-19-24-54.bpo-22047.gBV4vT.rst M Doc/library/argparse.rst M Lib/argparse.py M Lib/test/test_argparse.py diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index 2edf84e5f0444..80c382a981b8d 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -1898,6 +1898,12 @@ Argument groups Note that any arguments not in your user-defined groups will end up back in the usual "positional arguments" and "optional arguments" sections. + .. versionchanged:: 3.11 + Calling :meth:`add_argument_group` on an argument group is deprecated. + This feature was never supported and does not always work correctly. + The function exists on the API by accident through inheritance and + will be removed in the future. + Mutual exclusion ^^^^^^^^^^^^^^^^ @@ -1936,6 +1942,12 @@ Mutual exclusion *title* and *description* arguments of :meth:`~ArgumentParser.add_argument_group`. + .. versionchanged:: 3.11 + Calling :meth:`add_argument_group` or :meth:`add_mutually_exclusive_group` + on a mutually exclusive group is deprecated. These features were never + supported and do not always work correctly. The functions exist on the + API by accident through inheritance and will be removed in the future. + Parser defaults ^^^^^^^^^^^^^^^ diff --git a/Lib/argparse.py b/Lib/argparse.py index 8a81801ba9236..de95eedbee0ee 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -89,6 +89,8 @@ import re as _re import sys as _sys +import warnings + from gettext import gettext as _, ngettext SUPPRESS = '==SUPPRESS==' @@ -1648,6 +1650,14 @@ def _remove_action(self, action): super(_ArgumentGroup, self)._remove_action(action) self._group_actions.remove(action) + def add_argument_group(self, *args, **kwargs): + warnings.warn( + "Nesting argument groups is deprecated.", + category=DeprecationWarning, + stacklevel=2 + ) + return super().add_argument_group(*args, **kwargs) + class _MutuallyExclusiveGroup(_ArgumentGroup): @@ -1668,6 +1678,14 @@ def _remove_action(self, action): self._container._remove_action(action) self._group_actions.remove(action) + def add_mutually_exclusive_group(self, *args, **kwargs): + warnings.warn( + "Nesting mutually exclusive groups is deprecated.", + category=DeprecationWarning, + stacklevel=2 + ) + return super().add_mutually_exclusive_group(*args, **kwargs) + class ArgumentParser(_AttributeHolder, _ActionsContainer): """Object for parsing command line strings into Python objects. diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index eb37d4d365d24..4c23610b9e961 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -9,6 +9,7 @@ import tempfile import unittest import argparse +import warnings from io import StringIO @@ -2973,15 +2974,24 @@ def get_parser(self, required): class TestMutuallyExclusiveNested(MEMixin, TestCase): + # Nesting mutually exclusive groups is an undocumented feature + # that came about by accident through inheritance and has been + # the source of many bugs. It is deprecated and this test should + # eventually be removed along with it. + def get_parser(self, required): parser = ErrorRaisingArgumentParser(prog='PROG') group = parser.add_mutually_exclusive_group(required=required) group.add_argument('-a') group.add_argument('-b') - group2 = group.add_mutually_exclusive_group(required=required) + with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + group2 = group.add_mutually_exclusive_group(required=required) group2.add_argument('-c') group2.add_argument('-d') - group3 = group2.add_mutually_exclusive_group(required=required) + with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + group3 = group2.add_mutually_exclusive_group(required=required) group3.add_argument('-e') group3.add_argument('-f') return parser diff --git a/Misc/NEWS.d/next/Library/2021-12-15-19-24-54.bpo-22047.gBV4vT.rst b/Misc/NEWS.d/next/Library/2021-12-15-19-24-54.bpo-22047.gBV4vT.rst new file mode 100644 index 0000000000000..a381ad88af6c5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-15-19-24-54.bpo-22047.gBV4vT.rst @@ -0,0 +1,3 @@ +Calling :meth:`add_argument_group` on an argument group is deprecated. Calling :meth:`add_argument_group` or :meth:`add_mutually_exclusive_group` on a mutually exclusive group is deprecated. + +These features were never supported and do not always work correctly. The functions exist on the API by accident through inheritance and will be removed in the future. \ No newline at end of file From webhook-mailer at python.org Thu Dec 16 10:56:12 2021 From: webhook-mailer at python.org (markshannon) Date: Thu, 16 Dec 2021 15:56:12 -0000 Subject: [Python-checkins] Better randomization of stats filenames. (GH-30145) Message-ID: https://github.com/python/cpython/commit/86f42851c050d756679ae7797f8720adaef381c4 commit: 86f42851c050d756679ae7797f8720adaef381c4 branch: main author: Mark Shannon committer: markshannon date: 2021-12-16T15:56:01Z summary: Better randomization of stats filenames. (GH-30145) files: M Python/specialize.c diff --git a/Python/specialize.c b/Python/specialize.c index 730e2f045ebe5..1f168e31e6d3a 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -167,8 +167,20 @@ _Py_PrintSpecializationStats(int to_file) # else const char *dirname = "/tmp/py_stats/"; # endif - char buf[48]; - sprintf(buf, "%s%u_%u.txt", dirname, (unsigned)clock(), (unsigned)rand()); + /* Use random 160 bit number as file name, + * to avoid both accidental collisions and + * symlink attacks. */ + unsigned char rand[20]; + char hex_name[41]; + _PyOS_URandomNonblock(rand, 20); + for (int i = 0; i < 20; i++) { + hex_name[2*i] = "0123456789abcdef"[rand[i]&15]; + hex_name[2*i+1] = "0123456789abcdef"[(rand[i]>>4)&15]; + } + hex_name[40] = '\0'; + char buf[64]; + assert(strlen(dirname) + 40 + strlen(".txt") < 64); + sprintf(buf, "%s%s.txt", dirname, hex_name); FILE *fout = fopen(buf, "w"); if (fout) { out = fout; From webhook-mailer at python.org Thu Dec 16 14:57:52 2021 From: webhook-mailer at python.org (miss-islington) Date: Thu, 16 Dec 2021 19:57:52 -0000 Subject: [Python-checkins] bpo-46044: Annotate deprecated sdists formats (GH-30043) Message-ID: https://github.com/python/cpython/commit/ecdc0ccede5f9ac4042ff56f295d81df2f428950 commit: ecdc0ccede5f9ac4042ff56f295d81df2f428950 branch: main author: Matthias Bussonnier committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-16T11:57:39-08:00 summary: bpo-46044: Annotate deprecated sdists formats (GH-30043) While this page have deprecated informations it is still heavily index by Google. Discussed on twitter: https://twitter.com/brettsky/status/1469465729082662916 files: M Doc/distutils/sourcedist.rst diff --git a/Doc/distutils/sourcedist.rst b/Doc/distutils/sourcedist.rst index 0600663d00e9d..43fbb03547f78 100644 --- a/Doc/distutils/sourcedist.rst +++ b/Doc/distutils/sourcedist.rst @@ -23,25 +23,25 @@ option, for example:: to create a gzipped tarball and a zip file. The available formats are: -+-----------+-------------------------+---------+ -| Format | Description | Notes | -+===========+=========================+=========+ -| ``zip`` | zip file (:file:`.zip`) | (1),(3) | -+-----------+-------------------------+---------+ -| ``gztar`` | gzip'ed tar file | \(2) | -| | (:file:`.tar.gz`) | | -+-----------+-------------------------+---------+ -| ``bztar`` | bzip2'ed tar file | | -| | (:file:`.tar.bz2`) | | -+-----------+-------------------------+---------+ -| ``xztar`` | xz'ed tar file | | -| | (:file:`.tar.xz`) | | -+-----------+-------------------------+---------+ -| ``ztar`` | compressed tar file | \(4) | -| | (:file:`.tar.Z`) | | -+-----------+-------------------------+---------+ -| ``tar`` | tar file (:file:`.tar`) | | -+-----------+-------------------------+---------+ ++-----------+-------------------------+-------------+ +| Format | Description | Notes | ++===========+=========================+=============+ +| ``zip`` | zip file (:file:`.zip`) | (1),(3) | ++-----------+-------------------------+-------------+ +| ``gztar`` | gzip'ed tar file | \(2) | +| | (:file:`.tar.gz`) | | ++-----------+-------------------------+-------------+ +| ``bztar`` | bzip2'ed tar file | \(5) | +| | (:file:`.tar.bz2`) | | ++-----------+-------------------------+-------------+ +| ``xztar`` | xz'ed tar file | \(5) | +| | (:file:`.tar.xz`) | | ++-----------+-------------------------+-------------+ +| ``ztar`` | compressed tar file | \(5) | +| | (:file:`.tar.Z`) | | ++-----------+-------------------------+-------------+ +| ``tar`` | tar file (:file:`.tar`) | \(5) | ++-----------+-------------------------+-------------+ .. versionchanged:: 3.5 Added support for the ``xztar`` format. @@ -61,6 +61,9 @@ Notes: (4) requires the :program:`compress` program. Notice that this format is now pending for deprecation and will be removed in the future versions of Python. +(5) + deprecated by `PEP 527 `_; + `PyPI `_ only accepts ``.zip`` and ``.tar.gz`` files. When using any ``tar`` format (``gztar``, ``bztar``, ``xztar``, ``ztar`` or ``tar``), under Unix you can specify the ``owner`` and ``group`` names From webhook-mailer at python.org Thu Dec 16 15:48:52 2021 From: webhook-mailer at python.org (jaraco) Date: Thu, 16 Dec 2021 20:48:52 -0000 Subject: [Python-checkins] bpo-46105: Honor spec when generating requirement specs with urls and extras. (GH-30151) Message-ID: https://github.com/python/cpython/commit/109d96602199a91e94eb14b8cb3720841f22ded7 commit: 109d96602199a91e94eb14b8cb3720841f22ded7 branch: main author: Jason R. Coombs committer: jaraco date: 2021-12-16T15:48:35-05:00 summary: bpo-46105: Honor spec when generating requirement specs with urls and extras. (GH-30151) files: A Misc/NEWS.d/next/Library/2021-12-16-14-30-36.bpo-46105.pprB1K.rst M Lib/importlib/metadata/__init__.py M Lib/test/test_importlib/test_metadata_api.py diff --git a/Lib/importlib/metadata/__init__.py b/Lib/importlib/metadata/__init__.py index b3e8fb05f1d98..ec41ed39157a9 100644 --- a/Lib/importlib/metadata/__init__.py +++ b/Lib/importlib/metadata/__init__.py @@ -669,7 +669,7 @@ def _convert_egg_info_reqs_to_simple_reqs(sections): def make_condition(name): return name and f'extra == "{name}"' - def parse_condition(section): + def quoted_marker(section): section = section or '' extra, sep, markers = section.partition(':') if extra and markers: @@ -677,8 +677,17 @@ def parse_condition(section): conditions = list(filter(None, [markers, make_condition(extra)])) return '; ' + ' and '.join(conditions) if conditions else '' + def url_req_space(req): + """ + PEP 508 requires a space between the url_spec and the quoted_marker. + Ref python/importlib_metadata#357. + """ + # '@' is uniquely indicative of a url_req. + return ' ' * ('@' in req) + for section in sections: - yield section.value + parse_condition(section.name) + space = url_req_space(section.value) + yield section.value + space + quoted_marker(section.name) class DistributionFinder(MetaPathFinder): diff --git a/Lib/test/test_importlib/test_metadata_api.py b/Lib/test/test_importlib/test_metadata_api.py index dc9c234d15b78..4a45312e31cd5 100644 --- a/Lib/test/test_importlib/test_metadata_api.py +++ b/Lib/test/test_importlib/test_metadata_api.py @@ -235,6 +235,7 @@ def test_more_complex_deps_requires_text(self): [extra1] dep4 + dep6@ git+https://example.com/python/dep.git at v1.0.0 [extra2:python_version < "3"] dep5 @@ -247,6 +248,7 @@ def test_more_complex_deps_requires_text(self): 'dep3; python_version < "3"', 'dep4; extra == "extra1"', 'dep5; (python_version < "3") and extra == "extra2"', + 'dep6@ git+https://example.com/python/dep.git at v1.0.0 ; extra == "extra1"', ] # It's important that the environment marker expression be # wrapped in parentheses to avoid the following 'and' binding more diff --git a/Misc/NEWS.d/next/Library/2021-12-16-14-30-36.bpo-46105.pprB1K.rst b/Misc/NEWS.d/next/Library/2021-12-16-14-30-36.bpo-46105.pprB1K.rst new file mode 100644 index 0000000000000..145edccb2e7a5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-16-14-30-36.bpo-46105.pprB1K.rst @@ -0,0 +1,2 @@ +Honor spec when generating requirement specs with urls and extras +(importlib_metadata 4.8.3). From webhook-mailer at python.org Thu Dec 16 15:49:46 2021 From: webhook-mailer at python.org (jaraco) Date: Thu, 16 Dec 2021 20:49:46 -0000 Subject: [Python-checkins] bpo-44893: Implement EntryPoint as simple class with attributes. (GH-30150) Message-ID: https://github.com/python/cpython/commit/04deaee4c8d313717f3ea8f6a4fd70286d510d6e commit: 04deaee4c8d313717f3ea8f6a4fd70286d510d6e branch: main author: Jason R. Coombs committer: jaraco date: 2021-12-16T15:49:42-05:00 summary: bpo-44893: Implement EntryPoint as simple class with attributes. (GH-30150) * bpo-44893: Implement EntryPoint as simple class and deprecate tuple access in favor of attribute access. Syncs with importlib_metadata 4.8.1. * Apply refactorings found in importlib_metadata 4.8.2. files: A Lib/test/test_importlib/data/example2-1.0.0-py3-none-any.whl A Misc/NEWS.d/next/Library/2021-12-16-13-54-55.bpo-44893.I7aLiW.rst M Lib/importlib/metadata/__init__.py M Lib/importlib/metadata/_functools.py M Lib/importlib/metadata/_itertools.py M Lib/importlib/metadata/_meta.py M Lib/importlib/metadata/_text.py M Lib/test/test_importlib/fixtures.py M Lib/test/test_importlib/test_main.py M Lib/test/test_importlib/test_metadata_api.py M Lib/test/test_importlib/test_zip.py diff --git a/Lib/importlib/metadata/__init__.py b/Lib/importlib/metadata/__init__.py index ec41ed39157a9..d44541fcbfbf4 100644 --- a/Lib/importlib/metadata/__init__.py +++ b/Lib/importlib/metadata/__init__.py @@ -15,10 +15,9 @@ import collections from . import _adapters, _meta -from ._meta import PackageMetadata from ._collections import FreezableDefaultDict, Pair -from ._functools import method_cache -from ._itertools import unique_everseen +from ._functools import method_cache, pass_none +from ._itertools import always_iterable, unique_everseen from ._meta import PackageMetadata, SimplePath from contextlib import suppress @@ -121,8 +120,33 @@ def valid(line): return line and not line.startswith('#') -class EntryPoint( - collections.namedtuple('EntryPointBase', 'name value group')): +class DeprecatedTuple: + """ + Provide subscript item access for backward compatibility. + + >>> recwarn = getfixture('recwarn') + >>> ep = EntryPoint(name='name', value='value', group='group') + >>> ep[:] + ('name', 'value', 'group') + >>> ep[0] + 'name' + >>> len(recwarn) + 1 + """ + + _warn = functools.partial( + warnings.warn, + "EntryPoint tuple interface is deprecated. Access members by name.", + DeprecationWarning, + stacklevel=2, + ) + + def __getitem__(self, item): + self._warn() + return self._key()[item] + + +class EntryPoint(DeprecatedTuple): """An entry point as defined by Python packaging conventions. See `the packaging docs on entry points @@ -153,6 +177,9 @@ class EntryPoint( dist: Optional['Distribution'] = None + def __init__(self, name, value, group): + vars(self).update(name=name, value=value, group=group) + def load(self): """Load the entry point from its definition. If only a module is indicated by the value, return that module. Otherwise, @@ -179,7 +206,7 @@ def extras(self): return list(re.finditer(r'\w+', match.group('extras') or '')) def _for(self, dist): - self.dist = dist + vars(self).update(dist=dist) return self def __iter__(self): @@ -193,16 +220,31 @@ def __iter__(self): warnings.warn(msg, DeprecationWarning) return iter((self.name, self)) - def __reduce__(self): - return ( - self.__class__, - (self.name, self.value, self.group), - ) - def matches(self, **params): attrs = (getattr(self, param) for param in params) return all(map(operator.eq, params.values(), attrs)) + def _key(self): + return self.name, self.value, self.group + + def __lt__(self, other): + return self._key() < other._key() + + def __eq__(self, other): + return self._key() == other._key() + + def __setattr__(self, name, value): + raise AttributeError("EntryPoint objects are immutable.") + + def __repr__(self): + return ( + f'EntryPoint(name={self.name!r}, value={self.value!r}, ' + f'group={self.group!r})' + ) + + def __hash__(self): + return hash(self._key()) + class DeprecatedList(list): """ @@ -243,37 +285,26 @@ class DeprecatedList(list): stacklevel=2, ) - def __setitem__(self, *args, **kwargs): - self._warn() - return super().__setitem__(*args, **kwargs) - - def __delitem__(self, *args, **kwargs): - self._warn() - return super().__delitem__(*args, **kwargs) - - def append(self, *args, **kwargs): - self._warn() - return super().append(*args, **kwargs) - - def reverse(self, *args, **kwargs): - self._warn() - return super().reverse(*args, **kwargs) - - def extend(self, *args, **kwargs): - self._warn() - return super().extend(*args, **kwargs) - - def pop(self, *args, **kwargs): - self._warn() - return super().pop(*args, **kwargs) - - def remove(self, *args, **kwargs): - self._warn() - return super().remove(*args, **kwargs) - - def __iadd__(self, *args, **kwargs): - self._warn() - return super().__iadd__(*args, **kwargs) + def _wrap_deprecated_method(method_name: str): # type: ignore + def wrapped(self, *args, **kwargs): + self._warn() + return getattr(super(), method_name)(*args, **kwargs) + + return wrapped + + for method_name in [ + '__setitem__', + '__delitem__', + 'append', + 'reverse', + 'extend', + 'pop', + 'remove', + '__iadd__', + 'insert', + 'sort', + ]: + locals()[method_name] = _wrap_deprecated_method(method_name) def __add__(self, other): if not isinstance(other, tuple): @@ -281,14 +312,6 @@ def __add__(self, other): other = tuple(other) return self.__class__(tuple(self) + other) - def insert(self, *args, **kwargs): - self._warn() - return super().insert(*args, **kwargs) - - def sort(self, *args, **kwargs): - self._warn() - return super().sort(*args, **kwargs) - def __eq__(self, other): if not isinstance(other, tuple): self._warn() @@ -333,7 +356,7 @@ def names(self): """ Return the set of all names of all entry points. """ - return set(ep.name for ep in self) + return {ep.name for ep in self} @property def groups(self): @@ -344,21 +367,17 @@ def groups(self): >>> EntryPoints().groups set() """ - return set(ep.group for ep in self) + return {ep.group for ep in self} @classmethod def _from_text_for(cls, text, dist): return cls(ep._for(dist) for ep in cls._from_text(text)) - @classmethod - def _from_text(cls, text): - return itertools.starmap(EntryPoint, cls._parse_groups(text or '')) - @staticmethod - def _parse_groups(text): + def _from_text(text): return ( - (item.value.name, item.value.value, item.name) - for item in Sectioned.section_pairs(text) + EntryPoint(name=item.value.name, value=item.value.value, group=item.name) + for item in Sectioned.section_pairs(text or '') ) @@ -611,7 +630,6 @@ def files(self): missing. Result may be empty if the metadata exists but is empty. """ - file_lines = self._read_files_distinfo() or self._read_files_egginfo() def make_file(name, hash=None, size_str=None): result = PackagePath(name) @@ -620,7 +638,11 @@ def make_file(name, hash=None, size_str=None): result.dist = self return result - return file_lines and list(starmap(make_file, csv.reader(file_lines))) + @pass_none + def make_files(lines): + return list(starmap(make_file, csv.reader(lines))) + + return make_files(self._read_files_distinfo() or self._read_files_egginfo()) def _read_files_distinfo(self): """ @@ -742,6 +764,9 @@ class FastPath: """ Micro-optimized class for searching a path for children. + + >>> FastPath('').children() + ['...'] """ @functools.lru_cache() # type: ignore @@ -1011,6 +1036,18 @@ def packages_distributions() -> Mapping[str, List[str]]: """ pkg_to_dist = collections.defaultdict(list) for dist in distributions(): - for pkg in (dist.read_text('top_level.txt') or '').split(): + for pkg in _top_level_declared(dist) or _top_level_inferred(dist): pkg_to_dist[pkg].append(dist.metadata['Name']) return dict(pkg_to_dist) + + +def _top_level_declared(dist): + return (dist.read_text('top_level.txt') or '').split() + + +def _top_level_inferred(dist): + return { + f.parts[0] if len(f.parts) > 1 else f.with_suffix('').name + for f in always_iterable(dist.files) + if f.suffix == ".py" + } diff --git a/Lib/importlib/metadata/_functools.py b/Lib/importlib/metadata/_functools.py index 73f50d00bc04c..71f66bd03cb71 100644 --- a/Lib/importlib/metadata/_functools.py +++ b/Lib/importlib/metadata/_functools.py @@ -83,3 +83,22 @@ def wrapper(self, *args, **kwargs): wrapper.cache_clear = lambda: None return wrapper + + +# From jaraco.functools 3.3 +def pass_none(func): + """ + Wrap func so it's not called if its first param is None + + >>> print_text = pass_none(print) + >>> print_text('text') + text + >>> print_text(None) + """ + + @functools.wraps(func) + def wrapper(param, *args, **kwargs): + if param is not None: + return func(param, *args, **kwargs) + + return wrapper diff --git a/Lib/importlib/metadata/_itertools.py b/Lib/importlib/metadata/_itertools.py index dd45f2f096630..d4ca9b9140e3f 100644 --- a/Lib/importlib/metadata/_itertools.py +++ b/Lib/importlib/metadata/_itertools.py @@ -17,3 +17,57 @@ def unique_everseen(iterable, key=None): if k not in seen: seen_add(k) yield element + + +# copied from more_itertools 8.8 +def always_iterable(obj, base_type=(str, bytes)): + """If *obj* is iterable, return an iterator over its items:: + + >>> obj = (1, 2, 3) + >>> list(always_iterable(obj)) + [1, 2, 3] + + If *obj* is not iterable, return a one-item iterable containing *obj*:: + + >>> obj = 1 + >>> list(always_iterable(obj)) + [1] + + If *obj* is ``None``, return an empty iterable: + + >>> obj = None + >>> list(always_iterable(None)) + [] + + By default, binary and text strings are not considered iterable:: + + >>> obj = 'foo' + >>> list(always_iterable(obj)) + ['foo'] + + If *base_type* is set, objects for which ``isinstance(obj, base_type)`` + returns ``True`` won't be considered iterable. + + >>> obj = {'a': 1} + >>> list(always_iterable(obj)) # Iterate over the dict's keys + ['a'] + >>> list(always_iterable(obj, base_type=dict)) # Treat dicts as a unit + [{'a': 1}] + + Set *base_type* to ``None`` to avoid any special handling and treat objects + Python considers iterable as iterable: + + >>> obj = 'foo' + >>> list(always_iterable(obj, base_type=None)) + ['f', 'o', 'o'] + """ + if obj is None: + return iter(()) + + if (base_type is not None) and isinstance(obj, base_type): + return iter((obj,)) + + try: + return iter(obj) + except TypeError: + return iter((obj,)) diff --git a/Lib/importlib/metadata/_meta.py b/Lib/importlib/metadata/_meta.py index 1a6edbf957d5a..d5c0576194ece 100644 --- a/Lib/importlib/metadata/_meta.py +++ b/Lib/importlib/metadata/_meta.py @@ -37,7 +37,7 @@ class SimplePath(Protocol): def joinpath(self) -> 'SimplePath': ... # pragma: no cover - def __div__(self) -> 'SimplePath': + def __truediv__(self) -> 'SimplePath': ... # pragma: no cover def parent(self) -> 'SimplePath': diff --git a/Lib/importlib/metadata/_text.py b/Lib/importlib/metadata/_text.py index 766979d93c169..c88cfbb2349c6 100644 --- a/Lib/importlib/metadata/_text.py +++ b/Lib/importlib/metadata/_text.py @@ -80,7 +80,7 @@ def __hash__(self): return hash(self.lower()) def __contains__(self, other): - return super(FoldedCase, self).lower().__contains__(other.lower()) + return super().lower().__contains__(other.lower()) def in_(self, other): "Does self appear in other?" @@ -89,7 +89,7 @@ def in_(self, other): # cache lower since it's likely to be called frequently. @method_cache def lower(self): - return super(FoldedCase, self).lower() + return super().lower() def index(self, sub): return self.lower().index(sub.lower()) diff --git a/Lib/test/test_importlib/data/example2-1.0.0-py3-none-any.whl b/Lib/test/test_importlib/data/example2-1.0.0-py3-none-any.whl new file mode 100644 index 0000000000000..5ca93657f8196 Binary files /dev/null and b/Lib/test/test_importlib/data/example2-1.0.0-py3-none-any.whl differ diff --git a/Lib/test/test_importlib/fixtures.py b/Lib/test/test_importlib/fixtures.py index 12ed07d33744a..d7ed4e9d56ff5 100644 --- a/Lib/test/test_importlib/fixtures.py +++ b/Lib/test/test_importlib/fixtures.py @@ -8,8 +8,17 @@ import contextlib from test.support.os_helper import FS_NONASCII +from test.support import requires_zlib from typing import Dict, Union +try: + from importlib import resources + + getattr(resources, 'files') + getattr(resources, 'as_file') +except (ImportError, AttributeError): + import importlib_resources as resources # type: ignore + @contextlib.contextmanager def tempdir(): @@ -54,7 +63,7 @@ def setUp(self): class SiteDir(Fixtures): def setUp(self): - super(SiteDir, self).setUp() + super().setUp() self.site_dir = self.fixtures.enter_context(tempdir()) @@ -69,7 +78,7 @@ def add_sys_path(dir): sys.path.remove(str(dir)) def setUp(self): - super(OnSysPath, self).setUp() + super().setUp() self.fixtures.enter_context(self.add_sys_path(self.site_dir)) @@ -106,7 +115,7 @@ def main(): } def setUp(self): - super(DistInfoPkg, self).setUp() + super().setUp() build_files(DistInfoPkg.files, self.site_dir) def make_uppercase(self): @@ -131,7 +140,7 @@ class DistInfoPkgWithDot(OnSysPath, SiteDir): } def setUp(self): - super(DistInfoPkgWithDot, self).setUp() + super().setUp() build_files(DistInfoPkgWithDot.files, self.site_dir) @@ -152,13 +161,13 @@ class DistInfoPkgWithDotLegacy(OnSysPath, SiteDir): } def setUp(self): - super(DistInfoPkgWithDotLegacy, self).setUp() + super().setUp() build_files(DistInfoPkgWithDotLegacy.files, self.site_dir) class DistInfoPkgOffPath(SiteDir): def setUp(self): - super(DistInfoPkgOffPath, self).setUp() + super().setUp() build_files(DistInfoPkg.files, self.site_dir) @@ -198,7 +207,7 @@ def main(): } def setUp(self): - super(EggInfoPkg, self).setUp() + super().setUp() build_files(EggInfoPkg.files, prefix=self.site_dir) @@ -219,7 +228,7 @@ class EggInfoFile(OnSysPath, SiteDir): } def setUp(self): - super(EggInfoFile, self).setUp() + super().setUp() build_files(EggInfoFile.files, prefix=self.site_dir) @@ -285,3 +294,20 @@ def DALS(str): class NullFinder: def find_module(self, name): pass + + + at requires_zlib() +class ZipFixtures: + root = 'test.test_importlib.data' + + def _fixture_on_path(self, filename): + pkg_file = resources.files(self.root).joinpath(filename) + file = self.resources.enter_context(resources.as_file(pkg_file)) + assert file.name.startswith('example'), file.name + sys.path.insert(0, str(file)) + self.resources.callback(sys.path.pop, 0) + + def setUp(self): + # Add self.zip_name to the front of sys.path. + self.resources = contextlib.ExitStack() + self.addCleanup(self.resources.close) diff --git a/Lib/test/test_importlib/test_main.py b/Lib/test/test_importlib/test_main.py index 52cb63712a5cb..2e120f7ac50ac 100644 --- a/Lib/test/test_importlib/test_main.py +++ b/Lib/test/test_importlib/test_main.py @@ -19,6 +19,7 @@ distributions, entry_points, metadata, + packages_distributions, version, ) @@ -203,7 +204,7 @@ class InaccessibleSysPath(fixtures.OnSysPath, ffs.TestCase): site_dir = '/access-denied' def setUp(self): - super(InaccessibleSysPath, self).setUp() + super().setUp() self.setUpPyfakefs() self.fs.create_dir(self.site_dir, perm_bits=000) @@ -217,13 +218,21 @@ def test_discovery(self): class TestEntryPoints(unittest.TestCase): def __init__(self, *args): - super(TestEntryPoints, self).__init__(*args) - self.ep = importlib.metadata.EntryPoint('name', 'value', 'group') + super().__init__(*args) + self.ep = importlib.metadata.EntryPoint( + name='name', value='value', group='group' + ) def test_entry_point_pickleable(self): revived = pickle.loads(pickle.dumps(self.ep)) assert revived == self.ep + def test_positional_args(self): + """ + Capture legacy (namedtuple) construction, discouraged. + """ + EntryPoint('name', 'value', 'group') + def test_immutable(self): """EntryPoints should be immutable""" with self.assertRaises(AttributeError): @@ -254,8 +263,8 @@ def test_sortable(self): # EntryPoint objects are sortable, but result is undefined. sorted( [ - EntryPoint('b', 'val', 'group'), - EntryPoint('a', 'val', 'group'), + EntryPoint(name='b', value='val', group='group'), + EntryPoint(name='a', value='val', group='group'), ] ) @@ -271,3 +280,38 @@ def test_unicode_dir_on_sys_path(self): prefix=self.site_dir, ) list(distributions()) + + +class PackagesDistributionsPrebuiltTest(fixtures.ZipFixtures, unittest.TestCase): + def test_packages_distributions_example(self): + self._fixture_on_path('example-21.12-py3-none-any.whl') + assert packages_distributions()['example'] == ['example'] + + def test_packages_distributions_example2(self): + """ + Test packages_distributions on a wheel built + by trampolim. + """ + self._fixture_on_path('example2-1.0.0-py3-none-any.whl') + assert packages_distributions()['example2'] == ['example2'] + + +class PackagesDistributionsTest( + fixtures.OnSysPath, fixtures.SiteDir, unittest.TestCase +): + def test_packages_distributions_neither_toplevel_nor_files(self): + """ + Test a package built without 'top-level.txt' or a file list. + """ + fixtures.build_files( + { + 'trim_example-1.0.0.dist-info': { + 'METADATA': """ + Name: trim_example + Version: 1.0.0 + """, + } + }, + prefix=self.site_dir, + ) + packages_distributions() diff --git a/Lib/test/test_importlib/test_metadata_api.py b/Lib/test/test_importlib/test_metadata_api.py index 4a45312e31cd5..e16773a7e87ef 100644 --- a/Lib/test/test_importlib/test_metadata_api.py +++ b/Lib/test/test_importlib/test_metadata_api.py @@ -21,7 +21,7 @@ @contextlib.contextmanager def suppress_known_deprecation(): with warnings.catch_warnings(record=True) as ctx: - warnings.simplefilter('default') + warnings.simplefilter('default', category=DeprecationWarning) yield ctx @@ -113,7 +113,7 @@ def test_entry_points_unique_packages(self): for ep in entries ) # ns:sub doesn't exist in alt_pkg - assert 'ns:sub' not in entries + assert 'ns:sub' not in entries.names def test_entry_points_missing_name(self): with self.assertRaises(KeyError): @@ -194,10 +194,8 @@ def _test_files(files): file.read_text() def test_file_hash_repr(self): - assertRegex = self.assertRegex - util = [p for p in files('distinfo-pkg') if p.name == 'mod.py'][0] - assertRegex(repr(util.hash), '') + self.assertRegex(repr(util.hash), '') def test_files_dist_info(self): self._test_files(files('distinfo-pkg')) diff --git a/Lib/test/test_importlib/test_zip.py b/Lib/test/test_importlib/test_zip.py index bf16a3b95e18c..276f6288c9159 100644 --- a/Lib/test/test_importlib/test_zip.py +++ b/Lib/test/test_importlib/test_zip.py @@ -1,7 +1,7 @@ import sys import unittest -from contextlib import ExitStack +from . import fixtures from importlib.metadata import ( PackageNotFoundError, distribution, @@ -10,27 +10,11 @@ files, version, ) -from importlib import resources -from test.support import requires_zlib - - - at requires_zlib() -class TestZip(unittest.TestCase): - root = 'test.test_importlib.data' - - def _fixture_on_path(self, filename): - pkg_file = resources.files(self.root).joinpath(filename) - file = self.resources.enter_context(resources.as_file(pkg_file)) - assert file.name.startswith('example-'), file.name - sys.path.insert(0, str(file)) - self.resources.callback(sys.path.pop, 0) +class TestZip(fixtures.ZipFixtures, unittest.TestCase): def setUp(self): - # Find the path to the example-*.whl so we can add it to the front of - # sys.path, where we'll then try to find the metadata thereof. - self.resources = ExitStack() - self.addCleanup(self.resources.close) + super().setUp() self._fixture_on_path('example-21.12-py3-none-any.whl') def test_zip_version(self): @@ -63,13 +47,9 @@ def test_one_distribution(self): assert len(dists) == 1 - at requires_zlib() class TestEgg(TestZip): def setUp(self): - # Find the path to the example-*.egg so we can add it to the front of - # sys.path, where we'll then try to find the metadata thereof. - self.resources = ExitStack() - self.addCleanup(self.resources.close) + super().setUp() self._fixture_on_path('example-21.12-py3.6.egg') def test_files(self): diff --git a/Misc/NEWS.d/next/Library/2021-12-16-13-54-55.bpo-44893.I7aLiW.rst b/Misc/NEWS.d/next/Library/2021-12-16-13-54-55.bpo-44893.I7aLiW.rst new file mode 100644 index 0000000000000..e77c6ad2a483e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-16-13-54-55.bpo-44893.I7aLiW.rst @@ -0,0 +1,3 @@ +EntryPoint objects are no longer tuples. Recommended means to access is by +attribute ('.name', '.group') or accessor ('.load()'). Access by index is +deprecated and will raise deprecation warning. From webhook-mailer at python.org Thu Dec 16 16:19:23 2021 From: webhook-mailer at python.org (miss-islington) Date: Thu, 16 Dec 2021 21:19:23 -0000 Subject: [Python-checkins] bpo-46105: Honor spec when generating requirement specs with urls and extras. (GH-30151) Message-ID: https://github.com/python/cpython/commit/09d7319bfe0006d9aa3fc14833b69c24ccafdca6 commit: 09d7319bfe0006d9aa3fc14833b69c24ccafdca6 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-16T13:19:14-08:00 summary: bpo-46105: Honor spec when generating requirement specs with urls and extras. (GH-30151) (cherry picked from commit 109d96602199a91e94eb14b8cb3720841f22ded7) Co-authored-by: Jason R. Coombs files: A Misc/NEWS.d/next/Library/2021-12-16-14-30-36.bpo-46105.pprB1K.rst M Lib/importlib/metadata/__init__.py M Lib/test/test_importlib/test_metadata_api.py diff --git a/Lib/importlib/metadata/__init__.py b/Lib/importlib/metadata/__init__.py index b3e8fb05f1d98..ec41ed39157a9 100644 --- a/Lib/importlib/metadata/__init__.py +++ b/Lib/importlib/metadata/__init__.py @@ -669,7 +669,7 @@ def _convert_egg_info_reqs_to_simple_reqs(sections): def make_condition(name): return name and f'extra == "{name}"' - def parse_condition(section): + def quoted_marker(section): section = section or '' extra, sep, markers = section.partition(':') if extra and markers: @@ -677,8 +677,17 @@ def parse_condition(section): conditions = list(filter(None, [markers, make_condition(extra)])) return '; ' + ' and '.join(conditions) if conditions else '' + def url_req_space(req): + """ + PEP 508 requires a space between the url_spec and the quoted_marker. + Ref python/importlib_metadata#357. + """ + # '@' is uniquely indicative of a url_req. + return ' ' * ('@' in req) + for section in sections: - yield section.value + parse_condition(section.name) + space = url_req_space(section.value) + yield section.value + space + quoted_marker(section.name) class DistributionFinder(MetaPathFinder): diff --git a/Lib/test/test_importlib/test_metadata_api.py b/Lib/test/test_importlib/test_metadata_api.py index dc9c234d15b78..4a45312e31cd5 100644 --- a/Lib/test/test_importlib/test_metadata_api.py +++ b/Lib/test/test_importlib/test_metadata_api.py @@ -235,6 +235,7 @@ def test_more_complex_deps_requires_text(self): [extra1] dep4 + dep6@ git+https://example.com/python/dep.git at v1.0.0 [extra2:python_version < "3"] dep5 @@ -247,6 +248,7 @@ def test_more_complex_deps_requires_text(self): 'dep3; python_version < "3"', 'dep4; extra == "extra1"', 'dep5; (python_version < "3") and extra == "extra2"', + 'dep6@ git+https://example.com/python/dep.git at v1.0.0 ; extra == "extra1"', ] # It's important that the environment marker expression be # wrapped in parentheses to avoid the following 'and' binding more diff --git a/Misc/NEWS.d/next/Library/2021-12-16-14-30-36.bpo-46105.pprB1K.rst b/Misc/NEWS.d/next/Library/2021-12-16-14-30-36.bpo-46105.pprB1K.rst new file mode 100644 index 0000000000000..145edccb2e7a5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-16-14-30-36.bpo-46105.pprB1K.rst @@ -0,0 +1,2 @@ +Honor spec when generating requirement specs with urls and extras +(importlib_metadata 4.8.3). From webhook-mailer at python.org Thu Dec 16 18:00:23 2021 From: webhook-mailer at python.org (iritkatriel) Date: Thu, 16 Dec 2021 23:00:23 -0000 Subject: [Python-checkins] bpo-45635: Do not suppress errors in functions called from _PyErr_Display (GH-30073) Message-ID: https://github.com/python/cpython/commit/8d6155ee9d1b05946f951d0ba602b9f63810fe0f commit: 8d6155ee9d1b05946f951d0ba602b9f63810fe0f branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-12-16T23:00:13Z summary: bpo-45635: Do not suppress errors in functions called from _PyErr_Display (GH-30073) Co-authored-by: Erlend Egeberg Aasland files: A Misc/NEWS.d/next/Core and Builtins/2021-12-12-15-52-41.bpo-45635.ADVaPT.rst M Python/pythonrun.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-12-15-52-41.bpo-45635.ADVaPT.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-12-15-52-41.bpo-45635.ADVaPT.rst new file mode 100644 index 0000000000000..d2c97f564b2d2 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-12-15-52-41.bpo-45635.ADVaPT.rst @@ -0,0 +1 @@ +The code called from :c:func:`_PyErr_Display` was refactored to improve error handling. It now exits immediately upon an unrecoverable error. \ No newline at end of file diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 4fff088fc3e10..6f170a4dd63eb 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -629,14 +629,18 @@ parse_syntax_error(PyObject *err, PyObject **message, PyObject **filename, return 0; } -static void -print_error_text(PyObject *f, Py_ssize_t offset, Py_ssize_t end_offset, PyObject *text_obj) +static int +print_error_text(PyObject *f, Py_ssize_t offset, Py_ssize_t end_offset, + PyObject *text_obj) { - size_t caret_repetitions = (end_offset > 0 && end_offset > offset) ? end_offset - offset : 1; + size_t caret_repetitions = (end_offset > 0 && end_offset > offset) ? + end_offset - offset : 1; + /* Convert text to a char pointer; return if error */ const char *text = PyUnicode_AsUTF8(text_obj); - if (text == NULL) - return; + if (text == NULL) { + return -1; + } /* Convert offset from 1-based to 0-based */ offset--; @@ -675,27 +679,43 @@ print_error_text(PyObject *f, Py_ssize_t offset, Py_ssize_t end_offset, PyObject } /* Print text */ - PyFile_WriteString(" ", f); - PyFile_WriteString(text, f); + if (PyFile_WriteString(" ", f) < 0) { + return -1; + } + if (PyFile_WriteString(text, f) < 0) { + return -1; + } /* Make sure there's a newline at the end */ if (text[len] != '\n') { - PyFile_WriteString("\n", f); + if (PyFile_WriteString("\n", f) < 0) { + return -1; + } } /* Don't print caret if it points to the left of the text */ - if (offset < 0) - return; + if (offset < 0) { + return 0; + } /* Write caret line */ - PyFile_WriteString(" ", f); + if (PyFile_WriteString(" ", f) < 0) { + return -1; + } while (--offset >= 0) { - PyFile_WriteString(" ", f); + if (PyFile_WriteString(" ", f) < 0) { + return -1; + } } for (size_t caret_iter=0; caret_iter < caret_repetitions ; caret_iter++) { - PyFile_WriteString("^", f); + if (PyFile_WriteString("^", f) < 0) { + return -1; + } + } + if (PyFile_WriteString("\n", f) < 0) { + return -1; } - PyFile_WriteString("\n", f); + return 0; } @@ -953,6 +973,77 @@ print_exception_traceback(struct exception_print_context *ctx, PyObject *value) return err; } +static int +print_exception_file_and_line(struct exception_print_context *ctx, + PyObject **value_p) +{ + PyObject *f = ctx->file; + + _Py_IDENTIFIER(print_file_and_line); + PyObject *tmp; + int res = _PyObject_LookupAttrId(*value_p, &PyId_print_file_and_line, &tmp); + if (res <= 0) { + if (res < 0) { + PyErr_Clear(); + } + return 0; + } + Py_DECREF(tmp); + + PyObject *message, *filename, *text; + Py_ssize_t lineno, offset, end_lineno, end_offset; + if (!parse_syntax_error(*value_p, &message, &filename, + &lineno, &offset, + &end_lineno, &end_offset, &text)) { + PyErr_Clear(); + return 0; + } + + Py_SETREF(*value_p, message); + + PyObject *line = PyUnicode_FromFormat(" File \"%S\", line %zd\n", + filename, lineno); + Py_DECREF(filename); + if (line == NULL) { + goto error; + } + if (write_indented_margin(ctx, f) < 0) { + goto error; + } + if (PyFile_WriteObject(line, f, Py_PRINT_RAW) < 0) { + goto error; + } + Py_CLEAR(line); + + if (text != NULL) { + Py_ssize_t line_size; + const char *error_line = PyUnicode_AsUTF8AndSize(text, &line_size); + // If the location of the error spawn multiple lines, we want + // to just print the first one and highlight everything until + // the end of that one since we don't support multi-line error + // messages. + if (end_lineno > lineno) { + end_offset = (error_line != NULL) ? line_size : -1; + } + // Limit the amount of '^' that we can display to + // the size of the text in the source line. + if (error_line != NULL && end_offset > line_size + 1) { + end_offset = line_size + 1; + } + if (print_error_text(f, offset, end_offset, text) < 0) { + goto error; + } + Py_DECREF(text); + } + assert(!PyErr_Occurred()); + return 0; + +error: + Py_XDECREF(line); + Py_XDECREF(text); + return -1; +} + /* Prints the message line: module.qualname[: str(exc)] */ static int print_exception_message(struct exception_print_context *ctx, PyObject *type, @@ -1072,6 +1163,11 @@ static int print_exception_note(struct exception_print_context *ctx, PyObject *value) { PyObject *f = ctx->file; + + if (!PyExceptionInstance_Check(value)) { + return 0; + } + _Py_IDENTIFIER(__note__); PyObject *note = _PyObject_GetAttrId(value, &PyId___note__); @@ -1112,98 +1208,47 @@ print_exception_note(struct exception_print_context *ctx, PyObject *value) return -1; } -static void +static int print_exception(struct exception_print_context *ctx, PyObject *value) { - int err = 0; - PyObject *tmp; PyObject *f = ctx->file; - _Py_IDENTIFIER(print_file_and_line); - if (!PyExceptionInstance_Check(value)) { - if (print_exception_invalid_type(ctx, value) < 0) { - PyErr_Clear(); /* TODO: change to return -1 */ - } - return; + return print_exception_invalid_type(ctx, value); } Py_INCREF(value); fflush(stdout); - PyObject *type = (PyObject *) Py_TYPE(value); - err = print_exception_traceback(ctx, value); - if (err == 0 && - (err = _PyObject_LookupAttrId(value, &PyId_print_file_and_line, &tmp)) > 0) - { - PyObject *message, *filename, *text; - Py_ssize_t lineno, offset, end_lineno, end_offset; - err = 0; - Py_DECREF(tmp); - if (!parse_syntax_error(value, &message, &filename, - &lineno, &offset, - &end_lineno, &end_offset, &text)) { - PyErr_Clear(); - } - else { - Py_DECREF(value); - value = message; - - PyObject *line = PyUnicode_FromFormat(" File \"%S\", line %zd\n", - filename, lineno); - Py_DECREF(filename); - if (line != NULL) { - err = write_indented_margin(ctx, f); - if (err == 0) { - err = PyFile_WriteObject(line, f, Py_PRINT_RAW); - } - Py_DECREF(line); - } + if (print_exception_traceback(ctx, value) < 0) { + goto error; + } - if (text != NULL) { - Py_ssize_t line_size; - const char* error_line = PyUnicode_AsUTF8AndSize(text, &line_size); - // If the location of the error spawn multiple lines, we want - // to just print the first one and highlight everything until - // the end of that one since we don't support multi-line error - // messages. - if (end_lineno > lineno) { - end_offset = (error_line != NULL) ? line_size : -1; - } - // Limit the amount of '^' that we can display to - // the size of the text in the source line. - if (error_line != NULL && end_offset > line_size + 1) { - end_offset = line_size + 1; - } - print_error_text(f, offset, end_offset, text); - Py_DECREF(text); - } + /* grab the type now because value can change below */ + PyObject *type = (PyObject *) Py_TYPE(value); - /* Can't be bothered to check all those - PyFile_WriteString() calls */ - if (PyErr_Occurred()) - err = -1; - } + if (print_exception_file_and_line(ctx, &value) < 0) { + goto error; } - - if (err == 0) { - err = print_exception_message(ctx, type, value); + if (print_exception_message(ctx, type, value) < 0) { + goto error; } - if (err == 0) { - err = print_exception_suggestions(ctx, value); + if (print_exception_suggestions(ctx, value) < 0) { + goto error; } - if (err == 0) { - err = PyFile_WriteString("\n", f); + if (PyFile_WriteString("\n", f) < 0) { + goto error; } - if (err == 0 && PyExceptionInstance_Check(value)) { - err = print_exception_note(ctx, value); + if (print_exception_note(ctx, value) < 0) { + goto error; } Py_DECREF(value); - /* If an error happened here, don't show it. - XXX This is wrong, but too many callers rely on this behavior. */ - if (err != 0) - PyErr_Clear(); + assert(!PyErr_Occurred()); + return 0; +error: + Py_DECREF(value); + return -1; } static const char cause_message[] = @@ -1214,7 +1259,7 @@ static const char context_message[] = "During handling of the above exception, " "another exception occurred:\n"; -static void +static int print_exception_recursive(struct exception_print_context*, PyObject*); static int @@ -1227,10 +1272,12 @@ print_chained(struct exception_print_context* ctx, PyObject *value, return -1; } bool need_close = ctx->need_close; - print_exception_recursive(ctx, value); + int res = print_exception_recursive(ctx, value); ctx->need_close = need_close; - Py_LeaveRecursiveCall(); + if (res < 0) { + return -1; + } if (write_indented_margin(ctx, f) < 0) { return -1; @@ -1398,11 +1445,14 @@ print_exception_group(struct exception_print_context *ctx, PyObject *value) PyObject *exc = PyTuple_GET_ITEM(excs, i); if (!truncated) { - if (Py_EnterRecursiveCall(" in print_exception_recursive") != 0) { + if (Py_EnterRecursiveCall(" in print_exception_group") != 0) { return -1; } - print_exception_recursive(ctx, exc); + int res = print_exception_recursive(ctx, exc); Py_LeaveRecursiveCall(); + if (res < 0) { + return -1; + } } else { Py_ssize_t excs_remaining = num_excs - ctx->max_group_width; @@ -1445,33 +1495,25 @@ print_exception_group(struct exception_print_context *ctx, PyObject *value) return 0; } -static void +static int print_exception_recursive(struct exception_print_context *ctx, PyObject *value) { - int err = 0; if (ctx->seen != NULL) { /* Exception chaining */ - err = print_exception_cause_and_context(ctx, value); - } - if (err) { - /* don't do anything else */ - } - else if (!_PyBaseExceptionGroup_Check(value)) { - print_exception(ctx, value); - } - else { - int prev_depth = ctx->exception_group_depth; - err = print_exception_group(ctx, value); - if (err < 0) { - /* restore the depth as long as we're ignoring errors */ - ctx->exception_group_depth = prev_depth; + if (print_exception_cause_and_context(ctx, value) < 0) { + return -1; } - else { - assert(prev_depth == ctx->exception_group_depth); + } + if (!_PyBaseExceptionGroup_Check(value)) { + if (print_exception(ctx, value) < 0) { + return -1; } } - if (err != 0) - PyErr_Clear(); + else if (print_exception_group(ctx, value) < 0) { + return -1; + } + assert(!PyErr_Occurred()); + return 0; } #define PyErr_MAX_GROUP_WIDTH 15 @@ -1505,7 +1547,9 @@ _PyErr_Display(PyObject *file, PyObject *exception, PyObject *value, PyObject *t if (ctx.seen == NULL) { PyErr_Clear(); } - print_exception_recursive(&ctx, value); + if (print_exception_recursive(&ctx, value) < 0) { + PyErr_Clear(); + } Py_XDECREF(ctx.seen); /* Call file.flush() */ From webhook-mailer at python.org Thu Dec 16 19:58:28 2021 From: webhook-mailer at python.org (jaraco) Date: Fri, 17 Dec 2021 00:58:28 -0000 Subject: [Python-checkins] [3.9] bpo-46105: Honor spec when generating requirement specs with urls and extras. (GH-30151). (GH-30157) Message-ID: https://github.com/python/cpython/commit/864ec170e14b663f999eb415a4f1a0067ec6833a commit: 864ec170e14b663f999eb415a4f1a0067ec6833a branch: 3.9 author: Jason R. Coombs committer: jaraco date: 2021-12-16T19:58:19-05:00 summary: [3.9] bpo-46105: Honor spec when generating requirement specs with urls and extras. (GH-30151). (GH-30157) (cherry picked from commit 109d96602199a91e94eb14b8cb3720841f22ded7) Co-authored-by: Jason R. Coombs files: A Misc/NEWS.d/next/Library/2021-12-16-14-30-36.bpo-46105.pprB1K.rst M Lib/importlib/metadata.py M Lib/test/test_importlib/test_metadata_api.py diff --git a/Lib/importlib/metadata.py b/Lib/importlib/metadata.py index c6c7d31aa5d8a..594986ce23efa 100644 --- a/Lib/importlib/metadata.py +++ b/Lib/importlib/metadata.py @@ -344,17 +344,26 @@ def _convert_egg_info_reqs_to_simple_reqs(sections): def make_condition(name): return name and 'extra == "{name}"'.format(name=name) - def parse_condition(section): + def quoted_marker(section): section = section or '' extra, sep, markers = section.partition(':') if extra and markers: - markers = '({markers})'.format(markers=markers) + markers = f'({markers})' conditions = list(filter(None, [markers, make_condition(extra)])) return '; ' + ' and '.join(conditions) if conditions else '' + def url_req_space(req): + """ + PEP 508 requires a space between the url_spec and the quoted_marker. + Ref python/importlib_metadata#357. + """ + # '@' is uniquely indicative of a url_req. + return ' ' * ('@' in req) + for section, deps in sections.items(): for dep in deps: - yield dep + parse_condition(section) + space = url_req_space(dep) + yield dep + space + quoted_marker(section) class DistributionFinder(MetaPathFinder): diff --git a/Lib/test/test_importlib/test_metadata_api.py b/Lib/test/test_importlib/test_metadata_api.py index 1d7b29ae05fd1..420fbfeb3a704 100644 --- a/Lib/test/test_importlib/test_metadata_api.py +++ b/Lib/test/test_importlib/test_metadata_api.py @@ -121,6 +121,7 @@ def test_more_complex_deps_requires_text(self): [extra1] dep4 + dep6@ git+https://example.com/python/dep.git at v1.0.0 [extra2:python_version < "3"] dep5 @@ -132,6 +133,7 @@ def test_more_complex_deps_requires_text(self): 'dep3; python_version < "3"', 'dep4; extra == "extra1"', 'dep5; (python_version < "3") and extra == "extra2"', + 'dep6@ git+https://example.com/python/dep.git at v1.0.0 ; extra == "extra1"', ] # It's important that the environment marker expression be # wrapped in parentheses to avoid the following 'and' binding more diff --git a/Misc/NEWS.d/next/Library/2021-12-16-14-30-36.bpo-46105.pprB1K.rst b/Misc/NEWS.d/next/Library/2021-12-16-14-30-36.bpo-46105.pprB1K.rst new file mode 100644 index 0000000000000..145edccb2e7a5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-16-14-30-36.bpo-46105.pprB1K.rst @@ -0,0 +1,2 @@ +Honor spec when generating requirement specs with urls and extras +(importlib_metadata 4.8.3). From webhook-mailer at python.org Fri Dec 17 00:08:25 2021 From: webhook-mailer at python.org (miss-islington) Date: Fri, 17 Dec 2021 05:08:25 -0000 Subject: [Python-checkins] Fix a typo in the message from make_ssl_certs. (GH-30152) Message-ID: https://github.com/python/cpython/commit/69ef1b59983065ddb0b712dac3b04107c5059735 commit: 69ef1b59983065ddb0b712dac3b04107c5059735 branch: main author: Yilei "Dolee" Yang committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-16T21:08:18-08:00 summary: Fix a typo in the message from make_ssl_certs. (GH-30152) The file is utils.py not util.py. Automerge-Triggered-By: GH:gpshead files: M Lib/test/make_ssl_certs.py diff --git a/Lib/test/make_ssl_certs.py b/Lib/test/make_ssl_certs.py index c62896f861dab..94a35a64ab1ab 100644 --- a/Lib/test/make_ssl_certs.py +++ b/Lib/test/make_ssl_certs.py @@ -307,6 +307,6 @@ def print_cert(path): f.write(cert) unmake_ca() - print("update Lib/test/test_ssl.py and Lib/test/test_asyncio/util.py") + print("update Lib/test/test_ssl.py and Lib/test/test_asyncio/utils.py") print_cert('keycert.pem') print_cert('keycert3.pem') From webhook-mailer at python.org Fri Dec 17 00:49:57 2021 From: webhook-mailer at python.org (miss-islington) Date: Fri, 17 Dec 2021 05:49:57 -0000 Subject: [Python-checkins] Fix a typo in the message from make_ssl_certs. (GH-30152) Message-ID: https://github.com/python/cpython/commit/212014d8c4eca546104a719938899a51bd497487 commit: 212014d8c4eca546104a719938899a51bd497487 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-16T21:49:37-08:00 summary: Fix a typo in the message from make_ssl_certs. (GH-30152) The file is utils.py not util.py. Automerge-Triggered-By: GH:gpshead (cherry picked from commit 69ef1b59983065ddb0b712dac3b04107c5059735) Co-authored-by: Yilei "Dolee" Yang files: M Lib/test/make_ssl_certs.py diff --git a/Lib/test/make_ssl_certs.py b/Lib/test/make_ssl_certs.py index c62896f861dab..94a35a64ab1ab 100644 --- a/Lib/test/make_ssl_certs.py +++ b/Lib/test/make_ssl_certs.py @@ -307,6 +307,6 @@ def print_cert(path): f.write(cert) unmake_ca() - print("update Lib/test/test_ssl.py and Lib/test/test_asyncio/util.py") + print("update Lib/test/test_ssl.py and Lib/test/test_asyncio/utils.py") print_cert('keycert.pem') print_cert('keycert3.pem') From webhook-mailer at python.org Fri Dec 17 00:51:20 2021 From: webhook-mailer at python.org (gpshead) Date: Fri, 17 Dec 2021 05:51:20 -0000 Subject: [Python-checkins] Fix a typo in the message from make_ssl_certs. (GH-30152) (GH-30161) Message-ID: https://github.com/python/cpython/commit/cbb4d4a642f7f58f0dc1a89a4af6fb4bc80db41b commit: cbb4d4a642f7f58f0dc1a89a4af6fb4bc80db41b branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: gpshead date: 2021-12-16T21:51:11-08:00 summary: Fix a typo in the message from make_ssl_certs. (GH-30152) (GH-30161) The file is utils.py not util.py. Automerge-Triggered-By: GH:gpshead (cherry picked from commit 69ef1b59983065ddb0b712dac3b04107c5059735) Co-authored-by: Yilei "Dolee" Yang files: M Lib/test/make_ssl_certs.py diff --git a/Lib/test/make_ssl_certs.py b/Lib/test/make_ssl_certs.py index c62896f861dab..94a35a64ab1ab 100644 --- a/Lib/test/make_ssl_certs.py +++ b/Lib/test/make_ssl_certs.py @@ -307,6 +307,6 @@ def print_cert(path): f.write(cert) unmake_ca() - print("update Lib/test/test_ssl.py and Lib/test/test_asyncio/util.py") + print("update Lib/test/test_ssl.py and Lib/test/test_asyncio/utils.py") print_cert('keycert.pem') print_cert('keycert3.pem') From webhook-mailer at python.org Fri Dec 17 04:11:05 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Fri, 17 Dec 2021 09:11:05 -0000 Subject: [Python-checkins] bpo-46111: Fix unittest tests in optimized mode (GH-30163) Message-ID: https://github.com/python/cpython/commit/95a922b3bb3af247ec141d73fcdfbf68bb1d32a5 commit: 95a922b3bb3af247ec141d73fcdfbf68bb1d32a5 branch: main author: Serhiy Storchaka committer: serhiy-storchaka date: 2021-12-17T11:10:55+02:00 summary: bpo-46111: Fix unittest tests in optimized mode (GH-30163) files: M Lib/unittest/test/test_case.py M Lib/unittest/test/test_program.py M Lib/unittest/test/testmock/testpatch.py diff --git a/Lib/unittest/test/test_case.py b/Lib/unittest/test/test_case.py index ee4c0b354f72b..067ec8d458679 100644 --- a/Lib/unittest/test/test_case.py +++ b/Lib/unittest/test/test_case.py @@ -631,6 +631,8 @@ def testShortDescriptionWithMultiLineDocstring(self): 'Tests shortDescription() for a method with a longer ' 'docstring.') + @unittest.skipIf(sys.flags.optimize >= 2, + "Docstrings are omitted with -O2 and above") def testShortDescriptionWhitespaceTrimming(self): """ Tests shortDescription() whitespace is trimmed, so that the first diff --git a/Lib/unittest/test/test_program.py b/Lib/unittest/test/test_program.py index cc02b227e1da8..2bf7dd72ed21c 100644 --- a/Lib/unittest/test/test_program.py +++ b/Lib/unittest/test/test_program.py @@ -58,9 +58,9 @@ def removeTest(): class FooBar(unittest.TestCase): def testPass(self): - assert True + pass def testFail(self): - assert False + raise AssertionError class FooBarLoader(unittest.TestLoader): """Test loader that returns a suite containing FooBar.""" diff --git a/Lib/unittest/test/testmock/testpatch.py b/Lib/unittest/test/testmock/testpatch.py index d8c1515f8346c..233a5afffaed4 100644 --- a/Lib/unittest/test/testmock/testpatch.py +++ b/Lib/unittest/test/testmock/testpatch.py @@ -1875,9 +1875,10 @@ def foo(x=0): self.assertEqual(foo(), 1) self.assertEqual(foo(), 0) + orig_doc = foo.__doc__ with patch.object(foo, '__doc__', "FUN"): self.assertEqual(foo.__doc__, "FUN") - self.assertEqual(foo.__doc__, "TEST") + self.assertEqual(foo.__doc__, orig_doc) with patch.object(foo, '__module__', "testpatch2"): self.assertEqual(foo.__module__, "testpatch2") From webhook-mailer at python.org Fri Dec 17 04:30:00 2021 From: webhook-mailer at python.org (miss-islington) Date: Fri, 17 Dec 2021 09:30:00 -0000 Subject: [Python-checkins] bpo-46111: Fix unittest tests in optimized mode (GH-30163) Message-ID: https://github.com/python/cpython/commit/9fe8fb74a1e21ab881c70111813266d67bfda016 commit: 9fe8fb74a1e21ab881c70111813266d67bfda016 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-17T01:29:54-08:00 summary: bpo-46111: Fix unittest tests in optimized mode (GH-30163) (cherry picked from commit 95a922b3bb3af247ec141d73fcdfbf68bb1d32a5) Co-authored-by: Serhiy Storchaka files: M Lib/unittest/test/test_case.py M Lib/unittest/test/test_program.py M Lib/unittest/test/testmock/testpatch.py diff --git a/Lib/unittest/test/test_case.py b/Lib/unittest/test/test_case.py index 442651e1e4884..9b3a598ba6c85 100644 --- a/Lib/unittest/test/test_case.py +++ b/Lib/unittest/test/test_case.py @@ -611,6 +611,8 @@ def testShortDescriptionWithMultiLineDocstring(self): 'Tests shortDescription() for a method with a longer ' 'docstring.') + @unittest.skipIf(sys.flags.optimize >= 2, + "Docstrings are omitted with -O2 and above") def testShortDescriptionWhitespaceTrimming(self): """ Tests shortDescription() whitespace is trimmed, so that the first diff --git a/Lib/unittest/test/test_program.py b/Lib/unittest/test/test_program.py index 939af81b3b4cd..4746d71e0b603 100644 --- a/Lib/unittest/test/test_program.py +++ b/Lib/unittest/test/test_program.py @@ -58,9 +58,9 @@ def removeTest(): class FooBar(unittest.TestCase): def testPass(self): - assert True + pass def testFail(self): - assert False + raise AssertionError class FooBarLoader(unittest.TestLoader): """Test loader that returns a suite containing FooBar.""" diff --git a/Lib/unittest/test/testmock/testpatch.py b/Lib/unittest/test/testmock/testpatch.py index d8c1515f8346c..233a5afffaed4 100644 --- a/Lib/unittest/test/testmock/testpatch.py +++ b/Lib/unittest/test/testmock/testpatch.py @@ -1875,9 +1875,10 @@ def foo(x=0): self.assertEqual(foo(), 1) self.assertEqual(foo(), 0) + orig_doc = foo.__doc__ with patch.object(foo, '__doc__', "FUN"): self.assertEqual(foo.__doc__, "FUN") - self.assertEqual(foo.__doc__, "TEST") + self.assertEqual(foo.__doc__, orig_doc) with patch.object(foo, '__module__', "testpatch2"): self.assertEqual(foo.__module__, "testpatch2") From webhook-mailer at python.org Fri Dec 17 04:36:20 2021 From: webhook-mailer at python.org (miss-islington) Date: Fri, 17 Dec 2021 09:36:20 -0000 Subject: [Python-checkins] bpo-46111: Fix unittest tests in optimized mode (GH-30163) Message-ID: https://github.com/python/cpython/commit/72225b5bdf5d2c70307dbad0d3a1caa39c95a22a commit: 72225b5bdf5d2c70307dbad0d3a1caa39c95a22a branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-17T01:35:58-08:00 summary: bpo-46111: Fix unittest tests in optimized mode (GH-30163) (cherry picked from commit 95a922b3bb3af247ec141d73fcdfbf68bb1d32a5) Co-authored-by: Serhiy Storchaka files: M Lib/unittest/test/test_case.py M Lib/unittest/test/test_program.py M Lib/unittest/test/testmock/testpatch.py diff --git a/Lib/unittest/test/test_case.py b/Lib/unittest/test/test_case.py index 65dc0c65d5566..0ce23dd1a686f 100644 --- a/Lib/unittest/test/test_case.py +++ b/Lib/unittest/test/test_case.py @@ -611,6 +611,8 @@ def testShortDescriptionWithMultiLineDocstring(self): 'Tests shortDescription() for a method with a longer ' 'docstring.') + @unittest.skipIf(sys.flags.optimize >= 2, + "Docstrings are omitted with -O2 and above") def testShortDescriptionWhitespaceTrimming(self): """ Tests shortDescription() whitespace is trimmed, so that the first diff --git a/Lib/unittest/test/test_program.py b/Lib/unittest/test/test_program.py index 939af81b3b4cd..4746d71e0b603 100644 --- a/Lib/unittest/test/test_program.py +++ b/Lib/unittest/test/test_program.py @@ -58,9 +58,9 @@ def removeTest(): class FooBar(unittest.TestCase): def testPass(self): - assert True + pass def testFail(self): - assert False + raise AssertionError class FooBarLoader(unittest.TestLoader): """Test loader that returns a suite containing FooBar.""" diff --git a/Lib/unittest/test/testmock/testpatch.py b/Lib/unittest/test/testmock/testpatch.py index d8c1515f8346c..233a5afffaed4 100644 --- a/Lib/unittest/test/testmock/testpatch.py +++ b/Lib/unittest/test/testmock/testpatch.py @@ -1875,9 +1875,10 @@ def foo(x=0): self.assertEqual(foo(), 1) self.assertEqual(foo(), 0) + orig_doc = foo.__doc__ with patch.object(foo, '__doc__', "FUN"): self.assertEqual(foo.__doc__, "FUN") - self.assertEqual(foo.__doc__, "TEST") + self.assertEqual(foo.__doc__, orig_doc) with patch.object(foo, '__module__', "testpatch2"): self.assertEqual(foo.__module__, "testpatch2") From webhook-mailer at python.org Fri Dec 17 06:33:24 2021 From: webhook-mailer at python.org (miss-islington) Date: Fri, 17 Dec 2021 11:33:24 -0000 Subject: [Python-checkins] bpo-45755: [typing] Reveal class attributes of generic in generic aliases in `dir()` (GH-29962) Message-ID: https://github.com/python/cpython/commit/87539cc716fab47cd4f501f2441c4ab8e80bce6f commit: 87539cc716fab47cd4f501f2441c4ab8e80bce6f branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-17T03:33:07-08:00 summary: bpo-45755: [typing] Reveal class attributes of generic in generic aliases in `dir()` (GH-29962) (cherry picked from commit d6e13747161d7b634b47d2d3d212ed3be4a21fab) Co-authored-by: Ken Jin <28750310+Fidget-Spinner at users.noreply.github.com> files: A Misc/NEWS.d/next/Library/2021-12-07-21-55-22.bpo-45755.bRqKGa.rst M Lib/test/test_typing.py M Lib/typing.py diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index fdec29ea58773..82b6f8c1c6406 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -4994,6 +4994,17 @@ def test_special_attrs2(self): loaded = pickle.loads(s) self.assertIs(SpecialAttrsP, loaded) + def test_genericalias_dir(self): + class Foo(Generic[T]): + def bar(self): + pass + baz = 3 + # The class attributes of the original class should be visible even + # in dir() of the GenericAlias. See bpo-45755. + self.assertIn('bar', dir(Foo[int])) + self.assertIn('baz', dir(Foo[int])) + + class AllTests(BaseTestCase): """Tests for __all__.""" diff --git a/Lib/typing.py b/Lib/typing.py index b743d400c0e5f..25225470afbac 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -983,6 +983,9 @@ def __subclasscheck__(self, cls): raise TypeError("Subscripted generics cannot be used with" " class and instance checks") + def __dir__(self): + return list(set(super().__dir__() + + [attr for attr in dir(self.__origin__) if not _is_dunder(attr)])) # Special typing constructs Union, Optional, Generic, Callable and Tuple # use three special attributes for internal bookkeeping of generic types: diff --git a/Misc/NEWS.d/next/Library/2021-12-07-21-55-22.bpo-45755.bRqKGa.rst b/Misc/NEWS.d/next/Library/2021-12-07-21-55-22.bpo-45755.bRqKGa.rst new file mode 100644 index 0000000000000..e5201b0dfde2d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-07-21-55-22.bpo-45755.bRqKGa.rst @@ -0,0 +1,3 @@ +:mod:`typing` generic aliases now reveal the class attributes of the +original generic class when passed to ``dir()``. This was the behavior up to +Python 3.6, but was changed in 3.7-3.9. From webhook-mailer at python.org Fri Dec 17 07:55:11 2021 From: webhook-mailer at python.org (JulienPalard) Date: Fri, 17 Dec 2021 12:55:11 -0000 Subject: [Python-checkins] Doc: some rst linting. (GH-30149) Message-ID: https://github.com/python/cpython/commit/62a0a2a25dbe3ba6f2973a37a3022d982fdc163c commit: 62a0a2a25dbe3ba6f2973a37a3022d982fdc163c branch: main author: Julien Palard committer: JulienPalard date: 2021-12-17T13:55:03+01:00 summary: Doc: some rst linting. (GH-30149) files: M Doc/c-api/apiabiversion.rst M Doc/library/types.rst M Doc/whatsnew/3.6.rst diff --git a/Doc/c-api/apiabiversion.rst b/Doc/c-api/apiabiversion.rst index 53a42e7f28ef1..85b6e2f373877 100644 --- a/Doc/c-api/apiabiversion.rst +++ b/Doc/c-api/apiabiversion.rst @@ -63,7 +63,7 @@ See :ref:`stable` for a discussion of API and ABI stability across versions. .. c:var:: const unsigned long Py_Version The Python runtime version number encoded in a single constant integer, with - the same format as the c:macro:`PY_VERSION_HEX` macro. + the same format as the :c:macro:`PY_VERSION_HEX` macro. This contains the Python version used at run time. .. versionadded:: 3.11 diff --git a/Doc/library/types.rst b/Doc/library/types.rst index 5cd42f1fc2928..e0e77dfbfe7ed 100644 --- a/Doc/library/types.rst +++ b/Doc/library/types.rst @@ -239,7 +239,7 @@ Standard names are defined for the following types: The :term:`loader` which loaded the module. Defaults to ``None``. This attribute is to match :attr:`importlib.machinery.ModuleSpec.loader` - as stored in the attr:`__spec__` object. + as stored in the :attr:`__spec__` object. .. note:: A future version of Python may stop setting this attribute by default. @@ -264,7 +264,7 @@ Standard names are defined for the following types: :attr:`__name__` if the module is a package itself). Defaults to ``None``. This attribute is to match :attr:`importlib.machinery.ModuleSpec.parent` - as stored in the attr:`__spec__` object. + as stored in the :attr:`__spec__` object. .. note:: A future version of Python may stop setting this attribute by default. diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst index d7884ea30d7d2..a56d7a592305f 100644 --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -1422,7 +1422,7 @@ The socket module now supports the address family Victor Stinner.) New Linux constants ``TCP_USER_TIMEOUT`` and ``TCP_CONGESTION`` were added. -(Contributed by Omar Sandoval, issue:`26273`). +(Contributed by Omar Sandoval, :issue:`26273`). socketserver From webhook-mailer at python.org Fri Dec 17 09:46:33 2021 From: webhook-mailer at python.org (markshannon) Date: Fri, 17 Dec 2021 14:46:33 -0000 Subject: [Python-checkins] bpo-45711: Remove type and traceback from exc_info (GH-30122) Message-ID: https://github.com/python/cpython/commit/396b58345f81d4c8c5a52546d2288e666a1b9b8b commit: 396b58345f81d4c8c5a52546d2288e666a1b9b8b branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: markshannon date: 2021-12-17T14:46:22Z summary: bpo-45711: Remove type and traceback from exc_info (GH-30122) * Do not PUSH/POP traceback or type to the stack as part of exc_info * Remove exc_traceback and exc_type from _PyErr_StackItem * Add to what's new, because this change breaks things like Cython files: A Misc/NEWS.d/next/Core and Builtins/2021-12-15-15-17-04.bpo-45711.QK4QrB.rst M Doc/library/dis.rst M Doc/whatsnew/3.11.rst M Include/cpython/pystate.h M Include/internal/pycore_pyerrors.h M Lib/importlib/_bootstrap_external.py M Lib/test/test_dis.py M Lib/test/test_sys.py M Modules/_asynciomodule.c M Objects/genobject.c M Python/ceval.c M Python/compile.c M Python/errors.c M Python/pystate.c diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 35d9baadf6d16..ffade3c9bfe7c 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -474,13 +474,15 @@ the original TOS1. .. opcode:: END_ASYNC_FOR Terminates an :keyword:`async for` loop. Handles an exception raised - when awaiting a next item. If TOS is :exc:`StopAsyncIteration` pop 7 + when awaiting a next item. If TOS is :exc:`StopAsyncIteration` pop 3 values from the stack and restore the exception state using the second - three of them. Otherwise re-raise the exception using the three values + of them. Otherwise re-raise the exception using the value from the stack. An exception handler block is removed from the block stack. .. versionadded:: 3.8 + .. versionchanged:: 3.11 + Exception representation on the stack now consist of one, not three, items. .. opcode:: BEFORE_ASYNC_WITH @@ -561,8 +563,10 @@ iterations of the loop. .. opcode:: POP_EXCEPT - Pops three values from the stack, which are used to restore the exception state. + Pops a value from the stack, which is used to restore the exception state. + .. versionchanged:: 3.11 + Exception representation on the stack now consist of one, not three, items. .. opcode:: RERAISE @@ -572,11 +576,13 @@ iterations of the loop. .. versionadded:: 3.9 + .. versionchanged:: 3.11 + Exception representation on the stack now consist of one, not three, items. .. opcode:: PUSH_EXC_INFO - Pops the three values from the stack. Pushes the current exception to the top of the stack. - Pushes the three values originally popped back to the stack. + Pops a value from the stack. Pushes the current exception to the top of the stack. + Pushes the value originally popped back to the stack. Used in exception handlers. .. versionadded:: 3.11 @@ -584,8 +590,8 @@ iterations of the loop. .. opcode:: WITH_EXCEPT_START - Calls the function in position 8 on the stack with the top three - items on the stack as arguments. + Calls the function in position 4 on the stack with arguments (type, val, tb) + representing the exception at the top of the stack. Used to implement the call ``context_manager.__exit__(*exc_info())`` when an exception has occurred in a :keyword:`with` statement. @@ -593,6 +599,9 @@ iterations of the loop. .. versionchanged:: 3.11 The ``__exit__`` function is in position 8 of the stack rather than 7. + .. versionchanged:: 3.11 + The ``__exit__`` function is in position 4 of the stack rather than 7. + Exception representation on the stack now consist of one, not three, items. .. opcode:: POP_EXCEPT_AND_RERAISE @@ -890,10 +899,9 @@ All of the following opcodes use their arguments. Performs exception matching for ``except*``. Applies ``split(TOS)`` on the exception group representing TOS1. Jumps if no match is found. - Pops one item from the stack. If a match was found, pops the 3 items representing - the exception and pushes the 3 items representing the non-matching part of - the exception group, followed by the 3 items representing the matching part. - In other words, in case of a match it pops 4 items and pushes 6. + Pops one item from the stack (the match type). If a match was found, + next item (the exception) and pushes the non-matching part of the + exception group followed by the matching part. .. versionadded:: 3.11 @@ -903,8 +911,8 @@ All of the following opcodes use their arguments. Combines the raised and reraised exceptions list from TOS, into an exception group to propagate from a try-except* block. Uses the original exception group from TOS1 to reconstruct the structure of reraised exceptions. Pops - two items from the stack and pushes a triplet representing the exception to - reraise or three ``None`` if there isn't one. + two items from the stack and pushes 0 (for lasti, which is unused) followed + by the exception to reraise or ``None`` if there isn't one. .. versionadded:: 3.11 diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 3005d1d43f25b..5389ce8b258cf 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -195,6 +195,11 @@ Other CPython Implementation Changes reflected in the re-raised exception. (Contributed by Irit Katriel in :issue:`45711`.) +* The interpreter state's representation of handled exceptions (a.k.a exc_info, or + _PyErr_StackItem) now has only the ``exc_value`` field, ``exc_type`` and ``exc_traceback`` + have been removed as their values can be derived from ``exc_value``. + (Contributed by Irit Katriel in :issue:`45711`.) + New Modules =========== diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index aa518281c80f5..c37123c4f6922 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -56,7 +56,7 @@ typedef struct _err_stackitem { * This ensures that the exception state is not impacted by "yields" * from an except handler. */ - PyObject *exc_type, *exc_value, *exc_traceback; + PyObject *exc_value; struct _err_stackitem *previous_item; diff --git a/Include/internal/pycore_pyerrors.h b/Include/internal/pycore_pyerrors.h index 5e8d2025dfaf0..b9fc36cf06760 100644 --- a/Include/internal/pycore_pyerrors.h +++ b/Include/internal/pycore_pyerrors.h @@ -24,16 +24,7 @@ static inline PyObject* _PyErr_Occurred(PyThreadState *tstate) static inline void _PyErr_ClearExcState(_PyErr_StackItem *exc_state) { - PyObject *t, *v, *tb; - t = exc_state->exc_type; - v = exc_state->exc_value; - tb = exc_state->exc_traceback; - exc_state->exc_type = NULL; - exc_state->exc_value = NULL; - exc_state->exc_traceback = NULL; - Py_XDECREF(t); - Py_XDECREF(v); - Py_XDECREF(tb); + Py_CLEAR(exc_state->exc_value); } PyAPI_FUNC(PyObject*) _PyErr_StackItemToExcInfoTuple( @@ -114,6 +105,7 @@ PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalRefcountErrorFunc( #define _Py_FatalRefcountError(message) _Py_FatalRefcountErrorFunc(__func__, message) + #ifdef __cplusplus } #endif diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 0c1078accc819..5ead6caf9f3c7 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -371,9 +371,10 @@ def _write_atomic(path, data, mode=0o666): # Python 3.11a3 3464 (bpo-45636: Merge numeric BINARY_*/INPLACE_* into # BINARY_OP) # Python 3.11a3 3465 (Add COPY_FREE_VARS opcode) -# Python 3.11a3 3466 (bpo-45292: PEP-654 except*) +# Python 3.11a4 3466 (bpo-45292: PEP-654 except*) # Python 3.11a4 3467 (Change CALL_xxx opcodes) # Python 3.11a4 3468 (Add SEND opcode) +# Python 3.11a4 3469 (bpo-45711: remove type, traceback from exc_info) # # MAGIC must change whenever the bytecode emitted by the compiler may no @@ -383,7 +384,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 = (3468).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3469).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c _PYCACHE = '__pycache__' diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index c35f1d3ec8bd7..93b24da317575 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -310,33 +310,31 @@ def bug42562(): >> 14 PUSH_EXC_INFO %3d 16 LOAD_GLOBAL 0 (Exception) - 18 JUMP_IF_NOT_EXC_MATCH 26 (to 52) - 20 POP_TOP - 22 STORE_FAST 0 (e) - 24 POP_TOP - -%3d 26 LOAD_FAST 0 (e) - 28 LOAD_ATTR 1 (__traceback__) - 30 STORE_FAST 1 (tb) - 32 POP_EXCEPT - 34 LOAD_CONST 0 (None) - 36 STORE_FAST 0 (e) - 38 DELETE_FAST 0 (e) - -%3d 40 LOAD_FAST 1 (tb) - 42 RETURN_VALUE - >> 44 LOAD_CONST 0 (None) - 46 STORE_FAST 0 (e) - 48 DELETE_FAST 0 (e) - 50 RERAISE 1 - -%3d >> 52 RERAISE 0 - >> 54 POP_EXCEPT_AND_RERAISE + 18 JUMP_IF_NOT_EXC_MATCH 24 (to 48) + 20 STORE_FAST 0 (e) + +%3d 22 LOAD_FAST 0 (e) + 24 LOAD_ATTR 1 (__traceback__) + 26 STORE_FAST 1 (tb) + 28 POP_EXCEPT + 30 LOAD_CONST 0 (None) + 32 STORE_FAST 0 (e) + 34 DELETE_FAST 0 (e) + +%3d 36 LOAD_FAST 1 (tb) + 38 RETURN_VALUE + >> 40 LOAD_CONST 0 (None) + 42 STORE_FAST 0 (e) + 44 DELETE_FAST 0 (e) + 46 RERAISE 1 + +%3d >> 48 RERAISE 0 + >> 50 POP_EXCEPT_AND_RERAISE ExceptionTable: 2 to 8 -> 14 [0] - 14 to 24 -> 54 [3] lasti - 26 to 30 -> 44 [3] lasti - 44 to 52 -> 54 [3] lasti + 14 to 20 -> 50 [1] lasti + 22 to 26 -> 40 [1] lasti + 40 to 48 -> 50 [1] lasti """ % (TRACEBACK_CODE.co_firstlineno + 1, TRACEBACK_CODE.co_firstlineno + 2, TRACEBACK_CODE.co_firstlineno + 5, @@ -395,7 +393,7 @@ def _tryfinallyconst(b): >> 22 POP_EXCEPT_AND_RERAISE ExceptionTable: 2 to 2 -> 12 [0] - 12 to 20 -> 22 [3] lasti + 12 to 20 -> 22 [1] lasti """ % (_tryfinally.__code__.co_firstlineno + 1, _tryfinally.__code__.co_firstlineno + 2, _tryfinally.__code__.co_firstlineno + 4, @@ -418,7 +416,7 @@ def _tryfinallyconst(b): 22 RERAISE 0 >> 24 POP_EXCEPT_AND_RERAISE ExceptionTable: - 14 to 22 -> 24 [3] lasti + 14 to 22 -> 24 [1] lasti """ % (_tryfinallyconst.__code__.co_firstlineno + 1, _tryfinallyconst.__code__.co_firstlineno + 2, _tryfinallyconst.__code__.co_firstlineno + 4, @@ -864,7 +862,7 @@ async def async_def(): Positional-only arguments: 0 Kw-only arguments: 0 Number of locals: 2 -Stack size: 10 +Stack size: 6 Flags: OPTIMIZED, NEWLOCALS, COROUTINE Constants: 0: None @@ -1107,65 +1105,61 @@ def _prepare_test_cases(): Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=108, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='BINARY_OP', opcode=122, arg=11, argval=11, argrepr='/', offset=110, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=112, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=14, argval=144, argrepr='to 144', offset=114, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=12, argval=140, argrepr='to 140', offset=114, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=116, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=2, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=118, starts_line=22, is_jump_target=False, positions=None), - Instruction(opname='JUMP_IF_NOT_EXC_MATCH', opcode=121, arg=70, argval=140, argrepr='to 140', offset=120, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_IF_NOT_EXC_MATCH', opcode=121, arg=68, argval=136, argrepr='to 136', offset=120, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=122, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=124, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=126, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=128, starts_line=23, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=130, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=132, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=134, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=136, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=32, argval=204, argrepr='to 204', offset=138, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=140, starts_line=22, is_jump_target=True, positions=None), - Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=142, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=144, starts_line=25, is_jump_target=True, positions=None), - Instruction(opname='BEFORE_WITH', opcode=53, arg=None, argval=None, argrepr='', offset=146, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=148, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=150, starts_line=26, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Never reach this', argrepr="'Never reach this'", offset=152, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=154, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=156, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=158, starts_line=25, is_jump_target=False, positions=None), - Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=160, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=162, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_NO_KW', opcode=169, arg=3, argval=3, argrepr='', offset=164, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=166, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=11, argval=192, argrepr='to 192', offset=168, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=170, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=172, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=90, argval=180, argrepr='to 180', offset=174, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=4, argval=4, argrepr='', offset=176, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=178, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=180, starts_line=None, is_jump_target=True, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=124, starts_line=23, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=126, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=128, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=130, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=132, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=30, argval=196, argrepr='to 196', offset=134, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=136, starts_line=22, is_jump_target=True, positions=None), + Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=138, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=140, starts_line=25, is_jump_target=True, positions=None), + Instruction(opname='BEFORE_WITH', opcode=53, arg=None, argval=None, argrepr='', offset=142, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=144, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=146, starts_line=26, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Never reach this', argrepr="'Never reach this'", offset=148, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=150, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=152, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=154, starts_line=25, is_jump_target=False, positions=None), + Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=156, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=158, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_NO_KW', opcode=169, arg=3, argval=3, argrepr='', offset=160, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=162, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=9, argval=184, argrepr='to 184', offset=164, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=166, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=168, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=88, argval=176, argrepr='to 176', offset=170, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=2, argval=2, argrepr='', offset=172, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=174, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=176, starts_line=None, is_jump_target=True, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=178, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=180, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=182, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=184, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=186, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=188, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=184, starts_line=28, is_jump_target=True, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=186, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=188, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=190, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=192, starts_line=28, is_jump_target=True, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=194, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=196, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=198, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=200, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=202, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=204, starts_line=23, is_jump_target=True, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=206, 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=208, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=210, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=212, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=214, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=216, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=218, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=220, starts_line=None, 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=222, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=224, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=226, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=228, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=230, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=192, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=194, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=196, starts_line=23, is_jump_target=True, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=198, 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=200, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=202, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=204, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=206, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=208, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=210, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=212, starts_line=None, 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=214, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=216, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=218, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=220, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=222, starts_line=None, is_jump_target=False, positions=None), ] # One last piece of inspect fodder to check the default line number handling diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 41ac03b920e64..96075cf3b3473 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1340,7 +1340,7 @@ def bar(cls): check(bar, size('PP')) # generator def get_gen(): yield 1 - check(get_gen(), size('P2PPP4P4c8P2iciP')) + check(get_gen(), size('P2P4P4c8P2iciP')) # iterator check(iter('abc'), size('lP')) # callable-iterator diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-15-15-17-04.bpo-45711.QK4QrB.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-15-15-17-04.bpo-45711.QK4QrB.rst new file mode 100644 index 0000000000000..717f89ff0e279 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-15-15-17-04.bpo-45711.QK4QrB.rst @@ -0,0 +1 @@ +The interpreter state's representation of handled exceptions (a.k.a exc_info, or _PyErr_StackItem) now has only the ``exc_value`` field, ``exc_type`` and ``exc_traceback`` have been removed as their values can be derived from ``exc_value``. \ No newline at end of file diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 267faacde8a17..978a1fdd0d852 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -810,9 +810,7 @@ FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg) Py_VISIT(fut->dict); _PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state; - Py_VISIT(exc_state->exc_type); Py_VISIT(exc_state->exc_value); - Py_VISIT(exc_state->exc_traceback); return 0; } @@ -1376,10 +1374,6 @@ _asyncio_Future__make_cancelled_error_impl(FutureObj *self) PyException_SetContext(exc, Py_NewRef(exc_state->exc_value)); _PyErr_ClearExcState(exc_state); } - else { - assert(exc_state->exc_type == NULL); - assert(exc_state->exc_traceback == NULL); - } return exc; } @@ -2706,13 +2700,13 @@ task_step_impl(TaskObj *task, PyObject *exc) PyErr_NormalizeException(&et, &ev, &tb); if (tb != NULL) { PyException_SetTraceback(ev, tb); + Py_DECREF(tb); } + Py_XDECREF(et); FutureObj *fut = (FutureObj*)task; _PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state; - exc_state->exc_type = et; exc_state->exc_value = ev; - exc_state->exc_traceback = tb; return future_cancel(fut, NULL); } diff --git a/Objects/genobject.c b/Objects/genobject.c index 24a4e94bfc7a2..d093f3dd7de30 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -25,9 +25,7 @@ static const char *ASYNC_GEN_IGNORED_EXIT_MSG = static inline int exc_state_traverse(_PyErr_StackItem *exc_state, visitproc visit, void *arg) { - Py_VISIT(exc_state->exc_type); Py_VISIT(exc_state->exc_value); - Py_VISIT(exc_state->exc_traceback); return 0; } @@ -886,9 +884,7 @@ make_gen(PyTypeObject *type, PyFunctionObject *func) gen->gi_code = (PyCodeObject *)func->func_code; Py_INCREF(gen->gi_code); gen->gi_weakreflist = NULL; - gen->gi_exc_state.exc_type = NULL; gen->gi_exc_state.exc_value = NULL; - gen->gi_exc_state.exc_traceback = NULL; gen->gi_exc_state.previous_item = NULL; if (func->func_name != NULL) gen->gi_name = func->func_name; @@ -975,9 +971,7 @@ gen_new_with_qualname(PyTypeObject *type, PyFrameObject *f, Py_INCREF(gen->gi_code); Py_DECREF(f); gen->gi_weakreflist = NULL; - gen->gi_exc_state.exc_type = NULL; gen->gi_exc_state.exc_value = NULL; - gen->gi_exc_state.exc_traceback = NULL; gen->gi_exc_state.previous_item = NULL; if (name != NULL) gen->gi_name = name; diff --git a/Python/ceval.c b/Python/ceval.c index 87d6a2288e0dd..bac57ccb7cc75 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1094,29 +1094,11 @@ match_class(PyThreadState *tstate, PyObject *subject, PyObject *type, static int do_raise(PyThreadState *tstate, PyObject *exc, PyObject *cause); static PyObject *do_reraise_star(PyObject *excs, PyObject *orig); static int exception_group_match( - PyObject *exc_type, PyObject* exc_value, PyObject *match_type, + PyObject* exc_value, PyObject *match_type, PyObject **match, PyObject **rest); static int unpack_iterable(PyThreadState *, PyObject *, int, int, PyObject **); -#ifdef Py_DEBUG -static void -_assert_exception_type_is_redundant(PyObject* type, PyObject* val) -{ - if (type == NULL || type == Py_None) { - assert(val == type); - } - else { - assert(PyExceptionInstance_Check(val)); - assert(PyExceptionInstance_Class(val) == type); - } -} - -#define ASSERT_EXC_TYPE_IS_REDUNDANT(t, v) _assert_exception_type_is_redundant(t, v) -#else -#define ASSERT_EXC_TYPE_IS_REDUNDANT(t, v) -#endif - PyObject * PyEval_EvalCode(PyObject *co, PyObject *globals, PyObject *locals) { @@ -2737,25 +2719,15 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr } TARGET(POP_EXCEPT) { - PyObject *type, *value, *traceback; - _PyErr_StackItem *exc_info; - exc_info = tstate->exc_info; - type = exc_info->exc_type; - value = exc_info->exc_value; - traceback = exc_info->exc_traceback; - - exc_info->exc_type = POP(); + _PyErr_StackItem *exc_info = tstate->exc_info; + PyObject *value = exc_info->exc_value; exc_info->exc_value = POP(); - exc_info->exc_traceback = POP(); - ASSERT_EXC_TYPE_IS_REDUNDANT(exc_info->exc_type, exc_info->exc_value); - Py_XDECREF(type); Py_XDECREF(value); - Py_XDECREF(traceback); DISPATCH(); } TARGET(POP_EXCEPT_AND_RERAISE) { - PyObject *lasti = PEEK(4); + PyObject *lasti = PEEK(2); if (PyLong_Check(lasti)) { frame->f_lasti = PyLong_AsLong(lasti); assert(!_PyErr_Occurred(tstate)); @@ -2764,31 +2736,24 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr _PyErr_SetString(tstate, PyExc_SystemError, "lasti is not an int"); goto error; } - PyObject *type, *value, *traceback; - _PyErr_StackItem *exc_info; - type = POP(); - value = POP(); - traceback = POP(); - ASSERT_EXC_TYPE_IS_REDUNDANT(type, value); + PyObject *value = POP(); + assert(value); + assert(PyExceptionInstance_Check(value)); + PyObject *type = Py_NewRef(PyExceptionInstance_Class(value)); + PyObject *traceback = PyException_GetTraceback(value); Py_DECREF(POP()); /* lasti */ _PyErr_Restore(tstate, type, value, traceback); - exc_info = tstate->exc_info; - type = exc_info->exc_type; + + _PyErr_StackItem *exc_info = tstate->exc_info; value = exc_info->exc_value; - traceback = exc_info->exc_traceback; - exc_info->exc_type = POP(); exc_info->exc_value = POP(); - exc_info->exc_traceback = POP(); - ASSERT_EXC_TYPE_IS_REDUNDANT(exc_info->exc_type, exc_info->exc_value); - Py_XDECREF(type); Py_XDECREF(value); - Py_XDECREF(traceback); goto exception_unwind; } TARGET(RERAISE) { if (oparg) { - PyObject *lasti = PEEK(oparg+3); + PyObject *lasti = PEEK(oparg + 1); if (PyLong_Check(lasti)) { frame->f_lasti = PyLong_AsLong(lasti); assert(!_PyErr_Occurred(tstate)); @@ -2799,11 +2764,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr goto error; } } - PyObject *exc = POP(); PyObject *val = POP(); - PyObject *tb = POP(); - ASSERT_EXC_TYPE_IS_REDUNDANT(exc, val); - assert(PyExceptionClass_Check(exc)); + assert(val && PyExceptionInstance_Check(val)); + PyObject *exc = Py_NewRef(PyExceptionInstance_Class(val)); + PyObject *tb = PyException_GetTraceback(val); _PyErr_Restore(tstate, exc, val, tb); goto exception_unwind; } @@ -2823,35 +2787,21 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr PyObject *lasti_unused = Py_NewRef(_PyLong_GetZero()); PUSH(lasti_unused); - if (!Py_IsNone(val)) { - PyObject *tb = PyException_GetTraceback(val); - PUSH(tb ? tb : Py_NewRef(Py_None)); - PUSH(val); - PUSH(Py_NewRef(Py_TYPE(val))); - } - else { - // nothing to reraise - PUSH(Py_NewRef(Py_None)); - PUSH(val); - PUSH(Py_NewRef(Py_None)); - } + PUSH(val); DISPATCH(); } TARGET(END_ASYNC_FOR) { - PyObject *exc = POP(); PyObject *val = POP(); - PyObject *tb = POP(); - ASSERT_EXC_TYPE_IS_REDUNDANT(exc, val); - assert(PyExceptionClass_Check(exc)); - if (PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration)) { - Py_DECREF(exc); + assert(val && PyExceptionInstance_Check(val)); + if (PyErr_GivenExceptionMatches(val, PyExc_StopAsyncIteration)) { Py_DECREF(val); - Py_DECREF(tb); Py_DECREF(POP()); DISPATCH(); } else { + PyObject *exc = Py_NewRef(PyExceptionInstance_Class(val)); + PyObject *tb = PyException_GetTraceback(val); _PyErr_Restore(tstate, exc, val, tb); goto exception_unwind; } @@ -3971,16 +3921,15 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr TARGET(JUMP_IF_NOT_EG_MATCH) { PyObject *match_type = POP(); - PyObject *exc_type = TOP(); - PyObject *exc_value = SECOND(); if (check_except_star_type_valid(tstate, match_type) < 0) { Py_DECREF(match_type); goto error; } + PyObject *exc_value = TOP(); PyObject *match = NULL, *rest = NULL; - int res = exception_group_match(exc_type, exc_value, - match_type, &match, &rest); + int res = exception_group_match(exc_value, match_type, + &match, &rest); Py_DECREF(match_type); if (res < 0) { goto error; @@ -4001,46 +3950,21 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr else { /* Total or partial match - update the stack from - * [tb, val, exc] + * [val] * to - * [tb, rest, exc, tb, match, exc] + * [rest, match] * (rest can be Py_None) */ + PyObject *exc = TOP(); - PyObject *type = TOP(); - PyObject *val = SECOND(); - PyObject *tb = THIRD(); - - if (!Py_IsNone(rest)) { - /* tb remains the same */ - SET_TOP(Py_NewRef(Py_TYPE(rest))); - SET_SECOND(Py_NewRef(rest)); - SET_THIRD(Py_NewRef(tb)); - } - else { - SET_TOP(Py_NewRef(Py_None)); - SET_SECOND(Py_NewRef(Py_None)); - SET_THIRD(Py_NewRef(Py_None)); - } - /* Push match */ + SET_TOP(rest); + PUSH(match); - PUSH(Py_NewRef(tb)); - PUSH(Py_NewRef(match)); - PUSH(Py_NewRef(Py_TYPE(match))); + PyErr_SetExcInfo(NULL, Py_NewRef(match), NULL); - // set exc_info to the current match - PyErr_SetExcInfo( - Py_NewRef(Py_TYPE(match)), - Py_NewRef(match), - Py_NewRef(tb)); - - Py_DECREF(tb); - Py_DECREF(val); - Py_DECREF(type); + Py_DECREF(exc); - Py_DECREF(match); - Py_DECREF(rest); } DISPATCH(); @@ -4048,8 +3972,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr TARGET(JUMP_IF_NOT_EXC_MATCH) { PyObject *right = POP(); - ASSERT_EXC_TYPE_IS_REDUNDANT(TOP(), SECOND()); - PyObject *left = SECOND(); + PyObject *left = TOP(); assert(PyExceptionInstance_Check(left)); if (check_except_type_valid(tstate, right) < 0) { Py_DECREF(right); @@ -4465,26 +4388,24 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr } TARGET(WITH_EXCEPT_START) { - /* At the top of the stack are 8 values: - - (TOP, SECOND, THIRD) = exc_info() - - (FOURTH, FIFTH, SIXTH) = previous exception - - SEVENTH: lasti of exception in exc_info() - - EIGHTH: the context.__exit__ bound method - We call EIGHTH(TOP, SECOND, THIRD). - Then we push again the TOP exception and the __exit__ - return value. + /* At the top of the stack are 4 values: + - TOP = exc_info() + - SECOND = previous exception + - THIRD: lasti of exception in exc_info() + - FOURTH: the context.__exit__ bound method + We call FOURTH(type(TOP), TOP, GetTraceback(TOP)). + Then we push the __exit__ return value. */ PyObject *exit_func; PyObject *exc, *val, *tb, *res; - exc = TOP(); - val = SECOND(); - tb = THIRD(); - ASSERT_EXC_TYPE_IS_REDUNDANT(exc, val); - assert(!Py_IsNone(exc)); - assert(!PyLong_Check(exc)); - assert(PyLong_Check(PEEK(7))); - exit_func = PEEK(8); + val = TOP(); + assert(val && PyExceptionInstance_Check(val)); + exc = PyExceptionInstance_Class(val); + tb = PyException_GetTraceback(val); + Py_XDECREF(tb); + assert(PyLong_Check(PEEK(3))); + exit_func = PEEK(4); PyObject *stack[4] = {NULL, exc, val, tb}; res = PyObject_Vectorcall(exit_func, stack + 1, 3 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); @@ -4496,40 +4417,22 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr } TARGET(PUSH_EXC_INFO) { - PyObject *type = TOP(); - PyObject *value = SECOND(); - PyObject *tb = THIRD(); - ASSERT_EXC_TYPE_IS_REDUNDANT(type, value); + PyObject *value = TOP(); + _PyErr_StackItem *exc_info = tstate->exc_info; - SET_THIRD(exc_info->exc_traceback); if (exc_info->exc_value != NULL) { - SET_SECOND(exc_info->exc_value); - } - else { - Py_INCREF(Py_None); - SET_SECOND(Py_None); - } - if (exc_info->exc_type != NULL) { - SET_TOP(exc_info->exc_type); + SET_TOP(exc_info->exc_value); } else { Py_INCREF(Py_None); SET_TOP(Py_None); } - Py_INCREF(tb); - PUSH(tb); - exc_info->exc_traceback = tb; Py_INCREF(value); PUSH(value); assert(PyExceptionInstance_Check(value)); exc_info->exc_value = value; - Py_INCREF(type); - PUSH(type); - assert(PyExceptionClass_Check(type)); - exc_info->exc_type = type; - DISPATCH(); } @@ -5518,14 +5421,9 @@ MISS_WITH_OPARG_COUNTER(STORE_SUBSCR) PyException_SetTraceback(val, tb); else PyException_SetTraceback(val, Py_None); - if (tb == NULL) { - tb = Py_None; - Py_INCREF(Py_None); - } - PUSH(tb); + Py_XDECREF(tb); + Py_XDECREF(exc); PUSH(val); - PUSH(exc); - ASSERT_EXC_TYPE_IS_REDUNDANT(exc, val); JUMPTO(handler); /* Resume normal execution */ frame->f_state = FRAME_EXECUTING; @@ -6375,19 +6273,17 @@ do_raise(PyThreadState *tstate, PyObject *exc, PyObject *cause) */ static int -exception_group_match(PyObject *exc_type, PyObject* exc_value, - PyObject *match_type, PyObject **match, PyObject **rest) +exception_group_match(PyObject* exc_value, PyObject *match_type, + PyObject **match, PyObject **rest) { - if (Py_IsNone(exc_type)) { - assert(Py_IsNone(exc_value)); + if (Py_IsNone(exc_value)) { *match = Py_NewRef(Py_None); *rest = Py_NewRef(Py_None); return 0; } - assert(PyExceptionClass_Check(exc_type)); assert(PyExceptionInstance_Check(exc_value)); - if (PyErr_GivenExceptionMatches(exc_type, match_type)) { + if (PyErr_GivenExceptionMatches(exc_value, match_type)) { /* Full match of exc itself */ bool is_eg = _PyBaseExceptionGroup_Check(exc_value); if (is_eg) { diff --git a/Python/compile.c b/Python/compile.c index 6179ad980aade..8e90b1ab37037 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1048,9 +1048,9 @@ stack_effect(int opcode, int oparg, int jump) case POP_BLOCK: return 0; case POP_EXCEPT: - return -3; + return -1; case POP_EXCEPT_AND_RERAISE: - return -7; + return -3; case STORE_NAME: return -1; @@ -1095,7 +1095,7 @@ stack_effect(int opcode, int oparg, int jump) case JUMP_IF_NOT_EXC_MATCH: return -1; case JUMP_IF_NOT_EG_MATCH: - return jump > 0 ? -1 : 2; + return jump > 0 ? -1 : 0; case IMPORT_NAME: return -1; case IMPORT_FROM: @@ -1120,25 +1120,25 @@ stack_effect(int opcode, int oparg, int jump) /* Exception handling pseudo-instructions */ case SETUP_FINALLY: /* 0 in the normal flow. - * Restore the stack position and push 3 values before jumping to + * Restore the stack position and push 1 value before jumping to * the handler if an exception be raised. */ - return jump ? 3 : 0; + return jump ? 1 : 0; case SETUP_CLEANUP: /* As SETUP_FINALLY, but pushes lasti as well */ - return jump ? 4 : 0; + return jump ? 2 : 0; case SETUP_WITH: /* 0 in the normal flow. * Restore the stack position to the position before the result - * of __(a)enter__ and push 4 values before jumping to the handler + * of __(a)enter__ and push 2 values before jumping to the handler * if an exception be raised. */ - return jump ? -1 + 4 : 0; + return jump ? 1 : 0; case PREP_RERAISE_STAR: - return 2; + return 0; case RERAISE: - return -3; + return -1; case PUSH_EXC_INFO: - return 3; + return 1; case WITH_EXCEPT_START: return 1; @@ -1199,7 +1199,7 @@ stack_effect(int opcode, int oparg, int jump) case GET_YIELD_FROM_ITER: return 0; case END_ASYNC_FOR: - return -4; + return -2; case FORMAT_VALUE: /* If there's a fmt_spec on the stack, we go from 2->1, else 1->1. */ @@ -1888,13 +1888,11 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info, case FINALLY_END: if (preserve_tos) { - ADDOP(c, ROT_FOUR); + ADDOP(c, ROT_TWO); } - ADDOP(c, POP_TOP); - ADDOP(c, POP_TOP); - ADDOP(c, POP_TOP); + ADDOP(c, POP_TOP); /* exc_value */ if (preserve_tos) { - ADDOP(c, ROT_FOUR); + ADDOP(c, ROT_TWO); } ADDOP(c, POP_BLOCK); ADDOP(c, POP_EXCEPT); @@ -1927,7 +1925,7 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info, ADDOP(c, POP_BLOCK); } if (preserve_tos) { - ADDOP(c, ROT_FOUR); + ADDOP(c, ROT_TWO); } ADDOP(c, POP_BLOCK); ADDOP(c, POP_EXCEPT); @@ -3310,18 +3308,16 @@ compiler_try_star_finally(struct compiler *c, stmt_ty s) [] POP_BLOCK [] JUMP_FORWARD L0 - [tb, val, exc] L1: ) - [tb, val, exc, E1] JUMP_IF_NOT_EXC_MATCH L2 ) only if E1 - [tb, val, exc] POP - [tb, val] (or POP if no V1) - [tb] POP + [exc] L1: ) + [exc, E1] JUMP_IF_NOT_EXC_MATCH L2 ) only if E1 + [exc] (or POP if no V1) [] JUMP_FORWARD L0 - [tb, val, exc] L2: + [exc] L2: .............................etc....................... - [tb, val, exc] Ln+1: RERAISE # re-raise exception + [exc] Ln+1: RERAISE # re-raise exception [] L0: @@ -3372,7 +3368,6 @@ compiler_try_except(struct compiler *c, stmt_ty s) ADDOP_JUMP(c, JUMP_IF_NOT_EXC_MATCH, except); NEXT_BLOCK(c); } - ADDOP(c, POP_TOP); if (handler->v.ExceptHandler.name) { basicblock *cleanup_end, *cleanup_body; @@ -3383,7 +3378,6 @@ compiler_try_except(struct compiler *c, stmt_ty s) } compiler_nameop(c, handler->v.ExceptHandler.name, Store); - ADDOP(c, POP_TOP); /* try: @@ -3434,8 +3428,7 @@ compiler_try_except(struct compiler *c, stmt_ty s) if (!cleanup_body) return 0; - ADDOP(c, POP_TOP); - ADDOP(c, POP_TOP); + ADDOP(c, POP_TOP); /* exc_value */ compiler_use_next_block(c, cleanup_body); if (!compiler_push_fblock(c, HANDLER_CLEANUP, cleanup_body, NULL, NULL)) return 0; @@ -3467,52 +3460,42 @@ compiler_try_except(struct compiler *c, stmt_ty s) at the right; 'tb' is trace-back info, 'val' the exception instance, and 'typ' the exception's type.) - Value stack Label Instruction Argument - [] SETUP_FINALLY L1 - [] - [] POP_BLOCK - [] JUMP_FORWARD L0 + Value stack Label Instruction Argument + [] SETUP_FINALLY L1 + [] + [] POP_BLOCK + [] JUMP_FORWARD L0 - [tb, val, typ] L1: DUP_TOP_TWO ) save a copy of the - [tb, val, typ, orig, typ] POP_TOP ) original raised exception - [tb, val, typ, orig] ROT_FOUR ) - [orig, tb, val, typ] BUILD_LIST ) list for raised/reraised - [orig, tb, val, typ, res] ROT_FOUR ) exceptions ("result") + [exc] L1: DUP_TOP ) save copy of the original exception + [orig, exc] BUILD_LIST ) list for raised/reraised excs ("result") + [orig, exc, res] ROT_TWO - [orig, res, tb, val, typ] ) - [orig, res, tb, val, typ, E1] JUMP_IF_NOT_EXC_MATCH L2 ) only if E1 + [orig, res, exc] + [orig, res, exc, E1] JUMP_IF_NOT_EG_MATCH L2 - [orig, res, tb, rest, typ, tb, match, typ] POP - [orig, res, tb, rest, typ, tb, match] (or POP if no V1) - [orig, res, tb, rest, typ, tb] POP + [orig, res, rest, match] (or POP if no V1) - [orig, res, tb, rest, typ] SETUP_FINALLY R1 - [orig, res, tb, rest, typ] - [orig, res, tb, rest, typ] JUMP_FORWARD L2 + [orig, res, rest] SETUP_FINALLY R1 + [orig, res, rest] + [orig, res, rest] JUMP_FORWARD L2 - [orig, res, tb, rest, typ, i, tb, v, t] R1: POP ) exception raised in except* body - [orig, res, tb, rest, typ, i, tb, v] LIST_APPEND 6 ) add it to res - [orig, res, tb, rest, typ, i, tb] POP - [orig, res, tb, rest, typ, i] POP + [orig, res, rest, i, v] R1: LIST_APPEND 3 ) exc raised in except* body - add to res + [orig, res, rest, i] POP - [orig, res, tb, rest, typ] L2: + [orig, res, rest] L2: .............................etc....................... - [orig, res, tb, rest, typ] Ln+1: POP ) add unhandled exception - [orig, res, tb, rest] LIST_APPEND 2 ) to res (could be None) - [orig, res, tb] POP + [orig, res, rest] Ln+1: LIST_APPEND 1 ) add unhandled exc to res (could be None) - [orig, res] PREP_RERAISE_STAR - [i, tb, val, typ] POP_JUMP_IF_TRUE RER - [i, tb, val, typ] POP - [i, tb, val] POP - [i, tb] POP - [i] POP - [] JUMP_FORWARD L0 + [orig, res] PREP_RERAISE_STAR + [i, exc] POP_JUMP_IF_TRUE RER + [i, exc] POP + [i] POP + [] JUMP_FORWARD L0 - [i, tb, val, typ] RER: POP_EXCEPT_AND_RERAISE + [i, exc] RER: POP_EXCEPT_AND_RERAISE - [] L0: + [] L0: */ static int compiler_try_star_except(struct compiler *c, stmt_ty s) @@ -3573,30 +3556,25 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) if (i == 0) { /* Push the original EG into the stack */ /* - [tb, val, exc] DUP_TOP_TWO - [tb, val, exc, val, exc] POP_TOP - [tb, val, exc, val] ROT_FOUR - [val, tb, val, exc] + [exc] DUP_TOP + [orig, exc] */ - ADDOP(c, DUP_TOP_TWO); - ADDOP(c, POP_TOP); - ADDOP(c, ROT_FOUR); + ADDOP(c, DUP_TOP); /* create empty list for exceptions raised/reraise in the except* blocks */ /* - [val, tb, val, exc] BUILD_LIST - [val, tb, val, exc, []] ROT_FOUR - [val, [], tb, val, exc] + [orig, exc] BUILD_LIST + [orig, exc, []] ROT_TWO + [orig, [], exc] */ ADDOP_I(c, BUILD_LIST, 0); - ADDOP(c, ROT_FOUR); + ADDOP(c, ROT_TWO); } if (handler->v.ExceptHandler.type) { VISIT(c, expr, handler->v.ExceptHandler.type); ADDOP_JUMP(c, JUMP_IF_NOT_EG_MATCH, except); NEXT_BLOCK(c); } - ADDOP(c, POP_TOP); // exc_type basicblock *cleanup_end = compiler_new_block(c); if (cleanup_end == NULL) { @@ -3611,9 +3589,8 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) compiler_nameop(c, handler->v.ExceptHandler.name, Store); } else { - ADDOP(c, POP_TOP); // val + ADDOP(c, POP_TOP); // exc } - ADDOP(c, POP_TOP); // tb /* try: @@ -3657,9 +3634,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) } /* add exception raised to the res list */ - ADDOP(c, POP_TOP); // type - ADDOP_I(c, LIST_APPEND, 6); // exc - ADDOP(c, POP_TOP); // tb + ADDOP_I(c, LIST_APPEND, 3); // exc ADDOP(c, POP_TOP); // lasti ADDOP_JUMP(c, JUMP_ABSOLUTE, except); @@ -3667,9 +3642,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) if (i == n - 1) { /* Add exc to the list (if not None it's the unhandled part of the EG) */ - ADDOP(c, POP_TOP); - ADDOP_I(c, LIST_APPEND, 2); - ADDOP(c, POP_TOP); + ADDOP_I(c, LIST_APPEND, 1); ADDOP_JUMP(c, JUMP_FORWARD, reraise_star); } } @@ -3690,8 +3663,6 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) /* Nothing to reraise - pop it */ ADDOP(c, POP_TOP); ADDOP(c, POP_TOP); - ADDOP(c, POP_TOP); - ADDOP(c, POP_TOP); ADDOP(c, POP_BLOCK); ADDOP(c, POP_EXCEPT); ADDOP_JUMP(c, JUMP_FORWARD, end); @@ -5449,13 +5420,11 @@ compiler_with_except_finish(struct compiler *c, basicblock * cleanup) { return 0; ADDOP_JUMP(c, POP_JUMP_IF_TRUE, exit); NEXT_BLOCK(c); - ADDOP_I(c, RERAISE, 4); + ADDOP_I(c, RERAISE, 2); compiler_use_next_block(c, cleanup); ADDOP(c, POP_EXCEPT_AND_RERAISE); compiler_use_next_block(c, exit); - ADDOP(c, POP_TOP); - ADDOP(c, POP_TOP); - ADDOP(c, POP_TOP); + ADDOP(c, POP_TOP); /* exc_value */ ADDOP(c, POP_BLOCK); ADDOP(c, POP_EXCEPT); ADDOP(c, POP_TOP); @@ -5587,7 +5556,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos) E: WITH_EXCEPT_START (calls EXPR.__exit__) POP_JUMP_IF_TRUE T: RERAISE - T: POP_TOP * 3 (remove exception from stack) + T: POP_TOP (remove exception from stack) POP_EXCEPT POP_TOP EXIT: @@ -7368,7 +7337,10 @@ assemble_emit_exception_table_entry(struct assembler *a, int start, int end, bas int size = end-start; assert(end > start); int target = handler->b_offset; - int depth = handler->b_preserve_lasti ? handler->b_startdepth-4 : handler->b_startdepth-3; + int depth = handler->b_startdepth - 1; + if (handler->b_preserve_lasti) { + depth -= 1; + } assert(depth >= 0); int depth_lasti = (depth<<1) | handler->b_preserve_lasti; assemble_emit_exception_table_item(a, start, (1<<7)); diff --git a/Python/errors.c b/Python/errors.c index 5be15e54db25b..6c5fe41142304 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -84,11 +84,8 @@ _PyErr_GetTopmostException(PyThreadState *tstate) while ((exc_info->exc_value == NULL || exc_info->exc_value == Py_None) && exc_info->previous_item != NULL) { - assert(exc_info->exc_type == NULL || exc_info->exc_type == Py_None); exc_info = exc_info->previous_item; } - assert(exc_info->previous_item == NULL || - (exc_info->exc_type != NULL && exc_info->exc_type != Py_None)); return exc_info; } @@ -524,27 +521,17 @@ PyErr_GetExcInfo(PyObject **p_type, PyObject **p_value, PyObject **p_traceback) void PyErr_SetExcInfo(PyObject *type, PyObject *value, PyObject *traceback) { - PyObject *oldtype, *oldvalue, *oldtraceback; PyThreadState *tstate = _PyThreadState_GET(); - oldtype = tstate->exc_info->exc_type; - oldvalue = tstate->exc_info->exc_value; - oldtraceback = tstate->exc_info->exc_traceback; - + PyObject *oldvalue = tstate->exc_info->exc_value; - tstate->exc_info->exc_type = get_exc_type(value); - Py_XINCREF(tstate->exc_info->exc_type); tstate->exc_info->exc_value = value; - tstate->exc_info->exc_traceback = get_exc_traceback(value); - Py_XINCREF(tstate->exc_info->exc_traceback); /* These args are no longer used, but we still need to steal a ref */ Py_XDECREF(type); Py_XDECREF(traceback); - Py_XDECREF(oldtype); Py_XDECREF(oldvalue); - Py_XDECREF(oldtraceback); } @@ -629,9 +616,6 @@ _PyErr_ChainStackItem(_PyErr_StackItem *exc_info) exc_info_given = 1; } - assert( (exc_info->exc_type == NULL || exc_info->exc_type == Py_None) == - (exc_info->exc_value == NULL || exc_info->exc_value == Py_None) ); - if (exc_info->exc_value == NULL || exc_info->exc_value == Py_None) { return; } diff --git a/Python/pystate.c b/Python/pystate.c index 463b248f22336..0301ce676950b 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1028,9 +1028,7 @@ PyThreadState_Clear(PyThreadState *tstate) Py_CLEAR(tstate->curexc_value); Py_CLEAR(tstate->curexc_traceback); - Py_CLEAR(tstate->exc_state.exc_type); Py_CLEAR(tstate->exc_state.exc_value); - Py_CLEAR(tstate->exc_state.exc_traceback); /* The stack of exception states should contain just this thread. */ if (verbose && tstate->exc_info != &tstate->exc_state) { From webhook-mailer at python.org Fri Dec 17 09:48:12 2021 From: webhook-mailer at python.org (markshannon) Date: Fri, 17 Dec 2021 14:48:12 -0000 Subject: [Python-checkins] bpo-46072: Add top level stats struct (GH-30169) Message-ID: https://github.com/python/cpython/commit/efd6236d36b292c2c43540132c87cf8425e8d627 commit: efd6236d36b292c2c43540132c87cf8425e8d627 branch: main author: Mark Shannon committer: markshannon date: 2021-12-17T14:48:01Z summary: bpo-46072: Add top level stats struct (GH-30169) files: M Include/internal/pycore_code.h M Lib/opcode.py M Lib/test/test__opcode.py M Python/ceval.c M Python/specialize.c M Tools/scripts/summarize_stats.py diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index e9b1ad406496a..dfc75300315e2 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -281,20 +281,32 @@ void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, #define SPECIALIZATION_FAILURE_KINDS 30 -typedef struct _stats { - uint64_t specialization_success; - uint64_t specialization_failure; +typedef struct _specialization_stats { + uint64_t success; + uint64_t failure; uint64_t hit; uint64_t deferred; uint64_t miss; uint64_t deopt; - uint64_t unquickened; - uint64_t specialization_failure_kinds[SPECIALIZATION_FAILURE_KINDS]; + uint64_t failure_kinds[SPECIALIZATION_FAILURE_KINDS]; } SpecializationStats; -extern SpecializationStats _specialization_stats[256]; -#define STAT_INC(opname, name) _specialization_stats[opname].name++ -#define STAT_DEC(opname, name) _specialization_stats[opname].name-- +typedef struct _opcode_stats { + SpecializationStats specialization; + uint64_t execution_count; + uint64_t pair_count[256]; +} OpcodeStats; + +typedef struct _stats { + OpcodeStats opcode_stats[256]; +} PyStats; + +extern PyStats _py_stats; + +#define STAT_INC(opname, name) _py_stats.opcode_stats[opname].specialization.name++ +#define STAT_DEC(opname, name) _py_stats.opcode_stats[opname].specialization.name-- +#define OPCODE_EXE_INC(opname) _py_stats.opcode_stats[opname].execution_count++ + void _Py_PrintSpecializationStats(int to_file); PyAPI_FUNC(PyObject*) _Py_GetSpecializationStats(void); @@ -302,6 +314,7 @@ PyAPI_FUNC(PyObject*) _Py_GetSpecializationStats(void); #else #define STAT_INC(opname, name) ((void)0) #define STAT_DEC(opname, name) ((void)0) +#define OPCODE_EXE_INC(opname) ((void)0) #endif diff --git a/Lib/opcode.py b/Lib/opcode.py index 7b69988f91315..e654a1088b7ea 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -288,11 +288,10 @@ def jabs_op(name, op): "STORE_FAST__STORE_FAST", ] _specialization_stats = [ - "specialization_success", - "specialization_failure", + "success", + "failure", "hit", "deferred", "miss", "deopt", - "unquickened", ] diff --git a/Lib/test/test__opcode.py b/Lib/test/test__opcode.py index 6bbab539903ce..f6b6b3d3532bd 100644 --- a/Lib/test/test__opcode.py +++ b/Lib/test/test__opcode.py @@ -82,13 +82,13 @@ def test_specialization_stats(self): self.assertCountEqual(stats.keys(), specialized_opcodes) self.assertCountEqual( stats['load_attr'].keys(), - stat_names + ['specialization_failure_kinds']) + stat_names + ['failure_kinds']) for sn in stat_names: self.assertIsInstance(stats['load_attr'][sn], int) self.assertIsInstance( - stats['load_attr']['specialization_failure_kinds'], + stats['load_attr']['failure_kinds'], tuple) - for v in stats['load_attr']['specialization_failure_kinds']: + for v in stats['load_attr']['failure_kinds']: self.assertIsInstance(v, int) diff --git a/Python/ceval.c b/Python/ceval.c index bac57ccb7cc75..9976bdeffbe96 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1290,13 +1290,17 @@ eval_frame_handle_pending(PyThreadState *tstate) #define USE_COMPUTED_GOTOS 0 #endif -#define INSTRUCTION_START() frame->f_lasti = INSTR_OFFSET(); next_instr++ +#ifdef Py_STATS +#define INSTRUCTION_START(op) frame->f_lasti = INSTR_OFFSET(); next_instr++; OPCODE_EXE_INC(op); +#else +#define INSTRUCTION_START(op) frame->f_lasti = INSTR_OFFSET(); next_instr++ +#endif #if USE_COMPUTED_GOTOS -#define TARGET(op) TARGET_##op: INSTRUCTION_START(); +#define TARGET(op) TARGET_##op: INSTRUCTION_START(op); #define DISPATCH_GOTO() goto *opcode_targets[opcode] #else -#define TARGET(op) case op: INSTRUCTION_START(); +#define TARGET(op) case op: INSTRUCTION_START(op); #define DISPATCH_GOTO() goto dispatch_opcode #endif @@ -1416,7 +1420,7 @@ eval_frame_handle_pending(PyThreadState *tstate) opcode = _Py_OPCODE(word) | cframe.use_tracing OR_DTRACE_LINE; \ if (opcode == op) { \ oparg = _Py_OPARG(word); \ - INSTRUCTION_START(); \ + INSTRUCTION_START(op); \ goto PREDICT_ID(op); \ } \ } while(0) @@ -2186,7 +2190,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr TARGET(BINARY_SUBSCR) { PREDICTED(BINARY_SUBSCR); - STAT_INC(BINARY_SUBSCR, unquickened); PyObject *sub = POP(); PyObject *container = TOP(); PyObject *res = PyObject_GetItem(container, sub); @@ -2214,7 +2217,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr cache->adaptive.counter--; assert(cache->adaptive.original_oparg == 0); /* No need to set oparg here; it isn't used by BINARY_SUBSCR */ - STAT_DEC(BINARY_SUBSCR, unquickened); JUMP_TO_INSTRUCTION(BINARY_SUBSCR); } } @@ -2339,7 +2341,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr TARGET(STORE_SUBSCR) { PREDICTED(STORE_SUBSCR); - STAT_INC(STORE_SUBSCR, unquickened); PyObject *sub = TOP(); PyObject *container = SECOND(); PyObject *v = THIRD(); @@ -2369,7 +2370,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr STAT_INC(STORE_SUBSCR, deferred); // oparg is the adaptive cache counter UPDATE_PREV_INSTR_OPARG(next_instr, oparg - 1); - STAT_DEC(STORE_SUBSCR, unquickened); JUMP_TO_INSTRUCTION(STORE_SUBSCR); } } @@ -2933,7 +2933,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr TARGET(STORE_ATTR) { PREDICTED(STORE_ATTR); - STAT_INC(STORE_ATTR, unquickened); PyObject *name = GETITEM(names, oparg); PyObject *owner = TOP(); PyObject *v = SECOND(); @@ -3049,7 +3048,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr TARGET(LOAD_GLOBAL) { PREDICTED(LOAD_GLOBAL); - STAT_INC(LOAD_GLOBAL, unquickened); PyObject *name = GETITEM(names, oparg); PyObject *v; if (PyDict_CheckExact(GLOBALS()) @@ -3112,7 +3110,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr STAT_INC(LOAD_GLOBAL, deferred); cache->adaptive.counter--; oparg = cache->adaptive.original_oparg; - STAT_DEC(LOAD_GLOBAL, unquickened); JUMP_TO_INSTRUCTION(LOAD_GLOBAL); } } @@ -3532,7 +3529,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr TARGET(LOAD_ATTR) { PREDICTED(LOAD_ATTR); - STAT_INC(LOAD_ATTR, unquickened); PyObject *name = GETITEM(names, oparg); PyObject *owner = TOP(); PyObject *res = PyObject_GetAttr(owner, name); @@ -3560,7 +3556,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr STAT_INC(LOAD_ATTR, deferred); cache->adaptive.counter--; oparg = cache->adaptive.original_oparg; - STAT_DEC(LOAD_ATTR, unquickened); JUMP_TO_INSTRUCTION(LOAD_ATTR); } } @@ -3663,7 +3658,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr STAT_INC(STORE_ATTR, deferred); cache->adaptive.counter--; oparg = cache->adaptive.original_oparg; - STAT_DEC(STORE_ATTR, unquickened); JUMP_TO_INSTRUCTION(STORE_ATTR); } } @@ -3754,7 +3748,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr TARGET(COMPARE_OP) { PREDICTED(COMPARE_OP); - STAT_INC(COMPARE_OP, unquickened); assert(oparg <= Py_GE); PyObject *right = POP(); PyObject *left = TOP(); @@ -3783,7 +3776,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr STAT_INC(COMPARE_OP, deferred); cache->adaptive.counter--; oparg = cache->adaptive.original_oparg; - STAT_DEC(COMPARE_OP, unquickened); JUMP_TO_INSTRUCTION(COMPARE_OP); } } @@ -4438,7 +4430,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr TARGET(LOAD_METHOD) { PREDICTED(LOAD_METHOD); - STAT_INC(LOAD_METHOD, unquickened); /* Designed to work in tandem with CALL_METHOD. */ PyObject *name = GETITEM(names, oparg); PyObject *obj = TOP(); @@ -4491,7 +4482,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr STAT_INC(LOAD_METHOD, deferred); cache->adaptive.counter--; oparg = cache->adaptive.original_oparg; - STAT_DEC(LOAD_METHOD, unquickened); JUMP_TO_INSTRUCTION(LOAD_METHOD); } } @@ -4617,7 +4607,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr TARGET(CALL_NO_KW) { PyObject *function; PREDICTED(CALL_NO_KW); - STAT_INC(CALL_NO_KW, unquickened); kwnames = NULL; oparg += extra_args; nargs = oparg; @@ -5186,7 +5175,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr TARGET(BINARY_OP) { PREDICTED(BINARY_OP); - STAT_INC(BINARY_OP, unquickened); PyObject *rhs = POP(); PyObject *lhs = TOP(); assert(0 <= oparg); @@ -5216,7 +5204,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr STAT_INC(BINARY_OP, deferred); cache->adaptive.counter--; oparg = cache->adaptive.original_oparg; - STAT_DEC(BINARY_OP, unquickened); JUMP_TO_INSTRUCTION(BINARY_OP); } } @@ -5301,7 +5288,6 @@ opname ## _miss: \ cache_backoff(cache); \ } \ oparg = cache->original_oparg; \ - STAT_DEC(opname, unquickened); \ JUMP_TO_INSTRUCTION(opname); \ } @@ -5317,7 +5303,6 @@ opname ## _miss: \ next_instr[-1] = _Py_MAKECODEUNIT(opname ## _ADAPTIVE, oparg); \ STAT_INC(opname, deopt); \ } \ - STAT_DEC(opname, unquickened); \ JUMP_TO_INSTRUCTION(opname); \ } diff --git a/Python/specialize.c b/Python/specialize.c index 1f168e31e6d3a..8991fa94f8e36 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -40,7 +40,7 @@ Py_ssize_t _Py_QuickenedCount = 0; #ifdef Py_STATS -SpecializationStats _specialization_stats[256] = { 0 }; +PyStats _py_stats = { 0 }; #define ADD_STAT_TO_DICT(res, field) \ do { \ @@ -64,20 +64,19 @@ stats_to_dict(SpecializationStats *stats) if (res == NULL) { return NULL; } - ADD_STAT_TO_DICT(res, specialization_success); - ADD_STAT_TO_DICT(res, specialization_failure); + ADD_STAT_TO_DICT(res, success); + ADD_STAT_TO_DICT(res, failure); ADD_STAT_TO_DICT(res, hit); ADD_STAT_TO_DICT(res, deferred); ADD_STAT_TO_DICT(res, miss); ADD_STAT_TO_DICT(res, deopt); - ADD_STAT_TO_DICT(res, unquickened); PyObject *failure_kinds = PyTuple_New(SPECIALIZATION_FAILURE_KINDS); if (failure_kinds == NULL) { Py_DECREF(res); return NULL; } for (int i = 0; i < SPECIALIZATION_FAILURE_KINDS; i++) { - PyObject *stat = PyLong_FromUnsignedLongLong(stats->specialization_failure_kinds[i]); + PyObject *stat = PyLong_FromUnsignedLongLong(stats->failure_kinds[i]); if (stat == NULL) { Py_DECREF(res); Py_DECREF(failure_kinds); @@ -85,7 +84,7 @@ stats_to_dict(SpecializationStats *stats) } PyTuple_SET_ITEM(failure_kinds, i, stat); } - if (PyDict_SetItemString(res, "specialization_failure_kinds", failure_kinds)) { + if (PyDict_SetItemString(res, "failure_kinds", failure_kinds)) { Py_DECREF(res); Py_DECREF(failure_kinds); return NULL; @@ -101,7 +100,7 @@ add_stat_dict( int opcode, const char *name) { - SpecializationStats *stats = &_specialization_stats[opcode]; + SpecializationStats *stats = &_py_stats.opcode_stats[opcode].specialization; PyObject *d = stats_to_dict(stats); if (d == NULL) { return -1; @@ -137,25 +136,38 @@ _Py_GetSpecializationStats(void) { #endif -#define PRINT_STAT(name, field) fprintf(out, " %s." #field " : %" PRIu64 "\n", name, stats->field); +#define PRINT_STAT(i, field) \ + if (stats[i].field) { \ + fprintf(out, " opcode[%d]." #field " : %" PRIu64 "\n", i, stats[i].field); \ + } static void -print_stats(FILE *out, SpecializationStats *stats, const char *name) +print_spec_stats(FILE *out, OpcodeStats *stats) { - PRINT_STAT(name, specialization_success); - PRINT_STAT(name, specialization_failure); - PRINT_STAT(name, hit); - PRINT_STAT(name, deferred); - PRINT_STAT(name, miss); - PRINT_STAT(name, deopt); - PRINT_STAT(name, unquickened); - for (int i = 0; i < SPECIALIZATION_FAILURE_KINDS; i++) { - fprintf(out, " %s.specialization_failure_kinds[%d] : %" PRIu64 "\n", - name, i, stats->specialization_failure_kinds[i]); + for (int i = 0; i < 256; i++) { + PRINT_STAT(i, specialization.success); + PRINT_STAT(i, specialization.failure); + PRINT_STAT(i, specialization.hit); + PRINT_STAT(i, specialization.deferred); + PRINT_STAT(i, specialization.miss); + PRINT_STAT(i, specialization.deopt); + PRINT_STAT(i, execution_count); + for (int j = 0; j < SPECIALIZATION_FAILURE_KINDS; j++) { + uint64_t val = stats[i].specialization.failure_kinds[j]; + if (val) { + fprintf(out, " opcode[%d].specialization.failure_kinds[%d] : %" + PRIu64 "\n", i, j, val); + } + } } } #undef PRINT_STAT +static void +print_stats(FILE *out, PyStats *stats) { + print_spec_stats(out, stats->opcode_stats); +} + void _Py_PrintSpecializationStats(int to_file) { @@ -189,15 +201,7 @@ _Py_PrintSpecializationStats(int to_file) else { fprintf(out, "Specialization stats:\n"); } - print_stats(out, &_specialization_stats[LOAD_ATTR], "load_attr"); - print_stats(out, &_specialization_stats[LOAD_GLOBAL], "load_global"); - print_stats(out, &_specialization_stats[LOAD_METHOD], "load_method"); - print_stats(out, &_specialization_stats[BINARY_SUBSCR], "binary_subscr"); - print_stats(out, &_specialization_stats[STORE_SUBSCR], "store_subscr"); - print_stats(out, &_specialization_stats[STORE_ATTR], "store_attr"); - print_stats(out, &_specialization_stats[CALL_NO_KW], "call_no_kw"); - print_stats(out, &_specialization_stats[BINARY_OP], "binary_op"); - print_stats(out, &_specialization_stats[COMPARE_OP], "compare_op"); + print_stats(out, &_py_stats); if (out != stderr) { fclose(out); } @@ -205,7 +209,7 @@ _Py_PrintSpecializationStats(int to_file) #ifdef Py_STATS -#define SPECIALIZATION_FAIL(opcode, kind) _specialization_stats[opcode].specialization_failure_kinds[kind]++ +#define SPECIALIZATION_FAIL(opcode, kind) _py_stats.opcode_stats[opcode].specialization.failure_kinds[kind]++ #endif @@ -775,12 +779,12 @@ _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name, Sp goto success; } fail: - STAT_INC(LOAD_ATTR, specialization_failure); + STAT_INC(LOAD_ATTR, failure); assert(!PyErr_Occurred()); cache_backoff(cache0); return 0; success: - STAT_INC(LOAD_ATTR, specialization_success); + STAT_INC(LOAD_ATTR, success); assert(!PyErr_Occurred()); cache0->counter = initial_counter_value(); return 0; @@ -857,12 +861,12 @@ _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name, S goto success; } fail: - STAT_INC(STORE_ATTR, specialization_failure); + STAT_INC(STORE_ATTR, failure); assert(!PyErr_Occurred()); cache_backoff(cache0); return 0; success: - STAT_INC(STORE_ATTR, specialization_success); + STAT_INC(STORE_ATTR, success); assert(!PyErr_Occurred()); cache0->counter = initial_counter_value(); return 0; @@ -1013,12 +1017,12 @@ _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name, cache2->obj = descr; // Fall through. success: - STAT_INC(LOAD_METHOD, specialization_success); + STAT_INC(LOAD_METHOD, success); assert(!PyErr_Occurred()); cache0->counter = initial_counter_value(); return 0; fail: - STAT_INC(LOAD_METHOD, specialization_failure); + STAT_INC(LOAD_METHOD, failure); assert(!PyErr_Occurred()); cache_backoff(cache0); return 0; @@ -1084,12 +1088,12 @@ _Py_Specialize_LoadGlobal( *instr = _Py_MAKECODEUNIT(LOAD_GLOBAL_BUILTIN, _Py_OPARG(*instr)); goto success; fail: - STAT_INC(LOAD_GLOBAL, specialization_failure); + STAT_INC(LOAD_GLOBAL, failure); assert(!PyErr_Occurred()); cache_backoff(cache0); return 0; success: - STAT_INC(LOAD_GLOBAL, specialization_success); + STAT_INC(LOAD_GLOBAL, success); assert(!PyErr_Occurred()); cache0->counter = initial_counter_value(); return 0; @@ -1211,12 +1215,12 @@ _Py_Specialize_BinarySubscr( SPECIALIZATION_FAIL(BINARY_SUBSCR, binary_subscr_fail_kind(container_type, sub)); fail: - STAT_INC(BINARY_SUBSCR, specialization_failure); + STAT_INC(BINARY_SUBSCR, failure); assert(!PyErr_Occurred()); cache_backoff(cache0); return 0; success: - STAT_INC(BINARY_SUBSCR, specialization_success); + STAT_INC(BINARY_SUBSCR, success); assert(!PyErr_Occurred()); cache0->counter = initial_counter_value(); return 0; @@ -1259,12 +1263,12 @@ _Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub, _Py_CODEUNIT *ins goto fail; } fail: - STAT_INC(STORE_SUBSCR, specialization_failure); + STAT_INC(STORE_SUBSCR, failure); assert(!PyErr_Occurred()); *instr = _Py_MAKECODEUNIT(_Py_OPCODE(*instr), ADAPTIVE_CACHE_BACKOFF); return 0; success: - STAT_INC(STORE_SUBSCR, specialization_success); + STAT_INC(STORE_SUBSCR, success); assert(!PyErr_Occurred()); return 0; } @@ -1518,12 +1522,12 @@ _Py_Specialize_CallNoKw( } _PyAdaptiveEntry *cache0 = &cache->adaptive; if (fail) { - STAT_INC(CALL_NO_KW, specialization_failure); + STAT_INC(CALL_NO_KW, failure); assert(!PyErr_Occurred()); cache_backoff(cache0); } else { - STAT_INC(CALL_NO_KW, specialization_success); + STAT_INC(CALL_NO_KW, success); assert(!PyErr_Occurred()); cache0->counter = initial_counter_value(); } @@ -1604,11 +1608,11 @@ _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, } SPECIALIZATION_FAIL(BINARY_OP, SPEC_FAIL_OTHER); failure: - STAT_INC(BINARY_OP, specialization_failure); + STAT_INC(BINARY_OP, failure); cache_backoff(adaptive); return; success: - STAT_INC(BINARY_OP, specialization_success); + STAT_INC(BINARY_OP, success); adaptive->counter = initial_counter_value(); } @@ -1675,10 +1679,10 @@ _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, } SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_OTHER); failure: - STAT_INC(COMPARE_OP, specialization_failure); + STAT_INC(COMPARE_OP, failure); cache_backoff(adaptive); return; success: - STAT_INC(COMPARE_OP, specialization_success); + STAT_INC(COMPARE_OP, success); adaptive->counter = initial_counter_value(); } diff --git a/Tools/scripts/summarize_stats.py b/Tools/scripts/summarize_stats.py index 15b1887415e44..a5a8e93c17392 100644 --- a/Tools/scripts/summarize_stats.py +++ b/Tools/scripts/summarize_stats.py @@ -4,29 +4,50 @@ import collections import os.path +import opcode if os.name == "nt": DEFAULT_DIR = "c:\\temp\\py_stats\\" else: DEFAULT_DIR = "/tmp/py_stats/" +#Create list of all instruction names +specialized = iter(opcode._specialized_instructions) +opname = ["<0>"] +for name in opcode.opname[1:]: + if name.startswith("<"): + try: + name = next(specialized) + except StopIteration: + pass + opname.append(name) -TOTAL = "deferred", "hit", "miss", "unquickened" -def print_stats(name, family_stats): +TOTAL = "specialization.deferred", "specialization.hit", "specialization.miss", "execution_count" + +def print_specialization_stats(name, family_stats): + if "specialization.deferred" not in family_stats: + return total = sum(family_stats[kind] for kind in TOTAL) if total == 0: return print(name+":") for key in sorted(family_stats): - if not key.startswith("specialization"): - print(f"{key:>12}:{family_stats[key]:>12} {100*family_stats[key]/total:0.1f}%") - for key in ("specialization_success", "specialization_failure"): - print(f" {key}:{family_stats[key]:>12}") - total_failures = family_stats["specialization_failure"] + if key.startswith("specialization.failure_kinds"): + continue + if key.startswith("specialization."): + label = key[len("specialization."):] + elif key == "execution_count": + label = "unquickened" + if key not in ("specialization.success", "specialization.failure"): + print(f"{label:>12}:{family_stats[key]:>12} {100*family_stats[key]/total:0.1f}%") + for key in ("specialization.success", "specialization.failure"): + label = key[len("specialization."):] + print(f" {label}:{family_stats.get(key, 0):>12}") + total_failures = family_stats["specialization.failure"] failure_kinds = [ 0 ] * 30 for key in family_stats: - if not key.startswith("specialization_failure_kind"): + if not key.startswith("specialization.failure_kind"): continue _, index = key[:-1].split("[") index = int(index) @@ -36,18 +57,47 @@ def print_stats(name, family_stats): continue print(f" kind {index:>2}: {value:>8} {100*value/total_failures:0.1f}%") -def main(): - stats = collections.defaultdict(collections.Counter) +def gather_stats(): + stats = collections.Counter() for filename in os.listdir(DEFAULT_DIR): - for line in open(os.path.join(DEFAULT_DIR, filename)): - key, value = line.split(":") - key = key.strip() - family, stat = key.split(".") - value = int(value.strip()) - stats[family][stat] += value - - for name in sorted(stats): - print_stats(name, stats[name]) + with open(os.path.join(DEFAULT_DIR, filename)) as fd: + for line in fd: + key, value = line.split(":") + key = key.strip() + value = int(value.strip()) + stats[key] += value + return stats + +def extract_opcode_stats(stats): + opcode_stats = [ {} for _ in range(256) ] + for key, value in stats.items(): + if not key.startswith("opcode"): + continue + n, _, rest = key[7:].partition("]") + opcode_stats[int(n)][rest.strip(".")] = value + return opcode_stats + + +def main(): + stats = gather_stats() + opcode_stats = extract_opcode_stats(stats) + print("Execution counts:") + counts = [] + total = 0 + for i, opcode_stat in enumerate(opcode_stats): + if "execution_count" in opcode_stat: + count = opcode_stat['execution_count'] + counts.append((count, opname[i])) + total += count + counts.sort(reverse=True) + cummulative = 0 + for (count, name) in counts: + cummulative += count + print(f"{name}: {count} {100*count/total:0.1f}% {100*cummulative/total:0.1f}%") + print("Specialization stats:") + for i, opcode_stat in enumerate(opcode_stats): + name = opname[i] + print_specialization_stats(name, opcode_stat) if __name__ == "__main__": main() From webhook-mailer at python.org Fri Dec 17 10:17:40 2021 From: webhook-mailer at python.org (tiran) Date: Fri, 17 Dec 2021 15:17:40 -0000 Subject: [Python-checkins] bpo-46114: Fix OpenSSL version check for 3.0.1 (GH-30170) Message-ID: https://github.com/python/cpython/commit/2985feac4e02d590bb78bcce9e30864be53280ac commit: 2985feac4e02d590bb78bcce9e30864be53280ac branch: main author: Christian Heimes committer: tiran date: 2021-12-17T16:17:32+01:00 summary: bpo-46114: Fix OpenSSL version check for 3.0.1 (GH-30170) files: A Misc/NEWS.d/next/Tests/2021-12-17-14-46-19.bpo-46114.9iyZ_9.rst M .github/workflows/build.yml M Lib/test/test_ssl.py M Tools/ssl/multissltests.py diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 48671aa7a67cd..4504b29432cd2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -220,7 +220,7 @@ jobs: strategy: fail-fast: false matrix: - openssl_ver: [1.1.1l, 3.0.0] + openssl_ver: [1.1.1l, 3.0.1] env: OPENSSL_VER: ${{ matrix.openssl_ver }} MULTISSL_DIR: ${{ github.workspace }}/multissl diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 981e2fe82ee46..f99a3e8da95f8 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -540,7 +540,11 @@ def test_openssl_version(self): self.assertLessEqual(status, 15) libressl_ver = f"LibreSSL {major:d}" - openssl_ver = f"OpenSSL {major:d}.{minor:d}.{fix:d}" + if major >= 3: + # 3.x uses 0xMNN00PP0L + openssl_ver = f"OpenSSL {major:d}.{minor:d}.{patch:d}" + else: + openssl_ver = f"OpenSSL {major:d}.{minor:d}.{fix:d}" self.assertTrue( s.startswith((openssl_ver, libressl_ver)), (s, t, hex(n)) diff --git a/Misc/NEWS.d/next/Tests/2021-12-17-14-46-19.bpo-46114.9iyZ_9.rst b/Misc/NEWS.d/next/Tests/2021-12-17-14-46-19.bpo-46114.9iyZ_9.rst new file mode 100644 index 0000000000000..6878cea032387 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-12-17-14-46-19.bpo-46114.9iyZ_9.rst @@ -0,0 +1 @@ +Fix test case for OpenSSL 3.0.1 version. OpenSSL 3.0 uses ``0xMNN00PP0L``. diff --git a/Tools/ssl/multissltests.py b/Tools/ssl/multissltests.py index ba2663e9a399b..8fe5b5d0c2629 100755 --- a/Tools/ssl/multissltests.py +++ b/Tools/ssl/multissltests.py @@ -48,7 +48,7 @@ OPENSSL_RECENT_VERSIONS = [ "1.1.1l", - "3.0.0" + "3.0.1" ] LIBRESSL_OLD_VERSIONS = [ From webhook-mailer at python.org Fri Dec 17 10:18:00 2021 From: webhook-mailer at python.org (tiran) Date: Fri, 17 Dec 2021 15:18:00 -0000 Subject: [Python-checkins] bpo-44035: Show git diff after autoreconf and regen (GH-30117) Message-ID: https://github.com/python/cpython/commit/da8cf8a74714f4cc34fb768345cb1caf9dcddd62 commit: da8cf8a74714f4cc34fb768345cb1caf9dcddd62 branch: main author: Christian Heimes committer: tiran date: 2021-12-17T16:17:56+01:00 summary: bpo-44035: Show git diff after autoreconf and regen (GH-30117) files: M .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4504b29432cd2..e02e9ade1ae13 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -90,8 +90,10 @@ jobs: if test -n "$changes"; then echo "Generated files not up to date." echo "Perhaps you forgot to run make regen-all or build.bat --regen. ;)" - echo "configure files must be regenerated with a specific, unpatched version of autoconf." + echo "configure files must be regenerated with a specific version of autoconf." echo "$changes" + echo "" + git diff --staged || true exit 1 fi - name: Check exported libpython symbols From webhook-mailer at python.org Fri Dec 17 10:38:19 2021 From: webhook-mailer at python.org (miss-islington) Date: Fri, 17 Dec 2021 15:38:19 -0000 Subject: [Python-checkins] bpo-46114: Fix OpenSSL version check for 3.0.1 (GH-30170) Message-ID: https://github.com/python/cpython/commit/251d2eadc7f5b4042245709f41c38169a284e146 commit: 251d2eadc7f5b4042245709f41c38169a284e146 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-17T07:38:11-08:00 summary: bpo-46114: Fix OpenSSL version check for 3.0.1 (GH-30170) (cherry picked from commit 2985feac4e02d590bb78bcce9e30864be53280ac) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Tests/2021-12-17-14-46-19.bpo-46114.9iyZ_9.rst M .github/workflows/build.yml M Lib/test/test_ssl.py M Tools/ssl/multissltests.py diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c91fcc6d05fdb..b85cf17df33d8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -225,7 +225,7 @@ jobs: strategy: fail-fast: false matrix: - openssl_ver: [1.1.1l, 3.0.0] + openssl_ver: [1.1.1l, 3.0.1] env: OPENSSL_VER: ${{ matrix.openssl_ver }} MULTISSL_DIR: ${{ github.workspace }}/multissl diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index a485f7d4c3c0c..873db6403d1a0 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -539,7 +539,11 @@ def test_openssl_version(self): self.assertLessEqual(status, 15) libressl_ver = f"LibreSSL {major:d}" - openssl_ver = f"OpenSSL {major:d}.{minor:d}.{fix:d}" + if major >= 3: + # 3.x uses 0xMNN00PP0L + openssl_ver = f"OpenSSL {major:d}.{minor:d}.{patch:d}" + else: + openssl_ver = f"OpenSSL {major:d}.{minor:d}.{fix:d}" self.assertTrue( s.startswith((openssl_ver, libressl_ver)), (s, t, hex(n)) diff --git a/Misc/NEWS.d/next/Tests/2021-12-17-14-46-19.bpo-46114.9iyZ_9.rst b/Misc/NEWS.d/next/Tests/2021-12-17-14-46-19.bpo-46114.9iyZ_9.rst new file mode 100644 index 0000000000000..6878cea032387 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-12-17-14-46-19.bpo-46114.9iyZ_9.rst @@ -0,0 +1 @@ +Fix test case for OpenSSL 3.0.1 version. OpenSSL 3.0 uses ``0xMNN00PP0L``. diff --git a/Tools/ssl/multissltests.py b/Tools/ssl/multissltests.py index ba2663e9a399b..8fe5b5d0c2629 100755 --- a/Tools/ssl/multissltests.py +++ b/Tools/ssl/multissltests.py @@ -48,7 +48,7 @@ OPENSSL_RECENT_VERSIONS = [ "1.1.1l", - "3.0.0" + "3.0.1" ] LIBRESSL_OLD_VERSIONS = [ From webhook-mailer at python.org Fri Dec 17 11:02:42 2021 From: webhook-mailer at python.org (tiran) Date: Fri, 17 Dec 2021 16:02:42 -0000 Subject: [Python-checkins] [3.9] bpo-46114: Fix OpenSSL version check for 3.0.1 (GH-30170) (GH-30173) Message-ID: https://github.com/python/cpython/commit/a9b3edb66f2976a5895b6399ee905ac2f27718ac commit: a9b3edb66f2976a5895b6399ee905ac2f27718ac branch: 3.9 author: Christian Heimes committer: tiran date: 2021-12-17T17:02:38+01:00 summary: [3.9] bpo-46114: Fix OpenSSL version check for 3.0.1 (GH-30170) (GH-30173) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Tests/2021-12-17-14-46-19.bpo-46114.9iyZ_9.rst M .github/workflows/build.yml M Lib/test/test_ssl.py M Tools/ssl/multissltests.py diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 295b24c2cf136..e7f37f57e9a95 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -207,7 +207,7 @@ jobs: strategy: fail-fast: false matrix: - openssl_ver: [1.0.2u, 1.1.0l, 1.1.1l, 3.0.0] + openssl_ver: [1.0.2u, 1.1.0l, 1.1.1l, 3.0.1] env: OPENSSL_VER: ${{ matrix.openssl_ver }} MULTISSL_DIR: ${{ github.workspace }}/multissl diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 42ebcc04dc2b8..b5eb40f869709 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -589,13 +589,16 @@ def test_openssl_version(self): self.assertLessEqual(patch, 63) self.assertGreaterEqual(status, 0) self.assertLessEqual(status, 15) - # Version string as returned by {Open,Libre}SSL, the format might change - if IS_LIBRESSL: - self.assertTrue(s.startswith("LibreSSL {:d}".format(major)), - (s, t, hex(n))) + libressl_ver = f"LibreSSL {major:d}" + if major >= 3: + # 3.x uses 0xMNN00PP0L + openssl_ver = f"OpenSSL {major:d}.{minor:d}.{patch:d}" else: - self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)), - (s, t, hex(n))) + openssl_ver = f"OpenSSL {major:d}.{minor:d}.{fix:d}" + self.assertTrue( + s.startswith((openssl_ver, libressl_ver)), + (s, t, hex(n)) + ) @support.cpython_only def test_refcycle(self): diff --git a/Misc/NEWS.d/next/Tests/2021-12-17-14-46-19.bpo-46114.9iyZ_9.rst b/Misc/NEWS.d/next/Tests/2021-12-17-14-46-19.bpo-46114.9iyZ_9.rst new file mode 100644 index 0000000000000..6878cea032387 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-12-17-14-46-19.bpo-46114.9iyZ_9.rst @@ -0,0 +1 @@ +Fix test case for OpenSSL 3.0.1 version. OpenSSL 3.0 uses ``0xMNN00PP0L``. diff --git a/Tools/ssl/multissltests.py b/Tools/ssl/multissltests.py index 8888c4a6e5850..8732d01e51be0 100755 --- a/Tools/ssl/multissltests.py +++ b/Tools/ssl/multissltests.py @@ -50,7 +50,7 @@ OPENSSL_RECENT_VERSIONS = [ "1.1.1l", - "3.0.0" + "3.0.1" ] LIBRESSL_OLD_VERSIONS = [ From webhook-mailer at python.org Fri Dec 17 18:32:26 2021 From: webhook-mailer at python.org (brettcannon) Date: Fri, 17 Dec 2021 23:32:26 -0000 Subject: [Python-checkins] [3.9] bpo-46044: Annotate deprecated sdists formats (GH-30043) (GH-30155) Message-ID: https://github.com/python/cpython/commit/8202a7e3dd55d551906390742fc748d0747256b8 commit: 8202a7e3dd55d551906390742fc748d0747256b8 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: brettcannon date: 2021-12-17T15:32:22-08:00 summary: [3.9] bpo-46044: Annotate deprecated sdists formats (GH-30043) (GH-30155) Co-authored-by: Matthias Bussonnier Co-authored-by: Brett Cannon Co-authored-by: ?ric files: M Doc/distutils/sourcedist.rst diff --git a/Doc/distutils/sourcedist.rst b/Doc/distutils/sourcedist.rst index 0600663d00e9d..7b1e22f824e8c 100644 --- a/Doc/distutils/sourcedist.rst +++ b/Doc/distutils/sourcedist.rst @@ -23,25 +23,25 @@ option, for example:: to create a gzipped tarball and a zip file. The available formats are: -+-----------+-------------------------+---------+ -| Format | Description | Notes | -+===========+=========================+=========+ -| ``zip`` | zip file (:file:`.zip`) | (1),(3) | -+-----------+-------------------------+---------+ -| ``gztar`` | gzip'ed tar file | \(2) | -| | (:file:`.tar.gz`) | | -+-----------+-------------------------+---------+ -| ``bztar`` | bzip2'ed tar file | | -| | (:file:`.tar.bz2`) | | -+-----------+-------------------------+---------+ -| ``xztar`` | xz'ed tar file | | -| | (:file:`.tar.xz`) | | -+-----------+-------------------------+---------+ -| ``ztar`` | compressed tar file | \(4) | -| | (:file:`.tar.Z`) | | -+-----------+-------------------------+---------+ -| ``tar`` | tar file (:file:`.tar`) | | -+-----------+-------------------------+---------+ ++-----------+-------------------------+-------------+ +| Format | Description | Notes | ++===========+=========================+=============+ +| ``zip`` | zip file (:file:`.zip`) | (1),(3) | ++-----------+-------------------------+-------------+ +| ``gztar`` | gzip'ed tar file | \(2) | +| | (:file:`.tar.gz`) | | ++-----------+-------------------------+-------------+ +| ``bztar`` | bzip2'ed tar file | \(5) | +| | (:file:`.tar.bz2`) | | ++-----------+-------------------------+-------------+ +| ``xztar`` | xz'ed tar file | \(5) | +| | (:file:`.tar.xz`) | | ++-----------+-------------------------+-------------+ +| ``ztar`` | compressed tar file | (4),(5) | +| | (:file:`.tar.Z`) | | ++-----------+-------------------------+-------------+ +| ``tar`` | tar file (:file:`.tar`) | \(5) | ++-----------+-------------------------+-------------+ .. versionchanged:: 3.5 Added support for the ``xztar`` format. @@ -61,6 +61,9 @@ Notes: (4) requires the :program:`compress` program. Notice that this format is now pending for deprecation and will be removed in the future versions of Python. +(5) + deprecated by `PEP 527 `_; + `PyPI `_ only accepts ``.zip`` and ``.tar.gz`` files. When using any ``tar`` format (``gztar``, ``bztar``, ``xztar``, ``ztar`` or ``tar``), under Unix you can specify the ``owner`` and ``group`` names From webhook-mailer at python.org Fri Dec 17 18:32:26 2021 From: webhook-mailer at python.org (brettcannon) Date: Fri, 17 Dec 2021 23:32:26 -0000 Subject: [Python-checkins] [3.10] bpo-46044: Annotate deprecated sdists formats (GH-30043) (#30154) Message-ID: https://github.com/python/cpython/commit/dbd1dc23f60a6883adf1d18e660f163fa76b8ba9 commit: dbd1dc23f60a6883adf1d18e660f163fa76b8ba9 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: brettcannon date: 2021-12-17T15:32:02-08:00 summary: [3.10] bpo-46044: Annotate deprecated sdists formats (GH-30043) (#30154) (cherry picked from commit ecdc0ccede5f9ac4042ff56f295d81df2f428950) Co-authored-by: Matthias Bussonnier Co-authored-by: Brett Cannon Co-authored-by: ?ric files: M Doc/distutils/sourcedist.rst diff --git a/Doc/distutils/sourcedist.rst b/Doc/distutils/sourcedist.rst index 0600663d00e9d..7b1e22f824e8c 100644 --- a/Doc/distutils/sourcedist.rst +++ b/Doc/distutils/sourcedist.rst @@ -23,25 +23,25 @@ option, for example:: to create a gzipped tarball and a zip file. The available formats are: -+-----------+-------------------------+---------+ -| Format | Description | Notes | -+===========+=========================+=========+ -| ``zip`` | zip file (:file:`.zip`) | (1),(3) | -+-----------+-------------------------+---------+ -| ``gztar`` | gzip'ed tar file | \(2) | -| | (:file:`.tar.gz`) | | -+-----------+-------------------------+---------+ -| ``bztar`` | bzip2'ed tar file | | -| | (:file:`.tar.bz2`) | | -+-----------+-------------------------+---------+ -| ``xztar`` | xz'ed tar file | | -| | (:file:`.tar.xz`) | | -+-----------+-------------------------+---------+ -| ``ztar`` | compressed tar file | \(4) | -| | (:file:`.tar.Z`) | | -+-----------+-------------------------+---------+ -| ``tar`` | tar file (:file:`.tar`) | | -+-----------+-------------------------+---------+ ++-----------+-------------------------+-------------+ +| Format | Description | Notes | ++===========+=========================+=============+ +| ``zip`` | zip file (:file:`.zip`) | (1),(3) | ++-----------+-------------------------+-------------+ +| ``gztar`` | gzip'ed tar file | \(2) | +| | (:file:`.tar.gz`) | | ++-----------+-------------------------+-------------+ +| ``bztar`` | bzip2'ed tar file | \(5) | +| | (:file:`.tar.bz2`) | | ++-----------+-------------------------+-------------+ +| ``xztar`` | xz'ed tar file | \(5) | +| | (:file:`.tar.xz`) | | ++-----------+-------------------------+-------------+ +| ``ztar`` | compressed tar file | (4),(5) | +| | (:file:`.tar.Z`) | | ++-----------+-------------------------+-------------+ +| ``tar`` | tar file (:file:`.tar`) | \(5) | ++-----------+-------------------------+-------------+ .. versionchanged:: 3.5 Added support for the ``xztar`` format. @@ -61,6 +61,9 @@ Notes: (4) requires the :program:`compress` program. Notice that this format is now pending for deprecation and will be removed in the future versions of Python. +(5) + deprecated by `PEP 527 `_; + `PyPI `_ only accepts ``.zip`` and ``.tar.gz`` files. When using any ``tar`` format (``gztar``, ``bztar``, ``xztar``, ``ztar`` or ``tar``), under Unix you can specify the ``owner`` and ``group`` names From webhook-mailer at python.org Sat Dec 18 05:24:00 2021 From: webhook-mailer at python.org (Fidget-Spinner) Date: Sat, 18 Dec 2021 10:24:00 -0000 Subject: [Python-checkins] bpo-46104: Reduce use of pre-PEP 526 syntax in typing docs (GH-30148) Message-ID: https://github.com/python/cpython/commit/6ada013df170b0afb6b61a0d942388c6fd81cbc9 commit: 6ada013df170b0afb6b61a0d942388c6fd81cbc9 branch: main author: Alex Waygood committer: Fidget-Spinner <28750310+Fidget-Spinner at users.noreply.github.com> date: 2021-12-18T18:23:51+08:00 summary: bpo-46104: Reduce use of pre-PEP 526 syntax in typing docs (GH-30148) Co-authored-by: Andrew Svetlov files: M Doc/library/typing.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 735d477db4371..ec1b8d1a5ebcc 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -428,12 +428,12 @@ value of type :data:`Any` and assign it to any variable:: from typing import Any - a = None # type: Any - a = [] # OK - a = 2 # OK + a: Any = None + a = [] # OK + a = 2 # OK - s = '' # type: str - s = a # OK + s = '' # Inferred type of 's' is str + s = a # OK def foo(item: Any) -> int: # Typechecks; 'item' could be any type, @@ -1779,11 +1779,10 @@ Asynchronous programming correspond to those of :class:`Generator`, for example:: from collections.abc import Coroutine - c = None # type: Coroutine[list[str], str, int] - ... - x = c.send('hi') # type: list[str] + c: Coroutine[list[str], str, int] # Some coroutine defined elsewhere + x = c.send('hi') # Inferred type of 'x' is list[str] async def bar() -> None: - x = await c # type: int + y = await c # Inferred type of 'y' is int .. versionadded:: 3.5.3 From webhook-mailer at python.org Sat Dec 18 07:14:23 2021 From: webhook-mailer at python.org (miss-islington) Date: Sat, 18 Dec 2021 12:14:23 -0000 Subject: [Python-checkins] [3.9] bpo-46104: Reduce use of pre-PEP 526 syntax in typing docs (GH-30148) (GH-30180) Message-ID: https://github.com/python/cpython/commit/43cb8f483b9f815abf9801e05ec70ae55ca3c5a5 commit: 43cb8f483b9f815abf9801e05ec70ae55ca3c5a5 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-18T04:14:19-08:00 summary: [3.9] bpo-46104: Reduce use of pre-PEP 526 syntax in typing docs (GH-30148) (GH-30180) Co-authored-by: Andrew Svetlov (cherry picked from commit 6ada013df170b0afb6b61a0d942388c6fd81cbc9) Co-authored-by: Alex Waygood files: M Doc/library/typing.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 0eeaffb4352bf..34aaa1fac3077 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -358,12 +358,12 @@ value of type :data:`Any` and assign it to any variable:: from typing import Any - a = None # type: Any - a = [] # OK - a = 2 # OK + a: Any = None + a = [] # OK + a = 2 # OK - s = '' # type: str - s = a # OK + s = '' # Inferred type of 's' is str + s = a # OK def foo(item: Any) -> int: # Typechecks; 'item' could be any type, @@ -1445,11 +1445,10 @@ Asynchronous programming correspond to those of :class:`Generator`, for example:: from collections.abc import Coroutine - c = None # type: Coroutine[list[str], str, int] - ... - x = c.send('hi') # type: list[str] + c: Coroutine[list[str], str, int] # Some coroutine defined elsewhere + x = c.send('hi') # Inferred type of 'x' is list[str] async def bar() -> None: - x = await c # type: int + y = await c # Inferred type of 'y' is int .. versionadded:: 3.5.3 From webhook-mailer at python.org Sat Dec 18 07:14:29 2021 From: webhook-mailer at python.org (miss-islington) Date: Sat, 18 Dec 2021 12:14:29 -0000 Subject: [Python-checkins] [3.10] bpo-46104: Reduce use of pre-PEP 526 syntax in typing docs (GH-30148) (GH-30179) Message-ID: https://github.com/python/cpython/commit/a66be9185c6e0299293a06e21a6f599dfe6c3f60 commit: a66be9185c6e0299293a06e21a6f599dfe6c3f60 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-18T04:14:25-08:00 summary: [3.10] bpo-46104: Reduce use of pre-PEP 526 syntax in typing docs (GH-30148) (GH-30179) Co-authored-by: Andrew Svetlov (cherry picked from commit 6ada013df170b0afb6b61a0d942388c6fd81cbc9) Co-authored-by: Alex Waygood files: M Doc/library/typing.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 14e5c8fc7efea..c154364ee56ec 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -428,12 +428,12 @@ value of type :data:`Any` and assign it to any variable:: from typing import Any - a = None # type: Any - a = [] # OK - a = 2 # OK + a: Any = None + a = [] # OK + a = 2 # OK - s = '' # type: str - s = a # OK + s = '' # Inferred type of 's' is str + s = a # OK def foo(item: Any) -> int: # Typechecks; 'item' could be any type, @@ -1779,11 +1779,10 @@ Asynchronous programming correspond to those of :class:`Generator`, for example:: from collections.abc import Coroutine - c = None # type: Coroutine[list[str], str, int] - ... - x = c.send('hi') # type: list[str] + c: Coroutine[list[str], str, int] # Some coroutine defined elsewhere + x = c.send('hi') # Inferred type of 'x' is list[str] async def bar() -> None: - x = await c # type: int + y = await c # Inferred type of 'y' is int .. versionadded:: 3.5.3 From webhook-mailer at python.org Sat Dec 18 08:03:47 2021 From: webhook-mailer at python.org (zooba) Date: Sat, 18 Dec 2021 13:03:47 -0000 Subject: [Python-checkins] bpo-40915: Avoid compiler warnings by fixing mmapmodule conversion from LARGE_INTEGER to Py_ssize_t (GH-30175) Message-ID: https://github.com/python/cpython/commit/6214caafbe66e34e84c1809abf0b7aab6791956b commit: 6214caafbe66e34e84c1809abf0b7aab6791956b branch: main author: neonene <53406459+neonene at users.noreply.github.com> committer: zooba date: 2021-12-18T13:03:43Z summary: bpo-40915: Avoid compiler warnings by fixing mmapmodule conversion from LARGE_INTEGER to Py_ssize_t (GH-30175) files: M Modules/mmapmodule.c diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c index 21d53365776ab..399cb0a99ad65 100644 --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -536,7 +536,8 @@ mmap_resize_method(mmap_object *self, !SetEndOfFile(self->file_handle)) { /* resizing failed. try to remap the file */ file_resize_error = GetLastError(); - new_size = max_size.QuadPart = self->size; + max_size.QuadPart = self->size; + new_size = self->size; } } From webhook-mailer at python.org Sat Dec 18 08:05:50 2021 From: webhook-mailer at python.org (zooba) Date: Sat, 18 Dec 2021 13:05:50 -0000 Subject: [Python-checkins] bpo-46088: Automatically detect or install bootstrap Python runtime when building from Visual Studio (GH-30143) Message-ID: https://github.com/python/cpython/commit/6fc91daf730c60b08b4b32cdce28ff26505a0622 commit: 6fc91daf730c60b08b4b32cdce28ff26505a0622 branch: main author: Steve Dower committer: zooba date: 2021-12-18T13:05:45Z summary: bpo-46088: Automatically detect or install bootstrap Python runtime when building from Visual Studio (GH-30143) files: A Misc/NEWS.d/next/Build/2021-12-16-14-18-07.bpo-46088.8UUuAd.rst M PCbuild/_freeze_module.vcxproj M PCbuild/find_python.bat M PCbuild/pyproject.props M PCbuild/regen.targets diff --git a/Misc/NEWS.d/next/Build/2021-12-16-14-18-07.bpo-46088.8UUuAd.rst b/Misc/NEWS.d/next/Build/2021-12-16-14-18-07.bpo-46088.8UUuAd.rst new file mode 100644 index 0000000000000..408ed53111fd2 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-12-16-14-18-07.bpo-46088.8UUuAd.rst @@ -0,0 +1,2 @@ +Automatically detect or install bootstrap Python runtime when building from +Visual Studio. diff --git a/PCbuild/_freeze_module.vcxproj b/PCbuild/_freeze_module.vcxproj index 11a6a87daf91b..42798bf8113c7 100644 --- a/PCbuild/_freeze_module.vcxproj +++ b/PCbuild/_freeze_module.vcxproj @@ -432,7 +432,10 @@ - + = (3, 8)" >nul 2>nul) && (set PYTHON="%_Py_EXTERNALS_DIR%\pythonx86\tools\python.exe") && (set _Py_Python_Source=found in externals directory) && goto :found || rmdir /Q /S "%_Py_EXTERNALS_DIR%\pythonx86" @@ -53,15 +58,18 @@ @rem If it fails, retry with any available copy of Python @powershell.exe -Command Invoke-WebRequest %_Py_NUGET_URL% -OutFile '%_Py_NUGET%' @if errorlevel 1 ( - @%_Py_HOST_PYTHON% -E "%~dp0\urlretrieve.py" "%_Py_NUGET_URL%" "%_Py_NUGET%" + @%_Py_HOST_PYTHON% -E "%_Py_D%\urlretrieve.py" "%_Py_NUGET_URL%" "%_Py_NUGET%" ) ) - at echo Installing Python via nuget... + + at if not "%_Py_Quiet%"=="1" @echo Installing Python via nuget... @"%_Py_NUGET%" install pythonx86 -ExcludeVersion -OutputDirectory "%_Py_EXTERNALS_DIR%" @rem Quote it here; it's not quoted later because "py -x.y" wouldn't work @if not errorlevel 1 (set PYTHON="%_Py_EXTERNALS_DIR%\pythonx86\tools\python.exe") & (set _Py_Python_Source=found on nuget.org) & goto :found + at set _Py_D= + at set _Py_Quiet= @set _Py_Python_Source= @set _Py_EXTERNALS_DIR= @set _Py_NUGET= @@ -70,7 +78,10 @@ @exit /b 1 :found - at echo Using %PYTHON% (%_Py_Python_Source%) + at if "%_Py_Quiet%"=="1" (@echo %PYTHON%) else @echo Using %PYTHON% (%_Py_Python_Source%) + + at set _Py_D= + at set _Py_Quiet= @set _Py_Python_Source= @set _Py_EXTERNALS_DIR= @set _Py_NUGET= diff --git a/PCbuild/pyproject.props b/PCbuild/pyproject.props index bbcabb5cdb405..3465adec65b9a 100644 --- a/PCbuild/pyproject.props +++ b/PCbuild/pyproject.props @@ -225,4 +225,17 @@ public override bool Execute() { + + + + + + + @(_CmdExeLines) + + + + diff --git a/PCbuild/regen.targets b/PCbuild/regen.targets index c0bde1ec6ba51..a49d97190ce20 100644 --- a/PCbuild/regen.targets +++ b/PCbuild/regen.targets @@ -1,11 +1,5 @@ - - - $(PYTHON) - - - <_PegenSources Include="$(PySourcePath)Grammar\python.gram;$(PySourcePath)Grammar\Tokens" /> <_PegenOutputs Include="$(PySourcePath)Parser\parser.c" /> @@ -44,20 +38,26 @@ AlwaysCreate="False" /> - + - + - + @@ -65,14 +65,18 @@ WorkingDirectory="$(PySourcePath)" /> - + - + From webhook-mailer at python.org Sat Dec 18 08:26:38 2021 From: webhook-mailer at python.org (asvetlov) Date: Sat, 18 Dec 2021 13:26:38 -0000 Subject: [Python-checkins] bpo-46099: Fix pthread_getcpuclockid test on Solaris (GH-30140) Message-ID: https://github.com/python/cpython/commit/427a490c495cde8a152e938c6f02be65620e3e59 commit: 427a490c495cde8a152e938c6f02be65620e3e59 branch: main author: Jakub Kul?k committer: asvetlov date: 2021-12-18T15:26:24+02:00 summary: bpo-46099: Fix pthread_getcpuclockid test on Solaris (GH-30140) Co-authored-by: Andrew Svetlov files: M Lib/test/test_time.py diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py index f98aec2651d9d..1aa5874dfe272 100644 --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -117,12 +117,13 @@ def test_pthread_getcpuclockid(self): clk_id = time.pthread_getcpuclockid(threading.get_ident()) self.assertTrue(type(clk_id) is int) # when in 32-bit mode AIX only returns the predefined constant - if not platform.system() == "AIX": - self.assertNotEqual(clk_id, time.CLOCK_THREAD_CPUTIME_ID) - elif (sys.maxsize.bit_length() > 32): - self.assertNotEqual(clk_id, time.CLOCK_THREAD_CPUTIME_ID) - else: + if platform.system() == "AIX" and (sys.maxsize.bit_length() <= 32): self.assertEqual(clk_id, time.CLOCK_THREAD_CPUTIME_ID) + # Solaris returns CLOCK_THREAD_CPUTIME_ID when current thread is given + elif sys.platform.startswith("sunos"): + self.assertEqual(clk_id, time.CLOCK_THREAD_CPUTIME_ID) + else: + self.assertNotEqual(clk_id, time.CLOCK_THREAD_CPUTIME_ID) t1 = time.clock_gettime(clk_id) t2 = time.clock_gettime(clk_id) self.assertLessEqual(t1, t2) From webhook-mailer at python.org Sat Dec 18 08:49:09 2021 From: webhook-mailer at python.org (asvetlov) Date: Sat, 18 Dec 2021 13:49:09 -0000 Subject: [Python-checkins] bpo-46099: Fix pthread_getcpuclockid test on Solaris (GH-30140) (GH-30183) Message-ID: https://github.com/python/cpython/commit/4f945ad7a510ad6dde13353784e45239edcdc14e commit: 4f945ad7a510ad6dde13353784e45239edcdc14e branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: asvetlov date: 2021-12-18T15:49:01+02:00 summary: bpo-46099: Fix pthread_getcpuclockid test on Solaris (GH-30140) (GH-30183) Co-authored-by: Andrew Svetlov (cherry picked from commit 427a490c495cde8a152e938c6f02be65620e3e59) Co-authored-by: Jakub Kul?k Co-authored-by: Jakub Kul?k files: M Lib/test/test_time.py diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py index 875615ad51007..d89078f08f611 100644 --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -113,12 +113,13 @@ def test_pthread_getcpuclockid(self): clk_id = time.pthread_getcpuclockid(threading.get_ident()) self.assertTrue(type(clk_id) is int) # when in 32-bit mode AIX only returns the predefined constant - if not platform.system() == "AIX": - self.assertNotEqual(clk_id, time.CLOCK_THREAD_CPUTIME_ID) - elif (sys.maxsize.bit_length() > 32): - self.assertNotEqual(clk_id, time.CLOCK_THREAD_CPUTIME_ID) - else: + if platform.system() == "AIX" and (sys.maxsize.bit_length() <= 32): self.assertEqual(clk_id, time.CLOCK_THREAD_CPUTIME_ID) + # Solaris returns CLOCK_THREAD_CPUTIME_ID when current thread is given + elif sys.platform.startswith("sunos"): + self.assertEqual(clk_id, time.CLOCK_THREAD_CPUTIME_ID) + else: + self.assertNotEqual(clk_id, time.CLOCK_THREAD_CPUTIME_ID) t1 = time.clock_gettime(clk_id) t2 = time.clock_gettime(clk_id) self.assertLessEqual(t1, t2) From webhook-mailer at python.org Sat Dec 18 08:52:58 2021 From: webhook-mailer at python.org (Fidget-Spinner) Date: Sat, 18 Dec 2021 13:52:58 -0000 Subject: [Python-checkins] bpo-46113: Minor fixes in stdtypes documentation (GH-30167) Message-ID: https://github.com/python/cpython/commit/6f2df4295123f8b961d49474b7668f7564a534a4 commit: 6f2df4295123f8b961d49474b7668f7564a534a4 branch: main author: Vivek Vashist committer: Fidget-Spinner <28750310+Fidget-Spinner at users.noreply.github.com> date: 2021-12-18T21:52:51+08:00 summary: bpo-46113: Minor fixes in stdtypes documentation (GH-30167) * Fix#1 - isidentifier() function output * Fix#2 Update the str.splitlines() function parameter * Fix#3 Removed unwanted full stop for str and bytes types double quotes examples. * Fix#4 Updated class dict from **kwarg to **kwargs files: M Doc/library/stdtypes.rst diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 3c0ba94c73c6b..9d80661fdb821 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -1463,7 +1463,7 @@ Strings are immutable written in a variety of ways: * Single quotes: ``'allows embedded "double" quotes'`` -* Double quotes: ``"allows embedded 'single' quotes"``. +* Double quotes: ``"allows embedded 'single' quotes"`` * Triple quoted: ``'''Three single quotes'''``, ``"""Three double quotes"""`` Triple quoted strings may span multiple lines - all associated whitespace will @@ -1789,9 +1789,9 @@ expression support in the :mod:`re` module). >>> from keyword import iskeyword >>> 'hello'.isidentifier(), iskeyword('hello') - True, False + (True, False) >>> 'def'.isidentifier(), iskeyword('def') - True, True + (True, True) .. method:: str.islower() @@ -2058,7 +2058,7 @@ expression support in the :mod:`re` module). .. index:: single: universal newlines; str.splitlines method -.. method:: str.splitlines([keepends]) +.. method:: str.splitlines(keepends=False) Return a list of the lines in the string, breaking at line boundaries. Line breaks are not included in the resulting list unless *keepends* is given and @@ -2471,7 +2471,7 @@ data and are closely related to string objects in a variety of other ways. literals, except that a ``b`` prefix is added: * Single quotes: ``b'still allows embedded "double" quotes'`` - * Double quotes: ``b"still allows embedded 'single' quotes"``. + * Double quotes: ``b"still allows embedded 'single' quotes"`` * Triple quoted: ``b'''3 single quotes'''``, ``b"""3 double quotes"""`` Only ASCII characters are permitted in bytes literals (regardless of the @@ -4372,9 +4372,9 @@ Dictionaries can be created by placing a comma-separated list of ``key: value`` pairs within braces, for example: ``{'jack': 4098, 'sjoerd': 4127}`` or ``{4098: 'jack', 4127: 'sjoerd'}``, or by the :class:`dict` constructor. -.. class:: dict(**kwarg) - dict(mapping, **kwarg) - dict(iterable, **kwarg) +.. class:: dict(**kwargs) + dict(mapping, **kwargs) + dict(iterable, **kwargs) Return a new dictionary initialized from an optional positional argument and a possibly empty set of keyword arguments. From webhook-mailer at python.org Sat Dec 18 09:12:36 2021 From: webhook-mailer at python.org (Fidget-Spinner) Date: Sat, 18 Dec 2021 14:12:36 -0000 Subject: [Python-checkins] bpo-46113: Minor fixes in stdtypes documentation (GH-30167) (GH-30186) Message-ID: https://github.com/python/cpython/commit/bb286d45afa6740384bab97d0da68fe571efb6ec commit: bb286d45afa6740384bab97d0da68fe571efb6ec branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Fidget-Spinner <28750310+Fidget-Spinner at users.noreply.github.com> date: 2021-12-18T22:12:30+08:00 summary: bpo-46113: Minor fixes in stdtypes documentation (GH-30167) (GH-30186) * Fix-1 - isidentifier() function output * Fix-2 Update the str.splitlines() function parameter * Fix-3 Removed unwanted full stop for str and bytes types double quotes examples. * Fix-4 Updated class dict from **kwarg to **kwargs (cherry picked from commit 6f2df4295123f8b961d49474b7668f7564a534a4) Co-authored-by: Vivek Vashist files: M Doc/library/stdtypes.rst diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index e732bd8e42fb5..101bbca7be8b2 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -1425,7 +1425,7 @@ Strings are immutable written in a variety of ways: * Single quotes: ``'allows embedded "double" quotes'`` -* Double quotes: ``"allows embedded 'single' quotes"``. +* Double quotes: ``"allows embedded 'single' quotes"`` * Triple quoted: ``'''Three single quotes'''``, ``"""Three double quotes"""`` Triple quoted strings may span multiple lines - all associated whitespace will @@ -1751,9 +1751,9 @@ expression support in the :mod:`re` module). >>> from keyword import iskeyword >>> 'hello'.isidentifier(), iskeyword('hello') - True, False + (True, False) >>> 'def'.isidentifier(), iskeyword('def') - True, True + (True, True) .. method:: str.islower() @@ -2020,7 +2020,7 @@ expression support in the :mod:`re` module). .. index:: single: universal newlines; str.splitlines method -.. method:: str.splitlines([keepends]) +.. method:: str.splitlines(keepends=False) Return a list of the lines in the string, breaking at line boundaries. Line breaks are not included in the resulting list unless *keepends* is given and @@ -2433,7 +2433,7 @@ data and are closely related to string objects in a variety of other ways. literals, except that a ``b`` prefix is added: * Single quotes: ``b'still allows embedded "double" quotes'`` - * Double quotes: ``b"still allows embedded 'single' quotes"``. + * Double quotes: ``b"still allows embedded 'single' quotes"`` * Triple quoted: ``b'''3 single quotes'''``, ``b"""3 double quotes"""`` Only ASCII characters are permitted in bytes literals (regardless of the @@ -4334,9 +4334,9 @@ Dictionaries can be created by placing a comma-separated list of ``key: value`` pairs within braces, for example: ``{'jack': 4098, 'sjoerd': 4127}`` or ``{4098: 'jack', 4127: 'sjoerd'}``, or by the :class:`dict` constructor. -.. class:: dict(**kwarg) - dict(mapping, **kwarg) - dict(iterable, **kwarg) +.. class:: dict(**kwargs) + dict(mapping, **kwargs) + dict(iterable, **kwargs) Return a new dictionary initialized from an optional positional argument and a possibly empty set of keyword arguments. From webhook-mailer at python.org Sat Dec 18 09:23:43 2021 From: webhook-mailer at python.org (miss-islington) Date: Sat, 18 Dec 2021 14:23:43 -0000 Subject: [Python-checkins] bpo-37578: glob.glob -- added include_hidden parameter (GH-30153) Message-ID: https://github.com/python/cpython/commit/ae36cd1e792db9d6db4c6847ec2a7d50a71f2b68 commit: ae36cd1e792db9d6db4c6847ec2a7d50a71f2b68 branch: main author: andrei kulakov committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-18T06:23:34-08:00 summary: bpo-37578: glob.glob -- added include_hidden parameter (GH-30153) Automerge-Triggered-By: GH:asvetlov files: A Misc/NEWS.d/next/Library/2021-12-17-13-22-37.bpo-37578._tluuR.rst M Doc/library/glob.rst M Lib/glob.py M Lib/test/test_glob.py diff --git a/Doc/library/glob.rst b/Doc/library/glob.rst index 215f60d328c76..54621d1d12bb5 100644 --- a/Doc/library/glob.rst +++ b/Doc/library/glob.rst @@ -36,7 +36,8 @@ For example, ``'[?]'`` matches the character ``'?'``. The :mod:`pathlib` module offers high-level path objects. -.. function:: glob(pathname, *, root_dir=None, dir_fd=None, recursive=False) +.. function:: glob(pathname, *, root_dir=None, dir_fd=None, recursive=False, \ + include_hidden=False) Return a possibly-empty list of path names that match *pathname*, which must be a string containing a path specification. *pathname* can be either absolute @@ -64,6 +65,8 @@ For example, ``'[?]'`` matches the character ``'?'``. pattern is followed by an :data:`os.sep` or :data:`os.altsep` then files will not match. + If *include_hidden* is true, "``**``" pattern will match hidden directories. + .. audit-event:: glob.glob pathname,recursive glob.glob .. audit-event:: glob.glob/2 pathname,recursive,root_dir,dir_fd glob.glob @@ -77,8 +80,12 @@ For example, ``'[?]'`` matches the character ``'?'``. .. versionchanged:: 3.10 Added the *root_dir* and *dir_fd* parameters. + .. versionchanged:: 3.11 + Added the *include_hidden* parameter. + -.. function:: iglob(pathname, *, root_dir=None, dir_fd=None, recursive=False) +.. function:: iglob(pathname, *, root_dir=None, dir_fd=None, recursive=False, \ + include_hidden=False) Return an :term:`iterator` which yields the same values as :func:`glob` without actually storing them all simultaneously. @@ -92,6 +99,9 @@ For example, ``'[?]'`` matches the character ``'?'``. .. versionchanged:: 3.10 Added the *root_dir* and *dir_fd* parameters. + .. versionchanged:: 3.11 + Added the *include_hidden* parameter. + .. function:: escape(pathname) diff --git a/Lib/glob.py b/Lib/glob.py index 9fc08f45df115..a7256422d520f 100644 --- a/Lib/glob.py +++ b/Lib/glob.py @@ -10,20 +10,26 @@ __all__ = ["glob", "iglob", "escape"] -def glob(pathname, *, root_dir=None, dir_fd=None, recursive=False): +def glob(pathname, *, root_dir=None, dir_fd=None, recursive=False, + include_hidden=False): """Return a list of paths matching a pathname pattern. The pattern may contain simple shell-style wildcards a la - fnmatch. However, unlike fnmatch, filenames starting with a + fnmatch. Unlike fnmatch, filenames starting with a dot are special cases that are not matched by '*' and '?' - patterns. + patterns by default. - If recursive is true, the pattern '**' will match any files and + If `include_hidden` is true, the patterns '*', '?', '**' will match hidden + directories. + + If `recursive` is true, the pattern '**' will match any files and zero or more directories and subdirectories. """ - return list(iglob(pathname, root_dir=root_dir, dir_fd=dir_fd, recursive=recursive)) + return list(iglob(pathname, root_dir=root_dir, dir_fd=dir_fd, recursive=recursive, + include_hidden=include_hidden)) -def iglob(pathname, *, root_dir=None, dir_fd=None, recursive=False): +def iglob(pathname, *, root_dir=None, dir_fd=None, recursive=False, + include_hidden=False): """Return an iterator which yields the paths matching a pathname pattern. The pattern may contain simple shell-style wildcards a la @@ -40,7 +46,8 @@ def iglob(pathname, *, root_dir=None, dir_fd=None, recursive=False): root_dir = os.fspath(root_dir) else: root_dir = pathname[:0] - it = _iglob(pathname, root_dir, dir_fd, recursive, False) + it = _iglob(pathname, root_dir, dir_fd, recursive, False, + include_hidden=include_hidden) if not pathname or recursive and _isrecursive(pathname[:2]): try: s = next(it) # skip empty string @@ -50,7 +57,8 @@ def iglob(pathname, *, root_dir=None, dir_fd=None, recursive=False): pass return it -def _iglob(pathname, root_dir, dir_fd, recursive, dironly): +def _iglob(pathname, root_dir, dir_fd, recursive, dironly, + include_hidden=False): dirname, basename = os.path.split(pathname) if not has_magic(pathname): assert not dironly @@ -64,15 +72,18 @@ def _iglob(pathname, root_dir, dir_fd, recursive, dironly): return if not dirname: if recursive and _isrecursive(basename): - yield from _glob2(root_dir, basename, dir_fd, dironly) + yield from _glob2(root_dir, basename, dir_fd, dironly, + include_hidden=include_hidden) else: - yield from _glob1(root_dir, basename, dir_fd, dironly) + yield from _glob1(root_dir, basename, dir_fd, dironly, + include_hidden=include_hidden) return # `os.path.split()` returns the argument itself as a dirname if it is a # drive or UNC path. Prevent an infinite recursion if a drive or UNC path # contains magic characters (i.e. r'\\?\C:'). if dirname != pathname and has_magic(dirname): - dirs = _iglob(dirname, root_dir, dir_fd, recursive, True) + dirs = _iglob(dirname, root_dir, dir_fd, recursive, True, + include_hidden=include_hidden) else: dirs = [dirname] if has_magic(basename): @@ -83,20 +94,21 @@ def _iglob(pathname, root_dir, dir_fd, recursive, dironly): else: glob_in_dir = _glob0 for dirname in dirs: - for name in glob_in_dir(_join(root_dir, dirname), basename, dir_fd, dironly): + for name in glob_in_dir(_join(root_dir, dirname), basename, dir_fd, dironly, + include_hidden=include_hidden): yield os.path.join(dirname, name) # These 2 helper functions non-recursively glob inside a literal directory. # They return a list of basenames. _glob1 accepts a pattern while _glob0 # takes a literal basename (so it only has to check for its existence). -def _glob1(dirname, pattern, dir_fd, dironly): +def _glob1(dirname, pattern, dir_fd, dironly, include_hidden=False): names = _listdir(dirname, dir_fd, dironly) - if not _ishidden(pattern): - names = (x for x in names if not _ishidden(x)) + if include_hidden or not _ishidden(pattern): + names = (x for x in names if include_hidden or not _ishidden(x)) return fnmatch.filter(names, pattern) -def _glob0(dirname, basename, dir_fd, dironly): +def _glob0(dirname, basename, dir_fd, dironly, include_hidden=False): if basename: if _lexists(_join(dirname, basename), dir_fd): return [basename] @@ -118,10 +130,11 @@ def glob1(dirname, pattern): # This helper function recursively yields relative pathnames inside a literal # directory. -def _glob2(dirname, pattern, dir_fd, dironly): +def _glob2(dirname, pattern, dir_fd, dironly, include_hidden=False): assert _isrecursive(pattern) yield pattern[:0] - yield from _rlistdir(dirname, dir_fd, dironly) + yield from _rlistdir(dirname, dir_fd, dironly, + include_hidden=include_hidden) # If dironly is false, yields all file names inside a directory. # If dironly is true, yields only directory names. @@ -164,13 +177,14 @@ def _listdir(dirname, dir_fd, dironly): return list(it) # Recursively yields relative pathnames inside a literal directory. -def _rlistdir(dirname, dir_fd, dironly): +def _rlistdir(dirname, dir_fd, dironly, include_hidden=False): names = _listdir(dirname, dir_fd, dironly) for x in names: - if not _ishidden(x): + if include_hidden or not _ishidden(x): yield x path = _join(dirname, x) if dirname else x - for y in _rlistdir(path, dir_fd, dironly): + for y in _rlistdir(path, dir_fd, dironly, + include_hidden=include_hidden): yield _join(x, y) diff --git a/Lib/test/test_glob.py b/Lib/test/test_glob.py index 96db31b26814b..f4b5821f408cb 100644 --- a/Lib/test/test_glob.py +++ b/Lib/test/test_glob.py @@ -30,6 +30,7 @@ def setUp(self): self.mktemp('aab', 'F') self.mktemp('.aa', 'G') self.mktemp('.bb', 'H') + self.mktemp('.bb', '.J') self.mktemp('aaa', 'zzzF') self.mktemp('ZZZ') self.mktemp('EF') @@ -56,7 +57,9 @@ def glob(self, *parts, **kwargs): pattern = os.path.join(*parts) p = os.path.join(self.tempdir, pattern) res = glob.glob(p, **kwargs) + res2 = glob.iglob(p, **kwargs) self.assertCountEqual(glob.iglob(p, **kwargs), res) + bres = [os.fsencode(x) for x in res] self.assertCountEqual(glob.glob(os.fsencode(p), **kwargs), bres) self.assertCountEqual(glob.iglob(os.fsencode(p), **kwargs), bres) @@ -249,6 +252,17 @@ def test_escape_windows(self): def rglob(self, *parts, **kwargs): return self.glob(*parts, recursive=True, **kwargs) + def hglob(self, *parts, **kwargs): + return self.glob(*parts, include_hidden=True, **kwargs) + + def test_hidden_glob(self): + eq = self.assertSequencesEqual_noorder + l = [('aaa',), ('.aa',)] + eq(self.hglob('?aa'), self.joins(*l)) + eq(self.hglob('*aa'), self.joins(*l)) + l2 = [('.aa','G',)] + eq(self.hglob('**', 'G'), self.joins(*l2)) + def test_recursive_glob(self): eq = self.assertSequencesEqual_noorder full = [('EF',), ('ZZZ',), @@ -314,6 +328,10 @@ def test_recursive_glob(self): expect += [join('sym3', 'EF')] eq(glob.glob(join('**', 'EF'), recursive=True), expect) + rec = [('.bb','H'), ('.bb','.J'), ('.aa','G'), ('.aa',), ('.bb',)] + eq(glob.glob('**', recursive=True, include_hidden=True), + [join(*i) for i in full+rec]) + def test_glob_many_open_files(self): depth = 30 base = os.path.join(self.tempdir, 'deep') diff --git a/Misc/NEWS.d/next/Library/2021-12-17-13-22-37.bpo-37578._tluuR.rst b/Misc/NEWS.d/next/Library/2021-12-17-13-22-37.bpo-37578._tluuR.rst new file mode 100644 index 0000000000000..455d0648a94c2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-17-13-22-37.bpo-37578._tluuR.rst @@ -0,0 +1,3 @@ +Add *include_hidden* parameter to :func:`~glob.glob` and :func:`~glob.iglob` to +match hidden files and directories when using special characters like ``*``, +``**``, ``?`` and ``[]``. From webhook-mailer at python.org Sat Dec 18 09:26:18 2021 From: webhook-mailer at python.org (Fidget-Spinner) Date: Sat, 18 Dec 2021 14:26:18 -0000 Subject: [Python-checkins] bpo-46113: Minor fixes in stdtypes documentation (GH-30167) (GH-30187) Message-ID: https://github.com/python/cpython/commit/0da17eb06943a66fcd826ff591d47c22c2c0595a commit: 0da17eb06943a66fcd826ff591d47c22c2c0595a branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Fidget-Spinner <28750310+Fidget-Spinner at users.noreply.github.com> date: 2021-12-18T22:26:04+08:00 summary: bpo-46113: Minor fixes in stdtypes documentation (GH-30167) (GH-30187) * Fix-1 - isidentifier() function output * Fix-2 Update the str.splitlines() function parameter * Fix-3 Removed unwanted full stop for str and bytes types double quotes examples. * Fix-4 Updated class dict from **kwarg to **kwargs (cherry picked from commit 6f2df4295123f8b961d49474b7668f7564a534a4) Co-authored-by: Vivek Vashist files: M Doc/library/stdtypes.rst diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index c6ac6d2c712c1..bfa0e744f2c4f 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -1404,7 +1404,7 @@ Strings are immutable written in a variety of ways: * Single quotes: ``'allows embedded "double" quotes'`` -* Double quotes: ``"allows embedded 'single' quotes"``. +* Double quotes: ``"allows embedded 'single' quotes"`` * Triple quoted: ``'''Three single quotes'''``, ``"""Three double quotes"""`` Triple quoted strings may span multiple lines - all associated whitespace will @@ -1728,9 +1728,9 @@ expression support in the :mod:`re` module). >>> from keyword import iskeyword >>> 'hello'.isidentifier(), iskeyword('hello') - True, False + (True, False) >>> 'def'.isidentifier(), iskeyword('def') - True, True + (True, True) .. method:: str.islower() @@ -1997,7 +1997,7 @@ expression support in the :mod:`re` module). .. index:: single: universal newlines; str.splitlines method -.. method:: str.splitlines([keepends]) +.. method:: str.splitlines(keepends=False) Return a list of the lines in the string, breaking at line boundaries. Line breaks are not included in the resulting list unless *keepends* is given and @@ -2410,7 +2410,7 @@ data and are closely related to string objects in a variety of other ways. literals, except that a ``b`` prefix is added: * Single quotes: ``b'still allows embedded "double" quotes'`` - * Double quotes: ``b"still allows embedded 'single' quotes"``. + * Double quotes: ``b"still allows embedded 'single' quotes"`` * Triple quoted: ``b'''3 single quotes'''``, ``b"""3 double quotes"""`` Only ASCII characters are permitted in bytes literals (regardless of the @@ -4310,9 +4310,9 @@ Dictionaries can be created by placing a comma-separated list of ``key: value`` pairs within braces, for example: ``{'jack': 4098, 'sjoerd': 4127}`` or ``{4098: 'jack', 4127: 'sjoerd'}``, or by the :class:`dict` constructor. -.. class:: dict(**kwarg) - dict(mapping, **kwarg) - dict(iterable, **kwarg) +.. class:: dict(**kwargs) + dict(mapping, **kwargs) + dict(iterable, **kwargs) Return a new dictionary initialized from an optional positional argument and a possibly empty set of keyword arguments. From webhook-mailer at python.org Sat Dec 18 09:54:06 2021 From: webhook-mailer at python.org (tiran) Date: Sat, 18 Dec 2021 14:54:06 -0000 Subject: [Python-checkins] bpo-40280: Add Tools/wasm with helpers for cross building (GH-29984) Message-ID: https://github.com/python/cpython/commit/0339434835aa74dc78a38ae12ea7d2973c144eb1 commit: 0339434835aa74dc78a38ae12ea7d2973c144eb1 branch: main author: Christian Heimes committer: tiran date: 2021-12-18T15:54:02+01:00 summary: bpo-40280: Add Tools/wasm with helpers for cross building (GH-29984) Co-authored-by: Ethan Smith Co-authored-by: Brett Cannon files: A Misc/NEWS.d/next/Build/2021-12-13-21-03-52.bpo-40280.b7NG4Y.rst A Tools/wasm/README.md A Tools/wasm/config.site-wasm32-emscripten A Tools/wasm/wasm_assets.py M Makefile.pre.in M configure M configure.ac diff --git a/Makefile.pre.in b/Makefile.pre.in index 59c92a0568022..ed77bebfab901 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -830,6 +830,22 @@ $(DLLLIBRARY) libpython$(LDVERSION).dll.a: $(LIBRARY_OBJS) else true; \ fi +# wasm32-emscripten build +# wasm assets directory is relative to current build dir, e.g. "./usr/local". +# --preload-file turns a relative asset path into an absolute path. +WASM_ASSETS_DIR=".$(prefix)" +WASM_STDLIB="$(WASM_ASSETS_DIR)/local/lib/python$(VERSION)/os.py" + +$(WASM_STDLIB): $(srcdir)/Lib/*.py $(srcdir)/Lib/*/*.py \ + pybuilddir.txt $(srcdir)/Tools/wasm/wasm_assets.py + $(PYTHON_FOR_BUILD) $(srcdir)/Tools/wasm/wasm_assets.py \ + --builddir . --prefix $(prefix) + +python.html: Programs/python.o $(LIBRARY_DEPS) $(WASM_STDLIB) + $(LINKCC) $(PY_CORE_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/python.o \ + $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) \ + -s ASSERTIONS=1 --preload-file $(WASM_ASSETS_DIR) + ########################################################################## # Build static libmpdec.a LIBMPDEC_CFLAGS=$(PY_STDMODULE_CFLAGS) $(CCSHARED) @LIBMPDEC_CFLAGS@ @@ -938,6 +954,7 @@ Makefile Modules/config.c: Makefile.pre \ $(SHELL) $(MAKESETUP) -c $(srcdir)/Modules/config.c.in \ -s Modules \ Modules/Setup.local \ + @MODULES_SETUP_STDLIB@ \ $(srcdir)/Modules/Setup.bootstrap \ $(srcdir)/Modules/Setup @mv config.c Modules @@ -2379,6 +2396,7 @@ clean-retain-profile: pycremoval -rm -f pybuilddir.txt -rm -f Lib/lib2to3/*Grammar*.pickle -rm -f _bootstrap_python + -rm -f python.html python.js python.data -rm -f Programs/_testembed Programs/_freeze_module -rm -f Python/deepfreeze/*.[co] -rm -f Python/frozen_modules/*.h diff --git a/Misc/NEWS.d/next/Build/2021-12-13-21-03-52.bpo-40280.b7NG4Y.rst b/Misc/NEWS.d/next/Build/2021-12-13-21-03-52.bpo-40280.b7NG4Y.rst new file mode 100644 index 0000000000000..905ee44680276 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-12-13-21-03-52.bpo-40280.b7NG4Y.rst @@ -0,0 +1 @@ +A new directory ``Tools/wasm`` contains WebAssembly-related helpers like ``config.site`` override for wasm32-emscripten, wasm assets generator to bundle the stdlib, and a README. diff --git a/Tools/wasm/README.md b/Tools/wasm/README.md new file mode 100644 index 0000000000000..93c76b225db79 --- /dev/null +++ b/Tools/wasm/README.md @@ -0,0 +1,55 @@ +# Python WebAssembly (WASM) build + +This directory contains configuration and helpers to facilitate cross +compilation of CPython to WebAssembly (WASM). + +## wasm32-emscripten build + +Cross compiling to wasm32-emscripten platform needs the [Emscripten](https://emscripten.org/) +tool chain and a build Python interpreter. +All commands below are relative to a repository checkout. + +### Compile a build Python interpreter + +```shell +mkdir -p builddir/build +pushd builddir/build +../../configure -C +make -j$(nproc) +popd +``` + +### Fetch and build additional emscripten ports + +```shell +embuilder build zlib +``` + +### Cross compile to wasm32-emscripten + +```shell +mkdir -p builddir/emscripten +pushd builddir/emscripten + +CONFIG_SITE=../../Tools/wasm/config.site-wasm32-emscripten \ + emconfigure ../../configure -C \ + --host=wasm32-unknown-emscripten \ + --build=$(../../config.guess) \ + --with-build-python=$(pwd)/../build/python + +emmake make -j$(nproc) python.html +``` + +### Test in browser + +Serve `python.html` with a local webserver and open the file in a browser. + +```shell +emrun python.html +``` + +or + +```shell +python3 -m http.server +``` diff --git a/Tools/wasm/config.site-wasm32-emscripten b/Tools/wasm/config.site-wasm32-emscripten new file mode 100644 index 0000000000000..67304be060b52 --- /dev/null +++ b/Tools/wasm/config.site-wasm32-emscripten @@ -0,0 +1,70 @@ +# config.site override for cross compiling to wasm32-emscripten platform +# +# CONFIG_SITE=Tools/wasm/config.site-wasm32-emscripten \ +# emconfigure ./configure --host=wasm32-unknown-emscripten --build=... +# +# Written by Christian Heimes +# Partly based on pyodide's pyconfig.undefs.h file. +# + +# cannot be detected in cross builds +ac_cv_buggy_getaddrinfo=no + +# Emscripten has no /dev/pt* +ac_cv_file__dev_ptmx=no +ac_cv_file__dev_ptc=no + +# dummy readelf, Emscripten build does not need readelf. +ac_cv_prog_ac_ct_READELF=true + +# new undefined symbols / unsupported features +ac_cv_func_posix_spawn=no +ac_cv_func_posix_spawnp=no +ac_cv_func_eventfd=no +ac_cv_func_memfd_create=no +ac_cv_func_prlimit=no + +# unsupported syscall, https://github.com/emscripten-core/emscripten/issues/13393 +ac_cv_func_shutdown=no + +# breaks build, see https://github.com/ethanhs/python-wasm/issues/16 +ac_cv_lib_bz2_BZ2_bzCompress=no + +# The rest is based on pyodide +# https://github.com/pyodide/pyodide/blob/main/cpython/pyconfig.undefs.h + +ac_cv_func_epoll=no +ac_cv_func_epoll_create1=no +ac_cv_header_linux_vm_sockets_h=no +ac_cv_func_socketpair=no +ac_cv_func_utimensat=no +ac_cv_func_sigaction=no + +# Untested syscalls in emscripten +ac_cv_func_openat=no +ac_cv_func_mkdirat=no +ac_cv_func_fchownat=no +ac_cv_func_renameat=no +ac_cv_func_linkat=no +ac_cv_func_symlinkat=no +ac_cv_func_readlinkat=no +ac_cv_func_fchmodat=no +ac_cv_func_dup3=no + +# Syscalls not implemented in emscripten +ac_cv_func_preadv2=no +ac_cv_func_preadv=no +ac_cv_func_pwritev2=no +ac_cv_func_pwritev=no +ac_cv_func_pipe2=no +ac_cv_func_nice=no + +# Syscalls that resulted in a segfault +ac_cv_func_utimensat=no +ac_cv_header_sys_ioctl_h=no + +# sockets are supported, but only in non-blocking mode +# ac_cv_header_sys_socket_h=no + +# Unsupported functionality +#undef HAVE_PTHREAD_H diff --git a/Tools/wasm/wasm_assets.py b/Tools/wasm/wasm_assets.py new file mode 100755 index 0000000000000..6a4027184030f --- /dev/null +++ b/Tools/wasm/wasm_assets.py @@ -0,0 +1,174 @@ +#!/usr/bin/env python +"""Create a WASM asset bundle directory structure. + +The WASM asset bundles are pre-loaded by the final WASM build. The bundle +contains: + +- a stripped down, pyc-only stdlib zip file, e.g. {PREFIX}/lib/python311.zip +- os.py as marker module {PREFIX}/lib/python3.11/os.py +- empty lib-dynload directory, to make sure it is copied into the bundle {PREFIX}/lib/python3.11/lib-dynload/.empty +""" + +import argparse +import pathlib +import shutil +import sys +import zipfile + +# source directory +SRCDIR = pathlib.Path(__file__).parent.parent.parent.absolute() +SRCDIR_LIB = SRCDIR / "Lib" + +# sysconfig data relative to build dir. +SYSCONFIGDATA_GLOB = "build/lib.*/_sysconfigdata_*.py" + +# Library directory relative to $(prefix). +WASM_LIB = pathlib.PurePath("lib") +WASM_STDLIB_ZIP = ( + WASM_LIB / f"python{sys.version_info.major}{sys.version_info.minor}.zip" +) +WASM_STDLIB = ( + WASM_LIB / f"python{sys.version_info.major}.{sys.version_info.minor}" +) +WASM_DYNLOAD = WASM_STDLIB / "lib-dynload" + + +# Don't ship large files / packages that are not particularly useful at +# the moment. +OMIT_FILES = ( + # regression tests + "test/", + # user interfaces: TK, curses + "curses/", + "idlelib/", + "tkinter/", + "turtle.py", + "turtledemo/", + # package management + "ensurepip/", + "venv/", + # build system + "distutils/", + "lib2to3/", + # concurrency + "concurrent/", + "multiprocessing/", + # deprecated + "asyncore.py", + "asynchat.py", + # Synchronous network I/O and protocols are not supported; for example, + # socket.create_connection() raises an exception: + # "BlockingIOError: [Errno 26] Operation in progress". + "cgi.py", + "cgitb.py", + "email/", + "ftplib.py", + "http/", + "imaplib.py", + "nntplib.py", + "poplib.py", + "smtpd.py", + "smtplib.py", + "socketserver.py", + "telnetlib.py", + "urllib/", + "wsgiref/", + "xmlrpc/", + # dbm / gdbm + "dbm/", + # other platforms + "_aix_support.py", + "_bootsubprocess.py", + "_osx_support.py", + # webbrowser + "antigravity.py", + "webbrowser.py", + # ctypes + "ctypes/", + # Pure Python implementations of C extensions + "_pydecimal.py", + "_pyio.py", + # Misc unused or large files + "pydoc_data/", + "msilib/", +) + +# regression test sub directories +OMIT_SUBDIRS = ( + "ctypes/test/", + "tkinter/test/", + "unittest/test/", +) + + +OMIT_ABSOLUTE = {SRCDIR_LIB / name for name in OMIT_FILES} +OMIT_SUBDIRS_ABSOLUTE = tuple(str(SRCDIR_LIB / name) for name in OMIT_SUBDIRS) + + +def filterfunc(name: str) -> bool: + return not name.startswith(OMIT_SUBDIRS_ABSOLUTE) + + +def create_stdlib_zip( + args: argparse.Namespace, compression: int = zipfile.ZIP_DEFLATED, *, optimize: int = 0 +) -> None: + sysconfig_data = list(args.builddir.glob(SYSCONFIGDATA_GLOB)) + if not sysconfig_data: + raise ValueError("No sysconfigdata file found") + + with zipfile.PyZipFile( + args.wasm_stdlib_zip, mode="w", compression=compression, optimize=0 + ) as pzf: + for entry in sorted(args.srcdir_lib.iterdir()): + if entry.name == "__pycache__": + continue + if entry in OMIT_ABSOLUTE: + continue + if entry.name.endswith(".py") or entry.is_dir(): + # writepy() writes .pyc files (bytecode). + pzf.writepy(entry, filterfunc=filterfunc) + for entry in sysconfig_data: + pzf.writepy(entry) + + +def path(val: str) -> pathlib.Path: + return pathlib.Path(val).absolute() + + +parser = argparse.ArgumentParser() +parser.add_argument( + "--builddir", + help="absolute build directory", + default=pathlib.Path(".").absolute(), + type=path, +) +parser.add_argument( + "--prefix", help="install prefix", default=pathlib.Path("/usr/local"), type=path +) + + +def main(): + args = parser.parse_args() + + relative_prefix = args.prefix.relative_to(pathlib.Path("/")) + args.srcdir = SRCDIR + args.srcdir_lib = SRCDIR_LIB + args.wasm_root = args.builddir / relative_prefix + args.wasm_stdlib_zip = args.wasm_root / WASM_STDLIB_ZIP + args.wasm_stdlib = args.wasm_root / WASM_STDLIB + args.wasm_dynload = args.wasm_root / WASM_DYNLOAD + + # Empty, unused directory for dynamic libs, but required for site initialization. + args.wasm_dynload.mkdir(parents=True, exist_ok=True) + marker = args.wasm_dynload / ".empty" + marker.touch() + # os.py is a marker for finding the correct lib directory. + shutil.copy(args.srcdir_lib / "os.py", args.wasm_stdlib) + # The rest of stdlib that's useful in a WASM context. + create_stdlib_zip(args) + size = round(args.wasm_stdlib_zip.stat().st_size / 1024 ** 2, 2) + parser.exit(0, f"Created {args.wasm_stdlib_zip} ({size} MiB)\n") + + +if __name__ == "__main__": + main() diff --git a/configure b/configure index 1ede29989d948..eca63518dbca3 100755 --- a/configure +++ b/configure @@ -772,6 +772,7 @@ MODULE_TIME_FALSE MODULE_TIME_TRUE MODULE__IO_FALSE MODULE__IO_TRUE +MODULES_SETUP_STDLIB MODULE_BUILDTYPE TEST_MODULES LIBRARY_DEPS @@ -13298,7 +13299,13 @@ fi if test -z "$with_pymalloc" then + case $ac_sys_system in #( + Emscripten) : + with_pymalloc="no" ;; #( + *) : with_pymalloc="yes" + ;; +esac fi if test "$with_pymalloc" != "no" then @@ -21165,12 +21172,22 @@ fi if test "$enable_test_modules" = no; then TEST_MODULES=no - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } else + case $ac_sys_system in #( + Emscripten) : + TEST_MODULES=no ;; #( + *) : TEST_MODULES=yes - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + ;; +esac +fi +if test "x$TEST_MODULES" = xyes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + fi @@ -21189,7 +21206,7 @@ case $ac_sys_system in #( py_stdlib_not_available="_scproxy spwd" ;; #( Emscripten) : - py_stdlib_not_available="_curses _curses_panel _dbm _gdbm _multiprocessing _posixshmem _posixsubprocess _scproxy _xxsubinterpreters fcntl grp nis ossaudiodev resource spwd syslog termios" + py_stdlib_not_available="_ctypes _curses _curses_panel _dbm _gdbm _multiprocessing _posixshmem _posixsubprocess _scproxy _tkinter _xxsubinterpreters fcntl grp nis ossaudiodev resource readline spwd syslog termios" ;; #( *) : py_stdlib_not_available="_scproxy" @@ -21205,6 +21222,20 @@ case $host_cpu in #( esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for additional Modules/Setup files" >&5 +$as_echo_n "checking for additional Modules/Setup files... " >&6; } +case $ac_sys_system in #( + Emscripten) : + MODULES_SETUP_STDLIB=Modules/Setup.stdlib ;; #( + *) : + MODULES_SETUP_STDLIB= + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MODULES_SETUP_STDLIB" >&5 +$as_echo "$MODULES_SETUP_STDLIB" >&6; } + + + MODULE_BLOCK= @@ -25100,7 +25131,7 @@ fi $as_echo "$as_me: creating Makefile" >&6;} $SHELL $srcdir/Modules/makesetup -c $srcdir/Modules/config.c.in \ -s Modules \ - Modules/Setup.local $srcdir/Modules/Setup.bootstrap $srcdir/Modules/Setup + Modules/Setup.local $MODULES_SETUP_STDLIB $srcdir/Modules/Setup.bootstrap $srcdir/Modules/Setup mv config.c Modules if test -z "$PKG_CONFIG"; then diff --git a/configure.ac b/configure.ac index 86404bcadeaba..050b907ac8624 100644 --- a/configure.ac +++ b/configure.ac @@ -3865,7 +3865,11 @@ AC_ARG_WITH(pymalloc, if test -z "$with_pymalloc" then - with_pymalloc="yes" + dnl default to yes except for wasm32-emscripten + AS_CASE([$ac_sys_system], + [Emscripten], [with_pymalloc="no"], + [with_pymalloc="yes"] + ) fi if test "$with_pymalloc" != "no" then @@ -6253,11 +6257,15 @@ AC_ARG_ENABLE(test-modules, AS_HELP_STRING([--disable-test-modules], [don't build nor install test modules])) if test "$enable_test_modules" = no; then TEST_MODULES=no - AC_MSG_RESULT(yes) else - TEST_MODULES=yes - AC_MSG_RESULT(no) + AS_CASE([$ac_sys_system], + [Emscripten], [TEST_MODULES=no], + [TEST_MODULES=yes] + ) fi +AS_VAR_IF([TEST_MODULES], [yes], + [AC_MSG_RESULT(no)], [AC_MSG_RESULT(yes)] +) AC_SUBST(TEST_MODULES) dnl Modules that are not available on some platforms @@ -6272,6 +6280,7 @@ AS_CASE([$ac_sys_system], [FreeBSD*], [py_stdlib_not_available="_scproxy spwd"], [Emscripten], [ py_stdlib_not_available="m4_normalize([ + _ctypes _curses _curses_panel _dbm @@ -6280,12 +6289,14 @@ AS_CASE([$ac_sys_system], _posixshmem _posixsubprocess _scproxy + _tkinter _xxsubinterpreters fcntl grp nis ossaudiodev resource + readline spwd syslog termios @@ -6301,6 +6312,16 @@ AS_CASE([$host_cpu], ) AC_SUBST([MODULE_BUILDTYPE]) +dnl Use Modules/Setup.stdlib as additional provider? +AC_MSG_CHECKING([for additional Modules/Setup files]) +AS_CASE([$ac_sys_system], + [Emscripten], [MODULES_SETUP_STDLIB=Modules/Setup.stdlib], + [MODULES_SETUP_STDLIB=] +) +AC_MSG_RESULT([$MODULES_SETUP_STDLIB]) +AC_SUBST([MODULES_SETUP_STDLIB]) + + dnl _MODULE_BLOCK_ADD([VAR], [VALUE]) dnl internal: adds $1=quote($2) to MODULE_BLOCK AC_DEFUN([_MODULE_BLOCK_ADD], [AS_VAR_APPEND([MODULE_BLOCK], ["$1=_AS_QUOTE([$2])$as_nl"])]) @@ -6515,7 +6536,7 @@ fi AC_MSG_NOTICE([creating Makefile]) $SHELL $srcdir/Modules/makesetup -c $srcdir/Modules/config.c.in \ -s Modules \ - Modules/Setup.local $srcdir/Modules/Setup.bootstrap $srcdir/Modules/Setup + Modules/Setup.local $MODULES_SETUP_STDLIB $srcdir/Modules/Setup.bootstrap $srcdir/Modules/Setup mv config.c Modules if test -z "$PKG_CONFIG"; then From webhook-mailer at python.org Sat Dec 18 10:51:42 2021 From: webhook-mailer at python.org (asvetlov) Date: Sat, 18 Dec 2021 15:51:42 -0000 Subject: [Python-checkins] bpo-46099: Fix pthread_getcpuclockid test on Solaris (GH-30140) (#30184) Message-ID: https://github.com/python/cpython/commit/a328ad7f9a9b6cd624da5efcc76daf88e0d22312 commit: a328ad7f9a9b6cd624da5efcc76daf88e0d22312 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: asvetlov date: 2021-12-18T17:51:34+02:00 summary: bpo-46099: Fix pthread_getcpuclockid test on Solaris (GH-30140) (#30184) Co-authored-by: Andrew Svetlov (cherry picked from commit 427a490c495cde8a152e938c6f02be65620e3e59) Co-authored-by: Jakub Kul?k files: M Lib/test/test_time.py diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py index 90a123828b709..be9fb5ad5f0b1 100644 --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -112,12 +112,13 @@ def test_pthread_getcpuclockid(self): clk_id = time.pthread_getcpuclockid(threading.get_ident()) self.assertTrue(type(clk_id) is int) # when in 32-bit mode AIX only returns the predefined constant - if not platform.system() == "AIX": - self.assertNotEqual(clk_id, time.CLOCK_THREAD_CPUTIME_ID) - elif (sys.maxsize.bit_length() > 32): - self.assertNotEqual(clk_id, time.CLOCK_THREAD_CPUTIME_ID) - else: + if platform.system() == "AIX" and (sys.maxsize.bit_length() <= 32): self.assertEqual(clk_id, time.CLOCK_THREAD_CPUTIME_ID) + # Solaris returns CLOCK_THREAD_CPUTIME_ID when current thread is given + elif sys.platform.startswith("sunos"): + self.assertEqual(clk_id, time.CLOCK_THREAD_CPUTIME_ID) + else: + self.assertNotEqual(clk_id, time.CLOCK_THREAD_CPUTIME_ID) t1 = time.clock_gettime(clk_id) t2 = time.clock_gettime(clk_id) self.assertLessEqual(t1, t2) From webhook-mailer at python.org Sat Dec 18 16:19:16 2021 From: webhook-mailer at python.org (miss-islington) Date: Sat, 18 Dec 2021 21:19:16 -0000 Subject: [Python-checkins] bpo-46044: Fix doc typo introduced in GH-30043 (GH-30171) Message-ID: https://github.com/python/cpython/commit/fe68486197cb26a69ecce9353271d91adf885cb5 commit: fe68486197cb26a69ecce9353271d91adf885cb5 branch: main author: Matthias Bussonnier committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-18T13:19:07-08:00 summary: bpo-46044: Fix doc typo introduced in GH-30043 (GH-30171) See https://github.com/python/cpython/pull/30043/files#r770944718 My bad I likely messed up by using a repeat command in my editor Automerge-Triggered-By: GH:merwok files: M Doc/distutils/sourcedist.rst diff --git a/Doc/distutils/sourcedist.rst b/Doc/distutils/sourcedist.rst index 43fbb03547f78..7b1e22f824e8c 100644 --- a/Doc/distutils/sourcedist.rst +++ b/Doc/distutils/sourcedist.rst @@ -37,7 +37,7 @@ to create a gzipped tarball and a zip file. The available formats are: | ``xztar`` | xz'ed tar file | \(5) | | | (:file:`.tar.xz`) | | +-----------+-------------------------+-------------+ -| ``ztar`` | compressed tar file | \(5) | +| ``ztar`` | compressed tar file | (4),(5) | | | (:file:`.tar.Z`) | | +-----------+-------------------------+-------------+ | ``tar`` | tar file (:file:`.tar`) | \(5) | From webhook-mailer at python.org Sat Dec 18 21:29:22 2021 From: webhook-mailer at python.org (jaraco) Date: Sun, 19 Dec 2021 02:29:22 -0000 Subject: [Python-checkins] bpo-46125: Refactor tests to test traversable API directly. Includes changes from importlib_resources 5.4.0. (GH-30189) Message-ID: https://github.com/python/cpython/commit/9b52920173735ac609664c6a3a3021d24a95a092 commit: 9b52920173735ac609664c6a3a3021d24a95a092 branch: main author: Jason R. Coombs committer: jaraco date: 2021-12-18T21:28:49-05:00 summary: bpo-46125: Refactor tests to test traversable API directly. Includes changes from importlib_resources 5.4.0. (GH-30189) files: A Misc/NEWS.d/next/Library/2021-12-18-18-29-07.bpo-46125.LLmcox.rst M Lib/importlib/_common.py M Lib/importlib/_legacy.py M Lib/importlib/abc.py M Lib/importlib/resources.py M Lib/test/test_importlib/resources/util.py M Lib/test/test_importlib/test_contents.py M Lib/test/test_importlib/test_open.py M Lib/test/test_importlib/test_path.py M Lib/test/test_importlib/test_read.py M Lib/test/test_importlib/test_resource.py diff --git a/Lib/importlib/_common.py b/Lib/importlib/_common.py index 9b126f3174974..147ea19188f71 100644 --- a/Lib/importlib/_common.py +++ b/Lib/importlib/_common.py @@ -6,13 +6,12 @@ import types import importlib -from typing import Union, Any, Optional +from typing import Union, Optional from .abc import ResourceReader, Traversable from ._adapters import wrap_spec Package = Union[types.ModuleType, str] -Resource = Union[str, os.PathLike] def files(package): @@ -23,19 +22,6 @@ def files(package): return from_package(get_package(package)) -def normalize_path(path): - # type: (Any) -> str - """Normalize a path by ensuring it is a string. - - If the resulting string contains path separators, an exception is raised. - """ - str_path = str(path) - parent, file_name = os.path.split(str_path) - if parent: - raise ValueError(f'{path!r} must be only a file name') - return file_name - - def get_resource_reader(package): # type: (types.ModuleType) -> Optional[ResourceReader] """ diff --git a/Lib/importlib/_legacy.py b/Lib/importlib/_legacy.py index 477f89e4c3abd..1d5d3f1fbb1f6 100644 --- a/Lib/importlib/_legacy.py +++ b/Lib/importlib/_legacy.py @@ -4,12 +4,12 @@ import types import warnings -from typing import Union, Iterable, ContextManager, BinaryIO, TextIO +from typing import Union, Iterable, ContextManager, BinaryIO, TextIO, Any from . import _common Package = Union[types.ModuleType, str] -Resource = Union[str, os.PathLike] +Resource = str def deprecated(func): @@ -27,16 +27,29 @@ def wrapper(*args, **kwargs): return wrapper +def normalize_path(path): + # type: (Any) -> str + """Normalize a path by ensuring it is a string. + + If the resulting string contains path separators, an exception is raised. + """ + str_path = str(path) + parent, file_name = os.path.split(str_path) + if parent: + raise ValueError(f'{path!r} must be only a file name') + return file_name + + @deprecated def open_binary(package: Package, resource: Resource) -> BinaryIO: """Return a file-like object opened for binary reading of the resource.""" - return (_common.files(package) / _common.normalize_path(resource)).open('rb') + return (_common.files(package) / normalize_path(resource)).open('rb') @deprecated def read_binary(package: Package, resource: Resource) -> bytes: """Return the binary contents of the resource.""" - return (_common.files(package) / _common.normalize_path(resource)).read_bytes() + return (_common.files(package) / normalize_path(resource)).read_bytes() @deprecated @@ -47,7 +60,7 @@ def open_text( errors: str = 'strict', ) -> TextIO: """Return a file-like object opened for text reading of the resource.""" - return (_common.files(package) / _common.normalize_path(resource)).open( + return (_common.files(package) / normalize_path(resource)).open( 'r', encoding=encoding, errors=errors ) @@ -85,7 +98,7 @@ def is_resource(package: Package, name: str) -> bool: Directories are *not* resources. """ - resource = _common.normalize_path(name) + resource = normalize_path(name) return any( traversable.name == resource and traversable.is_file() for traversable in _common.files(package).iterdir() @@ -105,4 +118,4 @@ def path( raised if the file was deleted prior to the context manager exiting). """ - return _common.as_file(_common.files(package) / _common.normalize_path(resource)) + return _common.as_file(_common.files(package) / normalize_path(resource)) diff --git a/Lib/importlib/abc.py b/Lib/importlib/abc.py index 1d6843b2ddd44..f10441608ad71 100644 --- a/Lib/importlib/abc.py +++ b/Lib/importlib/abc.py @@ -381,7 +381,7 @@ def read_text(self, encoding=None): @abc.abstractmethod def is_dir(self) -> bool: """ - Return True if self is a dir + Return True if self is a directory """ @abc.abstractmethod diff --git a/Lib/importlib/resources.py b/Lib/importlib/resources.py index 6cc46283ba0a2..5b3bc0228d9ac 100644 --- a/Lib/importlib/resources.py +++ b/Lib/importlib/resources.py @@ -4,7 +4,6 @@ as_file, files, Package, - Resource, ) from ._legacy import ( @@ -15,6 +14,7 @@ read_text, is_resource, path, + Resource, ) from importlib.abc import ResourceReader diff --git a/Lib/test/test_importlib/resources/util.py b/Lib/test/test_importlib/resources/util.py index 719263223032a..11c8aa80806dc 100644 --- a/Lib/test/test_importlib/resources/util.py +++ b/Lib/test/test_importlib/resources/util.py @@ -1,10 +1,8 @@ import abc -import contextlib import importlib import io import sys import types -import warnings from pathlib import Path, PurePath from .. import data01 @@ -69,13 +67,6 @@ def create_package(file=None, path=None, is_package=True, contents=()): ) - at contextlib.contextmanager -def suppress_known_deprecation(): - with warnings.catch_warnings(record=True) as ctx: - warnings.simplefilter('default', category=DeprecationWarning) - yield ctx - - class CommonTests(metaclass=abc.ABCMeta): """ Tests shared by test_open, test_path, and test_read. @@ -106,18 +97,6 @@ def test_pathlib_path(self): path = PurePath('utf-8.file') self.execute(data01, path) - def test_absolute_path(self): - # An absolute path is a ValueError. - path = Path(__file__) - full_path = path.parent / 'utf-8.file' - with self.assertRaises(ValueError): - self.execute(data01, full_path) - - def test_relative_path(self): - # A reative path is a ValueError. - with self.assertRaises(ValueError): - self.execute(data01, '../data01/utf-8.file') - def test_importing_module_as_side_effect(self): # The anchor package can already be imported. del sys.modules[data01.__name__] diff --git a/Lib/test/test_importlib/test_contents.py b/Lib/test/test_importlib/test_contents.py index 575dcd2f30473..3323bf5b5cf56 100644 --- a/Lib/test/test_importlib/test_contents.py +++ b/Lib/test/test_importlib/test_contents.py @@ -15,8 +15,8 @@ class ContentsTests: } def test_contents(self): - with util.suppress_known_deprecation(): - assert self.expected <= set(resources.contents(self.data)) + contents = {path.name for path in resources.files(self.data).iterdir()} + assert self.expected <= contents class ContentsDiskTests(ContentsTests, unittest.TestCase): diff --git a/Lib/test/test_importlib/test_open.py b/Lib/test/test_importlib/test_open.py index a9c4a7085c197..df75e343d2c5b 100644 --- a/Lib/test/test_importlib/test_open.py +++ b/Lib/test/test_importlib/test_open.py @@ -7,47 +7,44 @@ class CommonBinaryTests(util.CommonTests, unittest.TestCase): def execute(self, package, path): - with util.suppress_known_deprecation(): - with resources.open_binary(package, path): - pass + target = resources.files(package).joinpath(path) + with target.open('rb'): + pass class CommonTextTests(util.CommonTests, unittest.TestCase): def execute(self, package, path): - with util.suppress_known_deprecation(): - with resources.open_text(package, path): - pass + target = resources.files(package).joinpath(path) + with target.open(): + pass class OpenTests: def test_open_binary(self): - with util.suppress_known_deprecation(): - with resources.open_binary(self.data, 'binary.file') as fp: - result = fp.read() - self.assertEqual(result, b'\x00\x01\x02\x03') + target = resources.files(self.data) / 'binary.file' + with target.open('rb') as fp: + result = fp.read() + self.assertEqual(result, b'\x00\x01\x02\x03') def test_open_text_default_encoding(self): - with util.suppress_known_deprecation(): - with resources.open_text(self.data, 'utf-8.file') as fp: - result = fp.read() + target = resources.files(self.data) / 'utf-8.file' + with target.open() as fp: + result = fp.read() self.assertEqual(result, 'Hello, UTF-8 world!\n') def test_open_text_given_encoding(self): - with util.suppress_known_deprecation(): - with resources.open_text( - self.data, 'utf-16.file', 'utf-16', 'strict' - ) as fp: - result = fp.read() + target = resources.files(self.data) / 'utf-16.file' + with target.open(encoding='utf-16', errors='strict') as fp: + result = fp.read() self.assertEqual(result, 'Hello, UTF-16 world!\n') def test_open_text_with_errors(self): # Raises UnicodeError without the 'errors' argument. - with util.suppress_known_deprecation(): - with resources.open_text(self.data, 'utf-16.file', 'utf-8', 'strict') as fp: - self.assertRaises(UnicodeError, fp.read) - with util.suppress_known_deprecation(): - with resources.open_text(self.data, 'utf-16.file', 'utf-8', 'ignore') as fp: - result = fp.read() + target = resources.files(self.data) / 'utf-16.file' + with target.open(encoding='utf-8', errors='strict') as fp: + self.assertRaises(UnicodeError, fp.read) + with target.open(encoding='utf-8', errors='ignore') as fp: + result = fp.read() self.assertEqual( result, 'H\x00e\x00l\x00l\x00o\x00,\x00 ' @@ -56,16 +53,12 @@ def test_open_text_with_errors(self): ) def test_open_binary_FileNotFoundError(self): - with util.suppress_known_deprecation(): - self.assertRaises( - FileNotFoundError, resources.open_binary, self.data, 'does-not-exist' - ) + target = resources.files(self.data) / 'does-not-exist' + self.assertRaises(FileNotFoundError, target.open, 'rb') def test_open_text_FileNotFoundError(self): - with util.suppress_known_deprecation(): - self.assertRaises( - FileNotFoundError, resources.open_text, self.data, 'does-not-exist' - ) + target = resources.files(self.data) / 'does-not-exist' + self.assertRaises(FileNotFoundError, target.open) class OpenDiskTests(OpenTests, unittest.TestCase): diff --git a/Lib/test/test_importlib/test_path.py b/Lib/test/test_importlib/test_path.py index 3ccbc6fbd2af3..6fc41f301d1ca 100644 --- a/Lib/test/test_importlib/test_path.py +++ b/Lib/test/test_importlib/test_path.py @@ -8,9 +8,8 @@ class CommonTests(util.CommonTests, unittest.TestCase): def execute(self, package, path): - with util.suppress_known_deprecation(): - with resources.path(package, path): - pass + with resources.as_file(resources.files(package).joinpath(path)): + pass class PathTests: @@ -18,13 +17,13 @@ def test_reading(self): # Path should be readable. # Test also implicitly verifies the returned object is a pathlib.Path # instance. - with util.suppress_known_deprecation(): - with resources.path(self.data, 'utf-8.file') as path: - self.assertTrue(path.name.endswith("utf-8.file"), repr(path)) - # pathlib.Path.read_text() was introduced in Python 3.5. - with path.open('r', encoding='utf-8') as file: - text = file.read() - self.assertEqual('Hello, UTF-8 world!\n', text) + target = resources.files(self.data) / 'utf-8.file' + with resources.as_file(target) as path: + self.assertTrue(path.name.endswith("utf-8.file"), repr(path)) + # pathlib.Path.read_text() was introduced in Python 3.5. + with path.open('r', encoding='utf-8') as file: + text = file.read() + self.assertEqual('Hello, UTF-8 world!\n', text) class PathDiskTests(PathTests, unittest.TestCase): @@ -34,9 +33,9 @@ def test_natural_path(self): # Guarantee the internal implementation detail that # file-system-backed resources do not get the tempdir # treatment. - with util.suppress_known_deprecation(): - with resources.path(self.data, 'utf-8.file') as path: - assert 'data' in str(path) + target = resources.files(self.data) / 'utf-8.file' + with resources.as_file(target) as path: + assert 'data' in str(path) class PathMemoryTests(PathTests, unittest.TestCase): @@ -54,9 +53,9 @@ class PathZipTests(PathTests, util.ZipSetup, unittest.TestCase): def test_remove_in_context_manager(self): # It is not an error if the file that was temporarily stashed on the # file system is removed inside the `with` stanza. - with util.suppress_known_deprecation(): - with resources.path(self.data, 'utf-8.file') as path: - path.unlink() + target = resources.files(self.data) / 'utf-8.file' + with resources.as_file(target) as path: + path.unlink() if __name__ == '__main__': diff --git a/Lib/test/test_importlib/test_read.py b/Lib/test/test_importlib/test_read.py index 1bab5c97f41bf..ebd72267776d9 100644 --- a/Lib/test/test_importlib/test_read.py +++ b/Lib/test/test_importlib/test_read.py @@ -7,40 +7,36 @@ class CommonBinaryTests(util.CommonTests, unittest.TestCase): def execute(self, package, path): - with util.suppress_known_deprecation(): - resources.read_binary(package, path) + resources.files(package).joinpath(path).read_bytes() class CommonTextTests(util.CommonTests, unittest.TestCase): def execute(self, package, path): - with util.suppress_known_deprecation(): - resources.read_text(package, path) + resources.files(package).joinpath(path).read_text() class ReadTests: - def test_read_binary(self): - with util.suppress_known_deprecation(): - result = resources.read_binary(self.data, 'binary.file') + def test_read_bytes(self): + result = resources.files(self.data).joinpath('binary.file').read_bytes() self.assertEqual(result, b'\0\1\2\3') def test_read_text_default_encoding(self): - with util.suppress_known_deprecation(): - result = resources.read_text(self.data, 'utf-8.file') + result = resources.files(self.data).joinpath('utf-8.file').read_text() self.assertEqual(result, 'Hello, UTF-8 world!\n') def test_read_text_given_encoding(self): - with util.suppress_known_deprecation(): - result = resources.read_text(self.data, 'utf-16.file', encoding='utf-16') + result = ( + resources.files(self.data) + .joinpath('utf-16.file') + .read_text(encoding='utf-16') + ) self.assertEqual(result, 'Hello, UTF-16 world!\n') def test_read_text_with_errors(self): # Raises UnicodeError without the 'errors' argument. - with util.suppress_known_deprecation(): - self.assertRaises( - UnicodeError, resources.read_text, self.data, 'utf-16.file' - ) - with util.suppress_known_deprecation(): - result = resources.read_text(self.data, 'utf-16.file', errors='ignore') + target = resources.files(self.data) / 'utf-16.file' + self.assertRaises(UnicodeError, target.read_text, encoding='utf-8') + result = target.read_text(encoding='utf-8', errors='ignore') self.assertEqual( result, 'H\x00e\x00l\x00l\x00o\x00,\x00 ' @@ -56,13 +52,15 @@ class ReadDiskTests(ReadTests, unittest.TestCase): class ReadZipTests(ReadTests, util.ZipSetup, unittest.TestCase): def test_read_submodule_resource(self): submodule = import_module('ziptestdata.subdirectory') - with util.suppress_known_deprecation(): - result = resources.read_binary(submodule, 'binary.file') + result = resources.files(submodule).joinpath('binary.file').read_bytes() self.assertEqual(result, b'\0\1\2\3') def test_read_submodule_resource_by_name(self): - with util.suppress_known_deprecation(): - result = resources.read_binary('ziptestdata.subdirectory', 'binary.file') + result = ( + resources.files('ziptestdata.subdirectory') + .joinpath('binary.file') + .read_bytes() + ) self.assertEqual(result, b'\0\1\2\3') diff --git a/Lib/test/test_importlib/test_resource.py b/Lib/test/test_importlib/test_resource.py index 39904591a5248..834b8bd8a2818 100644 --- a/Lib/test/test_importlib/test_resource.py +++ b/Lib/test/test_importlib/test_resource.py @@ -14,38 +14,18 @@ class ResourceTests: # Subclasses are expected to set the `data` attribute. - def test_is_resource_good_path(self): - with util.suppress_known_deprecation(): - self.assertTrue(resources.is_resource(self.data, 'binary.file')) - - def test_is_resource_missing(self): - with util.suppress_known_deprecation(): - self.assertFalse(resources.is_resource(self.data, 'not-a-file')) - - def test_is_resource_subresource_directory(self): - # Directories are not resources. - with util.suppress_known_deprecation(): - self.assertFalse(resources.is_resource(self.data, 'subdirectory')) - - def test_contents(self): - with util.suppress_known_deprecation(): - contents = set(resources.contents(self.data)) - # There may be cruft in the directory listing of the data directory. - # It could have a __pycache__ directory, - # an artifact of the - # test suite importing these modules, which - # are not germane to this test, so just filter them out. - contents.discard('__pycache__') - self.assertEqual( - sorted(contents), - [ - '__init__.py', - 'binary.file', - 'subdirectory', - 'utf-16.file', - 'utf-8.file', - ], - ) + def test_is_file_exists(self): + target = resources.files(self.data) / 'binary.file' + self.assertTrue(target.is_file()) + + def test_is_file_missing(self): + target = resources.files(self.data) / 'not-a-file' + self.assertFalse(target.is_file()) + + def test_is_dir(self): + target = resources.files(self.data) / 'subdirectory' + self.assertFalse(target.is_file()) + self.assertTrue(target.is_dir()) class ResourceDiskTests(ResourceTests, unittest.TestCase): @@ -57,34 +37,34 @@ class ResourceZipTests(ResourceTests, util.ZipSetup, unittest.TestCase): pass +def names(traversable): + return {item.name for item in traversable.iterdir()} + + class ResourceLoaderTests(unittest.TestCase): def test_resource_contents(self): package = util.create_package( file=data01, path=data01.__file__, contents=['A', 'B', 'C'] ) - with util.suppress_known_deprecation(): - self.assertEqual(set(resources.contents(package)), {'A', 'B', 'C'}) + self.assertEqual(names(resources.files(package)), {'A', 'B', 'C'}) - def test_resource_is_resource(self): + def test_is_file(self): package = util.create_package( file=data01, path=data01.__file__, contents=['A', 'B', 'C', 'D/E', 'D/F'] ) - with util.suppress_known_deprecation(): - self.assertTrue(resources.is_resource(package, 'B')) + self.assertTrue(resources.files(package).joinpath('B').is_file()) - def test_resource_directory_is_not_resource(self): + def test_is_dir(self): package = util.create_package( file=data01, path=data01.__file__, contents=['A', 'B', 'C', 'D/E', 'D/F'] ) - with util.suppress_known_deprecation(): - self.assertFalse(resources.is_resource(package, 'D')) + self.assertTrue(resources.files(package).joinpath('D').is_dir()) - def test_resource_missing_is_not_resource(self): + def test_resource_missing(self): package = util.create_package( file=data01, path=data01.__file__, contents=['A', 'B', 'C', 'D/E', 'D/F'] ) - with util.suppress_known_deprecation(): - self.assertFalse(resources.is_resource(package, 'Z')) + self.assertFalse(resources.files(package).joinpath('Z').is_file()) class ResourceCornerCaseTests(unittest.TestCase): @@ -102,8 +82,7 @@ def test_package_has_no_reader_fallback(self): module.__file__ = '/path/which/shall/not/be/named' module.__spec__.loader = module.__loader__ module.__spec__.origin = module.__file__ - with util.suppress_known_deprecation(): - self.assertFalse(resources.is_resource(module, 'A')) + self.assertFalse(resources.files(module).joinpath('A').is_file()) class ResourceFromZipsTest01(util.ZipSetupBase, unittest.TestCase): @@ -111,28 +90,26 @@ class ResourceFromZipsTest01(util.ZipSetupBase, unittest.TestCase): def test_is_submodule_resource(self): submodule = import_module('ziptestdata.subdirectory') - with util.suppress_known_deprecation(): - self.assertTrue(resources.is_resource(submodule, 'binary.file')) + self.assertTrue(resources.files(submodule).joinpath('binary.file').is_file()) def test_read_submodule_resource_by_name(self): - with util.suppress_known_deprecation(): - self.assertTrue( - resources.is_resource('ziptestdata.subdirectory', 'binary.file') - ) + self.assertTrue( + resources.files('ziptestdata.subdirectory') + .joinpath('binary.file') + .is_file() + ) def test_submodule_contents(self): submodule = import_module('ziptestdata.subdirectory') - with util.suppress_known_deprecation(): - self.assertEqual( - set(resources.contents(submodule)), {'__init__.py', 'binary.file'} - ) + self.assertEqual( + names(resources.files(submodule)), {'__init__.py', 'binary.file'} + ) def test_submodule_contents_by_name(self): - with util.suppress_known_deprecation(): - self.assertEqual( - set(resources.contents('ziptestdata.subdirectory')), - {'__init__.py', 'binary.file'}, - ) + self.assertEqual( + names(resources.files('ziptestdata.subdirectory')), + {'__init__.py', 'binary.file'}, + ) class ResourceFromZipsTest02(util.ZipSetupBase, unittest.TestCase): @@ -143,16 +120,14 @@ def test_unrelated_contents(self): Test thata zip with two unrelated subpackages return distinct resources. Ref python/importlib_resources#44. """ - with util.suppress_known_deprecation(): - self.assertEqual( - set(resources.contents('ziptestdata.one')), - {'__init__.py', 'resource1.txt'}, - ) - with util.suppress_known_deprecation(): - self.assertEqual( - set(resources.contents('ziptestdata.two')), - {'__init__.py', 'resource2.txt'}, - ) + self.assertEqual( + names(resources.files('ziptestdata.one')), + {'__init__.py', 'resource1.txt'}, + ) + self.assertEqual( + names(resources.files('ziptestdata.two')), + {'__init__.py', 'resource2.txt'}, + ) class DeletingZipsTest(unittest.TestCase): @@ -192,47 +167,43 @@ def tearDown(self): # If the test fails, this will probably fail too pass - def test_contents_does_not_keep_open(self): - with util.suppress_known_deprecation(): - c = resources.contents('ziptestdata') + def test_iterdir_does_not_keep_open(self): + c = [item.name for item in resources.files('ziptestdata').iterdir()] self.zip_path.unlink() del c - def test_is_resource_does_not_keep_open(self): - with util.suppress_known_deprecation(): - c = resources.is_resource('ziptestdata', 'binary.file') + def test_is_file_does_not_keep_open(self): + c = resources.files('ziptestdata').joinpath('binary.file').is_file() self.zip_path.unlink() del c - def test_is_resource_failure_does_not_keep_open(self): - with util.suppress_known_deprecation(): - c = resources.is_resource('ziptestdata', 'not-present') + def test_is_file_failure_does_not_keep_open(self): + c = resources.files('ziptestdata').joinpath('not-present').is_file() self.zip_path.unlink() del c @unittest.skip("Desired but not supported.") - def test_path_does_not_keep_open(self): - c = resources.path('ziptestdata', 'binary.file') + def test_as_file_does_not_keep_open(self): # pragma: no cover + c = resources.as_file(resources.files('ziptestdata') / 'binary.file') self.zip_path.unlink() del c def test_entered_path_does_not_keep_open(self): # This is what certifi does on import to make its bundle # available for the process duration. - with util.suppress_known_deprecation(): - c = resources.path('ziptestdata', 'binary.file').__enter__() + c = resources.as_file( + resources.files('ziptestdata') / 'binary.file' + ).__enter__() self.zip_path.unlink() del c def test_read_binary_does_not_keep_open(self): - with util.suppress_known_deprecation(): - c = resources.read_binary('ziptestdata', 'binary.file') + c = resources.files('ziptestdata').joinpath('binary.file').read_bytes() self.zip_path.unlink() del c def test_read_text_does_not_keep_open(self): - with util.suppress_known_deprecation(): - c = resources.read_text('ziptestdata', 'utf-8.file', encoding='utf-8') + c = resources.files('ziptestdata').joinpath('utf-8.file').read_text() self.zip_path.unlink() del c @@ -249,18 +220,19 @@ def tearDownClass(cls): sys.path.remove(cls.site_dir) def test_is_submodule_resource(self): - with util.suppress_known_deprecation(): - self.assertTrue( - resources.is_resource(import_module('namespacedata01'), 'binary.file') - ) + self.assertTrue( + resources.files(import_module('namespacedata01')) + .joinpath('binary.file') + .is_file() + ) def test_read_submodule_resource_by_name(self): - with util.suppress_known_deprecation(): - self.assertTrue(resources.is_resource('namespacedata01', 'binary.file')) + self.assertTrue( + resources.files('namespacedata01').joinpath('binary.file').is_file() + ) def test_submodule_contents(self): - with util.suppress_known_deprecation(): - contents = set(resources.contents(import_module('namespacedata01'))) + contents = names(resources.files(import_module('namespacedata01'))) try: contents.remove('__pycache__') except KeyError: @@ -268,8 +240,7 @@ def test_submodule_contents(self): self.assertEqual(contents, {'binary.file', 'utf-8.file', 'utf-16.file'}) def test_submodule_contents_by_name(self): - with util.suppress_known_deprecation(): - contents = set(resources.contents('namespacedata01')) + contents = names(resources.files('namespacedata01')) try: contents.remove('__pycache__') except KeyError: diff --git a/Misc/NEWS.d/next/Library/2021-12-18-18-29-07.bpo-46125.LLmcox.rst b/Misc/NEWS.d/next/Library/2021-12-18-18-29-07.bpo-46125.LLmcox.rst new file mode 100644 index 0000000000000..d2c3a32dfdc13 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-18-18-29-07.bpo-46125.LLmcox.rst @@ -0,0 +1,2 @@ +Refactor tests to test traversable API directly. Includes changes from +importlib 5.4.0. From webhook-mailer at python.org Sun Dec 19 06:23:05 2021 From: webhook-mailer at python.org (asvetlov) Date: Sun, 19 Dec 2021 11:23:05 -0000 Subject: [Python-checkins] bpo-42413: Replace `concurrent.futures.TimeoutError` and `asyncio.TimeoutError` with builtin `TimeoutError` (GH-30197) Message-ID: https://github.com/python/cpython/commit/da4b214304df38cf1831071804a2b83938f95923 commit: da4b214304df38cf1831071804a2b83938f95923 branch: main author: Kumar Aditya <59607654+kumaraditya303 at users.noreply.github.com> committer: asvetlov date: 2021-12-19T13:22:40+02:00 summary: bpo-42413: Replace `concurrent.futures.TimeoutError` and `asyncio.TimeoutError` with builtin `TimeoutError` (GH-30197) Co-authored-by: Andrew Svetlov files: A Misc/NEWS.d/next/Library/2020-11-26-10-23-46.bpo-42413.HFikOl.rst M Doc/library/asyncio-api-index.rst M Doc/library/asyncio-exceptions.rst M Doc/library/asyncio-task.rst M Doc/library/concurrent.futures.rst M Lib/asyncio/exceptions.py M Lib/concurrent/futures/_base.py diff --git a/Doc/library/asyncio-api-index.rst b/Doc/library/asyncio-api-index.rst index f558724d4a3ff..8bc7943a71739 100644 --- a/Doc/library/asyncio-api-index.rst +++ b/Doc/library/asyncio-api-index.rst @@ -203,11 +203,6 @@ Exceptions :class: full-width-table - * - :exc:`asyncio.TimeoutError` - - Raised on timeout by functions like :func:`wait_for`. - Keep in mind that ``asyncio.TimeoutError`` is **unrelated** - to the built-in :exc:`TimeoutError` exception. - * - :exc:`asyncio.CancelledError` - Raised when a Task is cancelled. See also :meth:`Task.cancel`. diff --git a/Doc/library/asyncio-exceptions.rst b/Doc/library/asyncio-exceptions.rst index 7166d5c4bd88f..9250f01b8a089 100644 --- a/Doc/library/asyncio-exceptions.rst +++ b/Doc/library/asyncio-exceptions.rst @@ -13,11 +13,12 @@ Exceptions .. exception:: TimeoutError - The operation has exceeded the given deadline. + A deprecated alias of :exc:`TimeoutError`, + raised when the operation has exceeded the given deadline. - .. important:: - This exception is different from the builtin :exc:`TimeoutError` - exception. + .. versionchanged:: 3.11 + + This class was made an alias of :exc:`TimeoutError`. .. exception:: CancelledError diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index bfc983e304bcc..cbc42ac26e48c 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -490,7 +490,7 @@ Timeouts completes. If a timeout occurs, it cancels the task and raises - :exc:`asyncio.TimeoutError`. + :exc:`TimeoutError`. To avoid the task :meth:`cancellation `, wrap it in :func:`shield`. @@ -520,7 +520,7 @@ Timeouts # Wait for at most 1 second try: await asyncio.wait_for(eternity(), timeout=1.0) - except asyncio.TimeoutError: + except TimeoutError: print('timeout!') asyncio.run(main()) @@ -532,7 +532,7 @@ Timeouts .. versionchanged:: 3.7 When *aw* is cancelled due to a timeout, ``wait_for`` waits for *aw* to be cancelled. Previously, it raised - :exc:`asyncio.TimeoutError` immediately. + :exc:`TimeoutError` immediately. .. deprecated-removed:: 3.8 3.10 The ``loop`` parameter. This function has been implicitly getting the @@ -561,7 +561,7 @@ Waiting Primitives *timeout* (a float or int), if specified, can be used to control the maximum number of seconds to wait before returning. - Note that this function does not raise :exc:`asyncio.TimeoutError`. + Note that this function does not raise :exc:`TimeoutError`. Futures or Tasks that aren't done when the timeout occurs are simply returned in the second set. @@ -649,7 +649,7 @@ Waiting Primitives Each coroutine returned can be awaited to get the earliest next result from the iterable of the remaining awaitables. - Raises :exc:`asyncio.TimeoutError` if the timeout occurs before + Raises :exc:`TimeoutError` if the timeout occurs before all Futures are done. .. deprecated-removed:: 3.8 3.10 @@ -762,7 +762,7 @@ Scheduling From Other Threads try: result = future.result(timeout) - except concurrent.futures.TimeoutError: + except TimeoutError: print('The coroutine took too long, cancelling the task...') future.cancel() except Exception as exc: diff --git a/Doc/library/concurrent.futures.rst b/Doc/library/concurrent.futures.rst index b4213b451157e..c9f6aa1f2637c 100644 --- a/Doc/library/concurrent.futures.rst +++ b/Doc/library/concurrent.futures.rst @@ -47,7 +47,7 @@ Executor Objects * *func* is executed asynchronously and several calls to *func* may be made concurrently. - The returned iterator raises a :exc:`concurrent.futures.TimeoutError` + The returned iterator raises a :exc:`TimeoutError` if :meth:`~iterator.__next__` is called and the result isn't available after *timeout* seconds from the original call to :meth:`Executor.map`. *timeout* can be an int or a float. If *timeout* is not specified or @@ -352,7 +352,7 @@ The :class:`Future` class encapsulates the asynchronous execution of a callable. Return the value returned by the call. If the call hasn't yet completed then this method will wait up to *timeout* seconds. If the call hasn't completed in *timeout* seconds, then a - :exc:`concurrent.futures.TimeoutError` will be raised. *timeout* can be + :exc:`TimeoutError` will be raised. *timeout* can be an int or float. If *timeout* is not specified or ``None``, there is no limit to the wait time. @@ -366,7 +366,7 @@ The :class:`Future` class encapsulates the asynchronous execution of a callable. Return the exception raised by the call. If the call hasn't yet completed then this method will wait up to *timeout* seconds. If the call hasn't completed in *timeout* seconds, then a - :exc:`concurrent.futures.TimeoutError` will be raised. *timeout* can be + :exc:`TimeoutError` will be raised. *timeout* can be an int or float. If *timeout* is not specified or ``None``, there is no limit to the wait time. @@ -482,7 +482,7 @@ Module Functions they complete (finished or cancelled futures). Any futures given by *fs* that are duplicated will be returned once. Any futures that completed before :func:`as_completed` is called will be yielded first. The returned iterator - raises a :exc:`concurrent.futures.TimeoutError` if :meth:`~iterator.__next__` + raises a :exc:`TimeoutError` if :meth:`~iterator.__next__` is called and the result isn't available after *timeout* seconds from the original call to :func:`as_completed`. *timeout* can be an int or float. If *timeout* is not specified or ``None``, there is no limit to the wait time. @@ -506,7 +506,13 @@ Exception classes .. exception:: TimeoutError - Raised when a future operation exceeds the given timeout. + A deprecated alias of :exc:`TimeoutError`, + raised when a future operation exceeds the given timeout. + + .. versionchanged:: 3.11 + + This class was made an alias of :exc:`TimeoutError`. + .. exception:: BrokenExecutor diff --git a/Lib/asyncio/exceptions.py b/Lib/asyncio/exceptions.py index f07e448657738..c764c9ffcfc19 100644 --- a/Lib/asyncio/exceptions.py +++ b/Lib/asyncio/exceptions.py @@ -10,8 +10,7 @@ class CancelledError(BaseException): """The Future or Task was cancelled.""" -class TimeoutError(Exception): - """The operation exceeded the given deadline.""" +TimeoutError = TimeoutError # make local alias for the standard exception class InvalidStateError(Exception): diff --git a/Lib/concurrent/futures/_base.py b/Lib/concurrent/futures/_base.py index 6095026cb278b..b0337399e5f25 100644 --- a/Lib/concurrent/futures/_base.py +++ b/Lib/concurrent/futures/_base.py @@ -50,9 +50,7 @@ class CancelledError(Error): """The Future was cancelled.""" pass -class TimeoutError(Error): - """The operation exceeded the given deadline.""" - pass +TimeoutError = TimeoutError # make local alias for the standard exception class InvalidStateError(Error): """The operation is not allowed in this state.""" diff --git a/Misc/NEWS.d/next/Library/2020-11-26-10-23-46.bpo-42413.HFikOl.rst b/Misc/NEWS.d/next/Library/2020-11-26-10-23-46.bpo-42413.HFikOl.rst new file mode 100644 index 0000000000000..85b7fe25074b3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-11-26-10-23-46.bpo-42413.HFikOl.rst @@ -0,0 +1,2 @@ +Replace ``concurrent.futures.TimeoutError`` and ``asyncio.TimeoutError`` +with builtin :exc:`TimeoutError`, keep these names as deprecated aliases. From webhook-mailer at python.org Sun Dec 19 09:06:51 2021 From: webhook-mailer at python.org (Fidget-Spinner) Date: Sun, 19 Dec 2021 14:06:51 -0000 Subject: [Python-checkins] bpo-46130: [docs] Add anchor for whatsnew/3.10 type hint section (GH-30199) Message-ID: https://github.com/python/cpython/commit/3d3615f41f4ea73fe6707eb3673dfab482cb6a2b commit: 3d3615f41f4ea73fe6707eb3673dfab482cb6a2b branch: main author: Rafael Fontenelle committer: Fidget-Spinner <28750310+Fidget-Spinner at users.noreply.github.com> date: 2021-12-19T22:06:35+08:00 summary: bpo-46130: [docs] Add anchor for whatsnew/3.10 type hint section (GH-30199) This allows the title to be translated to other languages without linking problems. files: M Doc/whatsnew/3.10.rst diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index 118563965091f..b56663f5eae8b 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -704,6 +704,7 @@ are added to enable the warning. See :ref:`io-text-encoding` for more information. +.. _new-feat-related-type-hints: New Features Related to Type Hints ================================== @@ -1429,7 +1430,7 @@ of types readily interpretable by type checkers. typing ------ -For major changes, see `New Features Related to Type Hints`_. +For major changes, see :ref:`new-feat-related-type-hints`. The behavior of :class:`typing.Literal` was changed to conform with :pep:`586` and to match the behavior of static type checkers specified in the PEP. From webhook-mailer at python.org Sun Dec 19 09:33:11 2021 From: webhook-mailer at python.org (miss-islington) Date: Sun, 19 Dec 2021 14:33:11 -0000 Subject: [Python-checkins] bpo-46130: [docs] Add anchor for whatsnew/3.10 type hint section (GH-30199) Message-ID: https://github.com/python/cpython/commit/9a28cf19b5d5f79eb072afc582f7baa9e7bd3ac2 commit: 9a28cf19b5d5f79eb072afc582f7baa9e7bd3ac2 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-19T06:32:49-08:00 summary: bpo-46130: [docs] Add anchor for whatsnew/3.10 type hint section (GH-30199) This allows the title to be translated to other languages without linking problems. (cherry picked from commit 3d3615f41f4ea73fe6707eb3673dfab482cb6a2b) Co-authored-by: Rafael Fontenelle files: M Doc/whatsnew/3.10.rst diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index c74e9f0ae5cb6..978651f33b206 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -704,6 +704,7 @@ are added to enable the warning. See :ref:`io-text-encoding` for more information. +.. _new-feat-related-type-hints: New Features Related to Type Hints ================================== @@ -1418,7 +1419,7 @@ of types readily interpretable by type checkers. typing ------ -For major changes, see `New Features Related to Type Hints`_. +For major changes, see :ref:`new-feat-related-type-hints`. The behavior of :class:`typing.Literal` was changed to conform with :pep:`586` and to match the behavior of static type checkers specified in the PEP. From webhook-mailer at python.org Sun Dec 19 09:36:07 2021 From: webhook-mailer at python.org (asvetlov) Date: Sun, 19 Dec 2021 14:36:07 -0000 Subject: [Python-checkins] bpo-46129: Rewrite asyncio.locks tests with IsolatedAsyncioTestCase (GH-30198) Message-ID: https://github.com/python/cpython/commit/9c06fd89514a9a2865e2adcc472095f6949cecb2 commit: 9c06fd89514a9a2865e2adcc472095f6949cecb2 branch: main author: Andrew Svetlov committer: asvetlov date: 2021-12-19T16:35:56+02:00 summary: bpo-46129: Rewrite asyncio.locks tests with IsolatedAsyncioTestCase (GH-30198) Co-authored-by: Kumar Aditya <59607654+kumaraditya303 at users.noreply.github.com> files: A Misc/NEWS.d/next/Tests/2021-12-19-12-20-57.bpo-46129.I3MunH.rst M Lib/test/test_asyncio/test_locks.py M Lib/unittest/async_case.py diff --git a/Lib/test/test_asyncio/test_locks.py b/Lib/test/test_asyncio/test_locks.py index b2492c1acfece..4ce338774f748 100644 --- a/Lib/test/test_asyncio/test_locks.py +++ b/Lib/test/test_asyncio/test_locks.py @@ -5,7 +5,6 @@ import re import asyncio -from test.test_asyncio import utils as test_utils STR_RGX_REPR = ( r'^<(?P.*?) object at (?P
.*?)' @@ -20,36 +19,29 @@ def tearDownModule(): asyncio.set_event_loop_policy(None) -class LockTests(test_utils.TestCase): +class LockTests(unittest.IsolatedAsyncioTestCase): - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() - - def test_repr(self): + async def test_repr(self): lock = asyncio.Lock() self.assertTrue(repr(lock).endswith('[unlocked]>')) self.assertTrue(RGX_REPR.match(repr(lock))) - self.loop.run_until_complete(lock.acquire()) + await lock.acquire() self.assertTrue(repr(lock).endswith('[locked]>')) self.assertTrue(RGX_REPR.match(repr(lock))) - def test_lock(self): + async def test_lock(self): lock = asyncio.Lock() - async def acquire_lock(): - return await lock - with self.assertRaisesRegex( TypeError, "object Lock can't be used in 'await' expression" ): - self.loop.run_until_complete(acquire_lock()) + await lock self.assertFalse(lock.locked()) - def test_lock_doesnt_accept_loop_parameter(self): + async def test_lock_doesnt_accept_loop_parameter(self): primitives_cls = [ asyncio.Lock, asyncio.Condition, @@ -58,17 +50,17 @@ def test_lock_doesnt_accept_loop_parameter(self): asyncio.BoundedSemaphore, ] + loop = asyncio.get_running_loop() + for cls in primitives_cls: with self.assertRaisesRegex( TypeError, rf'As of 3.10, the \*loop\* parameter was removed from ' rf'{cls.__name__}\(\) since it is no longer necessary' ): - cls(loop=self.loop) + cls(loop=loop) - def test_lock_by_with_statement(self): - loop = asyncio.new_event_loop() # don't use TestLoop quirks - self.set_event_loop(loop) + async def test_lock_by_with_statement(self): primitives = [ asyncio.Lock(), asyncio.Condition(), @@ -76,7 +68,7 @@ def test_lock_by_with_statement(self): asyncio.BoundedSemaphore(), ] - async def test(lock): + for lock in primitives: await asyncio.sleep(0.01) self.assertFalse(lock.locked()) with self.assertRaisesRegex( @@ -87,15 +79,11 @@ async def test(lock): pass self.assertFalse(lock.locked()) - for primitive in primitives: - loop.run_until_complete(test(primitive)) - self.assertFalse(primitive.locked()) - - def test_acquire(self): + async def test_acquire(self): lock = asyncio.Lock() result = [] - self.assertTrue(self.loop.run_until_complete(lock.acquire())) + self.assertTrue(await lock.acquire()) async def c1(result): if await lock.acquire(): @@ -112,27 +100,27 @@ async def c3(result): result.append(3) return True - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) + t1 = asyncio.create_task(c1(result)) + t2 = asyncio.create_task(c2(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) lock.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) - t3 = self.loop.create_task(c3(result)) + t3 = asyncio.create_task(c3(result)) lock.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1, 2], result) lock.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1, 2, 3], result) self.assertTrue(t1.done()) @@ -142,18 +130,17 @@ async def c3(result): self.assertTrue(t3.done()) self.assertTrue(t3.result()) - def test_acquire_cancel(self): + async def test_acquire_cancel(self): lock = asyncio.Lock() - self.assertTrue(self.loop.run_until_complete(lock.acquire())) + self.assertTrue(await lock.acquire()) - task = self.loop.create_task(lock.acquire()) - self.loop.call_soon(task.cancel) - self.assertRaises( - asyncio.CancelledError, - self.loop.run_until_complete, task) + task = asyncio.create_task(lock.acquire()) + asyncio.get_running_loop().call_soon(task.cancel) + with self.assertRaises(asyncio.CancelledError): + await task self.assertFalse(lock._waiters) - def test_cancel_race(self): + async def test_cancel_race(self): # Several tasks: # - A acquires the lock # - B is blocked in acquire() @@ -178,15 +165,15 @@ async def lockit(name, blocker): finally: lock.release() - fa = self.loop.create_future() - ta = self.loop.create_task(lockit('A', fa)) - test_utils.run_briefly(self.loop) + fa = asyncio.get_running_loop().create_future() + ta = asyncio.create_task(lockit('A', fa)) + await asyncio.sleep(0) self.assertTrue(lock.locked()) - tb = self.loop.create_task(lockit('B', None)) - test_utils.run_briefly(self.loop) + tb = asyncio.create_task(lockit('B', None)) + await asyncio.sleep(0) self.assertEqual(len(lock._waiters), 1) - tc = self.loop.create_task(lockit('C', None)) - test_utils.run_briefly(self.loop) + tc = asyncio.create_task(lockit('C', None)) + await asyncio.sleep(0) self.assertEqual(len(lock._waiters), 2) # Create the race and check. @@ -194,16 +181,17 @@ async def lockit(name, blocker): fa.set_result(None) tb.cancel() self.assertTrue(lock._waiters[0].cancelled()) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertFalse(lock.locked()) self.assertTrue(ta.done()) self.assertTrue(tb.cancelled()) - self.assertTrue(tc.done()) + await tc - def test_cancel_release_race(self): + async def test_cancel_release_race(self): # Issue 32734 # Acquire 4 locks, cancel second, release first # and 2 locks are taken at once. + loop = asyncio.get_running_loop() lock = asyncio.Lock() lock_count = 0 call_count = 0 @@ -215,27 +203,23 @@ async def lockit(): await lock.acquire() lock_count += 1 - async def lockandtrigger(): - await lock.acquire() - self.loop.call_soon(trigger) - def trigger(): t1.cancel() lock.release() - t0 = self.loop.create_task(lockandtrigger()) - t1 = self.loop.create_task(lockit()) - t2 = self.loop.create_task(lockit()) - t3 = self.loop.create_task(lockit()) + await lock.acquire() + + t1 = asyncio.create_task(lockit()) + t2 = asyncio.create_task(lockit()) + t3 = asyncio.create_task(lockit()) - # First loop acquires all - test_utils.run_briefly(self.loop) - self.assertTrue(t0.done()) + # Start scheduled tasks + await asyncio.sleep(0) - # Second loop calls trigger - test_utils.run_briefly(self.loop) - # Third loop calls cancellation - test_utils.run_briefly(self.loop) + loop.call_soon(trigger) + with self.assertRaises(asyncio.CancelledError): + # Wait for cancellation + await t1 # Make sure only one lock was taken self.assertEqual(lock_count, 1) @@ -245,62 +229,56 @@ def trigger(): # Cleanup the task that is stuck on acquire. t3.cancel() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertTrue(t3.cancelled()) - def test_finished_waiter_cancelled(self): + async def test_finished_waiter_cancelled(self): lock = asyncio.Lock() - ta = self.loop.create_task(lock.acquire()) - test_utils.run_briefly(self.loop) + await lock.acquire() self.assertTrue(lock.locked()) - tb = self.loop.create_task(lock.acquire()) - test_utils.run_briefly(self.loop) + tb = asyncio.create_task(lock.acquire()) + await asyncio.sleep(0) self.assertEqual(len(lock._waiters), 1) # Create a second waiter, wake up the first, and cancel it. # Without the fix, the second was not woken up. - tc = self.loop.create_task(lock.acquire()) - lock.release() + tc = asyncio.create_task(lock.acquire()) tb.cancel() - test_utils.run_briefly(self.loop) + lock.release() + await asyncio.sleep(0) self.assertTrue(lock.locked()) - self.assertTrue(ta.done()) self.assertTrue(tb.cancelled()) - def test_release_not_acquired(self): + # Cleanup + await tc + + async def test_release_not_acquired(self): lock = asyncio.Lock() self.assertRaises(RuntimeError, lock.release) - def test_release_no_waiters(self): + async def test_release_no_waiters(self): lock = asyncio.Lock() - self.loop.run_until_complete(lock.acquire()) + await lock.acquire() self.assertTrue(lock.locked()) lock.release() self.assertFalse(lock.locked()) - def test_context_manager(self): - async def f(): - lock = asyncio.Lock() - self.assertFalse(lock.locked()) - - async with lock: - self.assertTrue(lock.locked()) - - self.assertFalse(lock.locked()) + async def test_context_manager(self): + lock = asyncio.Lock() + self.assertFalse(lock.locked()) - self.loop.run_until_complete(f()) + async with lock: + self.assertTrue(lock.locked()) + self.assertFalse(lock.locked()) -class EventTests(test_utils.TestCase): - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() +class EventTests(unittest.IsolatedAsyncioTestCase): def test_repr(self): ev = asyncio.Event() @@ -316,7 +294,7 @@ def test_repr(self): self.assertTrue('waiters:1' in repr(ev)) self.assertTrue(RGX_REPR.match(repr(ev))) - def test_wait(self): + async def test_wait(self): ev = asyncio.Event() self.assertFalse(ev.is_set()) @@ -334,16 +312,16 @@ async def c3(result): if await ev.wait(): result.append(3) - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) + t1 = asyncio.create_task(c1(result)) + t2 = asyncio.create_task(c2(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) - t3 = self.loop.create_task(c3(result)) + t3 = asyncio.create_task(c3(result)) ev.set() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([3, 1, 2], result) self.assertTrue(t1.done()) @@ -353,24 +331,23 @@ async def c3(result): self.assertTrue(t3.done()) self.assertIsNone(t3.result()) - def test_wait_on_set(self): + async def test_wait_on_set(self): ev = asyncio.Event() ev.set() - res = self.loop.run_until_complete(ev.wait()) + res = await ev.wait() self.assertTrue(res) - def test_wait_cancel(self): + async def test_wait_cancel(self): ev = asyncio.Event() - wait = self.loop.create_task(ev.wait()) - self.loop.call_soon(wait.cancel) - self.assertRaises( - asyncio.CancelledError, - self.loop.run_until_complete, wait) + wait = asyncio.create_task(ev.wait()) + asyncio.get_running_loop().call_soon(wait.cancel) + with self.assertRaises(asyncio.CancelledError): + await wait self.assertFalse(ev._waiters) - def test_clear(self): + async def test_clear(self): ev = asyncio.Event() self.assertFalse(ev.is_set()) @@ -380,7 +357,7 @@ def test_clear(self): ev.clear() self.assertFalse(ev.is_set()) - def test_clear_with_waiters(self): + async def test_clear_with_waiters(self): ev = asyncio.Event() result = [] @@ -389,8 +366,8 @@ async def c1(result): result.append(1) return True - t = self.loop.create_task(c1(result)) - test_utils.run_briefly(self.loop) + t = asyncio.create_task(c1(result)) + await asyncio.sleep(0) self.assertEqual([], result) ev.set() @@ -401,7 +378,7 @@ async def c1(result): ev.set() self.assertEqual(1, len(ev._waiters)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) self.assertEqual(0, len(ev._waiters)) @@ -409,13 +386,9 @@ async def c1(result): self.assertTrue(t.result()) -class ConditionTests(test_utils.TestCase): - - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() +class ConditionTests(unittest.IsolatedAsyncioTestCase): - def test_wait(self): + async def test_wait(self): cond = asyncio.Condition() result = [] @@ -437,37 +410,37 @@ async def c3(result): result.append(3) return True - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) - t3 = self.loop.create_task(c3(result)) + t1 = asyncio.create_task(c1(result)) + t2 = asyncio.create_task(c2(result)) + t3 = asyncio.create_task(c3(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) self.assertFalse(cond.locked()) - self.assertTrue(self.loop.run_until_complete(cond.acquire())) + self.assertTrue(await cond.acquire()) cond.notify() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) self.assertTrue(cond.locked()) cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) self.assertTrue(cond.locked()) cond.notify(2) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) self.assertTrue(cond.locked()) cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1, 2], result) self.assertTrue(cond.locked()) cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1, 2, 3], result) self.assertTrue(cond.locked()) @@ -478,49 +451,47 @@ async def c3(result): self.assertTrue(t3.done()) self.assertTrue(t3.result()) - def test_wait_cancel(self): + async def test_wait_cancel(self): cond = asyncio.Condition() - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() - wait = self.loop.create_task(cond.wait()) - self.loop.call_soon(wait.cancel) - self.assertRaises( - asyncio.CancelledError, - self.loop.run_until_complete, wait) + wait = asyncio.create_task(cond.wait()) + asyncio.get_running_loop().call_soon(wait.cancel) + with self.assertRaises(asyncio.CancelledError): + await wait self.assertFalse(cond._waiters) self.assertTrue(cond.locked()) - def test_wait_cancel_contested(self): + async def test_wait_cancel_contested(self): cond = asyncio.Condition() - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() self.assertTrue(cond.locked()) - wait_task = self.loop.create_task(cond.wait()) - test_utils.run_briefly(self.loop) + wait_task = asyncio.create_task(cond.wait()) + await asyncio.sleep(0) self.assertFalse(cond.locked()) # Notify, but contest the lock before cancelling - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() self.assertTrue(cond.locked()) cond.notify() - self.loop.call_soon(wait_task.cancel) - self.loop.call_soon(cond.release) + asyncio.get_running_loop().call_soon(wait_task.cancel) + asyncio.get_running_loop().call_soon(cond.release) try: - self.loop.run_until_complete(wait_task) + await wait_task except asyncio.CancelledError: # Should not happen, since no cancellation points pass self.assertTrue(cond.locked()) - def test_wait_cancel_after_notify(self): + async def test_wait_cancel_after_notify(self): # See bpo-32841 waited = False cond = asyncio.Condition() - cond._loop = self.loop async def wait_on_cond(): nonlocal waited @@ -528,27 +499,26 @@ async def wait_on_cond(): waited = True # Make sure this area was reached await cond.wait() - waiter = asyncio.ensure_future(wait_on_cond(), loop=self.loop) - test_utils.run_briefly(self.loop) # Start waiting + waiter = asyncio.create_task(wait_on_cond()) + await asyncio.sleep(0) # Start waiting - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() cond.notify() - test_utils.run_briefly(self.loop) # Get to acquire() + await asyncio.sleep(0) # Get to acquire() waiter.cancel() - test_utils.run_briefly(self.loop) # Activate cancellation + await asyncio.sleep(0) # Activate cancellation cond.release() - test_utils.run_briefly(self.loop) # Cancellation should occur + await asyncio.sleep(0) # Cancellation should occur self.assertTrue(waiter.cancelled()) self.assertTrue(waited) - def test_wait_unacquired(self): + async def test_wait_unacquired(self): cond = asyncio.Condition() - self.assertRaises( - RuntimeError, - self.loop.run_until_complete, cond.wait()) + with self.assertRaises(RuntimeError): + await cond.wait() - def test_wait_for(self): + async def test_wait_for(self): cond = asyncio.Condition() presult = False @@ -564,40 +534,38 @@ async def c1(result): cond.release() return True - t = self.loop.create_task(c1(result)) + t = asyncio.create_task(c1(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() cond.notify() cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) presult = True - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() cond.notify() cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) self.assertTrue(t.done()) self.assertTrue(t.result()) - def test_wait_for_unacquired(self): + async def test_wait_for_unacquired(self): cond = asyncio.Condition() # predicate can return true immediately - res = self.loop.run_until_complete(cond.wait_for(lambda: [1, 2, 3])) + res = await cond.wait_for(lambda: [1, 2, 3]) self.assertEqual([1, 2, 3], res) - self.assertRaises( - RuntimeError, - self.loop.run_until_complete, - cond.wait_for(lambda: False)) + with self.assertRaises(RuntimeError): + await cond.wait_for(lambda: False) - def test_notify(self): + async def test_notify(self): cond = asyncio.Condition() result = [] @@ -622,24 +590,24 @@ async def c3(result): cond.release() return True - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) - t3 = self.loop.create_task(c3(result)) + t1 = asyncio.create_task(c1(result)) + t2 = asyncio.create_task(c2(result)) + t3 = asyncio.create_task(c3(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() cond.notify(1) cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() cond.notify(1) cond.notify(2048) cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1, 2, 3], result) self.assertTrue(t1.done()) @@ -649,7 +617,7 @@ async def c3(result): self.assertTrue(t3.done()) self.assertTrue(t3.result()) - def test_notify_all(self): + async def test_notify_all(self): cond = asyncio.Condition() result = [] @@ -668,16 +636,16 @@ async def c2(result): cond.release() return True - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) + t1 = asyncio.create_task(c1(result)) + t2 = asyncio.create_task(c2(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() cond.notify_all() cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1, 2], result) self.assertTrue(t1.done()) @@ -693,12 +661,12 @@ def test_notify_all_unacquired(self): cond = asyncio.Condition() self.assertRaises(RuntimeError, cond.notify_all) - def test_repr(self): + async def test_repr(self): cond = asyncio.Condition() self.assertTrue('unlocked' in repr(cond)) self.assertTrue(RGX_REPR.match(repr(cond))) - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() self.assertTrue('locked' in repr(cond)) cond._waiters.append(mock.Mock()) @@ -709,17 +677,14 @@ def test_repr(self): self.assertTrue('waiters:2' in repr(cond)) self.assertTrue(RGX_REPR.match(repr(cond))) - def test_context_manager(self): - async def f(): - cond = asyncio.Condition() - self.assertFalse(cond.locked()) - async with cond: - self.assertTrue(cond.locked()) - self.assertFalse(cond.locked()) - - self.loop.run_until_complete(f()) + async def test_context_manager(self): + cond = asyncio.Condition() + self.assertFalse(cond.locked()) + async with cond: + self.assertTrue(cond.locked()) + self.assertFalse(cond.locked()) - def test_explicit_lock(self): + async def test_explicit_lock(self): async def f(lock=None, cond=None): if lock is None: lock = asyncio.Lock() @@ -740,12 +705,12 @@ async def f(lock=None, cond=None): self.assertFalse(cond.locked()) # All should work in the same way. - self.loop.run_until_complete(f()) - self.loop.run_until_complete(f(asyncio.Lock())) + await f() + await f(asyncio.Lock()) lock = asyncio.Lock() - self.loop.run_until_complete(f(lock, asyncio.Condition(lock))) + await f(lock, asyncio.Condition(lock)) - def test_ambiguous_loops(self): + async def test_ambiguous_loops(self): loop = asyncio.new_event_loop() self.addCleanup(loop.close) @@ -780,38 +745,28 @@ async def wrong_loop_in_cond(): ): await cond.wait() - self.loop.run_until_complete(wrong_loop_in_lock()) - self.loop.run_until_complete(wrong_loop_in_cond()) - - def test_timeout_in_block(self): - loop = asyncio.new_event_loop() - self.addCleanup(loop.close) - - async def task_timeout(): - condition = asyncio.Condition() - async with condition: - with self.assertRaises(asyncio.TimeoutError): - await asyncio.wait_for(condition.wait(), timeout=0.5) - - loop.run_until_complete(task_timeout()) + await wrong_loop_in_lock() + await wrong_loop_in_cond() + async def test_timeout_in_block(self): + condition = asyncio.Condition() + async with condition: + with self.assertRaises(asyncio.TimeoutError): + await asyncio.wait_for(condition.wait(), timeout=0.5) -class SemaphoreTests(test_utils.TestCase): - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() +class SemaphoreTests(unittest.IsolatedAsyncioTestCase): def test_initial_value_zero(self): sem = asyncio.Semaphore(0) self.assertTrue(sem.locked()) - def test_repr(self): + async def test_repr(self): sem = asyncio.Semaphore() self.assertTrue(repr(sem).endswith('[unlocked, value:1]>')) self.assertTrue(RGX_REPR.match(repr(sem))) - self.loop.run_until_complete(sem.acquire()) + await sem.acquire() self.assertTrue(repr(sem).endswith('[locked]>')) self.assertTrue('waiters' not in repr(sem)) self.assertTrue(RGX_REPR.match(repr(sem))) @@ -824,18 +779,15 @@ def test_repr(self): self.assertTrue('waiters:2' in repr(sem)) self.assertTrue(RGX_REPR.match(repr(sem))) - def test_semaphore(self): + async def test_semaphore(self): sem = asyncio.Semaphore() self.assertEqual(1, sem._value) - async def acquire_lock(): - return await sem - with self.assertRaisesRegex( TypeError, "object Semaphore can't be used in 'await' expression", ): - self.loop.run_until_complete(acquire_lock()) + await sem self.assertFalse(sem.locked()) self.assertEqual(1, sem._value) @@ -843,12 +795,12 @@ async def acquire_lock(): def test_semaphore_value(self): self.assertRaises(ValueError, asyncio.Semaphore, -1) - def test_acquire(self): + async def test_acquire(self): sem = asyncio.Semaphore(3) result = [] - self.assertTrue(self.loop.run_until_complete(sem.acquire())) - self.assertTrue(self.loop.run_until_complete(sem.acquire())) + self.assertTrue(await sem.acquire()) + self.assertTrue(await sem.acquire()) self.assertFalse(sem.locked()) async def c1(result): @@ -871,23 +823,23 @@ async def c4(result): result.append(4) return True - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) - t3 = self.loop.create_task(c3(result)) + t1 = asyncio.create_task(c1(result)) + t2 = asyncio.create_task(c2(result)) + t3 = asyncio.create_task(c3(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) self.assertTrue(sem.locked()) self.assertEqual(2, len(sem._waiters)) self.assertEqual(0, sem._value) - t4 = self.loop.create_task(c4(result)) + t4 = asyncio.create_task(c4(result)) sem.release() sem.release() self.assertEqual(2, sem._value) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual(0, sem._value) self.assertEqual(3, len(result)) self.assertTrue(sem.locked()) @@ -902,64 +854,64 @@ async def c4(result): # cleanup locked semaphore sem.release() - self.loop.run_until_complete(asyncio.gather(*race_tasks)) + await asyncio.gather(*race_tasks) - def test_acquire_cancel(self): + async def test_acquire_cancel(self): sem = asyncio.Semaphore() - self.loop.run_until_complete(sem.acquire()) + await sem.acquire() - acquire = self.loop.create_task(sem.acquire()) - self.loop.call_soon(acquire.cancel) - self.assertRaises( - asyncio.CancelledError, - self.loop.run_until_complete, acquire) + acquire = asyncio.create_task(sem.acquire()) + asyncio.get_running_loop().call_soon(acquire.cancel) + with self.assertRaises(asyncio.CancelledError): + await acquire self.assertTrue((not sem._waiters) or all(waiter.done() for waiter in sem._waiters)) - def test_acquire_cancel_before_awoken(self): + async def test_acquire_cancel_before_awoken(self): sem = asyncio.Semaphore(value=0) - t1 = self.loop.create_task(sem.acquire()) - t2 = self.loop.create_task(sem.acquire()) - t3 = self.loop.create_task(sem.acquire()) - t4 = self.loop.create_task(sem.acquire()) + t1 = asyncio.create_task(sem.acquire()) + t2 = asyncio.create_task(sem.acquire()) + t3 = asyncio.create_task(sem.acquire()) + t4 = asyncio.create_task(sem.acquire()) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) - sem.release() t1.cancel() t2.cancel() + sem.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) num_done = sum(t.done() for t in [t3, t4]) self.assertEqual(num_done, 1) + self.assertTrue(t3.done()) + self.assertFalse(t4.done()) t3.cancel() t4.cancel() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) - def test_acquire_hang(self): + async def test_acquire_hang(self): sem = asyncio.Semaphore(value=0) - t1 = self.loop.create_task(sem.acquire()) - t2 = self.loop.create_task(sem.acquire()) - - test_utils.run_briefly(self.loop) + t1 = asyncio.create_task(sem.acquire()) + t2 = asyncio.create_task(sem.acquire()) + await asyncio.sleep(0) - sem.release() t1.cancel() - - test_utils.run_briefly(self.loop) + sem.release() + await asyncio.sleep(0) self.assertTrue(sem.locked()) + self.assertTrue(t2.done()) def test_release_not_acquired(self): sem = asyncio.BoundedSemaphore() self.assertRaises(ValueError, sem.release) - def test_release_no_waiters(self): + async def test_release_no_waiters(self): sem = asyncio.Semaphore() - self.loop.run_until_complete(sem.acquire()) + await sem.acquire() self.assertTrue(sem.locked()) sem.release() diff --git a/Lib/unittest/async_case.py b/Lib/unittest/async_case.py index d8bfaf6b67e00..3c57bb5cda2c0 100644 --- a/Lib/unittest/async_case.py +++ b/Lib/unittest/async_case.py @@ -5,7 +5,6 @@ from .case import TestCase - class IsolatedAsyncioTestCase(TestCase): # Names intentionally have a long prefix # to reduce a chance of clashing with user-defined attributes diff --git a/Misc/NEWS.d/next/Tests/2021-12-19-12-20-57.bpo-46129.I3MunH.rst b/Misc/NEWS.d/next/Tests/2021-12-19-12-20-57.bpo-46129.I3MunH.rst new file mode 100644 index 0000000000000..b06436a4c8460 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-12-19-12-20-57.bpo-46129.I3MunH.rst @@ -0,0 +1,2 @@ +Rewrite ``asyncio.locks`` tests with +:class:`unittest.IsolatedAsyncioTestCase` usage. From webhook-mailer at python.org Sun Dec 19 09:55:17 2021 From: webhook-mailer at python.org (zooba) Date: Sun, 19 Dec 2021 14:55:17 -0000 Subject: [Python-checkins] bpo-46123: Disable optimizations for _freeze_module.exe on MSVC for faster building (GH-30181) Message-ID: https://github.com/python/cpython/commit/0b582a4a1b24472a35ed7fc973728ac9d595f123 commit: 0b582a4a1b24472a35ed7fc973728ac9d595f123 branch: main author: neonene <53406459+neonene at users.noreply.github.com> committer: zooba date: 2021-12-19T14:55:13Z summary: bpo-46123: Disable optimizations for _freeze_module.exe on MSVC for faster building (GH-30181) files: M PCbuild/_freeze_module.vcxproj diff --git a/PCbuild/_freeze_module.vcxproj b/PCbuild/_freeze_module.vcxproj index 42798bf8113c7..59519cade2670 100644 --- a/PCbuild/_freeze_module.vcxproj +++ b/PCbuild/_freeze_module.vcxproj @@ -89,10 +89,13 @@ Py_NO_ENABLE_SHARED;Py_BUILD_CORE;_CONSOLE;%(PreprocessorDefinitions) + Disabled + false Console version.lib;ws2_32.lib;pathcch.lib;bcrypt.lib;%(AdditionalDependencies) + Default From webhook-mailer at python.org Sun Dec 19 10:17:45 2021 From: webhook-mailer at python.org (asvetlov) Date: Sun, 19 Dec 2021 15:17:45 -0000 Subject: [Python-checkins] [3.10] bpo-46129: Rewrite asyncio.locks tests with IsolatedAsyncioTestCase (GH-30198) (GH-30202) Message-ID: https://github.com/python/cpython/commit/cdb4579607ad5e0a3978ec29b8407bea4d19b4fa commit: cdb4579607ad5e0a3978ec29b8407bea4d19b4fa branch: 3.10 author: Andrew Svetlov committer: asvetlov date: 2021-12-19T17:17:40+02:00 summary: [3.10] bpo-46129: Rewrite asyncio.locks tests with IsolatedAsyncioTestCase (GH-30198) (GH-30202) Co-authored-by: Kumar Aditya <59607654+kumaraditya303 at users.noreply.github.com>. (cherry picked from commit 9c06fd89514a9a2865e2adcc472095f6949cecb2) Co-authored-by: Andrew Svetlov files: A Misc/NEWS.d/next/Tests/2021-12-19-12-20-57.bpo-46129.I3MunH.rst M Lib/test/test_asyncio/test_locks.py M Lib/unittest/async_case.py diff --git a/Lib/test/test_asyncio/test_locks.py b/Lib/test/test_asyncio/test_locks.py index 623db5fda6437..e2cd2ba0365fd 100644 --- a/Lib/test/test_asyncio/test_locks.py +++ b/Lib/test/test_asyncio/test_locks.py @@ -5,7 +5,6 @@ import re import asyncio -from test.test_asyncio import utils as test_utils STR_RGX_REPR = ( r'^<(?P.*?) object at (?P
.*?)' @@ -20,22 +19,18 @@ def tearDownModule(): asyncio.set_event_loop_policy(None) -class LockTests(test_utils.TestCase): +class LockTests(unittest.IsolatedAsyncioTestCase): - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() - - def test_repr(self): + async def test_repr(self): lock = asyncio.Lock() self.assertTrue(repr(lock).endswith('[unlocked]>')) self.assertTrue(RGX_REPR.match(repr(lock))) - self.loop.run_until_complete(lock.acquire()) + await lock.acquire() self.assertTrue(repr(lock).endswith('[locked]>')) self.assertTrue(RGX_REPR.match(repr(lock))) - def test_lock(self): + async def test_lock(self): lock = asyncio.Lock() with self.assertWarns(DeprecationWarning): @@ -47,11 +42,11 @@ def acquire_lock(): TypeError, "object is not iterable" ): - self.loop.run_until_complete(acquire_lock()) + await acquire_lock() self.assertFalse(lock.locked()) - def test_lock_doesnt_accept_loop_parameter(self): + async def test_lock_doesnt_accept_loop_parameter(self): primitives_cls = [ asyncio.Lock, asyncio.Condition, @@ -60,17 +55,17 @@ def test_lock_doesnt_accept_loop_parameter(self): asyncio.BoundedSemaphore, ] + loop = asyncio.get_running_loop() + for cls in primitives_cls: with self.assertRaisesRegex( TypeError, rf'As of 3.10, the \*loop\* parameter was removed from ' rf'{cls.__name__}\(\) since it is no longer necessary' ): - cls(loop=self.loop) + cls(loop=loop) - def test_lock_by_with_statement(self): - loop = asyncio.new_event_loop() # don't use TestLoop quirks - self.set_event_loop(loop) + async def test_lock_by_with_statement(self): primitives = [ asyncio.Lock(), asyncio.Condition(), @@ -91,15 +86,15 @@ def test(lock): pass self.assertFalse(lock.locked()) - for primitive in primitives: - loop.run_until_complete(test(primitive)) - self.assertFalse(primitive.locked()) + for lock in primitives: + await test(lock) + self.assertFalse(lock.locked()) - def test_acquire(self): + async def test_acquire(self): lock = asyncio.Lock() result = [] - self.assertTrue(self.loop.run_until_complete(lock.acquire())) + self.assertTrue(await lock.acquire()) async def c1(result): if await lock.acquire(): @@ -116,27 +111,27 @@ async def c3(result): result.append(3) return True - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) + t1 = asyncio.create_task(c1(result)) + t2 = asyncio.create_task(c2(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) lock.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) - t3 = self.loop.create_task(c3(result)) + t3 = asyncio.create_task(c3(result)) lock.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1, 2], result) lock.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1, 2, 3], result) self.assertTrue(t1.done()) @@ -146,18 +141,17 @@ async def c3(result): self.assertTrue(t3.done()) self.assertTrue(t3.result()) - def test_acquire_cancel(self): + async def test_acquire_cancel(self): lock = asyncio.Lock() - self.assertTrue(self.loop.run_until_complete(lock.acquire())) + self.assertTrue(await lock.acquire()) - task = self.loop.create_task(lock.acquire()) - self.loop.call_soon(task.cancel) - self.assertRaises( - asyncio.CancelledError, - self.loop.run_until_complete, task) + task = asyncio.create_task(lock.acquire()) + asyncio.get_running_loop().call_soon(task.cancel) + with self.assertRaises(asyncio.CancelledError): + await task self.assertFalse(lock._waiters) - def test_cancel_race(self): + async def test_cancel_race(self): # Several tasks: # - A acquires the lock # - B is blocked in acquire() @@ -182,15 +176,15 @@ async def lockit(name, blocker): finally: lock.release() - fa = self.loop.create_future() - ta = self.loop.create_task(lockit('A', fa)) - test_utils.run_briefly(self.loop) + fa = asyncio.get_running_loop().create_future() + ta = asyncio.create_task(lockit('A', fa)) + await asyncio.sleep(0) self.assertTrue(lock.locked()) - tb = self.loop.create_task(lockit('B', None)) - test_utils.run_briefly(self.loop) + tb = asyncio.create_task(lockit('B', None)) + await asyncio.sleep(0) self.assertEqual(len(lock._waiters), 1) - tc = self.loop.create_task(lockit('C', None)) - test_utils.run_briefly(self.loop) + tc = asyncio.create_task(lockit('C', None)) + await asyncio.sleep(0) self.assertEqual(len(lock._waiters), 2) # Create the race and check. @@ -198,16 +192,17 @@ async def lockit(name, blocker): fa.set_result(None) tb.cancel() self.assertTrue(lock._waiters[0].cancelled()) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertFalse(lock.locked()) self.assertTrue(ta.done()) self.assertTrue(tb.cancelled()) - self.assertTrue(tc.done()) + await tc - def test_cancel_release_race(self): + async def test_cancel_release_race(self): # Issue 32734 # Acquire 4 locks, cancel second, release first # and 2 locks are taken at once. + loop = asyncio.get_running_loop() lock = asyncio.Lock() lock_count = 0 call_count = 0 @@ -219,27 +214,23 @@ async def lockit(): await lock.acquire() lock_count += 1 - async def lockandtrigger(): - await lock.acquire() - self.loop.call_soon(trigger) - def trigger(): t1.cancel() lock.release() - t0 = self.loop.create_task(lockandtrigger()) - t1 = self.loop.create_task(lockit()) - t2 = self.loop.create_task(lockit()) - t3 = self.loop.create_task(lockit()) + await lock.acquire() - # First loop acquires all - test_utils.run_briefly(self.loop) - self.assertTrue(t0.done()) + t1 = asyncio.create_task(lockit()) + t2 = asyncio.create_task(lockit()) + t3 = asyncio.create_task(lockit()) - # Second loop calls trigger - test_utils.run_briefly(self.loop) - # Third loop calls cancellation - test_utils.run_briefly(self.loop) + # Start scheduled tasks + await asyncio.sleep(0) + + loop.call_soon(trigger) + with self.assertRaises(asyncio.CancelledError): + # Wait for cancellation + await t1 # Make sure only one lock was taken self.assertEqual(lock_count, 1) @@ -249,62 +240,56 @@ def trigger(): # Cleanup the task that is stuck on acquire. t3.cancel() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertTrue(t3.cancelled()) - def test_finished_waiter_cancelled(self): + async def test_finished_waiter_cancelled(self): lock = asyncio.Lock() - ta = self.loop.create_task(lock.acquire()) - test_utils.run_briefly(self.loop) + await lock.acquire() self.assertTrue(lock.locked()) - tb = self.loop.create_task(lock.acquire()) - test_utils.run_briefly(self.loop) + tb = asyncio.create_task(lock.acquire()) + await asyncio.sleep(0) self.assertEqual(len(lock._waiters), 1) # Create a second waiter, wake up the first, and cancel it. # Without the fix, the second was not woken up. - tc = self.loop.create_task(lock.acquire()) - lock.release() + tc = asyncio.create_task(lock.acquire()) tb.cancel() - test_utils.run_briefly(self.loop) + lock.release() + await asyncio.sleep(0) self.assertTrue(lock.locked()) - self.assertTrue(ta.done()) self.assertTrue(tb.cancelled()) - def test_release_not_acquired(self): + # Cleanup + await tc + + async def test_release_not_acquired(self): lock = asyncio.Lock() self.assertRaises(RuntimeError, lock.release) - def test_release_no_waiters(self): + async def test_release_no_waiters(self): lock = asyncio.Lock() - self.loop.run_until_complete(lock.acquire()) + await lock.acquire() self.assertTrue(lock.locked()) lock.release() self.assertFalse(lock.locked()) - def test_context_manager(self): - async def f(): - lock = asyncio.Lock() - self.assertFalse(lock.locked()) - - async with lock: - self.assertTrue(lock.locked()) - - self.assertFalse(lock.locked()) + async def test_context_manager(self): + lock = asyncio.Lock() + self.assertFalse(lock.locked()) - self.loop.run_until_complete(f()) + async with lock: + self.assertTrue(lock.locked()) + self.assertFalse(lock.locked()) -class EventTests(test_utils.TestCase): - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() +class EventTests(unittest.IsolatedAsyncioTestCase): def test_repr(self): ev = asyncio.Event() @@ -320,7 +305,7 @@ def test_repr(self): self.assertTrue('waiters:1' in repr(ev)) self.assertTrue(RGX_REPR.match(repr(ev))) - def test_wait(self): + async def test_wait(self): ev = asyncio.Event() self.assertFalse(ev.is_set()) @@ -338,16 +323,16 @@ async def c3(result): if await ev.wait(): result.append(3) - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) + t1 = asyncio.create_task(c1(result)) + t2 = asyncio.create_task(c2(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) - t3 = self.loop.create_task(c3(result)) + t3 = asyncio.create_task(c3(result)) ev.set() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([3, 1, 2], result) self.assertTrue(t1.done()) @@ -357,24 +342,23 @@ async def c3(result): self.assertTrue(t3.done()) self.assertIsNone(t3.result()) - def test_wait_on_set(self): + async def test_wait_on_set(self): ev = asyncio.Event() ev.set() - res = self.loop.run_until_complete(ev.wait()) + res = await ev.wait() self.assertTrue(res) - def test_wait_cancel(self): + async def test_wait_cancel(self): ev = asyncio.Event() - wait = self.loop.create_task(ev.wait()) - self.loop.call_soon(wait.cancel) - self.assertRaises( - asyncio.CancelledError, - self.loop.run_until_complete, wait) + wait = asyncio.create_task(ev.wait()) + asyncio.get_running_loop().call_soon(wait.cancel) + with self.assertRaises(asyncio.CancelledError): + await wait self.assertFalse(ev._waiters) - def test_clear(self): + async def test_clear(self): ev = asyncio.Event() self.assertFalse(ev.is_set()) @@ -384,7 +368,7 @@ def test_clear(self): ev.clear() self.assertFalse(ev.is_set()) - def test_clear_with_waiters(self): + async def test_clear_with_waiters(self): ev = asyncio.Event() result = [] @@ -393,8 +377,8 @@ async def c1(result): result.append(1) return True - t = self.loop.create_task(c1(result)) - test_utils.run_briefly(self.loop) + t = asyncio.create_task(c1(result)) + await asyncio.sleep(0) self.assertEqual([], result) ev.set() @@ -405,7 +389,7 @@ async def c1(result): ev.set() self.assertEqual(1, len(ev._waiters)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) self.assertEqual(0, len(ev._waiters)) @@ -413,13 +397,9 @@ async def c1(result): self.assertTrue(t.result()) -class ConditionTests(test_utils.TestCase): - - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() +class ConditionTests(unittest.IsolatedAsyncioTestCase): - def test_wait(self): + async def test_wait(self): cond = asyncio.Condition() result = [] @@ -441,37 +421,37 @@ async def c3(result): result.append(3) return True - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) - t3 = self.loop.create_task(c3(result)) + t1 = asyncio.create_task(c1(result)) + t2 = asyncio.create_task(c2(result)) + t3 = asyncio.create_task(c3(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) self.assertFalse(cond.locked()) - self.assertTrue(self.loop.run_until_complete(cond.acquire())) + self.assertTrue(await cond.acquire()) cond.notify() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) self.assertTrue(cond.locked()) cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) self.assertTrue(cond.locked()) cond.notify(2) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) self.assertTrue(cond.locked()) cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1, 2], result) self.assertTrue(cond.locked()) cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1, 2, 3], result) self.assertTrue(cond.locked()) @@ -482,49 +462,47 @@ async def c3(result): self.assertTrue(t3.done()) self.assertTrue(t3.result()) - def test_wait_cancel(self): + async def test_wait_cancel(self): cond = asyncio.Condition() - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() - wait = self.loop.create_task(cond.wait()) - self.loop.call_soon(wait.cancel) - self.assertRaises( - asyncio.CancelledError, - self.loop.run_until_complete, wait) + wait = asyncio.create_task(cond.wait()) + asyncio.get_running_loop().call_soon(wait.cancel) + with self.assertRaises(asyncio.CancelledError): + await wait self.assertFalse(cond._waiters) self.assertTrue(cond.locked()) - def test_wait_cancel_contested(self): + async def test_wait_cancel_contested(self): cond = asyncio.Condition() - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() self.assertTrue(cond.locked()) - wait_task = self.loop.create_task(cond.wait()) - test_utils.run_briefly(self.loop) + wait_task = asyncio.create_task(cond.wait()) + await asyncio.sleep(0) self.assertFalse(cond.locked()) # Notify, but contest the lock before cancelling - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() self.assertTrue(cond.locked()) cond.notify() - self.loop.call_soon(wait_task.cancel) - self.loop.call_soon(cond.release) + asyncio.get_running_loop().call_soon(wait_task.cancel) + asyncio.get_running_loop().call_soon(cond.release) try: - self.loop.run_until_complete(wait_task) + await wait_task except asyncio.CancelledError: # Should not happen, since no cancellation points pass self.assertTrue(cond.locked()) - def test_wait_cancel_after_notify(self): + async def test_wait_cancel_after_notify(self): # See bpo-32841 waited = False cond = asyncio.Condition() - cond._loop = self.loop async def wait_on_cond(): nonlocal waited @@ -532,27 +510,26 @@ async def wait_on_cond(): waited = True # Make sure this area was reached await cond.wait() - waiter = asyncio.ensure_future(wait_on_cond(), loop=self.loop) - test_utils.run_briefly(self.loop) # Start waiting + waiter = asyncio.create_task(wait_on_cond()) + await asyncio.sleep(0) # Start waiting - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() cond.notify() - test_utils.run_briefly(self.loop) # Get to acquire() + await asyncio.sleep(0) # Get to acquire() waiter.cancel() - test_utils.run_briefly(self.loop) # Activate cancellation + await asyncio.sleep(0) # Activate cancellation cond.release() - test_utils.run_briefly(self.loop) # Cancellation should occur + await asyncio.sleep(0) # Cancellation should occur self.assertTrue(waiter.cancelled()) self.assertTrue(waited) - def test_wait_unacquired(self): + async def test_wait_unacquired(self): cond = asyncio.Condition() - self.assertRaises( - RuntimeError, - self.loop.run_until_complete, cond.wait()) + with self.assertRaises(RuntimeError): + await cond.wait() - def test_wait_for(self): + async def test_wait_for(self): cond = asyncio.Condition() presult = False @@ -568,40 +545,38 @@ async def c1(result): cond.release() return True - t = self.loop.create_task(c1(result)) + t = asyncio.create_task(c1(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() cond.notify() cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) presult = True - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() cond.notify() cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) self.assertTrue(t.done()) self.assertTrue(t.result()) - def test_wait_for_unacquired(self): + async def test_wait_for_unacquired(self): cond = asyncio.Condition() # predicate can return true immediately - res = self.loop.run_until_complete(cond.wait_for(lambda: [1, 2, 3])) + res = await cond.wait_for(lambda: [1, 2, 3]) self.assertEqual([1, 2, 3], res) - self.assertRaises( - RuntimeError, - self.loop.run_until_complete, - cond.wait_for(lambda: False)) + with self.assertRaises(RuntimeError): + await cond.wait_for(lambda: False) - def test_notify(self): + async def test_notify(self): cond = asyncio.Condition() result = [] @@ -626,24 +601,24 @@ async def c3(result): cond.release() return True - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) - t3 = self.loop.create_task(c3(result)) + t1 = asyncio.create_task(c1(result)) + t2 = asyncio.create_task(c2(result)) + t3 = asyncio.create_task(c3(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() cond.notify(1) cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() cond.notify(1) cond.notify(2048) cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1, 2, 3], result) self.assertTrue(t1.done()) @@ -653,7 +628,7 @@ async def c3(result): self.assertTrue(t3.done()) self.assertTrue(t3.result()) - def test_notify_all(self): + async def test_notify_all(self): cond = asyncio.Condition() result = [] @@ -672,16 +647,16 @@ async def c2(result): cond.release() return True - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) + t1 = asyncio.create_task(c1(result)) + t2 = asyncio.create_task(c2(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() cond.notify_all() cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1, 2], result) self.assertTrue(t1.done()) @@ -697,12 +672,12 @@ def test_notify_all_unacquired(self): cond = asyncio.Condition() self.assertRaises(RuntimeError, cond.notify_all) - def test_repr(self): + async def test_repr(self): cond = asyncio.Condition() self.assertTrue('unlocked' in repr(cond)) self.assertTrue(RGX_REPR.match(repr(cond))) - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() self.assertTrue('locked' in repr(cond)) cond._waiters.append(mock.Mock()) @@ -713,17 +688,14 @@ def test_repr(self): self.assertTrue('waiters:2' in repr(cond)) self.assertTrue(RGX_REPR.match(repr(cond))) - def test_context_manager(self): - async def f(): - cond = asyncio.Condition() - self.assertFalse(cond.locked()) - async with cond: - self.assertTrue(cond.locked()) - self.assertFalse(cond.locked()) - - self.loop.run_until_complete(f()) + async def test_context_manager(self): + cond = asyncio.Condition() + self.assertFalse(cond.locked()) + async with cond: + self.assertTrue(cond.locked()) + self.assertFalse(cond.locked()) - def test_explicit_lock(self): + async def test_explicit_lock(self): async def f(lock=None, cond=None): if lock is None: lock = asyncio.Lock() @@ -744,12 +716,12 @@ async def f(lock=None, cond=None): self.assertFalse(cond.locked()) # All should work in the same way. - self.loop.run_until_complete(f()) - self.loop.run_until_complete(f(asyncio.Lock())) + await f() + await f(asyncio.Lock()) lock = asyncio.Lock() - self.loop.run_until_complete(f(lock, asyncio.Condition(lock))) + await f(lock, asyncio.Condition(lock)) - def test_ambiguous_loops(self): + async def test_ambiguous_loops(self): loop = asyncio.new_event_loop() self.addCleanup(loop.close) @@ -784,38 +756,28 @@ async def wrong_loop_in_cond(): ): await cond.wait() - self.loop.run_until_complete(wrong_loop_in_lock()) - self.loop.run_until_complete(wrong_loop_in_cond()) - - def test_timeout_in_block(self): - loop = asyncio.new_event_loop() - self.addCleanup(loop.close) + await wrong_loop_in_lock() + await wrong_loop_in_cond() - async def task_timeout(): - condition = asyncio.Condition() - async with condition: - with self.assertRaises(asyncio.TimeoutError): - await asyncio.wait_for(condition.wait(), timeout=0.5) + async def test_timeout_in_block(self): + condition = asyncio.Condition() + async with condition: + with self.assertRaises(asyncio.TimeoutError): + await asyncio.wait_for(condition.wait(), timeout=0.5) - loop.run_until_complete(task_timeout()) - -class SemaphoreTests(test_utils.TestCase): - - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() +class SemaphoreTests(unittest.IsolatedAsyncioTestCase): def test_initial_value_zero(self): sem = asyncio.Semaphore(0) self.assertTrue(sem.locked()) - def test_repr(self): + async def test_repr(self): sem = asyncio.Semaphore() self.assertTrue(repr(sem).endswith('[unlocked, value:1]>')) self.assertTrue(RGX_REPR.match(repr(sem))) - self.loop.run_until_complete(sem.acquire()) + await sem.acquire() self.assertTrue(repr(sem).endswith('[locked]>')) self.assertTrue('waiters' not in repr(sem)) self.assertTrue(RGX_REPR.match(repr(sem))) @@ -828,7 +790,7 @@ def test_repr(self): self.assertTrue('waiters:2' in repr(sem)) self.assertTrue(RGX_REPR.match(repr(sem))) - def test_semaphore(self): + async def test_semaphore(self): sem = asyncio.Semaphore() self.assertEqual(1, sem._value) @@ -841,7 +803,7 @@ def acquire_lock(): TypeError, "'Semaphore' object is not iterable", ): - self.loop.run_until_complete(acquire_lock()) + await acquire_lock() self.assertFalse(sem.locked()) self.assertEqual(1, sem._value) @@ -849,12 +811,12 @@ def acquire_lock(): def test_semaphore_value(self): self.assertRaises(ValueError, asyncio.Semaphore, -1) - def test_acquire(self): + async def test_acquire(self): sem = asyncio.Semaphore(3) result = [] - self.assertTrue(self.loop.run_until_complete(sem.acquire())) - self.assertTrue(self.loop.run_until_complete(sem.acquire())) + self.assertTrue(await sem.acquire()) + self.assertTrue(await sem.acquire()) self.assertFalse(sem.locked()) async def c1(result): @@ -877,23 +839,23 @@ async def c4(result): result.append(4) return True - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) - t3 = self.loop.create_task(c3(result)) + t1 = asyncio.create_task(c1(result)) + t2 = asyncio.create_task(c2(result)) + t3 = asyncio.create_task(c3(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) self.assertTrue(sem.locked()) self.assertEqual(2, len(sem._waiters)) self.assertEqual(0, sem._value) - t4 = self.loop.create_task(c4(result)) + t4 = asyncio.create_task(c4(result)) sem.release() sem.release() self.assertEqual(2, sem._value) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual(0, sem._value) self.assertEqual(3, len(result)) self.assertTrue(sem.locked()) @@ -908,64 +870,64 @@ async def c4(result): # cleanup locked semaphore sem.release() - self.loop.run_until_complete(asyncio.gather(*race_tasks)) + await asyncio.gather(*race_tasks) - def test_acquire_cancel(self): + async def test_acquire_cancel(self): sem = asyncio.Semaphore() - self.loop.run_until_complete(sem.acquire()) + await sem.acquire() - acquire = self.loop.create_task(sem.acquire()) - self.loop.call_soon(acquire.cancel) - self.assertRaises( - asyncio.CancelledError, - self.loop.run_until_complete, acquire) + acquire = asyncio.create_task(sem.acquire()) + asyncio.get_running_loop().call_soon(acquire.cancel) + with self.assertRaises(asyncio.CancelledError): + await acquire self.assertTrue((not sem._waiters) or all(waiter.done() for waiter in sem._waiters)) - def test_acquire_cancel_before_awoken(self): + async def test_acquire_cancel_before_awoken(self): sem = asyncio.Semaphore(value=0) - t1 = self.loop.create_task(sem.acquire()) - t2 = self.loop.create_task(sem.acquire()) - t3 = self.loop.create_task(sem.acquire()) - t4 = self.loop.create_task(sem.acquire()) + t1 = asyncio.create_task(sem.acquire()) + t2 = asyncio.create_task(sem.acquire()) + t3 = asyncio.create_task(sem.acquire()) + t4 = asyncio.create_task(sem.acquire()) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) - sem.release() t1.cancel() t2.cancel() + sem.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) num_done = sum(t.done() for t in [t3, t4]) self.assertEqual(num_done, 1) + self.assertTrue(t3.done()) + self.assertFalse(t4.done()) t3.cancel() t4.cancel() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) - def test_acquire_hang(self): + async def test_acquire_hang(self): sem = asyncio.Semaphore(value=0) - t1 = self.loop.create_task(sem.acquire()) - t2 = self.loop.create_task(sem.acquire()) + t1 = asyncio.create_task(sem.acquire()) + t2 = asyncio.create_task(sem.acquire()) + await asyncio.sleep(0) - test_utils.run_briefly(self.loop) - - sem.release() t1.cancel() - - test_utils.run_briefly(self.loop) + sem.release() + await asyncio.sleep(0) self.assertTrue(sem.locked()) + self.assertTrue(t2.done()) def test_release_not_acquired(self): sem = asyncio.BoundedSemaphore() self.assertRaises(ValueError, sem.release) - def test_release_no_waiters(self): + async def test_release_no_waiters(self): sem = asyncio.Semaphore() - self.loop.run_until_complete(sem.acquire()) + await sem.acquire() self.assertTrue(sem.locked()) sem.release() diff --git a/Lib/unittest/async_case.py b/Lib/unittest/async_case.py index 4f9a80be80c5a..23231199f9870 100644 --- a/Lib/unittest/async_case.py +++ b/Lib/unittest/async_case.py @@ -4,7 +4,6 @@ from .case import TestCase - class IsolatedAsyncioTestCase(TestCase): # Names intentionally have a long prefix # to reduce a chance of clashing with user-defined attributes diff --git a/Misc/NEWS.d/next/Tests/2021-12-19-12-20-57.bpo-46129.I3MunH.rst b/Misc/NEWS.d/next/Tests/2021-12-19-12-20-57.bpo-46129.I3MunH.rst new file mode 100644 index 0000000000000..b06436a4c8460 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-12-19-12-20-57.bpo-46129.I3MunH.rst @@ -0,0 +1,2 @@ +Rewrite ``asyncio.locks`` tests with +:class:`unittest.IsolatedAsyncioTestCase` usage. From webhook-mailer at python.org Sun Dec 19 11:59:42 2021 From: webhook-mailer at python.org (asvetlov) Date: Sun, 19 Dec 2021 16:59:42 -0000 Subject: [Python-checkins] [3.9] bpo-46129: Rewrite asyncio.locks tests with IsolatedAsyncioTestCase (GH-30198) (GH-30204) Message-ID: https://github.com/python/cpython/commit/f8fce5e4e4338fbe49e5e7a5a856101f69081a08 commit: f8fce5e4e4338fbe49e5e7a5a856101f69081a08 branch: 3.9 author: Andrew Svetlov committer: asvetlov date: 2021-12-19T18:59:37+02:00 summary: [3.9] bpo-46129: Rewrite asyncio.locks tests with IsolatedAsyncioTestCase (GH-30198) (GH-30204) Co-authored-by: Kumar Aditya <59607654+kumaraditya303 at users.noreply.github.com>. (cherry picked from commit 9c06fd89514a9a2865e2adcc472095f6949cecb2) Co-authored-by: Andrew Svetlov files: A Misc/NEWS.d/next/Tests/2021-12-19-12-20-57.bpo-46129.I3MunH.rst M Lib/test/test_asyncio/test_locks.py M Lib/unittest/async_case.py diff --git a/Lib/test/test_asyncio/test_locks.py b/Lib/test/test_asyncio/test_locks.py index 8c93fae2b51c6..cfb6421b38f60 100644 --- a/Lib/test/test_asyncio/test_locks.py +++ b/Lib/test/test_asyncio/test_locks.py @@ -5,7 +5,6 @@ import re import asyncio -from test.test_asyncio import utils as test_utils STR_RGX_REPR = ( r'^<(?P.*?) object at (?P
.*?)' @@ -20,86 +19,67 @@ def tearDownModule(): asyncio.set_event_loop_policy(None) -class LockTests(test_utils.TestCase): +class LockTests(unittest.IsolatedAsyncioTestCase): - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() - - def test_ctor_loop(self): + async def test_ctor_loop(self): loop = mock.Mock() with self.assertWarns(DeprecationWarning): lock = asyncio.Lock(loop=loop) self.assertIs(lock._loop, loop) with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=self.loop) - self.assertIs(lock._loop, self.loop) + lock = asyncio.Lock(loop=asyncio.get_running_loop()) + self.assertIs(lock._loop, asyncio.get_running_loop()) - def test_ctor_noloop(self): - asyncio.set_event_loop(self.loop) + async def test_ctor_noloop(self): lock = asyncio.Lock() - self.assertIs(lock._loop, self.loop) + self.assertIs(lock._loop, asyncio.get_running_loop()) - def test_repr(self): + async def test_repr(self): with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=self.loop) + lock = asyncio.Lock(loop=asyncio.get_running_loop()) self.assertTrue(repr(lock).endswith('[unlocked]>')) self.assertTrue(RGX_REPR.match(repr(lock))) - self.loop.run_until_complete(lock.acquire()) + await lock.acquire() self.assertTrue(repr(lock).endswith('[locked]>')) self.assertTrue(RGX_REPR.match(repr(lock))) - def test_lock(self): - with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=self.loop) - - @asyncio.coroutine - def acquire_lock(): - return (yield from lock) + async def test_lock(self): + lock = asyncio.Lock() with self.assertRaisesRegex( TypeError, - "object is not iterable" + "object Lock can't be used in 'await' expression" ): - self.loop.run_until_complete(acquire_lock()) + await lock self.assertFalse(lock.locked()) - def test_lock_by_with_statement(self): - loop = asyncio.new_event_loop() # don't use TestLoop quirks - self.set_event_loop(loop) - with self.assertWarns(DeprecationWarning): - primitives = [ - asyncio.Lock(loop=loop), - asyncio.Condition(loop=loop), - asyncio.Semaphore(loop=loop), - asyncio.BoundedSemaphore(loop=loop), - ] - - @asyncio.coroutine - def test(lock): - yield from asyncio.sleep(0.01) - self.assertFalse(lock.locked()) - with self.assertRaisesRegex( - TypeError, - "object is not iterable" - ): - with (yield from lock): - pass - self.assertFalse(lock.locked()) + async def test_lock_by_with_statement(self): + primitives = [ + asyncio.Lock(), + asyncio.Condition(), + asyncio.Semaphore(), + asyncio.BoundedSemaphore(), + ] - for primitive in primitives: - loop.run_until_complete(test(primitive)) - self.assertFalse(primitive.locked()) + for lock in primitives: + await asyncio.sleep(0.01) + self.assertFalse(lock.locked()) + with self.assertRaisesRegex( + TypeError, + r"object \w+ can't be used in 'await' expression" + ): + with await lock: + pass + self.assertFalse(lock.locked()) - def test_acquire(self): - with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=self.loop) + async def test_acquire(self): + lock = asyncio.Lock() result = [] - self.assertTrue(self.loop.run_until_complete(lock.acquire())) + self.assertTrue(await lock.acquire()) async def c1(result): if await lock.acquire(): @@ -116,27 +96,27 @@ async def c3(result): result.append(3) return True - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) + t1 = asyncio.create_task(c1(result)) + t2 = asyncio.create_task(c2(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) lock.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) - t3 = self.loop.create_task(c3(result)) + t3 = asyncio.create_task(c3(result)) lock.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1, 2], result) lock.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1, 2, 3], result) self.assertTrue(t1.done()) @@ -146,19 +126,18 @@ async def c3(result): self.assertTrue(t3.done()) self.assertTrue(t3.result()) - def test_acquire_cancel(self): + async def test_acquire_cancel(self): with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=self.loop) - self.assertTrue(self.loop.run_until_complete(lock.acquire())) - - task = self.loop.create_task(lock.acquire()) - self.loop.call_soon(task.cancel) - self.assertRaises( - asyncio.CancelledError, - self.loop.run_until_complete, task) + lock = asyncio.Lock(loop=asyncio.get_running_loop()) + self.assertTrue(await lock.acquire()) + + task = asyncio.create_task(lock.acquire()) + asyncio.get_running_loop().call_soon(task.cancel) + with self.assertRaises(asyncio.CancelledError): + await task self.assertFalse(lock._waiters) - def test_cancel_race(self): + async def test_cancel_race(self): # Several tasks: # - A acquires the lock # - B is blocked in acquire() @@ -174,7 +153,7 @@ def test_cancel_race(self): # Setup: A has the lock, b and c are waiting. with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=self.loop) + lock = asyncio.Lock(loop=asyncio.get_running_loop()) async def lockit(name, blocker): await lock.acquire() @@ -184,15 +163,15 @@ async def lockit(name, blocker): finally: lock.release() - fa = self.loop.create_future() - ta = self.loop.create_task(lockit('A', fa)) - test_utils.run_briefly(self.loop) + fa = asyncio.get_running_loop().create_future() + ta = asyncio.create_task(lockit('A', fa)) + await asyncio.sleep(0) self.assertTrue(lock.locked()) - tb = self.loop.create_task(lockit('B', None)) - test_utils.run_briefly(self.loop) + tb = asyncio.create_task(lockit('B', None)) + await asyncio.sleep(0) self.assertEqual(len(lock._waiters), 1) - tc = self.loop.create_task(lockit('C', None)) - test_utils.run_briefly(self.loop) + tc = asyncio.create_task(lockit('C', None)) + await asyncio.sleep(0) self.assertEqual(len(lock._waiters), 2) # Create the race and check. @@ -200,18 +179,19 @@ async def lockit(name, blocker): fa.set_result(None) tb.cancel() self.assertTrue(lock._waiters[0].cancelled()) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertFalse(lock.locked()) self.assertTrue(ta.done()) self.assertTrue(tb.cancelled()) - self.assertTrue(tc.done()) + await tc - def test_cancel_release_race(self): + async def test_cancel_release_race(self): # Issue 32734 # Acquire 4 locks, cancel second, release first # and 2 locks are taken at once. + loop = asyncio.get_running_loop() with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=self.loop) + lock = asyncio.Lock(loop=loop) lock_count = 0 call_count = 0 @@ -222,27 +202,23 @@ async def lockit(): await lock.acquire() lock_count += 1 - async def lockandtrigger(): - await lock.acquire() - self.loop.call_soon(trigger) - def trigger(): t1.cancel() lock.release() - t0 = self.loop.create_task(lockandtrigger()) - t1 = self.loop.create_task(lockit()) - t2 = self.loop.create_task(lockit()) - t3 = self.loop.create_task(lockit()) + await lock.acquire() - # First loop acquires all - test_utils.run_briefly(self.loop) - self.assertTrue(t0.done()) + t1 = asyncio.create_task(lockit()) + t2 = asyncio.create_task(lockit()) + t3 = asyncio.create_task(lockit()) - # Second loop calls trigger - test_utils.run_briefly(self.loop) - # Third loop calls cancellation - test_utils.run_briefly(self.loop) + # Start scheduled tasks + await asyncio.sleep(0) + + loop.call_soon(trigger) + with self.assertRaises(asyncio.CancelledError): + # Wait for cancellation + await t1 # Make sure only one lock was taken self.assertEqual(lock_count, 1) @@ -252,84 +228,78 @@ def trigger(): # Cleanup the task that is stuck on acquire. t3.cancel() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertTrue(t3.cancelled()) - def test_finished_waiter_cancelled(self): + async def test_finished_waiter_cancelled(self): with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=self.loop) + lock = asyncio.Lock(loop=asyncio.get_running_loop()) - ta = self.loop.create_task(lock.acquire()) - test_utils.run_briefly(self.loop) + await lock.acquire() self.assertTrue(lock.locked()) - tb = self.loop.create_task(lock.acquire()) - test_utils.run_briefly(self.loop) + tb = asyncio.create_task(lock.acquire()) + await asyncio.sleep(0) self.assertEqual(len(lock._waiters), 1) # Create a second waiter, wake up the first, and cancel it. # Without the fix, the second was not woken up. - tc = self.loop.create_task(lock.acquire()) - lock.release() + tc = asyncio.create_task(lock.acquire()) tb.cancel() - test_utils.run_briefly(self.loop) + lock.release() + await asyncio.sleep(0) self.assertTrue(lock.locked()) - self.assertTrue(ta.done()) self.assertTrue(tb.cancelled()) - def test_release_not_acquired(self): + # Cleanup + await tc + + async def test_release_not_acquired(self): with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=self.loop) + lock = asyncio.Lock(loop=asyncio.get_running_loop()) self.assertRaises(RuntimeError, lock.release) - def test_release_no_waiters(self): + async def test_release_no_waiters(self): with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=self.loop) - self.loop.run_until_complete(lock.acquire()) + lock = asyncio.Lock(loop=asyncio.get_running_loop()) + await lock.acquire() self.assertTrue(lock.locked()) lock.release() self.assertFalse(lock.locked()) - def test_context_manager(self): - async def f(): - lock = asyncio.Lock() - self.assertFalse(lock.locked()) - - async with lock: - self.assertTrue(lock.locked()) - - self.assertFalse(lock.locked()) + async def test_context_manager(self): + lock = asyncio.Lock() + self.assertFalse(lock.locked()) - self.loop.run_until_complete(f()) + async with lock: + self.assertTrue(lock.locked()) + self.assertFalse(lock.locked()) -class EventTests(test_utils.TestCase): - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() +class EventTests(unittest.IsolatedAsyncioTestCase): - def test_ctor_loop(self): + async def test_ctor_loop(self): loop = mock.Mock() with self.assertWarns(DeprecationWarning): ev = asyncio.Event(loop=loop) self.assertIs(ev._loop, loop) with self.assertWarns(DeprecationWarning): - ev = asyncio.Event(loop=self.loop) - self.assertIs(ev._loop, self.loop) + ev = asyncio.Event(loop=asyncio.get_running_loop()) + self.assertIs(ev._loop, asyncio.get_running_loop()) - def test_ctor_noloop(self): - asyncio.set_event_loop(self.loop) + async def test_ctor_noloop(self): + asyncio.set_event_loop(asyncio.get_running_loop()) ev = asyncio.Event() - self.assertIs(ev._loop, self.loop) + self.assertIs(ev._loop, asyncio.get_running_loop()) - def test_repr(self): + async def test_repr(self): with self.assertWarns(DeprecationWarning): - ev = asyncio.Event(loop=self.loop) + ev = asyncio.Event(loop=asyncio.get_running_loop()) self.assertTrue(repr(ev).endswith('[unset]>')) match = RGX_REPR.match(repr(ev)) self.assertEqual(match.group('extras'), 'unset') @@ -342,9 +312,9 @@ def test_repr(self): self.assertTrue('waiters:1' in repr(ev)) self.assertTrue(RGX_REPR.match(repr(ev))) - def test_wait(self): + async def test_wait(self): with self.assertWarns(DeprecationWarning): - ev = asyncio.Event(loop=self.loop) + ev = asyncio.Event(loop=asyncio.get_running_loop()) self.assertFalse(ev.is_set()) result = [] @@ -361,16 +331,16 @@ async def c3(result): if await ev.wait(): result.append(3) - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) + t1 = asyncio.create_task(c1(result)) + t2 = asyncio.create_task(c2(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) - t3 = self.loop.create_task(c3(result)) + t3 = asyncio.create_task(c3(result)) ev.set() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([3, 1, 2], result) self.assertTrue(t1.done()) @@ -380,28 +350,24 @@ async def c3(result): self.assertTrue(t3.done()) self.assertIsNone(t3.result()) - def test_wait_on_set(self): - with self.assertWarns(DeprecationWarning): - ev = asyncio.Event(loop=self.loop) + async def test_wait_on_set(self): + ev = asyncio.Event() ev.set() - res = self.loop.run_until_complete(ev.wait()) + res = await ev.wait() self.assertTrue(res) - def test_wait_cancel(self): - with self.assertWarns(DeprecationWarning): - ev = asyncio.Event(loop=self.loop) + async def test_wait_cancel(self): + ev = asyncio.Event() - wait = self.loop.create_task(ev.wait()) - self.loop.call_soon(wait.cancel) - self.assertRaises( - asyncio.CancelledError, - self.loop.run_until_complete, wait) + wait = asyncio.create_task(ev.wait()) + asyncio.get_running_loop().call_soon(wait.cancel) + with self.assertRaises(asyncio.CancelledError): + await wait self.assertFalse(ev._waiters) - def test_clear(self): - with self.assertWarns(DeprecationWarning): - ev = asyncio.Event(loop=self.loop) + async def test_clear(self): + ev = asyncio.Event() self.assertFalse(ev.is_set()) ev.set() @@ -410,9 +376,8 @@ def test_clear(self): ev.clear() self.assertFalse(ev.is_set()) - def test_clear_with_waiters(self): - with self.assertWarns(DeprecationWarning): - ev = asyncio.Event(loop=self.loop) + async def test_clear_with_waiters(self): + ev = asyncio.Event() result = [] async def c1(result): @@ -420,8 +385,8 @@ async def c1(result): result.append(1) return True - t = self.loop.create_task(c1(result)) - test_utils.run_briefly(self.loop) + t = asyncio.create_task(c1(result)) + await asyncio.sleep(0) self.assertEqual([], result) ev.set() @@ -432,7 +397,7 @@ async def c1(result): ev.set() self.assertEqual(1, len(ev._waiters)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) self.assertEqual(0, len(ev._waiters)) @@ -440,29 +405,23 @@ async def c1(result): self.assertTrue(t.result()) -class ConditionTests(test_utils.TestCase): +class ConditionTests(unittest.IsolatedAsyncioTestCase): - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() - - def test_ctor_loop(self): + async def test_ctor_loop(self): loop = mock.Mock() with self.assertWarns(DeprecationWarning): cond = asyncio.Condition(loop=loop) self.assertIs(cond._loop, loop) - cond = asyncio.Condition(loop=self.loop) - self.assertIs(cond._loop, self.loop) + cond = asyncio.Condition(loop=asyncio.get_running_loop()) + self.assertIs(cond._loop, asyncio.get_running_loop()) - def test_ctor_noloop(self): - asyncio.set_event_loop(self.loop) + async def test_ctor_noloop(self): cond = asyncio.Condition() - self.assertIs(cond._loop, self.loop) + self.assertIs(cond._loop, asyncio.get_running_loop()) - def test_wait(self): - with self.assertWarns(DeprecationWarning): - cond = asyncio.Condition(loop=self.loop) + async def test_wait(self): + cond = asyncio.Condition() result = [] async def c1(result): @@ -483,37 +442,37 @@ async def c3(result): result.append(3) return True - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) - t3 = self.loop.create_task(c3(result)) + t1 = asyncio.create_task(c1(result)) + t2 = asyncio.create_task(c2(result)) + t3 = asyncio.create_task(c3(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) self.assertFalse(cond.locked()) - self.assertTrue(self.loop.run_until_complete(cond.acquire())) + self.assertTrue(await cond.acquire()) cond.notify() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) self.assertTrue(cond.locked()) cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) self.assertTrue(cond.locked()) cond.notify(2) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) self.assertTrue(cond.locked()) cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1, 2], result) self.assertTrue(cond.locked()) cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1, 2, 3], result) self.assertTrue(cond.locked()) @@ -524,49 +483,46 @@ async def c3(result): self.assertTrue(t3.done()) self.assertTrue(t3.result()) - def test_wait_cancel(self): - with self.assertWarns(DeprecationWarning): - cond = asyncio.Condition(loop=self.loop) - self.loop.run_until_complete(cond.acquire()) - - wait = self.loop.create_task(cond.wait()) - self.loop.call_soon(wait.cancel) - self.assertRaises( - asyncio.CancelledError, - self.loop.run_until_complete, wait) + async def test_wait_cancel(self): + cond = asyncio.Condition() + await cond.acquire() + + wait = asyncio.create_task(cond.wait()) + asyncio.get_running_loop().call_soon(wait.cancel) + with self.assertRaises(asyncio.CancelledError): + await wait self.assertFalse(cond._waiters) self.assertTrue(cond.locked()) - def test_wait_cancel_contested(self): - with self.assertWarns(DeprecationWarning): - cond = asyncio.Condition(loop=self.loop) + async def test_wait_cancel_contested(self): + cond = asyncio.Condition() - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() self.assertTrue(cond.locked()) - wait_task = self.loop.create_task(cond.wait()) - test_utils.run_briefly(self.loop) + wait_task = asyncio.create_task(cond.wait()) + await asyncio.sleep(0) self.assertFalse(cond.locked()) # Notify, but contest the lock before cancelling - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() self.assertTrue(cond.locked()) cond.notify() - self.loop.call_soon(wait_task.cancel) - self.loop.call_soon(cond.release) + asyncio.get_running_loop().call_soon(wait_task.cancel) + asyncio.get_running_loop().call_soon(cond.release) try: - self.loop.run_until_complete(wait_task) + await wait_task except asyncio.CancelledError: # Should not happen, since no cancellation points pass self.assertTrue(cond.locked()) - def test_wait_cancel_after_notify(self): + async def test_wait_cancel_after_notify(self): # See bpo-32841 with self.assertWarns(DeprecationWarning): - cond = asyncio.Condition(loop=self.loop) + cond = asyncio.Condition(loop=asyncio.get_running_loop()) waited = False async def wait_on_cond(): @@ -575,30 +531,27 @@ async def wait_on_cond(): waited = True # Make sure this area was reached await cond.wait() - waiter = asyncio.ensure_future(wait_on_cond(), loop=self.loop) - test_utils.run_briefly(self.loop) # Start waiting + waiter = asyncio.create_task(wait_on_cond()) + await asyncio.sleep(0) # Start waiting - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() cond.notify() - test_utils.run_briefly(self.loop) # Get to acquire() + await asyncio.sleep(0) # Get to acquire() waiter.cancel() - test_utils.run_briefly(self.loop) # Activate cancellation + await asyncio.sleep(0) # Activate cancellation cond.release() - test_utils.run_briefly(self.loop) # Cancellation should occur + await asyncio.sleep(0) # Cancellation should occur self.assertTrue(waiter.cancelled()) self.assertTrue(waited) - def test_wait_unacquired(self): - with self.assertWarns(DeprecationWarning): - cond = asyncio.Condition(loop=self.loop) - self.assertRaises( - RuntimeError, - self.loop.run_until_complete, cond.wait()) + async def test_wait_unacquired(self): + cond = asyncio.Condition() + with self.assertRaises(RuntimeError): + await cond.wait() - def test_wait_for(self): - with self.assertWarns(DeprecationWarning): - cond = asyncio.Condition(loop=self.loop) + async def test_wait_for(self): + cond = asyncio.Condition() presult = False def predicate(): @@ -613,43 +566,39 @@ async def c1(result): cond.release() return True - t = self.loop.create_task(c1(result)) + t = asyncio.create_task(c1(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() cond.notify() cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) presult = True - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() cond.notify() cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) self.assertTrue(t.done()) self.assertTrue(t.result()) - def test_wait_for_unacquired(self): - with self.assertWarns(DeprecationWarning): - cond = asyncio.Condition(loop=self.loop) + async def test_wait_for_unacquired(self): + cond = asyncio.Condition() # predicate can return true immediately - res = self.loop.run_until_complete(cond.wait_for(lambda: [1, 2, 3])) + res = await cond.wait_for(lambda: [1, 2, 3]) self.assertEqual([1, 2, 3], res) - self.assertRaises( - RuntimeError, - self.loop.run_until_complete, - cond.wait_for(lambda: False)) + with self.assertRaises(RuntimeError): + await cond.wait_for(lambda: False) - def test_notify(self): - with self.assertWarns(DeprecationWarning): - cond = asyncio.Condition(loop=self.loop) + async def test_notify(self): + cond = asyncio.Condition() result = [] async def c1(result): @@ -673,24 +622,24 @@ async def c3(result): cond.release() return True - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) - t3 = self.loop.create_task(c3(result)) + t1 = asyncio.create_task(c1(result)) + t2 = asyncio.create_task(c2(result)) + t3 = asyncio.create_task(c3(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() cond.notify(1) cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() cond.notify(1) cond.notify(2048) cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1, 2, 3], result) self.assertTrue(t1.done()) @@ -700,9 +649,8 @@ async def c3(result): self.assertTrue(t3.done()) self.assertTrue(t3.result()) - def test_notify_all(self): - with self.assertWarns(DeprecationWarning): - cond = asyncio.Condition(loop=self.loop) + async def test_notify_all(self): + cond = asyncio.Condition() result = [] @@ -720,16 +668,16 @@ async def c2(result): cond.release() return True - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) + t1 = asyncio.create_task(c1(result)) + t2 = asyncio.create_task(c2(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() cond.notify_all() cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1, 2], result) self.assertTrue(t1.done()) @@ -738,22 +686,19 @@ async def c2(result): self.assertTrue(t2.result()) def test_notify_unacquired(self): - with self.assertWarns(DeprecationWarning): - cond = asyncio.Condition(loop=self.loop) + cond = asyncio.Condition() self.assertRaises(RuntimeError, cond.notify) def test_notify_all_unacquired(self): - with self.assertWarns(DeprecationWarning): - cond = asyncio.Condition(loop=self.loop) + cond = asyncio.Condition() self.assertRaises(RuntimeError, cond.notify_all) - def test_repr(self): - with self.assertWarns(DeprecationWarning): - cond = asyncio.Condition(loop=self.loop) + async def test_repr(self): + cond = asyncio.Condition() self.assertTrue('unlocked' in repr(cond)) self.assertTrue(RGX_REPR.match(repr(cond))) - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() self.assertTrue('locked' in repr(cond)) cond._waiters.append(mock.Mock()) @@ -764,79 +709,106 @@ def test_repr(self): self.assertTrue('waiters:2' in repr(cond)) self.assertTrue(RGX_REPR.match(repr(cond))) - def test_context_manager(self): - async def f(): - cond = asyncio.Condition() + async def test_context_manager(self): + cond = asyncio.Condition() + self.assertFalse(cond.locked()) + async with cond: + self.assertTrue(cond.locked()) + self.assertFalse(cond.locked()) + + async def test_explicit_lock(self): + async def f(lock=None, cond=None): + if lock is None: + lock = asyncio.Lock() + if cond is None: + cond = asyncio.Condition(lock) + self.assertIs(cond._lock, lock) + self.assertFalse(lock.locked()) self.assertFalse(cond.locked()) async with cond: + self.assertTrue(lock.locked()) self.assertTrue(cond.locked()) + self.assertFalse(lock.locked()) + self.assertFalse(cond.locked()) + async with lock: + self.assertTrue(lock.locked()) + self.assertTrue(cond.locked()) + self.assertFalse(lock.locked()) self.assertFalse(cond.locked()) - self.loop.run_until_complete(f()) - - def test_explicit_lock(self): - with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=self.loop) - cond = asyncio.Condition(lock, loop=self.loop) - - self.assertIs(cond._lock, lock) - self.assertIs(cond._loop, lock._loop) - - def test_ambiguous_loops(self): - loop = self.new_test_loop() - self.addCleanup(loop.close) - with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=self.loop) - with self.assertRaises(ValueError): - asyncio.Condition(lock, loop=loop) + # All should work in the same way. + await f() + await f(asyncio.Lock()) + lock = asyncio.Lock() + await f(lock, asyncio.Condition(lock)) - def test_timeout_in_block(self): + async def test_ambiguous_loops(self): loop = asyncio.new_event_loop() self.addCleanup(loop.close) - async def task_timeout(): - condition = asyncio.Condition(loop=loop) - async with condition: - with self.assertRaises(asyncio.TimeoutError): - await asyncio.wait_for(condition.wait(), timeout=0.5) + async def wrong_loop_in_lock(): + with self.assertWarns(DeprecationWarning): + asyncio.Lock(loop=loop) + lock = asyncio.Lock() + lock._loop = loop # use private API for testing + async with lock: + # acquired immediately via the fast-path + # without interaction with any event loop. + # cond.acquire() will trigger waiting on the lock + # and it will discover the event loop mismatch. + with self.assertRaisesRegex( + ValueError, + "loop argument must agree with lock", + ): + asyncio.Condition(lock) + + async def wrong_loop_in_cond(): + # Same analogy here with the condition's loop. + lock = asyncio.Lock() + async with lock: + with self.assertRaisesRegex( + ValueError, + "loop argument must agree with lock" + ): + asyncio.Condition(lock, loop=loop) - with self.assertWarns(DeprecationWarning): - loop.run_until_complete(task_timeout()) + await wrong_loop_in_lock() + await wrong_loop_in_cond() + async def test_timeout_in_block(self): + condition = asyncio.Condition() + async with condition: + with self.assertRaises(asyncio.TimeoutError): + await asyncio.wait_for(condition.wait(), timeout=0.5) -class SemaphoreTests(test_utils.TestCase): - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() +class SemaphoreTests(unittest.IsolatedAsyncioTestCase): - def test_ctor_loop(self): + async def test_ctor_loop(self): loop = mock.Mock() with self.assertWarns(DeprecationWarning): sem = asyncio.Semaphore(loop=loop) self.assertIs(sem._loop, loop) with self.assertWarns(DeprecationWarning): - sem = asyncio.Semaphore(loop=self.loop) - self.assertIs(sem._loop, self.loop) + sem = asyncio.Semaphore(loop=asyncio.get_running_loop()) + self.assertIs(sem._loop, asyncio.get_running_loop()) - def test_ctor_noloop(self): - asyncio.set_event_loop(self.loop) + async def test_ctor_noloop(self): sem = asyncio.Semaphore() - self.assertIs(sem._loop, self.loop) + self.assertIs(sem._loop, asyncio.get_running_loop()) - def test_initial_value_zero(self): + async def test_initial_value_zero(self): with self.assertWarns(DeprecationWarning): - sem = asyncio.Semaphore(0, loop=self.loop) + sem = asyncio.Semaphore(0, loop=asyncio.get_running_loop()) self.assertTrue(sem.locked()) - def test_repr(self): - with self.assertWarns(DeprecationWarning): - sem = asyncio.Semaphore(loop=self.loop) + async def test_repr(self): + sem = asyncio.Semaphore() self.assertTrue(repr(sem).endswith('[unlocked, value:1]>')) self.assertTrue(RGX_REPR.match(repr(sem))) - self.loop.run_until_complete(sem.acquire()) + await sem.acquire() self.assertTrue(repr(sem).endswith('[locked]>')) self.assertTrue('waiters' not in repr(sem)) self.assertTrue(RGX_REPR.match(repr(sem))) @@ -849,21 +821,15 @@ def test_repr(self): self.assertTrue('waiters:2' in repr(sem)) self.assertTrue(RGX_REPR.match(repr(sem))) - def test_semaphore(self): - with self.assertWarns(DeprecationWarning): - sem = asyncio.Semaphore(loop=self.loop) + async def test_semaphore(self): + sem = asyncio.Semaphore() self.assertEqual(1, sem._value) - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def acquire_lock(): - return (yield from sem) - with self.assertRaisesRegex( TypeError, - "'Semaphore' object is not iterable", + "object Semaphore can't be used in 'await' expression", ): - self.loop.run_until_complete(acquire_lock()) + await sem self.assertFalse(sem.locked()) self.assertEqual(1, sem._value) @@ -871,13 +837,12 @@ def acquire_lock(): def test_semaphore_value(self): self.assertRaises(ValueError, asyncio.Semaphore, -1) - def test_acquire(self): - with self.assertWarns(DeprecationWarning): - sem = asyncio.Semaphore(3, loop=self.loop) + async def test_acquire(self): + sem = asyncio.Semaphore(3) result = [] - self.assertTrue(self.loop.run_until_complete(sem.acquire())) - self.assertTrue(self.loop.run_until_complete(sem.acquire())) + self.assertTrue(await sem.acquire()) + self.assertTrue(await sem.acquire()) self.assertFalse(sem.locked()) async def c1(result): @@ -900,23 +865,23 @@ async def c4(result): result.append(4) return True - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) - t3 = self.loop.create_task(c3(result)) + t1 = asyncio.create_task(c1(result)) + t2 = asyncio.create_task(c2(result)) + t3 = asyncio.create_task(c3(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) self.assertTrue(sem.locked()) self.assertEqual(2, len(sem._waiters)) self.assertEqual(0, sem._value) - t4 = self.loop.create_task(c4(result)) + t4 = asyncio.create_task(c4(result)) sem.release() sem.release() self.assertEqual(2, sem._value) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual(0, sem._value) self.assertEqual(3, len(result)) self.assertTrue(sem.locked()) @@ -931,69 +896,65 @@ async def c4(result): # cleanup locked semaphore sem.release() - self.loop.run_until_complete(asyncio.gather(*race_tasks)) + await asyncio.gather(*race_tasks) - def test_acquire_cancel(self): - with self.assertWarns(DeprecationWarning): - sem = asyncio.Semaphore(loop=self.loop) - self.loop.run_until_complete(sem.acquire()) - - acquire = self.loop.create_task(sem.acquire()) - self.loop.call_soon(acquire.cancel) - self.assertRaises( - asyncio.CancelledError, - self.loop.run_until_complete, acquire) + async def test_acquire_cancel(self): + sem = asyncio.Semaphore() + await sem.acquire() + + acquire = asyncio.create_task(sem.acquire()) + asyncio.get_running_loop().call_soon(acquire.cancel) + with self.assertRaises(asyncio.CancelledError): + await acquire self.assertTrue((not sem._waiters) or all(waiter.done() for waiter in sem._waiters)) - def test_acquire_cancel_before_awoken(self): - with self.assertWarns(DeprecationWarning): - sem = asyncio.Semaphore(value=0, loop=self.loop) + async def test_acquire_cancel_before_awoken(self): + sem = asyncio.Semaphore(value=0) - t1 = self.loop.create_task(sem.acquire()) - t2 = self.loop.create_task(sem.acquire()) - t3 = self.loop.create_task(sem.acquire()) - t4 = self.loop.create_task(sem.acquire()) + t1 = asyncio.create_task(sem.acquire()) + t2 = asyncio.create_task(sem.acquire()) + t3 = asyncio.create_task(sem.acquire()) + t4 = asyncio.create_task(sem.acquire()) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) - sem.release() t1.cancel() t2.cancel() + sem.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) num_done = sum(t.done() for t in [t3, t4]) self.assertEqual(num_done, 1) + self.assertTrue(t3.done()) + self.assertFalse(t4.done()) t3.cancel() t4.cancel() - test_utils.run_briefly(self.loop) - - def test_acquire_hang(self): - with self.assertWarns(DeprecationWarning): - sem = asyncio.Semaphore(value=0, loop=self.loop) + await asyncio.sleep(0) - t1 = self.loop.create_task(sem.acquire()) - t2 = self.loop.create_task(sem.acquire()) + async def test_acquire_hang(self): + sem = asyncio.Semaphore(value=0) - test_utils.run_briefly(self.loop) + t1 = asyncio.create_task(sem.acquire()) + t2 = asyncio.create_task(sem.acquire()) + await asyncio.sleep(0) - sem.release() t1.cancel() - - test_utils.run_briefly(self.loop) + sem.release() + await asyncio.sleep(0) self.assertTrue(sem.locked()) + self.assertTrue(t2.done()) - def test_release_not_acquired(self): + async def test_release_not_acquired(self): with self.assertWarns(DeprecationWarning): - sem = asyncio.BoundedSemaphore(loop=self.loop) + sem = asyncio.BoundedSemaphore(loop=asyncio.get_running_loop()) self.assertRaises(ValueError, sem.release) - def test_release_no_waiters(self): - with self.assertWarns(DeprecationWarning): - sem = asyncio.Semaphore(loop=self.loop) - self.loop.run_until_complete(sem.acquire()) + async def test_release_no_waiters(self): + sem = asyncio.Semaphore() + await sem.acquire() self.assertTrue(sem.locked()) sem.release() diff --git a/Lib/unittest/async_case.py b/Lib/unittest/async_case.py index 22cb61b7211c6..a2980e797ac5b 100644 --- a/Lib/unittest/async_case.py +++ b/Lib/unittest/async_case.py @@ -4,7 +4,6 @@ from .case import TestCase - class IsolatedAsyncioTestCase(TestCase): # Names intentionally have a long prefix # to reduce a chance of clashing with user-defined attributes diff --git a/Misc/NEWS.d/next/Tests/2021-12-19-12-20-57.bpo-46129.I3MunH.rst b/Misc/NEWS.d/next/Tests/2021-12-19-12-20-57.bpo-46129.I3MunH.rst new file mode 100644 index 0000000000000..b06436a4c8460 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-12-19-12-20-57.bpo-46129.I3MunH.rst @@ -0,0 +1,2 @@ +Rewrite ``asyncio.locks`` tests with +:class:`unittest.IsolatedAsyncioTestCase` usage. From webhook-mailer at python.org Sun Dec 19 13:12:45 2021 From: webhook-mailer at python.org (asvetlov) Date: Sun, 19 Dec 2021 18:12:45 -0000 Subject: [Python-checkins] Fix test error about deprecation warning (#30205) Message-ID: https://github.com/python/cpython/commit/2352644377f0d2febc226ba30c94046e4cc50130 commit: 2352644377f0d2febc226ba30c94046e4cc50130 branch: 3.9 author: Andrew Svetlov committer: asvetlov date: 2021-12-19T20:12:24+02:00 summary: Fix test error about deprecation warning (#30205) files: M Lib/test/test_asyncio/test_locks.py diff --git a/Lib/test/test_asyncio/test_locks.py b/Lib/test/test_asyncio/test_locks.py index cfb6421b38f60..b9aae360384ea 100644 --- a/Lib/test/test_asyncio/test_locks.py +++ b/Lib/test/test_asyncio/test_locks.py @@ -770,7 +770,8 @@ async def wrong_loop_in_cond(): ValueError, "loop argument must agree with lock" ): - asyncio.Condition(lock, loop=loop) + with self.assertWarns(DeprecationWarning): + asyncio.Condition(lock, loop=loop) await wrong_loop_in_lock() await wrong_loop_in_cond() From webhook-mailer at python.org Sun Dec 19 15:20:40 2021 From: webhook-mailer at python.org (rhettinger) Date: Sun, 19 Dec 2021 20:20:40 -0000 Subject: [Python-checkins] bpo-46076: Improve documentation for per-attribute docstrings with `__slots__` (GH-30109) Message-ID: https://github.com/python/cpython/commit/aeb9ef4c7287fe367b6e9adcf1c5f994d5bc1a09 commit: aeb9ef4c7287fe367b6e9adcf1c5f994d5bc1a09 branch: main author: Alex Waygood committer: rhettinger date: 2021-12-19T14:20:07-06:00 summary: bpo-46076: Improve documentation for per-attribute docstrings with `__slots__` (GH-30109) files: M Doc/reference/datamodel.rst diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index aa0d91ad1c97d..48c54d729424c 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1944,9 +1944,12 @@ Notes on using *__slots__* * Nonempty *__slots__* does not work for classes derived from "variable-length" built-in types such as :class:`int`, :class:`bytes` and :class:`tuple`. -* Any non-string iterable may be assigned to *__slots__*. Mappings may also be - used; however, in the future, special meaning may be assigned to the values - corresponding to each key. +* Any non-string :term:`iterable` may be assigned to *__slots__*. + +* If a :class:`dictionary ` is used to assign *__slots__*, the dictionary + keys will be used as the slot names. The values of the dictionary can be used + to provide per-attribute docstrings that will be recognised by + :func:`inspect.getdoc` and displayed in the output of :func:`help`. * :attr:`~instance.__class__` assignment works only if both classes have the same *__slots__*. From webhook-mailer at python.org Sun Dec 19 15:24:39 2021 From: webhook-mailer at python.org (rhettinger) Date: Sun, 19 Dec 2021 20:24:39 -0000 Subject: [Python-checkins] bpo-46131: add fastpath for PyFloat_Check() (#30200) Message-ID: https://github.com/python/cpython/commit/2ef06d412531d1163dbc72877c88aedf3ed82a25 commit: 2ef06d412531d1163dbc72877c88aedf3ed82a25 branch: main author: Matti Picus committer: rhettinger date: 2021-12-19T14:24:30-06:00 summary: bpo-46131: add fastpath for PyFloat_Check() (#30200) files: A Misc/NEWS.d/next/C API/2021-12-19-13-02-59.bpo-46131.ZBWQtO.rst M Doc/c-api/typeobj.rst M Include/floatobject.h M Include/object.h M Objects/floatobject.c M Objects/typeobject.c M Tools/gdb/libpython.py diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index cd8723efef6bb..eed2ac2c092ec 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -1145,6 +1145,7 @@ and :c:type:`PyType_Type` effectively act as defaults.) .. XXX Document more flags here? + .. data:: Py_TPFLAGS_FLOAT_SUBCLASS .. data:: Py_TPFLAGS_LONG_SUBCLASS .. data:: Py_TPFLAGS_LIST_SUBCLASS .. data:: Py_TPFLAGS_TUPLE_SUBCLASS diff --git a/Include/floatobject.h b/Include/floatobject.h index 3b6ca478eaef2..51be745e11cfa 100644 --- a/Include/floatobject.h +++ b/Include/floatobject.h @@ -14,6 +14,8 @@ extern "C" { PyAPI_DATA(PyTypeObject) PyFloat_Type; #define PyFloat_Check(op) PyObject_TypeCheck(op, &PyFloat_Type) +#define PyFloat_Check(op) \ + PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_FLOAT_SUBCLASS) #define PyFloat_CheckExact(op) Py_IS_TYPE(op, &PyFloat_Type) #ifdef Py_NAN diff --git a/Include/object.h b/Include/object.h index e5544e8b588ed..ee817a545a2b5 100644 --- a/Include/object.h +++ b/Include/object.h @@ -397,6 +397,7 @@ given type object has a specified feature. #define _Py_TPFLAGS_MATCH_SELF (1UL << 22) /* These flags are used to determine if a type is a subclass. */ +#define Py_TPFLAGS_FLOAT_SUBCLASS (1UL << 23) #define Py_TPFLAGS_LONG_SUBCLASS (1UL << 24) #define Py_TPFLAGS_LIST_SUBCLASS (1UL << 25) #define Py_TPFLAGS_TUPLE_SUBCLASS (1UL << 26) diff --git a/Misc/NEWS.d/next/C API/2021-12-19-13-02-59.bpo-46131.ZBWQtO.rst b/Misc/NEWS.d/next/C API/2021-12-19-13-02-59.bpo-46131.ZBWQtO.rst new file mode 100644 index 0000000000000..08768ca594966 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2021-12-19-13-02-59.bpo-46131.ZBWQtO.rst @@ -0,0 +1,2 @@ +Add a fast path for ``PyFloat_Check`` via a ``Py_TPFLAGS_FLOAT_SUBCLASS`` +flag. diff --git a/Objects/floatobject.c b/Objects/floatobject.c index f8620d6f8ef0b..37434f32bd995 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -1959,6 +1959,7 @@ PyTypeObject PyFloat_Type = { 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_FLOAT_SUBCLASS | _Py_TPFLAGS_MATCH_SELF, /* tp_flags */ float_new__doc__, /* tp_doc */ 0, /* tp_traverse */ diff --git a/Objects/typeobject.c b/Objects/typeobject.c index af35180cdb983..8bd92801da4ba 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -5783,6 +5783,9 @@ inherit_special(PyTypeObject *type, PyTypeObject *base) else if (PyType_IsSubtype(base, &PyDict_Type)) { type->tp_flags |= Py_TPFLAGS_DICT_SUBCLASS; } + else if (PyType_IsSubtype(base, &PyFloat_Type)) { + type->tp_flags |= Py_TPFLAGS_FLOAT_SUBCLASS; + } if (PyType_HasFeature(base, _Py_TPFLAGS_MATCH_SELF)) { type->tp_flags |= _Py_TPFLAGS_MATCH_SELF; } diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py index a0a95e3fc63cb..41d1c3cc6e1bd 100755 --- a/Tools/gdb/libpython.py +++ b/Tools/gdb/libpython.py @@ -85,6 +85,7 @@ def _sizeof_void_p(): Py_TPFLAGS_MANAGED_DICT = (1 << 4) Py_TPFLAGS_HEAPTYPE = (1 << 9) +Py_TPFLAGS_FLOAT_SUBCLASS = (1 << 23) Py_TPFLAGS_LONG_SUBCLASS = (1 << 24) Py_TPFLAGS_LIST_SUBCLASS = (1 << 25) Py_TPFLAGS_TUPLE_SUBCLASS = (1 << 26) @@ -379,6 +380,8 @@ def subclass_from_type(cls, t): if tp_flags & Py_TPFLAGS_HEAPTYPE: return HeapTypeObjectPtr + if tp_flags & Py_TPFLAGS_FLOAT_SUBCLASS: + return PyFloatObjectPtr if tp_flags & Py_TPFLAGS_LONG_SUBCLASS: return PyLongObjectPtr if tp_flags & Py_TPFLAGS_LIST_SUBCLASS: @@ -910,6 +913,16 @@ class PyNoneStructPtr(PyObjectPtr): def proxyval(self, visited): return None +class PyFloatObjectPtr(PyObjectPtr): + _typename = 'PyFloatObject' + + def proxyval(self, visited): + return self.field('ob_fval') + + def write_repr(self, out, visited): + proxy = self.proxyval(visited) + out.write("%s" % proxy) + class PyFrameObjectPtr(PyObjectPtr): _typename = 'PyFrameObject' From webhook-mailer at python.org Sun Dec 19 16:05:55 2021 From: webhook-mailer at python.org (rhettinger) Date: Sun, 19 Dec 2021 21:05:55 -0000 Subject: [Python-checkins] Revert "bpo-46131: add fastpath for PyFloat_Check() (GH-30200)" (GH-30208) Message-ID: https://github.com/python/cpython/commit/29ea68bd1dcf30842c2ed908a6d815bc1d90f484 commit: 29ea68bd1dcf30842c2ed908a6d815bc1d90f484 branch: main author: Raymond Hettinger committer: rhettinger date: 2021-12-19T15:05:46-06:00 summary: Revert "bpo-46131: add fastpath for PyFloat_Check() (GH-30200)" (GH-30208) This reverts commit 2ef06d412531d1163dbc72877c88aedf3ed82a25. files: D Misc/NEWS.d/next/C API/2021-12-19-13-02-59.bpo-46131.ZBWQtO.rst M Doc/c-api/typeobj.rst M Include/floatobject.h M Include/object.h M Objects/floatobject.c M Objects/typeobject.c M Tools/gdb/libpython.py diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index eed2ac2c092ec..cd8723efef6bb 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -1145,7 +1145,6 @@ and :c:type:`PyType_Type` effectively act as defaults.) .. XXX Document more flags here? - .. data:: Py_TPFLAGS_FLOAT_SUBCLASS .. data:: Py_TPFLAGS_LONG_SUBCLASS .. data:: Py_TPFLAGS_LIST_SUBCLASS .. data:: Py_TPFLAGS_TUPLE_SUBCLASS diff --git a/Include/floatobject.h b/Include/floatobject.h index 51be745e11cfa..3b6ca478eaef2 100644 --- a/Include/floatobject.h +++ b/Include/floatobject.h @@ -14,8 +14,6 @@ extern "C" { PyAPI_DATA(PyTypeObject) PyFloat_Type; #define PyFloat_Check(op) PyObject_TypeCheck(op, &PyFloat_Type) -#define PyFloat_Check(op) \ - PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_FLOAT_SUBCLASS) #define PyFloat_CheckExact(op) Py_IS_TYPE(op, &PyFloat_Type) #ifdef Py_NAN diff --git a/Include/object.h b/Include/object.h index ee817a545a2b5..e5544e8b588ed 100644 --- a/Include/object.h +++ b/Include/object.h @@ -397,7 +397,6 @@ given type object has a specified feature. #define _Py_TPFLAGS_MATCH_SELF (1UL << 22) /* These flags are used to determine if a type is a subclass. */ -#define Py_TPFLAGS_FLOAT_SUBCLASS (1UL << 23) #define Py_TPFLAGS_LONG_SUBCLASS (1UL << 24) #define Py_TPFLAGS_LIST_SUBCLASS (1UL << 25) #define Py_TPFLAGS_TUPLE_SUBCLASS (1UL << 26) diff --git a/Misc/NEWS.d/next/C API/2021-12-19-13-02-59.bpo-46131.ZBWQtO.rst b/Misc/NEWS.d/next/C API/2021-12-19-13-02-59.bpo-46131.ZBWQtO.rst deleted file mode 100644 index 08768ca594966..0000000000000 --- a/Misc/NEWS.d/next/C API/2021-12-19-13-02-59.bpo-46131.ZBWQtO.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add a fast path for ``PyFloat_Check`` via a ``Py_TPFLAGS_FLOAT_SUBCLASS`` -flag. diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 37434f32bd995..f8620d6f8ef0b 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -1959,7 +1959,6 @@ PyTypeObject PyFloat_Type = { 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_FLOAT_SUBCLASS | _Py_TPFLAGS_MATCH_SELF, /* tp_flags */ float_new__doc__, /* tp_doc */ 0, /* tp_traverse */ diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 8bd92801da4ba..af35180cdb983 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -5783,9 +5783,6 @@ inherit_special(PyTypeObject *type, PyTypeObject *base) else if (PyType_IsSubtype(base, &PyDict_Type)) { type->tp_flags |= Py_TPFLAGS_DICT_SUBCLASS; } - else if (PyType_IsSubtype(base, &PyFloat_Type)) { - type->tp_flags |= Py_TPFLAGS_FLOAT_SUBCLASS; - } if (PyType_HasFeature(base, _Py_TPFLAGS_MATCH_SELF)) { type->tp_flags |= _Py_TPFLAGS_MATCH_SELF; } diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py index 41d1c3cc6e1bd..a0a95e3fc63cb 100755 --- a/Tools/gdb/libpython.py +++ b/Tools/gdb/libpython.py @@ -85,7 +85,6 @@ def _sizeof_void_p(): Py_TPFLAGS_MANAGED_DICT = (1 << 4) Py_TPFLAGS_HEAPTYPE = (1 << 9) -Py_TPFLAGS_FLOAT_SUBCLASS = (1 << 23) Py_TPFLAGS_LONG_SUBCLASS = (1 << 24) Py_TPFLAGS_LIST_SUBCLASS = (1 << 25) Py_TPFLAGS_TUPLE_SUBCLASS = (1 << 26) @@ -380,8 +379,6 @@ def subclass_from_type(cls, t): if tp_flags & Py_TPFLAGS_HEAPTYPE: return HeapTypeObjectPtr - if tp_flags & Py_TPFLAGS_FLOAT_SUBCLASS: - return PyFloatObjectPtr if tp_flags & Py_TPFLAGS_LONG_SUBCLASS: return PyLongObjectPtr if tp_flags & Py_TPFLAGS_LIST_SUBCLASS: @@ -913,16 +910,6 @@ class PyNoneStructPtr(PyObjectPtr): def proxyval(self, visited): return None -class PyFloatObjectPtr(PyObjectPtr): - _typename = 'PyFloatObject' - - def proxyval(self, visited): - return self.field('ob_fval') - - def write_repr(self, out, visited): - proxy = self.proxyval(visited) - out.write("%s" % proxy) - class PyFrameObjectPtr(PyObjectPtr): _typename = 'PyFrameObject' From webhook-mailer at python.org Sun Dec 19 16:11:21 2021 From: webhook-mailer at python.org (rhettinger) Date: Sun, 19 Dec 2021 21:11:21 -0000 Subject: [Python-checkins] bpo-46076: Improve documentation for per-attribute docstrings with `__slots__` (GH-30109) (GH-30206) Message-ID: https://github.com/python/cpython/commit/d7537ac8e3a3ef15d2c5f3fe90e998618b6a97b9 commit: d7537ac8e3a3ef15d2c5f3fe90e998618b6a97b9 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: rhettinger date: 2021-12-19T15:11:12-06:00 summary: bpo-46076: Improve documentation for per-attribute docstrings with `__slots__` (GH-30109) (GH-30206) files: M Doc/reference/datamodel.rst diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index d2e586a1989dd..be1f714113293 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1877,9 +1877,12 @@ Notes on using *__slots__* * Nonempty *__slots__* does not work for classes derived from "variable-length" built-in types such as :class:`int`, :class:`bytes` and :class:`tuple`. -* Any non-string iterable may be assigned to *__slots__*. Mappings may also be - used; however, in the future, special meaning may be assigned to the values - corresponding to each key. +* Any non-string :term:`iterable` may be assigned to *__slots__*. + +* If a :class:`dictionary ` is used to assign *__slots__*, the dictionary + keys will be used as the slot names. The values of the dictionary can be used + to provide per-attribute docstrings that will be recognised by + :func:`inspect.getdoc` and displayed in the output of :func:`help`. * :attr:`~instance.__class__` assignment works only if both classes have the same *__slots__*. From webhook-mailer at python.org Sun Dec 19 16:11:41 2021 From: webhook-mailer at python.org (rhettinger) Date: Sun, 19 Dec 2021 21:11:41 -0000 Subject: [Python-checkins] bpo-46076: Improve documentation for per-attribute docstrings with `__slots__` (GH-30109) (GH-30207) Message-ID: https://github.com/python/cpython/commit/8bfb11a791679a33024c9857e082afed0d71e0b4 commit: 8bfb11a791679a33024c9857e082afed0d71e0b4 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: rhettinger date: 2021-12-19T15:11:37-06:00 summary: bpo-46076: Improve documentation for per-attribute docstrings with `__slots__` (GH-30109) (GH-30207) files: M Doc/reference/datamodel.rst diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 1f0fc17ad360e..967308b95ffcb 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1868,9 +1868,12 @@ Notes on using *__slots__* * Nonempty *__slots__* does not work for classes derived from "variable-length" built-in types such as :class:`int`, :class:`bytes` and :class:`tuple`. -* Any non-string iterable may be assigned to *__slots__*. Mappings may also be - used; however, in the future, special meaning may be assigned to the values - corresponding to each key. +* Any non-string :term:`iterable` may be assigned to *__slots__*. + +* If a :class:`dictionary ` is used to assign *__slots__*, the dictionary + keys will be used as the slot names. The values of the dictionary can be used + to provide per-attribute docstrings that will be recognised by + :func:`inspect.getdoc` and displayed in the output of :func:`help`. * :attr:`~instance.__class__` assignment works only if both classes have the same *__slots__*. From webhook-mailer at python.org Sun Dec 19 23:48:52 2021 From: webhook-mailer at python.org (Fidget-Spinner) Date: Mon, 20 Dec 2021 04:48:52 -0000 Subject: [Python-checkins] bpo-46104: Fix example broken by GH-30148 (GH-30203) Message-ID: https://github.com/python/cpython/commit/7c5c3f7254d78babcaf7a2ec187fd6ec53b8403c commit: 7c5c3f7254d78babcaf7a2ec187fd6ec53b8403c branch: main author: Alex Waygood committer: Fidget-Spinner <28750310+Fidget-Spinner at users.noreply.github.com> date: 2021-12-20T12:48:35+08:00 summary: bpo-46104: Fix example broken by GH-30148 (GH-30203) See discussion in GH-30179. files: M Doc/library/typing.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index ec1b8d1a5ebcc..727941b57b547 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -432,7 +432,7 @@ value of type :data:`Any` and assign it to any variable:: a = [] # OK a = 2 # OK - s = '' # Inferred type of 's' is str + s: str = '' s = a # OK def foo(item: Any) -> int: From webhook-mailer at python.org Mon Dec 20 01:02:14 2021 From: webhook-mailer at python.org (miss-islington) Date: Mon, 20 Dec 2021 06:02:14 -0000 Subject: [Python-checkins] [3.9] bpo-46104: Fix example broken by GH-30148 (GH-30203) (GH-30210) Message-ID: https://github.com/python/cpython/commit/8e4564d14ae0fc97cfea4de9e271468d4c28a6fe commit: 8e4564d14ae0fc97cfea4de9e271468d4c28a6fe branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-19T22:02:04-08:00 summary: [3.9] bpo-46104: Fix example broken by GH-30148 (GH-30203) (GH-30210) See discussion in GH-30179. (cherry picked from commit 7c5c3f7254d78babcaf7a2ec187fd6ec53b8403c) Co-authored-by: Alex Waygood Automerge-Triggered-By: GH:Fidget-Spinner files: M Doc/library/typing.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 34aaa1fac3077..2da544884db1d 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -362,7 +362,7 @@ value of type :data:`Any` and assign it to any variable:: a = [] # OK a = 2 # OK - s = '' # Inferred type of 's' is str + s: str = '' s = a # OK def foo(item: Any) -> int: From webhook-mailer at python.org Mon Dec 20 01:02:14 2021 From: webhook-mailer at python.org (miss-islington) Date: Mon, 20 Dec 2021 06:02:14 -0000 Subject: [Python-checkins] [3.10] bpo-46104: Fix example broken by GH-30148 (GH-30203) (GH-30209) Message-ID: https://github.com/python/cpython/commit/0c0bd78ccf8e1eb1d8ecfce423daf2a2f8ca6d3b commit: 0c0bd78ccf8e1eb1d8ecfce423daf2a2f8ca6d3b branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-19T22:01:51-08:00 summary: [3.10] bpo-46104: Fix example broken by GH-30148 (GH-30203) (GH-30209) See discussion in GH-30179. (cherry picked from commit 7c5c3f7254d78babcaf7a2ec187fd6ec53b8403c) Co-authored-by: Alex Waygood Automerge-Triggered-By: GH:Fidget-Spinner files: M Doc/library/typing.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index c154364ee56ec..3adb495ff7933 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -432,7 +432,7 @@ value of type :data:`Any` and assign it to any variable:: a = [] # OK a = 2 # OK - s = '' # Inferred type of 's' is str + s: str = '' s = a # OK def foo(item: Any) -> int: From webhook-mailer at python.org Mon Dec 20 05:23:40 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Mon, 20 Dec 2021 10:23:40 -0000 Subject: [Python-checkins] bpo-23819: Get rid of assert statements in test_asyncio (GH-30212) Message-ID: https://github.com/python/cpython/commit/6ca78affc8023bc5023189d64d8050857662042a commit: 6ca78affc8023bc5023189d64d8050857662042a branch: main author: Serhiy Storchaka committer: serhiy-storchaka date: 2021-12-20T12:23:05+02:00 summary: bpo-23819: Get rid of assert statements in test_asyncio (GH-30212) To keep checks even if run tests with optimized Python. Either use special assertion methods like assertEqual() or raise an AssertionError explicitly. files: M Lib/test/test_asyncio/test_base_events.py M Lib/test/test_asyncio/test_events.py M Lib/test/test_asyncio/test_futures.py M Lib/test/test_asyncio/test_sendfile.py M Lib/test/test_asyncio/test_sock_lowlevel.py M Lib/test/test_asyncio/test_sslproto.py M Lib/test/test_asyncio/test_streams.py M Lib/test/test_asyncio/test_tasks.py M Lib/test/test_asyncio/test_unix_events.py M Lib/test/test_asyncio/utils.py diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index d812bc9edea57..4c0d09e6f702e 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -647,7 +647,7 @@ def run_loop(): 'Exception in callback.*zero'), exc_info=(ZeroDivisionError, MOCK_ANY, MOCK_ANY)) - assert not mock_handler.called + self.assertFalse(mock_handler.called) def test_set_exc_handler_broken(self): def run_loop(): @@ -1007,22 +1007,26 @@ def __init__(self, create_future=False): if create_future: self.done = asyncio.get_running_loop().create_future() + def _assert_state(self, *expected): + if self.state not in expected: + raise AssertionError(f'state: {self.state!r}, expected: {expected!r}') + def connection_made(self, transport): self.transport = transport - assert self.state == 'INITIAL', self.state + self._assert_state('INITIAL') self.state = 'CONNECTED' transport.write(b'GET / HTTP/1.0\r\nHost: example.com\r\n\r\n') def data_received(self, data): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.nbytes += len(data) def eof_received(self): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.state = 'EOF' def connection_lost(self, exc): - assert self.state in ('CONNECTED', 'EOF'), self.state + self._assert_state('CONNECTED', 'EOF') self.state = 'CLOSED' if self.done: self.done.set_result(None) @@ -1037,20 +1041,24 @@ def __init__(self, create_future=False, loop=None): if create_future: self.done = loop.create_future() + def _assert_state(self, expected): + if self.state != expected: + raise AssertionError(f'state: {self.state!r}, expected: {expected!r}') + def connection_made(self, transport): self.transport = transport - assert self.state == 'INITIAL', self.state + self._assert_state('INITIAL') self.state = 'INITIALIZED' def datagram_received(self, data, addr): - assert self.state == 'INITIALIZED', self.state + self._assert_state('INITIALIZED') self.nbytes += len(data) def error_received(self, exc): - assert self.state == 'INITIALIZED', self.state + self._assert_state('INITIALIZED') def connection_lost(self, exc): - assert self.state == 'INITIALIZED', self.state + self._assert_state('INITIALIZED') self.state = 'CLOSED' if self.done: self.done.set_result(None) @@ -1399,7 +1407,7 @@ def test_create_connection_bluetooth(self, m_socket): addr = ('00:01:02:03:04:05', 1) def getaddrinfo(host, port, *args, **kw): - assert (host, port) == addr + self.assertEqual((host, port), addr) return [(999, 1, 999, '', (addr, 1))] m_socket.getaddrinfo = getaddrinfo @@ -1698,7 +1706,7 @@ def test_create_datagram_endpoint_sock_unix(self): lambda: MyDatagramProto(create_future=True, loop=self.loop), family=socket.AF_UNIX) transport, protocol = self.loop.run_until_complete(fut) - assert transport._sock.family == socket.AF_UNIX + self.assertEqual(transport._sock.family, socket.AF_UNIX) transport.close() self.loop.run_until_complete(protocol.done) self.assertEqual('CLOSED', protocol.state) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index fe791fa4232c0..c46c9dd40c83b 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -88,23 +88,27 @@ def __init__(self, loop=None): self.connected = loop.create_future() self.done = loop.create_future() + def _assert_state(self, *expected): + if self.state not in expected: + raise AssertionError(f'state: {self.state!r}, expected: {expected!r}') + def connection_made(self, transport): self.transport = transport - assert self.state == 'INITIAL', self.state + self._assert_state('INITIAL') self.state = 'CONNECTED' if self.connected: self.connected.set_result(None) def data_received(self, data): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.nbytes += len(data) def eof_received(self): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.state = 'EOF' def connection_lost(self, exc): - assert self.state in ('CONNECTED', 'EOF'), self.state + self._assert_state('CONNECTED', 'EOF') self.state = 'CLOSED' if self.done: self.done.set_result(None) @@ -125,20 +129,24 @@ def __init__(self, loop=None): if loop is not None: self.done = loop.create_future() + def _assert_state(self, expected): + if self.state != expected: + raise AssertionError(f'state: {self.state!r}, expected: {expected!r}') + def connection_made(self, transport): self.transport = transport - assert self.state == 'INITIAL', self.state + self._assert_state('INITIAL') self.state = 'INITIALIZED' def datagram_received(self, data, addr): - assert self.state == 'INITIALIZED', self.state + self._assert_state('INITIALIZED') self.nbytes += len(data) def error_received(self, exc): - assert self.state == 'INITIALIZED', self.state + self._assert_state('INITIALIZED') def connection_lost(self, exc): - assert self.state == 'INITIALIZED', self.state + self._assert_state('INITIALIZED') self.state = 'CLOSED' if self.done: self.done.set_result(None) @@ -154,23 +162,27 @@ def __init__(self, loop=None): if loop is not None: self.done = loop.create_future() + def _assert_state(self, expected): + if self.state != expected: + raise AssertionError(f'state: {self.state!r}, expected: {expected!r}') + def connection_made(self, transport): self.transport = transport - assert self.state == ['INITIAL'], self.state + self._assert_state(['INITIAL']) self.state.append('CONNECTED') def data_received(self, data): - assert self.state == ['INITIAL', 'CONNECTED'], self.state + self._assert_state(['INITIAL', 'CONNECTED']) self.nbytes += len(data) def eof_received(self): - assert self.state == ['INITIAL', 'CONNECTED'], self.state + self._assert_state(['INITIAL', 'CONNECTED']) self.state.append('EOF') def connection_lost(self, exc): if 'EOF' not in self.state: self.state.append('EOF') # It is okay if EOF is missed. - assert self.state == ['INITIAL', 'CONNECTED', 'EOF'], self.state + self._assert_state(['INITIAL', 'CONNECTED', 'EOF']) self.state.append('CLOSED') if self.done: self.done.set_result(None) @@ -185,13 +197,17 @@ def __init__(self, loop=None): if loop is not None: self.done = loop.create_future() + def _assert_state(self, expected): + if self.state != expected: + raise AssertionError(f'state: {self.state!r}, expected: {expected!r}') + def connection_made(self, transport): self.transport = transport - assert self.state == 'INITIAL', self.state + self._assert_state('INITIAL') self.state = 'CONNECTED' def connection_lost(self, exc): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.state = 'CLOSED' if self.done: self.done.set_result(None) @@ -210,31 +226,35 @@ def __init__(self, loop): self.got_data = {1: asyncio.Event(), 2: asyncio.Event()} + def _assert_state(self, expected): + if self.state != expected: + raise AssertionError(f'state: {self.state!r}, expected: {expected!r}') + def connection_made(self, transport): self.transport = transport - assert self.state == 'INITIAL', self.state + self._assert_state('INITIAL') self.state = 'CONNECTED' self.connected.set_result(None) def connection_lost(self, exc): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.state = 'CLOSED' self.completed.set_result(None) def pipe_data_received(self, fd, data): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.data[fd] += data self.got_data[fd].set() def pipe_connection_lost(self, fd, exc): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') if exc: self.disconnects[fd].set_exception(exc) else: self.disconnects[fd].set_result(exc) def process_exited(self): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.returncode = self.transport.get_returncode() @@ -1284,7 +1304,7 @@ def test_create_datagram_endpoint_sock(self): else: break else: - assert False, 'Can not create socket.' + self.fail('Can not create socket.') f = self.loop.create_datagram_endpoint( lambda: MyDatagramProto(loop=self.loop), sock=sock) diff --git a/Lib/test/test_asyncio/test_futures.py b/Lib/test/test_asyncio/test_futures.py index 42b9499edd78b..0c379e0fb0f95 100644 --- a/Lib/test/test_asyncio/test_futures.py +++ b/Lib/test/test_asyncio/test_futures.py @@ -54,30 +54,30 @@ def done(self): or self.__exception is not None) def result(self): - assert not self.cancelled() + self.assertFalse(self.cancelled()) if self.__exception is not None: raise self.__exception return self.__result def exception(self): - assert not self.cancelled() + self.assertFalse(self.cancelled()) return self.__exception def set_result(self, result): - assert not self.done() - assert result is not None + self.assertFalse(self.done()) + self.assertIsNotNone(result) self.__result = result def set_exception(self, exception): - assert not self.done() - assert exception is not None + self.assertFalse(self.done()) + self.assertIsNotNone(exception) self.__exception = exception def __iter__(self): if not self.done(): self._asyncio_future_blocking = True yield self - assert self.done() + self.assertTrue(self.done()) return self.result() @@ -91,12 +91,12 @@ def setUp(self): def test_wrap_future(self): f = DuckFuture() g = asyncio.wrap_future(f) - assert g is f + self.assertIs(g, f) def test_ensure_future(self): f = DuckFuture() g = asyncio.ensure_future(f) - assert g is f + self.assertIs(g, f) class BaseFutureTests: diff --git a/Lib/test/test_asyncio/test_sendfile.py b/Lib/test/test_asyncio/test_sendfile.py index 01c698653ec67..0a5466a0af152 100644 --- a/Lib/test/test_asyncio/test_sendfile.py +++ b/Lib/test/test_asyncio/test_sendfile.py @@ -36,25 +36,29 @@ def __init__(self, loop=None, close_after=0): self.data = bytearray() self.close_after = close_after + def _assert_state(self, *expected): + if self.state not in expected: + raise AssertionError(f'state: {self.state!r}, expected: {expected!r}') + def connection_made(self, transport): self.transport = transport - assert self.state == 'INITIAL', self.state + self._assert_state('INITIAL') self.state = 'CONNECTED' if self.connected: self.connected.set_result(None) def eof_received(self): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.state = 'EOF' def connection_lost(self, exc): - assert self.state in ('CONNECTED', 'EOF'), self.state + self._assert_state('CONNECTED', 'EOF') self.state = 'CLOSED' if self.done: self.done.set_result(None) def data_received(self, data): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.nbytes += len(data) self.data.extend(data) super().data_received(data) diff --git a/Lib/test/test_asyncio/test_sock_lowlevel.py b/Lib/test/test_asyncio/test_sock_lowlevel.py index d8a5df8ede1f8..ab022a357d205 100644 --- a/Lib/test/test_asyncio/test_sock_lowlevel.py +++ b/Lib/test/test_asyncio/test_sock_lowlevel.py @@ -23,24 +23,28 @@ def __init__(self, loop=None): self.connected = loop.create_future() self.done = loop.create_future() + def _assert_state(self, *expected): + if self.state not in expected: + raise AssertionError(f'state: {self.state!r}, expected: {expected!r}') + def connection_made(self, transport): self.transport = transport - assert self.state == 'INITIAL', self.state + self._assert_state('INITIAL') self.state = 'CONNECTED' if self.connected: self.connected.set_result(None) transport.write(b'GET / HTTP/1.0\r\nHost: example.com\r\n\r\n') def data_received(self, data): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.nbytes += len(data) def eof_received(self): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.state = 'EOF' def connection_lost(self, exc): - assert self.state in ('CONNECTED', 'EOF'), self.state + self._assert_state('CONNECTED', 'EOF') self.state = 'CLOSED' if self.done: self.done.set_result(None) @@ -451,7 +455,7 @@ def test_create_connection_sock(self): else: break else: - assert False, 'Can not create socket.' + self.fail('Can not create socket.') f = self.loop.create_connection( lambda: MyProto(loop=self.loop), sock=sock) diff --git a/Lib/test/test_asyncio/test_sslproto.py b/Lib/test/test_asyncio/test_sslproto.py index a47e43dd4cadb..22a216a83e3f9 100644 --- a/Lib/test/test_asyncio/test_sslproto.py +++ b/Lib/test/test_asyncio/test_sslproto.py @@ -383,9 +383,9 @@ def connection_made(self, tr): def get_buffer(self, sizehint): return self.buf - def buffer_updated(self, nsize): - assert nsize == 1 - self.on_data.set_result(bytes(self.buf[:nsize])) + def buffer_updated(slf, nsize): + self.assertEqual(nsize, 1) + slf.on_data.set_result(bytes(slf.buf[:nsize])) class ClientProtoSecond(asyncio.Protocol): def __init__(self, on_data, on_eof): diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py index a6ea24ceceda2..227b2279e172c 100644 --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -987,10 +987,10 @@ def test_eof_feed_when_closing_writer(self): wr.close() f = wr.wait_closed() self.loop.run_until_complete(f) - assert rd.at_eof() + self.assertTrue(rd.at_eof()) f = rd.read() data = self.loop.run_until_complete(f) - assert data == b'' + self.assertEqual(data, b'') self.assertEqual(messages, []) diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index a88cb89e4e6ee..832ff80f115ca 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -278,7 +278,7 @@ async def coro(): self.set_event_loop(loop) fut = asyncio.ensure_future(Aw(coro()), loop=loop) loop.run_until_complete(fut) - assert fut.result() == 'ok' + self.assertEqual(fut.result(), 'ok') def test_ensure_future_neither(self): with self.assertRaises(TypeError): @@ -1016,7 +1016,7 @@ async def inner(): async def main(): result = await asyncio.wait_for(inner(), timeout=.01) - assert result == 1 + self.assertEqual(result, 1) asyncio.run(main()) diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py index 643638564e342..c3422850ce1b7 100644 --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -34,7 +34,8 @@ def EXITCODE(exitcode): def SIGNAL(signum): - assert 1 <= signum <= 68 + if not 1 <= signum <= 68: + raise AssertionError(f'invalid signum {signum}') return 32768 - signum diff --git a/Lib/test/test_asyncio/utils.py b/Lib/test/test_asyncio/utils.py index 3765194cd0dd2..0b9cde6878f37 100644 --- a/Lib/test/test_asyncio/utils.py +++ b/Lib/test/test_asyncio/utils.py @@ -409,12 +409,13 @@ def _remove_writer(self, fd): return False def assert_writer(self, fd, callback, *args): - assert fd in self.writers, 'fd {} is not registered'.format(fd) + if fd not in self.writers: + raise AssertionError(f'fd {fd} is not registered') handle = self.writers[fd] - assert handle._callback == callback, '{!r} != {!r}'.format( - handle._callback, callback) - assert handle._args == args, '{!r} != {!r}'.format( - handle._args, args) + if handle._callback != callback: + raise AssertionError(f'{handle._callback!r} != {callback!r}') + if handle._args != args: + raise AssertionError(f'{handle._args!r} != {args!r}') def _ensure_fd_no_transport(self, fd): if not isinstance(fd, int): @@ -530,7 +531,8 @@ def close_loop(loop): thread.join() def set_event_loop(self, loop, *, cleanup=True): - assert loop is not None + if loop is None: + raise AssertionError('loop is None') # ensure that the event loop is passed explicitly in asyncio events.set_event_loop(None) if cleanup: From webhook-mailer at python.org Mon Dec 20 07:51:23 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Mon, 20 Dec 2021 12:51:23 -0000 Subject: [Python-checkins] bpo-23819: Get rid of assert statements in test_asyncio (GH-30212) (GH-30213) Message-ID: https://github.com/python/cpython/commit/95948169d75bed3936284ea2225e83e07ec5fe20 commit: 95948169d75bed3936284ea2225e83e07ec5fe20 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: serhiy-storchaka date: 2021-12-20T14:50:45+02:00 summary: bpo-23819: Get rid of assert statements in test_asyncio (GH-30212) (GH-30213) To keep checks even if run tests with optimized Python. Either use special assertion methods like assertEqual() or raise an AssertionError explicitly. (cherry picked from commit 6ca78affc8023bc5023189d64d8050857662042a) Co-authored-by: Serhiy Storchaka files: M Lib/test/test_asyncio/test_base_events.py M Lib/test/test_asyncio/test_events.py M Lib/test/test_asyncio/test_futures.py M Lib/test/test_asyncio/test_sendfile.py M Lib/test/test_asyncio/test_sock_lowlevel.py M Lib/test/test_asyncio/test_sslproto.py M Lib/test/test_asyncio/test_streams.py M Lib/test/test_asyncio/test_tasks.py M Lib/test/test_asyncio/test_unix_events.py M Lib/test/test_asyncio/utils.py diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index 5691d4250aca9..f7ef23e55090e 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -643,7 +643,7 @@ def run_loop(): 'Exception in callback.*zero'), exc_info=(ZeroDivisionError, MOCK_ANY, MOCK_ANY)) - assert not mock_handler.called + self.assertFalse(mock_handler.called) def test_set_exc_handler_broken(self): def run_loop(): @@ -1003,22 +1003,26 @@ def __init__(self, create_future=False): if create_future: self.done = asyncio.get_running_loop().create_future() + def _assert_state(self, *expected): + if self.state not in expected: + raise AssertionError(f'state: {self.state!r}, expected: {expected!r}') + def connection_made(self, transport): self.transport = transport - assert self.state == 'INITIAL', self.state + self._assert_state('INITIAL') self.state = 'CONNECTED' transport.write(b'GET / HTTP/1.0\r\nHost: example.com\r\n\r\n') def data_received(self, data): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.nbytes += len(data) def eof_received(self): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.state = 'EOF' def connection_lost(self, exc): - assert self.state in ('CONNECTED', 'EOF'), self.state + self._assert_state('CONNECTED', 'EOF') self.state = 'CLOSED' if self.done: self.done.set_result(None) @@ -1033,20 +1037,24 @@ def __init__(self, create_future=False, loop=None): if create_future: self.done = loop.create_future() + def _assert_state(self, expected): + if self.state != expected: + raise AssertionError(f'state: {self.state!r}, expected: {expected!r}') + def connection_made(self, transport): self.transport = transport - assert self.state == 'INITIAL', self.state + self._assert_state('INITIAL') self.state = 'INITIALIZED' def datagram_received(self, data, addr): - assert self.state == 'INITIALIZED', self.state + self._assert_state('INITIALIZED') self.nbytes += len(data) def error_received(self, exc): - assert self.state == 'INITIALIZED', self.state + self._assert_state('INITIALIZED') def connection_lost(self, exc): - assert self.state == 'INITIALIZED', self.state + self._assert_state('INITIALIZED') self.state = 'CLOSED' if self.done: self.done.set_result(None) @@ -1395,7 +1403,7 @@ def test_create_connection_bluetooth(self, m_socket): addr = ('00:01:02:03:04:05', 1) def getaddrinfo(host, port, *args, **kw): - assert (host, port) == addr + self.assertEqual((host, port), addr) return [(999, 1, 999, '', (addr, 1))] m_socket.getaddrinfo = getaddrinfo @@ -1694,7 +1702,7 @@ def test_create_datagram_endpoint_sock_unix(self): lambda: MyDatagramProto(create_future=True, loop=self.loop), family=socket.AF_UNIX) transport, protocol = self.loop.run_until_complete(fut) - assert transport._sock.family == socket.AF_UNIX + self.assertEqual(transport._sock.family, socket.AF_UNIX) transport.close() self.loop.run_until_complete(protocol.done) self.assertEqual('CLOSED', protocol.state) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 778dd43f68848..bed7b5d30b85a 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -87,23 +87,27 @@ def __init__(self, loop=None): self.connected = loop.create_future() self.done = loop.create_future() + def _assert_state(self, *expected): + if self.state not in expected: + raise AssertionError(f'state: {self.state!r}, expected: {expected!r}') + def connection_made(self, transport): self.transport = transport - assert self.state == 'INITIAL', self.state + self._assert_state('INITIAL') self.state = 'CONNECTED' if self.connected: self.connected.set_result(None) def data_received(self, data): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.nbytes += len(data) def eof_received(self): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.state = 'EOF' def connection_lost(self, exc): - assert self.state in ('CONNECTED', 'EOF'), self.state + self._assert_state('CONNECTED', 'EOF') self.state = 'CLOSED' if self.done: self.done.set_result(None) @@ -124,20 +128,24 @@ def __init__(self, loop=None): if loop is not None: self.done = loop.create_future() + def _assert_state(self, expected): + if self.state != expected: + raise AssertionError(f'state: {self.state!r}, expected: {expected!r}') + def connection_made(self, transport): self.transport = transport - assert self.state == 'INITIAL', self.state + self._assert_state('INITIAL') self.state = 'INITIALIZED' def datagram_received(self, data, addr): - assert self.state == 'INITIALIZED', self.state + self._assert_state('INITIALIZED') self.nbytes += len(data) def error_received(self, exc): - assert self.state == 'INITIALIZED', self.state + self._assert_state('INITIALIZED') def connection_lost(self, exc): - assert self.state == 'INITIALIZED', self.state + self._assert_state('INITIALIZED') self.state = 'CLOSED' if self.done: self.done.set_result(None) @@ -153,23 +161,27 @@ def __init__(self, loop=None): if loop is not None: self.done = loop.create_future() + def _assert_state(self, expected): + if self.state != expected: + raise AssertionError(f'state: {self.state!r}, expected: {expected!r}') + def connection_made(self, transport): self.transport = transport - assert self.state == ['INITIAL'], self.state + self._assert_state(['INITIAL']) self.state.append('CONNECTED') def data_received(self, data): - assert self.state == ['INITIAL', 'CONNECTED'], self.state + self._assert_state(['INITIAL', 'CONNECTED']) self.nbytes += len(data) def eof_received(self): - assert self.state == ['INITIAL', 'CONNECTED'], self.state + self._assert_state(['INITIAL', 'CONNECTED']) self.state.append('EOF') def connection_lost(self, exc): if 'EOF' not in self.state: self.state.append('EOF') # It is okay if EOF is missed. - assert self.state == ['INITIAL', 'CONNECTED', 'EOF'], self.state + self._assert_state(['INITIAL', 'CONNECTED', 'EOF']) self.state.append('CLOSED') if self.done: self.done.set_result(None) @@ -184,13 +196,17 @@ def __init__(self, loop=None): if loop is not None: self.done = loop.create_future() + def _assert_state(self, expected): + if self.state != expected: + raise AssertionError(f'state: {self.state!r}, expected: {expected!r}') + def connection_made(self, transport): self.transport = transport - assert self.state == 'INITIAL', self.state + self._assert_state('INITIAL') self.state = 'CONNECTED' def connection_lost(self, exc): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.state = 'CLOSED' if self.done: self.done.set_result(None) @@ -209,31 +225,35 @@ def __init__(self, loop): self.got_data = {1: asyncio.Event(), 2: asyncio.Event()} + def _assert_state(self, expected): + if self.state != expected: + raise AssertionError(f'state: {self.state!r}, expected: {expected!r}') + def connection_made(self, transport): self.transport = transport - assert self.state == 'INITIAL', self.state + self._assert_state('INITIAL') self.state = 'CONNECTED' self.connected.set_result(None) def connection_lost(self, exc): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.state = 'CLOSED' self.completed.set_result(None) def pipe_data_received(self, fd, data): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.data[fd] += data self.got_data[fd].set() def pipe_connection_lost(self, fd, exc): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') if exc: self.disconnects[fd].set_exception(exc) else: self.disconnects[fd].set_result(exc) def process_exited(self): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.returncode = self.transport.get_returncode() @@ -1283,7 +1303,7 @@ def test_create_datagram_endpoint_sock(self): else: break else: - assert False, 'Can not create socket.' + self.fail('Can not create socket.') f = self.loop.create_datagram_endpoint( lambda: MyDatagramProto(loop=self.loop), sock=sock) diff --git a/Lib/test/test_asyncio/test_futures.py b/Lib/test/test_asyncio/test_futures.py index 42b9499edd78b..0c379e0fb0f95 100644 --- a/Lib/test/test_asyncio/test_futures.py +++ b/Lib/test/test_asyncio/test_futures.py @@ -54,30 +54,30 @@ def done(self): or self.__exception is not None) def result(self): - assert not self.cancelled() + self.assertFalse(self.cancelled()) if self.__exception is not None: raise self.__exception return self.__result def exception(self): - assert not self.cancelled() + self.assertFalse(self.cancelled()) return self.__exception def set_result(self, result): - assert not self.done() - assert result is not None + self.assertFalse(self.done()) + self.assertIsNotNone(result) self.__result = result def set_exception(self, exception): - assert not self.done() - assert exception is not None + self.assertFalse(self.done()) + self.assertIsNotNone(exception) self.__exception = exception def __iter__(self): if not self.done(): self._asyncio_future_blocking = True yield self - assert self.done() + self.assertTrue(self.done()) return self.result() @@ -91,12 +91,12 @@ def setUp(self): def test_wrap_future(self): f = DuckFuture() g = asyncio.wrap_future(f) - assert g is f + self.assertIs(g, f) def test_ensure_future(self): f = DuckFuture() g = asyncio.ensure_future(f) - assert g is f + self.assertIs(g, f) class BaseFutureTests: diff --git a/Lib/test/test_asyncio/test_sendfile.py b/Lib/test/test_asyncio/test_sendfile.py index 01c698653ec67..0a5466a0af152 100644 --- a/Lib/test/test_asyncio/test_sendfile.py +++ b/Lib/test/test_asyncio/test_sendfile.py @@ -36,25 +36,29 @@ def __init__(self, loop=None, close_after=0): self.data = bytearray() self.close_after = close_after + def _assert_state(self, *expected): + if self.state not in expected: + raise AssertionError(f'state: {self.state!r}, expected: {expected!r}') + def connection_made(self, transport): self.transport = transport - assert self.state == 'INITIAL', self.state + self._assert_state('INITIAL') self.state = 'CONNECTED' if self.connected: self.connected.set_result(None) def eof_received(self): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.state = 'EOF' def connection_lost(self, exc): - assert self.state in ('CONNECTED', 'EOF'), self.state + self._assert_state('CONNECTED', 'EOF') self.state = 'CLOSED' if self.done: self.done.set_result(None) def data_received(self, data): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.nbytes += len(data) self.data.extend(data) super().data_received(data) diff --git a/Lib/test/test_asyncio/test_sock_lowlevel.py b/Lib/test/test_asyncio/test_sock_lowlevel.py index d8a5df8ede1f8..ab022a357d205 100644 --- a/Lib/test/test_asyncio/test_sock_lowlevel.py +++ b/Lib/test/test_asyncio/test_sock_lowlevel.py @@ -23,24 +23,28 @@ def __init__(self, loop=None): self.connected = loop.create_future() self.done = loop.create_future() + def _assert_state(self, *expected): + if self.state not in expected: + raise AssertionError(f'state: {self.state!r}, expected: {expected!r}') + def connection_made(self, transport): self.transport = transport - assert self.state == 'INITIAL', self.state + self._assert_state('INITIAL') self.state = 'CONNECTED' if self.connected: self.connected.set_result(None) transport.write(b'GET / HTTP/1.0\r\nHost: example.com\r\n\r\n') def data_received(self, data): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.nbytes += len(data) def eof_received(self): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.state = 'EOF' def connection_lost(self, exc): - assert self.state in ('CONNECTED', 'EOF'), self.state + self._assert_state('CONNECTED', 'EOF') self.state = 'CLOSED' if self.done: self.done.set_result(None) @@ -451,7 +455,7 @@ def test_create_connection_sock(self): else: break else: - assert False, 'Can not create socket.' + self.fail('Can not create socket.') f = self.loop.create_connection( lambda: MyProto(loop=self.loop), sock=sock) diff --git a/Lib/test/test_asyncio/test_sslproto.py b/Lib/test/test_asyncio/test_sslproto.py index a47e43dd4cadb..22a216a83e3f9 100644 --- a/Lib/test/test_asyncio/test_sslproto.py +++ b/Lib/test/test_asyncio/test_sslproto.py @@ -383,9 +383,9 @@ def connection_made(self, tr): def get_buffer(self, sizehint): return self.buf - def buffer_updated(self, nsize): - assert nsize == 1 - self.on_data.set_result(bytes(self.buf[:nsize])) + def buffer_updated(slf, nsize): + self.assertEqual(nsize, 1) + slf.on_data.set_result(bytes(slf.buf[:nsize])) class ClientProtoSecond(asyncio.Protocol): def __init__(self, on_data, on_eof): diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py index a6ea24ceceda2..227b2279e172c 100644 --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -987,10 +987,10 @@ def test_eof_feed_when_closing_writer(self): wr.close() f = wr.wait_closed() self.loop.run_until_complete(f) - assert rd.at_eof() + self.assertTrue(rd.at_eof()) f = rd.read() data = self.loop.run_until_complete(f) - assert data == b'' + self.assertEqual(data, b'') self.assertEqual(messages, []) diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 773d5057fe4b2..1c05944c42d25 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -329,7 +329,7 @@ def coro(): self.set_event_loop(loop) fut = asyncio.ensure_future(Aw(coro()), loop=loop) loop.run_until_complete(fut) - assert fut.result() == 'ok' + self.assertEqual(fut.result(), 'ok') def test_ensure_future_neither(self): with self.assertRaises(TypeError): @@ -1155,7 +1155,7 @@ async def inner(): async def main(): result = await asyncio.wait_for(inner(), timeout=.01) - assert result == 1 + self.assertEqual(result, 1) asyncio.run(main()) diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py index 643638564e342..c3422850ce1b7 100644 --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -34,7 +34,8 @@ def EXITCODE(exitcode): def SIGNAL(signum): - assert 1 <= signum <= 68 + if not 1 <= signum <= 68: + raise AssertionError(f'invalid signum {signum}') return 32768 - signum diff --git a/Lib/test/test_asyncio/utils.py b/Lib/test/test_asyncio/utils.py index 3765194cd0dd2..0b9cde6878f37 100644 --- a/Lib/test/test_asyncio/utils.py +++ b/Lib/test/test_asyncio/utils.py @@ -409,12 +409,13 @@ def _remove_writer(self, fd): return False def assert_writer(self, fd, callback, *args): - assert fd in self.writers, 'fd {} is not registered'.format(fd) + if fd not in self.writers: + raise AssertionError(f'fd {fd} is not registered') handle = self.writers[fd] - assert handle._callback == callback, '{!r} != {!r}'.format( - handle._callback, callback) - assert handle._args == args, '{!r} != {!r}'.format( - handle._args, args) + if handle._callback != callback: + raise AssertionError(f'{handle._callback!r} != {callback!r}') + if handle._args != args: + raise AssertionError(f'{handle._args!r} != {args!r}') def _ensure_fd_no_transport(self, fd): if not isinstance(fd, int): @@ -530,7 +531,8 @@ def close_loop(loop): thread.join() def set_event_loop(self, loop, *, cleanup=True): - assert loop is not None + if loop is None: + raise AssertionError('loop is None') # ensure that the event loop is passed explicitly in asyncio events.set_event_loop(None) if cleanup: From webhook-mailer at python.org Mon Dec 20 10:43:42 2021 From: webhook-mailer at python.org (pablogsal) Date: Mon, 20 Dec 2021 15:43:42 -0000 Subject: [Python-checkins] bpo-46110: Add a recursion check to avoid stack overflow in the PEG parser (GH-30177) Message-ID: https://github.com/python/cpython/commit/e9898bf153d26059261ffef11f7643ae991e2a4c commit: e9898bf153d26059261ffef11f7643ae991e2a4c branch: main author: Pablo Galindo Salgado committer: pablogsal date: 2021-12-20T15:43:26Z summary: bpo-46110: Add a recursion check to avoid stack overflow in the PEG parser (GH-30177) Co-authored-by: Batuhan Taskaya files: A Misc/NEWS.d/next/Core and Builtins/2021-12-18-02-37-07.bpo-46110.B6hAfu.rst M Lib/test/test_syntax.py M Parser/parser.c M Parser/pegen.c M Tools/peg_generator/pegen/c_generator.py diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 6286529d2734e..c95bc15e7273d 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -1729,6 +1729,14 @@ def test_syntax_error_on_deeply_nested_blocks(self): """ self._check_error(source, "too many statically nested blocks") + @support.cpython_only + def test_error_on_parser_stack_overflow(self): + source = "-" * 100000 + "4" + for mode in ["exec", "eval", "single"]: + with self.subTest(mode=mode): + with self.assertRaises(MemoryError): + compile(source, "", mode) + def load_tests(loader, tests, pattern): tests.addTest(doctest.DocTestSuite()) diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-18-02-37-07.bpo-46110.B6hAfu.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-18-02-37-07.bpo-46110.B6hAfu.rst new file mode 100644 index 0000000000000..593d2855972c4 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-18-02-37-07.bpo-46110.B6hAfu.rst @@ -0,0 +1,2 @@ +Add a maximum recursion check to the PEG parser to avoid stack overflow. +Patch by Pablo Galindo diff --git a/Parser/parser.c b/Parser/parser.c index 4d576aa781542..07a04c917430c 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -6,6 +6,8 @@ #else # define D(x) #endif + +# define MAXSTACK 6000 static const int n_keyword_lists = 9; static KeywordToken *reserved_keywords[] = { (KeywordToken[]) {{NULL, -1}}, @@ -968,16 +970,19 @@ static asdl_seq *_loop1_222_rule(Parser *p); static mod_ty file_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } mod_ty _res = NULL; int _mark = p->mark; { // statements? $ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> file[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "statements? $")); @@ -993,7 +998,7 @@ file_rule(Parser *p) _res = _PyPegen_make_module ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1004,7 +1009,7 @@ file_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1012,16 +1017,19 @@ file_rule(Parser *p) static mod_ty interactive_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } mod_ty _res = NULL; int _mark = p->mark; { // statement_newline if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> interactive[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "statement_newline")); @@ -1034,7 +1042,7 @@ interactive_rule(Parser *p) _res = _PyAST_Interactive ( a , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1045,7 +1053,7 @@ interactive_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1053,16 +1061,19 @@ interactive_rule(Parser *p) static mod_ty eval_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } mod_ty _res = NULL; int _mark = p->mark; { // expressions NEWLINE* $ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> eval[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions NEWLINE* $")); @@ -1081,7 +1092,7 @@ eval_rule(Parser *p) _res = _PyAST_Expression ( a , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1092,7 +1103,7 @@ eval_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1100,16 +1111,19 @@ eval_rule(Parser *p) static mod_ty func_type_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } mod_ty _res = NULL; int _mark = p->mark; { // '(' type_expressions? ')' '->' expression NEWLINE* $ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> func_type[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' type_expressions? ')' '->' expression NEWLINE* $")); @@ -1140,7 +1154,7 @@ func_type_rule(Parser *p) _res = _PyAST_FunctionType ( a , b , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1151,7 +1165,7 @@ func_type_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1159,16 +1173,19 @@ func_type_rule(Parser *p) static expr_ty fstring_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> fstring[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); @@ -1187,7 +1204,7 @@ fstring_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1195,16 +1212,19 @@ fstring_rule(Parser *p) static asdl_stmt_seq* statements_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_stmt_seq* _res = NULL; int _mark = p->mark; { // statement+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statements[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "statement+")); @@ -1217,7 +1237,7 @@ statements_rule(Parser *p) _res = ( asdl_stmt_seq* ) _PyPegen_seq_flatten ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1228,7 +1248,7 @@ statements_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1236,16 +1256,19 @@ statements_rule(Parser *p) static asdl_stmt_seq* statement_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_stmt_seq* _res = NULL; int _mark = p->mark; { // compound_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statement[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "compound_stmt")); @@ -1258,7 +1281,7 @@ statement_rule(Parser *p) _res = ( asdl_stmt_seq* ) _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1269,7 +1292,7 @@ statement_rule(Parser *p) } { // simple_stmts if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statement[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "simple_stmts")); @@ -1282,7 +1305,7 @@ statement_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1293,7 +1316,7 @@ statement_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1301,16 +1324,19 @@ statement_rule(Parser *p) static asdl_stmt_seq* statement_newline_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_stmt_seq* _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -1319,7 +1345,7 @@ statement_newline_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // compound_stmt NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statement_newline[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "compound_stmt NEWLINE")); @@ -1335,7 +1361,7 @@ statement_newline_rule(Parser *p) _res = ( asdl_stmt_seq* ) _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1346,7 +1372,7 @@ statement_newline_rule(Parser *p) } { // simple_stmts if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statement_newline[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "simple_stmts")); @@ -1365,7 +1391,7 @@ statement_newline_rule(Parser *p) } { // NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statement_newline[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); @@ -1377,7 +1403,7 @@ statement_newline_rule(Parser *p) D(fprintf(stderr, "%*c+ statement_newline[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -1387,7 +1413,7 @@ statement_newline_rule(Parser *p) _res = ( asdl_stmt_seq* ) _PyPegen_singleton_seq ( p , CHECK ( stmt_ty , _PyAST_Pass ( EXTRA ) ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1398,7 +1424,7 @@ statement_newline_rule(Parser *p) } { // $ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statement_newline[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "$")); @@ -1411,7 +1437,7 @@ statement_newline_rule(Parser *p) _res = _PyPegen_interactive_exit ( p ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1422,7 +1448,7 @@ statement_newline_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1430,16 +1456,19 @@ statement_newline_rule(Parser *p) static asdl_stmt_seq* simple_stmts_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_stmt_seq* _res = NULL; int _mark = p->mark; { // simple_stmt !';' NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmts[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "simple_stmt !';' NEWLINE")); @@ -1457,7 +1486,7 @@ simple_stmts_rule(Parser *p) _res = ( asdl_stmt_seq* ) _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1468,7 +1497,7 @@ simple_stmts_rule(Parser *p) } { // ';'.simple_stmt+ ';'? NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmts[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "';'.simple_stmt+ ';'? NEWLINE")); @@ -1488,7 +1517,7 @@ simple_stmts_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1499,7 +1528,7 @@ simple_stmts_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1520,20 +1549,23 @@ simple_stmts_rule(Parser *p) static stmt_ty simple_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; if (_PyPegen_is_memoized(p, simple_stmt_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -1542,7 +1574,7 @@ simple_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // assignment if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment")); @@ -1561,7 +1593,7 @@ simple_stmt_rule(Parser *p) } { // star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); @@ -1573,7 +1605,7 @@ simple_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ simple_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -1583,7 +1615,7 @@ simple_stmt_rule(Parser *p) _res = _PyAST_Expr ( e , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1594,7 +1626,7 @@ simple_stmt_rule(Parser *p) } { // &'return' return_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'return' return_stmt")); @@ -1615,7 +1647,7 @@ simple_stmt_rule(Parser *p) } { // &('import' | 'from') import_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('import' | 'from') import_stmt")); @@ -1636,7 +1668,7 @@ simple_stmt_rule(Parser *p) } { // &'raise' raise_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'raise' raise_stmt")); @@ -1657,7 +1689,7 @@ simple_stmt_rule(Parser *p) } { // 'pass' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'pass'")); @@ -1669,7 +1701,7 @@ simple_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ simple_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'pass'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -1679,7 +1711,7 @@ simple_stmt_rule(Parser *p) _res = _PyAST_Pass ( EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1690,7 +1722,7 @@ simple_stmt_rule(Parser *p) } { // &'del' del_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'del' del_stmt")); @@ -1711,7 +1743,7 @@ simple_stmt_rule(Parser *p) } { // &'yield' yield_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'yield' yield_stmt")); @@ -1732,7 +1764,7 @@ simple_stmt_rule(Parser *p) } { // &'assert' assert_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'assert' assert_stmt")); @@ -1753,7 +1785,7 @@ simple_stmt_rule(Parser *p) } { // 'break' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'break'")); @@ -1765,7 +1797,7 @@ simple_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ simple_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'break'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -1775,7 +1807,7 @@ simple_stmt_rule(Parser *p) _res = _PyAST_Break ( EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1786,7 +1818,7 @@ simple_stmt_rule(Parser *p) } { // 'continue' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'continue'")); @@ -1798,7 +1830,7 @@ simple_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ simple_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'continue'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -1808,7 +1840,7 @@ simple_stmt_rule(Parser *p) _res = _PyAST_Continue ( EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1819,7 +1851,7 @@ simple_stmt_rule(Parser *p) } { // &'global' global_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'global' global_stmt")); @@ -1840,7 +1872,7 @@ simple_stmt_rule(Parser *p) } { // &'nonlocal' nonlocal_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'nonlocal' nonlocal_stmt")); @@ -1862,7 +1894,7 @@ simple_stmt_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, simple_stmt_type, _res); - D(p->level--); + p->level--; return _res; } @@ -1878,16 +1910,19 @@ simple_stmt_rule(Parser *p) static stmt_ty compound_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; { // &('def' | '@' | ASYNC) function_def if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('def' | '@' | ASYNC) function_def")); @@ -1908,7 +1943,7 @@ compound_stmt_rule(Parser *p) } { // &'if' if_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'if' if_stmt")); @@ -1929,7 +1964,7 @@ compound_stmt_rule(Parser *p) } { // &('class' | '@') class_def if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('class' | '@') class_def")); @@ -1950,7 +1985,7 @@ compound_stmt_rule(Parser *p) } { // &('with' | ASYNC) with_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('with' | ASYNC) with_stmt")); @@ -1971,7 +2006,7 @@ compound_stmt_rule(Parser *p) } { // &('for' | ASYNC) for_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('for' | ASYNC) for_stmt")); @@ -1992,7 +2027,7 @@ compound_stmt_rule(Parser *p) } { // &'try' try_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'try' try_stmt")); @@ -2013,7 +2048,7 @@ compound_stmt_rule(Parser *p) } { // &'while' while_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'while' while_stmt")); @@ -2034,7 +2069,7 @@ compound_stmt_rule(Parser *p) } { // match_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "match_stmt")); @@ -2053,7 +2088,7 @@ compound_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -2066,16 +2101,19 @@ compound_stmt_rule(Parser *p) static stmt_ty assignment_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -2084,7 +2122,7 @@ assignment_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME ':' expression ['=' annotated_rhs] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME ':' expression ['=' annotated_rhs]")); @@ -2105,7 +2143,7 @@ assignment_rule(Parser *p) D(fprintf(stderr, "%*c+ assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME ':' expression ['=' annotated_rhs]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2115,7 +2153,7 @@ assignment_rule(Parser *p) _res = CHECK_VERSION ( stmt_ty , 6 , "Variable annotation syntax is" , _PyAST_AnnAssign ( CHECK ( expr_ty , _PyPegen_set_expr_context ( p , a , Store ) ) , b , c , 1 , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2126,7 +2164,7 @@ assignment_rule(Parser *p) } { // ('(' single_target ')' | single_subscript_attribute_target) ':' expression ['=' annotated_rhs] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('(' single_target ')' | single_subscript_attribute_target) ':' expression ['=' annotated_rhs]")); @@ -2147,7 +2185,7 @@ assignment_rule(Parser *p) D(fprintf(stderr, "%*c+ assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "('(' single_target ')' | single_subscript_attribute_target) ':' expression ['=' annotated_rhs]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2157,7 +2195,7 @@ assignment_rule(Parser *p) _res = CHECK_VERSION ( stmt_ty , 6 , "Variable annotations syntax is" , _PyAST_AnnAssign ( a , b , c , 0 , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2168,7 +2206,7 @@ assignment_rule(Parser *p) } { // ((star_targets '='))+ (yield_expr | star_expressions) !'=' TYPE_COMMENT? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))+ (yield_expr | star_expressions) !'=' TYPE_COMMENT?")); @@ -2188,7 +2226,7 @@ assignment_rule(Parser *p) D(fprintf(stderr, "%*c+ assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "((star_targets '='))+ (yield_expr | star_expressions) !'=' TYPE_COMMENT?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2198,7 +2236,7 @@ assignment_rule(Parser *p) _res = _PyAST_Assign ( a , b , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2209,7 +2247,7 @@ assignment_rule(Parser *p) } { // single_target augassign ~ (yield_expr | star_expressions) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "single_target augassign ~ (yield_expr | star_expressions)")); @@ -2230,7 +2268,7 @@ assignment_rule(Parser *p) D(fprintf(stderr, "%*c+ assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "single_target augassign ~ (yield_expr | star_expressions)")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2240,7 +2278,7 @@ assignment_rule(Parser *p) _res = _PyAST_AugAssign ( a , b -> kind , c , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2249,13 +2287,13 @@ assignment_rule(Parser *p) D(fprintf(stderr, "%*c%s assignment[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "single_target augassign ~ (yield_expr | star_expressions)")); if (_cut_var) { - D(p->level--); + p->level--; return NULL; } } if (p->call_invalid_rules) { // invalid_assignment if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_assignment")); @@ -2274,7 +2312,7 @@ assignment_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -2282,16 +2320,19 @@ assignment_rule(Parser *p) static expr_ty annotated_rhs_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // yield_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> annotated_rhs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); @@ -2310,7 +2351,7 @@ annotated_rhs_rule(Parser *p) } { // star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> annotated_rhs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); @@ -2329,7 +2370,7 @@ annotated_rhs_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -2350,16 +2391,19 @@ annotated_rhs_rule(Parser *p) static AugOperator* augassign_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } AugOperator* _res = NULL; int _mark = p->mark; { // '+=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+='")); @@ -2372,7 +2416,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , Add ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2383,7 +2427,7 @@ augassign_rule(Parser *p) } { // '-=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-='")); @@ -2396,7 +2440,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , Sub ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2407,7 +2451,7 @@ augassign_rule(Parser *p) } { // '*=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*='")); @@ -2420,7 +2464,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , Mult ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2431,7 +2475,7 @@ augassign_rule(Parser *p) } { // '@=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@='")); @@ -2444,7 +2488,7 @@ augassign_rule(Parser *p) _res = CHECK_VERSION ( AugOperator* , 5 , "The '@' operator is" , _PyPegen_augoperator ( p , MatMult ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2455,7 +2499,7 @@ augassign_rule(Parser *p) } { // '/=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'/='")); @@ -2468,7 +2512,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , Div ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2479,7 +2523,7 @@ augassign_rule(Parser *p) } { // '%=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'%='")); @@ -2492,7 +2536,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , Mod ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2503,7 +2547,7 @@ augassign_rule(Parser *p) } { // '&=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'&='")); @@ -2516,7 +2560,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , BitAnd ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2527,7 +2571,7 @@ augassign_rule(Parser *p) } { // '|=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'|='")); @@ -2540,7 +2584,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , BitOr ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2551,7 +2595,7 @@ augassign_rule(Parser *p) } { // '^=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'^='")); @@ -2564,7 +2608,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , BitXor ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2575,7 +2619,7 @@ augassign_rule(Parser *p) } { // '<<=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'<<='")); @@ -2588,7 +2632,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , LShift ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2599,7 +2643,7 @@ augassign_rule(Parser *p) } { // '>>=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'>>='")); @@ -2612,7 +2656,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , RShift ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2623,7 +2667,7 @@ augassign_rule(Parser *p) } { // '**=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**='")); @@ -2636,7 +2680,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , Pow ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2647,7 +2691,7 @@ augassign_rule(Parser *p) } { // '//=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'//='")); @@ -2660,7 +2704,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , FloorDiv ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2671,7 +2715,7 @@ augassign_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -2679,16 +2723,19 @@ augassign_rule(Parser *p) static stmt_ty return_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -2697,7 +2744,7 @@ return_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'return' star_expressions? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> return_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'return' star_expressions?")); @@ -2712,7 +2759,7 @@ return_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ return_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'return' star_expressions?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2722,7 +2769,7 @@ return_stmt_rule(Parser *p) _res = _PyAST_Return ( a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2733,7 +2780,7 @@ return_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -2741,16 +2788,19 @@ return_stmt_rule(Parser *p) static stmt_ty raise_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -2759,7 +2809,7 @@ raise_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'raise' expression ['from' expression] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> raise_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'raise' expression ['from' expression]")); @@ -2777,7 +2827,7 @@ raise_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ raise_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'raise' expression ['from' expression]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2787,7 +2837,7 @@ raise_stmt_rule(Parser *p) _res = _PyAST_Raise ( a , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2798,7 +2848,7 @@ raise_stmt_rule(Parser *p) } { // 'raise' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> raise_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'raise'")); @@ -2810,7 +2860,7 @@ raise_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ raise_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'raise'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2820,7 +2870,7 @@ raise_stmt_rule(Parser *p) _res = _PyAST_Raise ( NULL , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2831,7 +2881,7 @@ raise_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -2839,16 +2889,19 @@ raise_stmt_rule(Parser *p) static stmt_ty global_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -2857,7 +2910,7 @@ global_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'global' ','.NAME+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> global_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'global' ','.NAME+")); @@ -2872,7 +2925,7 @@ global_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ global_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'global' ','.NAME+")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2882,7 +2935,7 @@ global_stmt_rule(Parser *p) _res = _PyAST_Global ( CHECK ( asdl_identifier_seq* , _PyPegen_map_names_to_ids ( p , a ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2893,7 +2946,7 @@ global_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -2901,16 +2954,19 @@ global_stmt_rule(Parser *p) static stmt_ty nonlocal_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -2919,7 +2975,7 @@ nonlocal_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'nonlocal' ','.NAME+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> nonlocal_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'nonlocal' ','.NAME+")); @@ -2934,7 +2990,7 @@ nonlocal_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ nonlocal_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'nonlocal' ','.NAME+")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2944,7 +3000,7 @@ nonlocal_stmt_rule(Parser *p) _res = _PyAST_Nonlocal ( CHECK ( asdl_identifier_seq* , _PyPegen_map_names_to_ids ( p , a ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2955,7 +3011,7 @@ nonlocal_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -2963,16 +3019,19 @@ nonlocal_stmt_rule(Parser *p) static stmt_ty del_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -2981,7 +3040,7 @@ del_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'del' del_targets &(';' | NEWLINE) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'del' del_targets &(';' | NEWLINE)")); @@ -2998,7 +3057,7 @@ del_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ del_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'del' del_targets &(';' | NEWLINE)")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3008,7 +3067,7 @@ del_stmt_rule(Parser *p) _res = _PyAST_Delete ( a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3019,7 +3078,7 @@ del_stmt_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_del_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_del_stmt")); @@ -3038,7 +3097,7 @@ del_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3046,16 +3105,19 @@ del_stmt_rule(Parser *p) static stmt_ty yield_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3064,7 +3126,7 @@ yield_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // yield_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> yield_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); @@ -3076,7 +3138,7 @@ yield_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ yield_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3086,7 +3148,7 @@ yield_stmt_rule(Parser *p) _res = _PyAST_Expr ( y , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3097,7 +3159,7 @@ yield_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3105,16 +3167,19 @@ yield_stmt_rule(Parser *p) static stmt_ty assert_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3123,7 +3188,7 @@ assert_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'assert' expression [',' expression] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> assert_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'assert' expression [',' expression]")); @@ -3141,7 +3206,7 @@ assert_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ assert_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'assert' expression [',' expression]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3151,7 +3216,7 @@ assert_stmt_rule(Parser *p) _res = _PyAST_Assert ( a , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3162,7 +3227,7 @@ assert_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3170,16 +3235,19 @@ assert_stmt_rule(Parser *p) static stmt_ty import_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; { // import_name if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "import_name")); @@ -3198,7 +3266,7 @@ import_stmt_rule(Parser *p) } { // import_from if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "import_from")); @@ -3217,7 +3285,7 @@ import_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3225,16 +3293,19 @@ import_stmt_rule(Parser *p) static stmt_ty import_name_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3243,7 +3314,7 @@ import_name_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'import' dotted_as_names if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_name[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'import' dotted_as_names")); @@ -3258,7 +3329,7 @@ import_name_rule(Parser *p) D(fprintf(stderr, "%*c+ import_name[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'import' dotted_as_names")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3268,7 +3339,7 @@ import_name_rule(Parser *p) _res = _PyAST_Import ( a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3279,7 +3350,7 @@ import_name_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3289,16 +3360,19 @@ import_name_rule(Parser *p) static stmt_ty import_from_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3307,7 +3381,7 @@ import_from_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'from' (('.' | '...'))* dotted_name 'import' import_from_targets if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from' (('.' | '...'))* dotted_name 'import' import_from_targets")); @@ -3331,7 +3405,7 @@ import_from_rule(Parser *p) D(fprintf(stderr, "%*c+ import_from[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'from' (('.' | '...'))* dotted_name 'import' import_from_targets")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3341,7 +3415,7 @@ import_from_rule(Parser *p) _res = _PyAST_ImportFrom ( b -> v . Name . id , c , _PyPegen_seq_count_dots ( a ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3352,7 +3426,7 @@ import_from_rule(Parser *p) } { // 'from' (('.' | '...'))+ 'import' import_from_targets if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from' (('.' | '...'))+ 'import' import_from_targets")); @@ -3373,7 +3447,7 @@ import_from_rule(Parser *p) D(fprintf(stderr, "%*c+ import_from[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'from' (('.' | '...'))+ 'import' import_from_targets")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3383,7 +3457,7 @@ import_from_rule(Parser *p) _res = _PyAST_ImportFrom ( NULL , b , _PyPegen_seq_count_dots ( a ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3394,7 +3468,7 @@ import_from_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3406,16 +3480,19 @@ import_from_rule(Parser *p) static asdl_alias_seq* import_from_targets_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_alias_seq* _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3424,7 +3501,7 @@ import_from_targets_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '(' import_from_as_names ','? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' import_from_as_names ','? ')'")); @@ -3447,7 +3524,7 @@ import_from_targets_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3458,7 +3535,7 @@ import_from_targets_rule(Parser *p) } { // import_from_as_names !',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "import_from_as_names !','")); @@ -3479,7 +3556,7 @@ import_from_targets_rule(Parser *p) } { // '*' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*'")); @@ -3491,7 +3568,7 @@ import_from_targets_rule(Parser *p) D(fprintf(stderr, "%*c+ import_from_targets[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3501,7 +3578,7 @@ import_from_targets_rule(Parser *p) _res = ( asdl_alias_seq* ) _PyPegen_singleton_seq ( p , CHECK ( alias_ty , _PyPegen_alias_for_star ( p , EXTRA ) ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3512,7 +3589,7 @@ import_from_targets_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_import_from_targets if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_import_from_targets")); @@ -3531,7 +3608,7 @@ import_from_targets_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3539,16 +3616,19 @@ import_from_targets_rule(Parser *p) static asdl_alias_seq* import_from_as_names_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_alias_seq* _res = NULL; int _mark = p->mark; { // ','.import_from_as_name+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from_as_names[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.import_from_as_name+")); @@ -3561,7 +3641,7 @@ import_from_as_names_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3572,7 +3652,7 @@ import_from_as_names_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3580,16 +3660,19 @@ import_from_as_names_rule(Parser *p) static alias_ty import_from_as_name_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } alias_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3598,7 +3681,7 @@ import_from_as_name_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME ['as' NAME] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from_as_name[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME ['as' NAME]")); @@ -3613,7 +3696,7 @@ import_from_as_name_rule(Parser *p) D(fprintf(stderr, "%*c+ import_from_as_name[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME ['as' NAME]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3623,7 +3706,7 @@ import_from_as_name_rule(Parser *p) _res = _PyAST_alias ( a -> v . Name . id , ( b ) ? ( ( expr_ty ) b ) -> v . Name . id : NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3634,7 +3717,7 @@ import_from_as_name_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3642,16 +3725,19 @@ import_from_as_name_rule(Parser *p) static asdl_alias_seq* dotted_as_names_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_alias_seq* _res = NULL; int _mark = p->mark; { // ','.dotted_as_name+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dotted_as_names[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.dotted_as_name+")); @@ -3664,7 +3750,7 @@ dotted_as_names_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3675,7 +3761,7 @@ dotted_as_names_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3683,16 +3769,19 @@ dotted_as_names_rule(Parser *p) static alias_ty dotted_as_name_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } alias_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3701,7 +3790,7 @@ dotted_as_name_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // dotted_name ['as' NAME] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dotted_as_name[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dotted_name ['as' NAME]")); @@ -3716,7 +3805,7 @@ dotted_as_name_rule(Parser *p) D(fprintf(stderr, "%*c+ dotted_as_name[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dotted_name ['as' NAME]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3726,7 +3815,7 @@ dotted_as_name_rule(Parser *p) _res = _PyAST_alias ( a -> v . Name . id , ( b ) ? ( ( expr_ty ) b ) -> v . Name . id : NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3737,7 +3826,7 @@ dotted_as_name_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3747,10 +3836,13 @@ static expr_ty dotted_name_raw(Parser *); static expr_ty dotted_name_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, dotted_name_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -3758,37 +3850,42 @@ dotted_name_rule(Parser *p) while (1) { int tmpvar_0 = _PyPegen_update_memo(p, _mark, dotted_name_type, _res); if (tmpvar_0) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; p->in_raw_rule++; void *_raw = dotted_name_raw(p); p->in_raw_rule--; - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty dotted_name_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // dotted_name '.' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dotted_name[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dotted_name '.' NAME")); @@ -3807,7 +3904,7 @@ dotted_name_raw(Parser *p) _res = _PyPegen_join_names_with_dot ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3818,7 +3915,7 @@ dotted_name_raw(Parser *p) } { // NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dotted_name[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); @@ -3837,7 +3934,7 @@ dotted_name_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3845,20 +3942,23 @@ dotted_name_raw(Parser *p) static asdl_stmt_seq* block_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_stmt_seq* _res = NULL; if (_PyPegen_is_memoized(p, block_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; { // NEWLINE INDENT statements DEDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT statements DEDENT")); @@ -3880,7 +3980,7 @@ block_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3891,7 +3991,7 @@ block_rule(Parser *p) } { // simple_stmts if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "simple_stmts")); @@ -3910,7 +4010,7 @@ block_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_block")); @@ -3930,7 +4030,7 @@ block_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, block_type, _res); - D(p->level--); + p->level--; return _res; } @@ -3938,16 +4038,19 @@ block_rule(Parser *p) static asdl_expr_seq* decorators_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_expr_seq* _res = NULL; int _mark = p->mark; { // (('@' named_expression NEWLINE))+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> decorators[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(('@' named_expression NEWLINE))+")); @@ -3960,7 +4063,7 @@ decorators_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3971,7 +4074,7 @@ decorators_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3979,16 +4082,19 @@ decorators_rule(Parser *p) static stmt_ty class_def_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; { // decorators class_def_raw if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_def[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "decorators class_def_raw")); @@ -4004,7 +4110,7 @@ class_def_rule(Parser *p) _res = _PyPegen_class_def_decorators ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4015,7 +4121,7 @@ class_def_rule(Parser *p) } { // class_def_raw if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_def[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "class_def_raw")); @@ -4034,7 +4140,7 @@ class_def_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4042,16 +4148,19 @@ class_def_rule(Parser *p) static stmt_ty class_def_raw_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -4060,7 +4169,7 @@ class_def_raw_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_class_def_raw if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_class_def_raw")); @@ -4079,7 +4188,7 @@ class_def_raw_rule(Parser *p) } { // 'class' NAME ['(' arguments? ')'] &&':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class' NAME ['(' arguments? ')'] &&':' block")); @@ -4103,7 +4212,7 @@ class_def_raw_rule(Parser *p) D(fprintf(stderr, "%*c+ class_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'class' NAME ['(' arguments? ')'] &&':' block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4113,7 +4222,7 @@ class_def_raw_rule(Parser *p) _res = _PyAST_ClassDef ( a -> v . Name . id , ( b ) ? ( ( expr_ty ) b ) -> v . Call . args : NULL , ( b ) ? ( ( expr_ty ) b ) -> v . Call . keywords : NULL , c , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4124,7 +4233,7 @@ class_def_raw_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4132,16 +4241,19 @@ class_def_raw_rule(Parser *p) static stmt_ty function_def_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; { // decorators function_def_raw if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> function_def[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "decorators function_def_raw")); @@ -4157,7 +4269,7 @@ function_def_rule(Parser *p) _res = _PyPegen_function_def_decorators ( p , d , f ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4168,7 +4280,7 @@ function_def_rule(Parser *p) } { // function_def_raw if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> function_def[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "function_def_raw")); @@ -4187,7 +4299,7 @@ function_def_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4198,16 +4310,19 @@ function_def_rule(Parser *p) static stmt_ty function_def_raw_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -4216,7 +4331,7 @@ function_def_raw_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_def_raw if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> function_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_def_raw")); @@ -4235,7 +4350,7 @@ function_def_raw_rule(Parser *p) } { // 'def' NAME &&'(' params? ')' ['->' expression] &&':' func_type_comment? block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> function_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'def' NAME &&'(' params? ')' ['->' expression] &&':' func_type_comment? block")); @@ -4271,7 +4386,7 @@ function_def_raw_rule(Parser *p) D(fprintf(stderr, "%*c+ function_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'def' NAME &&'(' params? ')' ['->' expression] &&':' func_type_comment? block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4281,7 +4396,7 @@ function_def_raw_rule(Parser *p) _res = _PyAST_FunctionDef ( n -> v . Name . id , ( params ) ? params : CHECK ( arguments_ty , _PyPegen_empty_arguments ( p ) ) , b , NULL , a , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4292,7 +4407,7 @@ function_def_raw_rule(Parser *p) } { // ASYNC 'def' NAME &&'(' params? ')' ['->' expression] &&':' func_type_comment? block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> function_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC 'def' NAME &&'(' params? ')' ['->' expression] &&':' func_type_comment? block")); @@ -4331,7 +4446,7 @@ function_def_raw_rule(Parser *p) D(fprintf(stderr, "%*c+ function_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC 'def' NAME &&'(' params? ')' ['->' expression] &&':' func_type_comment? block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4341,7 +4456,7 @@ function_def_raw_rule(Parser *p) _res = CHECK_VERSION ( stmt_ty , 5 , "Async functions are" , _PyAST_AsyncFunctionDef ( n -> v . Name . id , ( params ) ? params : CHECK ( arguments_ty , _PyPegen_empty_arguments ( p ) ) , b , NULL , a , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4352,7 +4467,7 @@ function_def_raw_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4360,16 +4475,19 @@ function_def_raw_rule(Parser *p) static arguments_ty params_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arguments_ty _res = NULL; int _mark = p->mark; if (p->call_invalid_rules) { // invalid_parameters if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> params[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_parameters")); @@ -4388,7 +4506,7 @@ params_rule(Parser *p) } { // parameters if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> params[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "parameters")); @@ -4407,7 +4525,7 @@ params_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4420,16 +4538,19 @@ params_rule(Parser *p) static arguments_ty parameters_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arguments_ty _res = NULL; int _mark = p->mark; { // slash_no_default param_no_default* param_with_default* star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_no_default param_no_default* param_with_default* star_etc?")); @@ -4451,7 +4572,7 @@ parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , a , NULL , b , c , d ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4462,7 +4583,7 @@ parameters_rule(Parser *p) } { // slash_with_default param_with_default* star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default param_with_default* star_etc?")); @@ -4481,7 +4602,7 @@ parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , NULL , a , NULL , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4492,7 +4613,7 @@ parameters_rule(Parser *p) } { // param_no_default+ param_with_default* star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default+ param_with_default* star_etc?")); @@ -4511,7 +4632,7 @@ parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , NULL , NULL , a , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4522,7 +4643,7 @@ parameters_rule(Parser *p) } { // param_with_default+ star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default+ star_etc?")); @@ -4538,7 +4659,7 @@ parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , NULL , NULL , NULL , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4549,7 +4670,7 @@ parameters_rule(Parser *p) } { // star_etc if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_etc")); @@ -4562,7 +4683,7 @@ parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , NULL , NULL , NULL , NULL , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4573,7 +4694,7 @@ parameters_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4581,16 +4702,19 @@ parameters_rule(Parser *p) static asdl_arg_seq* slash_no_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_arg_seq* _res = NULL; int _mark = p->mark; { // param_no_default+ '/' ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slash_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default+ '/' ','")); @@ -4609,7 +4733,7 @@ slash_no_default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4620,7 +4744,7 @@ slash_no_default_rule(Parser *p) } { // param_no_default+ '/' &')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slash_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default+ '/' &')'")); @@ -4638,7 +4762,7 @@ slash_no_default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4649,7 +4773,7 @@ slash_no_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4659,16 +4783,19 @@ slash_no_default_rule(Parser *p) static SlashWithDefault* slash_with_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } SlashWithDefault* _res = NULL; int _mark = p->mark; { // param_no_default* param_with_default+ '/' ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slash_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default* param_with_default+ '/' ','")); @@ -4690,7 +4817,7 @@ slash_with_default_rule(Parser *p) _res = _PyPegen_slash_with_default ( p , ( asdl_arg_seq* ) a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4701,7 +4828,7 @@ slash_with_default_rule(Parser *p) } { // param_no_default* param_with_default+ '/' &')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slash_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default* param_with_default+ '/' &')'")); @@ -4722,7 +4849,7 @@ slash_with_default_rule(Parser *p) _res = _PyPegen_slash_with_default ( p , ( asdl_arg_seq* ) a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4733,7 +4860,7 @@ slash_with_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4745,16 +4872,19 @@ slash_with_default_rule(Parser *p) static StarEtc* star_etc_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } StarEtc* _res = NULL; int _mark = p->mark; { // '*' param_no_default param_maybe_default* kwds? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' param_no_default param_maybe_default* kwds?")); @@ -4776,7 +4906,7 @@ star_etc_rule(Parser *p) _res = _PyPegen_star_etc ( p , a , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4787,7 +4917,7 @@ star_etc_rule(Parser *p) } { // '*' ',' param_maybe_default+ kwds? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' ',' param_maybe_default+ kwds?")); @@ -4809,7 +4939,7 @@ star_etc_rule(Parser *p) _res = _PyPegen_star_etc ( p , NULL , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4820,7 +4950,7 @@ star_etc_rule(Parser *p) } { // kwds if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwds")); @@ -4833,7 +4963,7 @@ star_etc_rule(Parser *p) _res = _PyPegen_star_etc ( p , NULL , NULL , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4844,7 +4974,7 @@ star_etc_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_star_etc if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_star_etc")); @@ -4863,7 +4993,7 @@ star_etc_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4871,16 +5001,19 @@ star_etc_rule(Parser *p) static arg_ty kwds_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arg_ty _res = NULL; int _mark = p->mark; { // '**' param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwds[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' param_no_default")); @@ -4896,7 +5029,7 @@ kwds_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4907,7 +5040,7 @@ kwds_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4915,16 +5048,19 @@ kwds_rule(Parser *p) static arg_ty param_no_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arg_ty _res = NULL; int _mark = p->mark; { // param ',' TYPE_COMMENT? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param ',' TYPE_COMMENT?")); @@ -4943,7 +5079,7 @@ param_no_default_rule(Parser *p) _res = _PyPegen_add_type_comment_to_arg ( p , a , tc ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4954,7 +5090,7 @@ param_no_default_rule(Parser *p) } { // param TYPE_COMMENT? &')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param TYPE_COMMENT? &')'")); @@ -4972,7 +5108,7 @@ param_no_default_rule(Parser *p) _res = _PyPegen_add_type_comment_to_arg ( p , a , tc ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4983,7 +5119,7 @@ param_no_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4991,16 +5127,19 @@ param_no_default_rule(Parser *p) static NameDefaultPair* param_with_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } NameDefaultPair* _res = NULL; int _mark = p->mark; { // param default ',' TYPE_COMMENT? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param default ',' TYPE_COMMENT?")); @@ -5022,7 +5161,7 @@ param_with_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , tc ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5033,7 +5172,7 @@ param_with_default_rule(Parser *p) } { // param default TYPE_COMMENT? &')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param default TYPE_COMMENT? &')'")); @@ -5054,7 +5193,7 @@ param_with_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , tc ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5065,7 +5204,7 @@ param_with_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5075,16 +5214,19 @@ param_with_default_rule(Parser *p) static NameDefaultPair* param_maybe_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } NameDefaultPair* _res = NULL; int _mark = p->mark; { // param default? ',' TYPE_COMMENT? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param_maybe_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param default? ',' TYPE_COMMENT?")); @@ -5106,7 +5248,7 @@ param_maybe_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , tc ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5117,7 +5259,7 @@ param_maybe_default_rule(Parser *p) } { // param default? TYPE_COMMENT? &')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param_maybe_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param default? TYPE_COMMENT? &')'")); @@ -5138,7 +5280,7 @@ param_maybe_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , tc ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5149,7 +5291,7 @@ param_maybe_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5157,16 +5299,19 @@ param_maybe_default_rule(Parser *p) static arg_ty param_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arg_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -5175,7 +5320,7 @@ param_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME annotation? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME annotation?")); @@ -5190,7 +5335,7 @@ param_rule(Parser *p) D(fprintf(stderr, "%*c+ param[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME annotation?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -5200,7 +5345,7 @@ param_rule(Parser *p) _res = _PyAST_arg ( a -> v . Name . id , b , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5211,7 +5356,7 @@ param_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5219,16 +5364,19 @@ param_rule(Parser *p) static expr_ty annotation_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // ':' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> annotation[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':' expression")); @@ -5244,7 +5392,7 @@ annotation_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5255,7 +5403,7 @@ annotation_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5263,16 +5411,19 @@ annotation_rule(Parser *p) static expr_ty default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // '=' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'=' expression")); @@ -5288,7 +5439,7 @@ default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5299,7 +5450,7 @@ default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5310,16 +5461,19 @@ default_rule(Parser *p) static stmt_ty if_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -5328,7 +5482,7 @@ if_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_if_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> if_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_if_stmt")); @@ -5347,7 +5501,7 @@ if_stmt_rule(Parser *p) } { // 'if' named_expression ':' block elif_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> if_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' named_expression ':' block elif_stmt")); @@ -5371,7 +5525,7 @@ if_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ if_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' named_expression ':' block elif_stmt")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -5381,7 +5535,7 @@ if_stmt_rule(Parser *p) _res = _PyAST_If ( a , b , CHECK ( asdl_stmt_seq* , _PyPegen_singleton_seq ( p , c ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5392,7 +5546,7 @@ if_stmt_rule(Parser *p) } { // 'if' named_expression ':' block else_block? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> if_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' named_expression ':' block else_block?")); @@ -5416,7 +5570,7 @@ if_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ if_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' named_expression ':' block else_block?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -5426,7 +5580,7 @@ if_stmt_rule(Parser *p) _res = _PyAST_If ( a , b , c , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5437,7 +5591,7 @@ if_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5448,16 +5602,19 @@ if_stmt_rule(Parser *p) static stmt_ty elif_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -5466,7 +5623,7 @@ elif_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_elif_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> elif_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_elif_stmt")); @@ -5485,7 +5642,7 @@ elif_stmt_rule(Parser *p) } { // 'elif' named_expression ':' block elif_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> elif_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'elif' named_expression ':' block elif_stmt")); @@ -5509,7 +5666,7 @@ elif_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ elif_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'elif' named_expression ':' block elif_stmt")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -5519,7 +5676,7 @@ elif_stmt_rule(Parser *p) _res = _PyAST_If ( a , b , CHECK ( asdl_stmt_seq* , _PyPegen_singleton_seq ( p , c ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5530,7 +5687,7 @@ elif_stmt_rule(Parser *p) } { // 'elif' named_expression ':' block else_block? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> elif_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'elif' named_expression ':' block else_block?")); @@ -5554,7 +5711,7 @@ elif_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ elif_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'elif' named_expression ':' block else_block?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -5564,7 +5721,7 @@ elif_stmt_rule(Parser *p) _res = _PyAST_If ( a , b , c , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5575,7 +5732,7 @@ elif_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5583,16 +5740,19 @@ elif_stmt_rule(Parser *p) static asdl_stmt_seq* else_block_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_stmt_seq* _res = NULL; int _mark = p->mark; if (p->call_invalid_rules) { // invalid_else_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> else_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_else_stmt")); @@ -5611,7 +5771,7 @@ else_block_rule(Parser *p) } { // 'else' &&':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> else_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else' &&':' block")); @@ -5630,7 +5790,7 @@ else_block_rule(Parser *p) _res = b; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5641,7 +5801,7 @@ else_block_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5649,16 +5809,19 @@ else_block_rule(Parser *p) static stmt_ty while_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -5667,7 +5830,7 @@ while_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_while_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> while_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_while_stmt")); @@ -5686,7 +5849,7 @@ while_stmt_rule(Parser *p) } { // 'while' named_expression ':' block else_block? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> while_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'while' named_expression ':' block else_block?")); @@ -5710,7 +5873,7 @@ while_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ while_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'while' named_expression ':' block else_block?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -5720,7 +5883,7 @@ while_stmt_rule(Parser *p) _res = _PyAST_While ( a , b , c , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5731,7 +5894,7 @@ while_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5743,16 +5906,19 @@ while_stmt_rule(Parser *p) static stmt_ty for_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -5761,7 +5927,7 @@ for_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_for_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_for_stmt")); @@ -5780,7 +5946,7 @@ for_stmt_rule(Parser *p) } { // 'for' star_targets 'in' ~ star_expressions &&':' TYPE_COMMENT? block else_block? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'for' star_targets 'in' ~ star_expressions &&':' TYPE_COMMENT? block else_block?")); @@ -5816,7 +5982,7 @@ for_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ for_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'for' star_targets 'in' ~ star_expressions &&':' TYPE_COMMENT? block else_block?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -5826,7 +5992,7 @@ for_stmt_rule(Parser *p) _res = _PyAST_For ( t , ex , b , el , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5835,13 +6001,13 @@ for_stmt_rule(Parser *p) D(fprintf(stderr, "%*c%s for_stmt[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'for' star_targets 'in' ~ star_expressions &&':' TYPE_COMMENT? block else_block?")); if (_cut_var) { - D(p->level--); + p->level--; return NULL; } } { // ASYNC 'for' star_targets 'in' ~ star_expressions &&':' TYPE_COMMENT? block else_block? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC 'for' star_targets 'in' ~ star_expressions &&':' TYPE_COMMENT? block else_block?")); @@ -5880,7 +6046,7 @@ for_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ for_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC 'for' star_targets 'in' ~ star_expressions &&':' TYPE_COMMENT? block else_block?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -5890,7 +6056,7 @@ for_stmt_rule(Parser *p) _res = CHECK_VERSION ( stmt_ty , 5 , "Async for loops are" , _PyAST_AsyncFor ( t , ex , b , el , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5899,13 +6065,13 @@ for_stmt_rule(Parser *p) D(fprintf(stderr, "%*c%s for_stmt[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "ASYNC 'for' star_targets 'in' ~ star_expressions &&':' TYPE_COMMENT? block else_block?")); if (_cut_var) { - D(p->level--); + p->level--; return NULL; } } if (p->call_invalid_rules) { // invalid_for_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_for_target")); @@ -5924,7 +6090,7 @@ for_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5938,16 +6104,19 @@ for_stmt_rule(Parser *p) static stmt_ty with_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -5956,7 +6125,7 @@ with_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_with_stmt_indent if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_with_stmt_indent")); @@ -5975,7 +6144,7 @@ with_stmt_rule(Parser *p) } { // 'with' '(' ','.with_item+ ','? ')' ':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'with' '(' ','.with_item+ ','? ')' ':' block")); @@ -6006,7 +6175,7 @@ with_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'with' '(' ','.with_item+ ','? ')' ':' block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6016,7 +6185,7 @@ with_stmt_rule(Parser *p) _res = _PyAST_With ( a , b , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6027,7 +6196,7 @@ with_stmt_rule(Parser *p) } { // 'with' ','.with_item+ ':' TYPE_COMMENT? block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'with' ','.with_item+ ':' TYPE_COMMENT? block")); @@ -6051,7 +6220,7 @@ with_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'with' ','.with_item+ ':' TYPE_COMMENT? block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6061,7 +6230,7 @@ with_stmt_rule(Parser *p) _res = _PyAST_With ( a , b , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6072,7 +6241,7 @@ with_stmt_rule(Parser *p) } { // ASYNC 'with' '(' ','.with_item+ ','? ')' ':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC 'with' '(' ','.with_item+ ','? ')' ':' block")); @@ -6106,7 +6275,7 @@ with_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC 'with' '(' ','.with_item+ ','? ')' ':' block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6116,7 +6285,7 @@ with_stmt_rule(Parser *p) _res = CHECK_VERSION ( stmt_ty , 5 , "Async with statements are" , _PyAST_AsyncWith ( a , b , NULL , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6127,7 +6296,7 @@ with_stmt_rule(Parser *p) } { // ASYNC 'with' ','.with_item+ ':' TYPE_COMMENT? block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC 'with' ','.with_item+ ':' TYPE_COMMENT? block")); @@ -6154,7 +6323,7 @@ with_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC 'with' ','.with_item+ ':' TYPE_COMMENT? block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6164,7 +6333,7 @@ with_stmt_rule(Parser *p) _res = CHECK_VERSION ( stmt_ty , 5 , "Async with statements are" , _PyAST_AsyncWith ( a , b , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6175,7 +6344,7 @@ with_stmt_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_with_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_with_stmt")); @@ -6194,7 +6363,7 @@ with_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6205,16 +6374,19 @@ with_stmt_rule(Parser *p) static withitem_ty with_item_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } withitem_ty _res = NULL; int _mark = p->mark; { // expression 'as' star_target &(',' | ')' | ':') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_item[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression 'as' star_target &(',' | ')' | ':')")); @@ -6235,7 +6407,7 @@ with_item_rule(Parser *p) _res = _PyAST_withitem ( e , t , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6246,7 +6418,7 @@ with_item_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_with_item if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_item[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_with_item")); @@ -6265,7 +6437,7 @@ with_item_rule(Parser *p) } { // expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_item[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression")); @@ -6278,7 +6450,7 @@ with_item_rule(Parser *p) _res = _PyAST_withitem ( e , NULL , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6289,7 +6461,7 @@ with_item_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6301,16 +6473,19 @@ with_item_rule(Parser *p) static stmt_ty try_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6319,7 +6494,7 @@ try_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_try_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> try_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_try_stmt")); @@ -6338,7 +6513,7 @@ try_stmt_rule(Parser *p) } { // 'try' &&':' block finally_block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> try_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'try' &&':' block finally_block")); @@ -6359,7 +6534,7 @@ try_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' &&':' block finally_block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6369,7 +6544,7 @@ try_stmt_rule(Parser *p) _res = _PyAST_Try ( b , NULL , NULL , f , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6380,7 +6555,7 @@ try_stmt_rule(Parser *p) } { // 'try' &&':' block except_block+ else_block? finally_block? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> try_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'try' &&':' block except_block+ else_block? finally_block?")); @@ -6407,7 +6582,7 @@ try_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' &&':' block except_block+ else_block? finally_block?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6417,7 +6592,7 @@ try_stmt_rule(Parser *p) _res = _PyAST_Try ( b , ex , el , f , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6428,7 +6603,7 @@ try_stmt_rule(Parser *p) } { // 'try' &&':' block except_star_block+ else_block? finally_block? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> try_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'try' &&':' block except_star_block+ else_block? finally_block?")); @@ -6455,7 +6630,7 @@ try_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' &&':' block except_star_block+ else_block? finally_block?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6465,7 +6640,7 @@ try_stmt_rule(Parser *p) _res = _PyAST_TryStar ( b , ex , el , f , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6476,7 +6651,7 @@ try_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6488,16 +6663,19 @@ try_stmt_rule(Parser *p) static excepthandler_ty except_block_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } excepthandler_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6506,7 +6684,7 @@ except_block_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_except_stmt_indent if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> except_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_except_stmt_indent")); @@ -6525,7 +6703,7 @@ except_block_rule(Parser *p) } { // 'except' expression ['as' NAME] ':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> except_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' expression ['as' NAME] ':' block")); @@ -6549,7 +6727,7 @@ except_block_rule(Parser *p) D(fprintf(stderr, "%*c+ except_block[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' expression ['as' NAME] ':' block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6559,7 +6737,7 @@ except_block_rule(Parser *p) _res = _PyAST_ExceptHandler ( e , ( t ) ? ( ( expr_ty ) t ) -> v . Name . id : NULL , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6570,7 +6748,7 @@ except_block_rule(Parser *p) } { // 'except' ':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> except_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' ':' block")); @@ -6588,7 +6766,7 @@ except_block_rule(Parser *p) D(fprintf(stderr, "%*c+ except_block[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' ':' block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6598,7 +6776,7 @@ except_block_rule(Parser *p) _res = _PyAST_ExceptHandler ( NULL , NULL , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6609,7 +6787,7 @@ except_block_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_except_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> except_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_except_stmt")); @@ -6628,7 +6806,7 @@ except_block_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6639,16 +6817,19 @@ except_block_rule(Parser *p) static excepthandler_ty except_star_block_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } excepthandler_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6657,7 +6838,7 @@ except_star_block_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_except_star_stmt_indent if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> except_star_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_except_star_stmt_indent")); @@ -6676,7 +6857,7 @@ except_star_block_rule(Parser *p) } { // 'except' '*' expression ['as' NAME] ':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> except_star_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' '*' expression ['as' NAME] ':' block")); @@ -6703,7 +6884,7 @@ except_star_block_rule(Parser *p) D(fprintf(stderr, "%*c+ except_star_block[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' '*' expression ['as' NAME] ':' block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6713,7 +6894,7 @@ except_star_block_rule(Parser *p) _res = _PyAST_ExceptHandler ( e , ( t ) ? ( ( expr_ty ) t ) -> v . Name . id : NULL , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6724,7 +6905,7 @@ except_star_block_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_except_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> except_star_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_except_stmt")); @@ -6743,7 +6924,7 @@ except_star_block_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6751,16 +6932,19 @@ except_star_block_rule(Parser *p) static asdl_stmt_seq* finally_block_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_stmt_seq* _res = NULL; int _mark = p->mark; if (p->call_invalid_rules) { // invalid_finally_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> finally_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_finally_stmt")); @@ -6779,7 +6963,7 @@ finally_block_rule(Parser *p) } { // 'finally' &&':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> finally_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally' &&':' block")); @@ -6798,7 +6982,7 @@ finally_block_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6809,7 +6993,7 @@ finally_block_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6819,16 +7003,19 @@ finally_block_rule(Parser *p) static stmt_ty match_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6837,7 +7024,7 @@ match_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // "match" subject_expr ':' NEWLINE INDENT case_block+ DEDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> match_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"match\" subject_expr ':' NEWLINE INDENT case_block+ DEDENT")); @@ -6867,7 +7054,7 @@ match_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ match_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"match\" subject_expr ':' NEWLINE INDENT case_block+ DEDENT")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6877,7 +7064,7 @@ match_stmt_rule(Parser *p) _res = CHECK_VERSION ( stmt_ty , 10 , "Pattern matching is" , _PyAST_Match ( subject , cases , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6888,7 +7075,7 @@ match_stmt_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_match_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> match_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_match_stmt")); @@ -6907,7 +7094,7 @@ match_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6915,16 +7102,19 @@ match_stmt_rule(Parser *p) static expr_ty subject_expr_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6933,7 +7123,7 @@ subject_expr_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // star_named_expression ',' star_named_expressions? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> subject_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?")); @@ -6951,7 +7141,7 @@ subject_expr_rule(Parser *p) D(fprintf(stderr, "%*c+ subject_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6961,7 +7151,7 @@ subject_expr_rule(Parser *p) _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq* , _PyPegen_seq_insert_in_front ( p , value , values ) ) , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6972,7 +7162,7 @@ subject_expr_rule(Parser *p) } { // named_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> subject_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression")); @@ -6991,7 +7181,7 @@ subject_expr_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6999,16 +7189,19 @@ subject_expr_rule(Parser *p) static match_case_ty case_block_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } match_case_ty _res = NULL; int _mark = p->mark; if (p->call_invalid_rules) { // invalid_case_block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> case_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_case_block")); @@ -7027,7 +7220,7 @@ case_block_rule(Parser *p) } { // "case" patterns guard? ':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> case_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"case\" patterns guard? ':' block")); @@ -7052,7 +7245,7 @@ case_block_rule(Parser *p) _res = _PyAST_match_case ( pattern , guard , body , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7063,7 +7256,7 @@ case_block_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7071,16 +7264,19 @@ case_block_rule(Parser *p) static expr_ty guard_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // 'if' named_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> guard[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' named_expression")); @@ -7096,7 +7292,7 @@ guard_rule(Parser *p) _res = guard; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7107,7 +7303,7 @@ guard_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7115,16 +7311,19 @@ guard_rule(Parser *p) static pattern_ty patterns_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -7133,7 +7332,7 @@ patterns_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // open_sequence_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> patterns[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "open_sequence_pattern")); @@ -7145,7 +7344,7 @@ patterns_rule(Parser *p) D(fprintf(stderr, "%*c+ patterns[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "open_sequence_pattern")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7155,7 +7354,7 @@ patterns_rule(Parser *p) _res = _PyAST_MatchSequence ( patterns , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7166,7 +7365,7 @@ patterns_rule(Parser *p) } { // pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> patterns[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "pattern")); @@ -7185,7 +7384,7 @@ patterns_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7193,16 +7392,19 @@ patterns_rule(Parser *p) static pattern_ty pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; { // as_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "as_pattern")); @@ -7221,7 +7423,7 @@ pattern_rule(Parser *p) } { // or_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "or_pattern")); @@ -7240,7 +7442,7 @@ pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7248,16 +7450,19 @@ pattern_rule(Parser *p) static pattern_ty as_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -7266,7 +7471,7 @@ as_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // or_pattern 'as' pattern_capture_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> as_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "or_pattern 'as' pattern_capture_target")); @@ -7284,7 +7489,7 @@ as_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ as_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "or_pattern 'as' pattern_capture_target")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7294,7 +7499,7 @@ as_pattern_rule(Parser *p) _res = _PyAST_MatchAs ( pattern , target -> v . Name . id , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7305,7 +7510,7 @@ as_pattern_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_as_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> as_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_as_pattern")); @@ -7324,7 +7529,7 @@ as_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7332,16 +7537,19 @@ as_pattern_rule(Parser *p) static pattern_ty or_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -7350,7 +7558,7 @@ or_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '|'.closed_pattern+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> or_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'|'.closed_pattern+")); @@ -7362,7 +7570,7 @@ or_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ or_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'|'.closed_pattern+")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7372,7 +7580,7 @@ or_pattern_rule(Parser *p) _res = asdl_seq_LEN ( patterns ) == 1 ? asdl_seq_GET ( patterns , 0 ) : _PyAST_MatchOr ( patterns , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7383,7 +7591,7 @@ or_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7399,16 +7607,19 @@ or_pattern_rule(Parser *p) static pattern_ty closed_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; { // literal_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> closed_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "literal_pattern")); @@ -7427,7 +7638,7 @@ closed_pattern_rule(Parser *p) } { // capture_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> closed_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "capture_pattern")); @@ -7446,7 +7657,7 @@ closed_pattern_rule(Parser *p) } { // wildcard_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> closed_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "wildcard_pattern")); @@ -7465,7 +7676,7 @@ closed_pattern_rule(Parser *p) } { // value_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> closed_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "value_pattern")); @@ -7484,7 +7695,7 @@ closed_pattern_rule(Parser *p) } { // group_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> closed_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "group_pattern")); @@ -7503,7 +7714,7 @@ closed_pattern_rule(Parser *p) } { // sequence_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> closed_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "sequence_pattern")); @@ -7522,7 +7733,7 @@ closed_pattern_rule(Parser *p) } { // mapping_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> closed_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "mapping_pattern")); @@ -7541,7 +7752,7 @@ closed_pattern_rule(Parser *p) } { // class_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> closed_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "class_pattern")); @@ -7560,7 +7771,7 @@ closed_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7574,16 +7785,19 @@ closed_pattern_rule(Parser *p) static pattern_ty literal_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -7592,7 +7806,7 @@ literal_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // signed_number !('+' | '-') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "signed_number !('+' | '-')")); @@ -7606,7 +7820,7 @@ literal_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "signed_number !('+' | '-')")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7616,7 +7830,7 @@ literal_pattern_rule(Parser *p) _res = _PyAST_MatchValue ( value , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7627,7 +7841,7 @@ literal_pattern_rule(Parser *p) } { // complex_number if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "complex_number")); @@ -7639,7 +7853,7 @@ literal_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "complex_number")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7649,7 +7863,7 @@ literal_pattern_rule(Parser *p) _res = _PyAST_MatchValue ( value , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7660,7 +7874,7 @@ literal_pattern_rule(Parser *p) } { // strings if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "strings")); @@ -7672,7 +7886,7 @@ literal_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "strings")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7682,7 +7896,7 @@ literal_pattern_rule(Parser *p) _res = _PyAST_MatchValue ( value , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7693,7 +7907,7 @@ literal_pattern_rule(Parser *p) } { // 'None' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); @@ -7705,7 +7919,7 @@ literal_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7715,7 +7929,7 @@ literal_pattern_rule(Parser *p) _res = _PyAST_MatchSingleton ( Py_None , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7726,7 +7940,7 @@ literal_pattern_rule(Parser *p) } { // 'True' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); @@ -7738,7 +7952,7 @@ literal_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7748,7 +7962,7 @@ literal_pattern_rule(Parser *p) _res = _PyAST_MatchSingleton ( Py_True , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7759,7 +7973,7 @@ literal_pattern_rule(Parser *p) } { // 'False' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); @@ -7771,7 +7985,7 @@ literal_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7781,7 +7995,7 @@ literal_pattern_rule(Parser *p) _res = _PyAST_MatchSingleton ( Py_False , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7792,7 +8006,7 @@ literal_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7806,16 +8020,19 @@ literal_pattern_rule(Parser *p) static expr_ty literal_expr_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -7824,7 +8041,7 @@ literal_expr_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // signed_number !('+' | '-') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "signed_number !('+' | '-')")); @@ -7845,7 +8062,7 @@ literal_expr_rule(Parser *p) } { // complex_number if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "complex_number")); @@ -7864,7 +8081,7 @@ literal_expr_rule(Parser *p) } { // strings if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "strings")); @@ -7883,7 +8100,7 @@ literal_expr_rule(Parser *p) } { // 'None' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); @@ -7895,7 +8112,7 @@ literal_expr_rule(Parser *p) D(fprintf(stderr, "%*c+ literal_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7905,7 +8122,7 @@ literal_expr_rule(Parser *p) _res = _PyAST_Constant ( Py_None , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7916,7 +8133,7 @@ literal_expr_rule(Parser *p) } { // 'True' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); @@ -7928,7 +8145,7 @@ literal_expr_rule(Parser *p) D(fprintf(stderr, "%*c+ literal_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7938,7 +8155,7 @@ literal_expr_rule(Parser *p) _res = _PyAST_Constant ( Py_True , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7949,7 +8166,7 @@ literal_expr_rule(Parser *p) } { // 'False' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); @@ -7961,7 +8178,7 @@ literal_expr_rule(Parser *p) D(fprintf(stderr, "%*c+ literal_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7971,7 +8188,7 @@ literal_expr_rule(Parser *p) _res = _PyAST_Constant ( Py_False , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7982,7 +8199,7 @@ literal_expr_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7992,16 +8209,19 @@ literal_expr_rule(Parser *p) static expr_ty complex_number_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -8010,7 +8230,7 @@ complex_number_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // signed_real_number '+' imaginary_number if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> complex_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "signed_real_number '+' imaginary_number")); @@ -8028,7 +8248,7 @@ complex_number_rule(Parser *p) D(fprintf(stderr, "%*c+ complex_number[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "signed_real_number '+' imaginary_number")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -8038,7 +8258,7 @@ complex_number_rule(Parser *p) _res = _PyAST_BinOp ( real , Add , imag , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8049,7 +8269,7 @@ complex_number_rule(Parser *p) } { // signed_real_number '-' imaginary_number if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> complex_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "signed_real_number '-' imaginary_number")); @@ -8067,7 +8287,7 @@ complex_number_rule(Parser *p) D(fprintf(stderr, "%*c+ complex_number[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "signed_real_number '-' imaginary_number")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -8077,7 +8297,7 @@ complex_number_rule(Parser *p) _res = _PyAST_BinOp ( real , Sub , imag , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8088,7 +8308,7 @@ complex_number_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8096,16 +8316,19 @@ complex_number_rule(Parser *p) static expr_ty signed_number_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -8114,7 +8337,7 @@ signed_number_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NUMBER if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> signed_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NUMBER")); @@ -8133,7 +8356,7 @@ signed_number_rule(Parser *p) } { // '-' NUMBER if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> signed_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-' NUMBER")); @@ -8148,7 +8371,7 @@ signed_number_rule(Parser *p) D(fprintf(stderr, "%*c+ signed_number[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-' NUMBER")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -8158,7 +8381,7 @@ signed_number_rule(Parser *p) _res = _PyAST_UnaryOp ( USub , number , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8169,7 +8392,7 @@ signed_number_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8177,16 +8400,19 @@ signed_number_rule(Parser *p) static expr_ty signed_real_number_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -8195,7 +8421,7 @@ signed_real_number_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // real_number if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> signed_real_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "real_number")); @@ -8214,7 +8440,7 @@ signed_real_number_rule(Parser *p) } { // '-' real_number if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> signed_real_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-' real_number")); @@ -8229,7 +8455,7 @@ signed_real_number_rule(Parser *p) D(fprintf(stderr, "%*c+ signed_real_number[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-' real_number")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -8239,7 +8465,7 @@ signed_real_number_rule(Parser *p) _res = _PyAST_UnaryOp ( USub , real , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8250,7 +8476,7 @@ signed_real_number_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8258,16 +8484,19 @@ signed_real_number_rule(Parser *p) static expr_ty real_number_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // NUMBER if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> real_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NUMBER")); @@ -8280,7 +8509,7 @@ real_number_rule(Parser *p) _res = _PyPegen_ensure_real ( p , real ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8291,7 +8520,7 @@ real_number_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8299,16 +8528,19 @@ real_number_rule(Parser *p) static expr_ty imaginary_number_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // NUMBER if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> imaginary_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NUMBER")); @@ -8321,7 +8553,7 @@ imaginary_number_rule(Parser *p) _res = _PyPegen_ensure_imaginary ( p , imag ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8332,7 +8564,7 @@ imaginary_number_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8340,16 +8572,19 @@ imaginary_number_rule(Parser *p) static pattern_ty capture_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -8358,7 +8593,7 @@ capture_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // pattern_capture_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> capture_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "pattern_capture_target")); @@ -8370,7 +8605,7 @@ capture_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ capture_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "pattern_capture_target")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -8380,7 +8615,7 @@ capture_pattern_rule(Parser *p) _res = _PyAST_MatchAs ( NULL , target -> v . Name . id , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8391,7 +8626,7 @@ capture_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8399,16 +8634,19 @@ capture_pattern_rule(Parser *p) static expr_ty pattern_capture_target_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // !"_" NAME !('.' | '(' | '=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> pattern_capture_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!\"_\" NAME !('.' | '(' | '=')")); @@ -8425,7 +8663,7 @@ pattern_capture_target_rule(Parser *p) _res = _PyPegen_set_expr_context ( p , name , Store ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8436,7 +8674,7 @@ pattern_capture_target_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8444,16 +8682,19 @@ pattern_capture_target_rule(Parser *p) static pattern_ty wildcard_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -8462,7 +8703,7 @@ wildcard_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // "_" if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> wildcard_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"_\"")); @@ -8474,7 +8715,7 @@ wildcard_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ wildcard_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"_\"")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -8484,7 +8725,7 @@ wildcard_pattern_rule(Parser *p) _res = _PyAST_MatchAs ( NULL , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8495,7 +8736,7 @@ wildcard_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8503,16 +8744,19 @@ wildcard_pattern_rule(Parser *p) static pattern_ty value_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -8521,7 +8765,7 @@ value_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // attr !('.' | '(' | '=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> value_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "attr !('.' | '(' | '=')")); @@ -8535,7 +8779,7 @@ value_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ value_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "attr !('.' | '(' | '=')")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -8545,7 +8789,7 @@ value_pattern_rule(Parser *p) _res = _PyAST_MatchValue ( attr , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8556,7 +8800,7 @@ value_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8566,10 +8810,13 @@ static expr_ty attr_raw(Parser *); static expr_ty attr_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, attr_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -8577,37 +8824,42 @@ attr_rule(Parser *p) while (1) { int tmpvar_1 = _PyPegen_update_memo(p, _mark, attr_type, _res); if (tmpvar_1) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; p->in_raw_rule++; void *_raw = attr_raw(p); p->in_raw_rule--; - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty attr_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -8616,7 +8868,7 @@ attr_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // name_or_attr '.' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> attr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "name_or_attr '.' NAME")); @@ -8634,7 +8886,7 @@ attr_raw(Parser *p) D(fprintf(stderr, "%*c+ attr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "name_or_attr '.' NAME")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -8644,7 +8896,7 @@ attr_raw(Parser *p) _res = _PyAST_Attribute ( value , attr -> v . Name . id , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8655,7 +8907,7 @@ attr_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8664,16 +8916,19 @@ attr_raw(Parser *p) static expr_ty name_or_attr_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // attr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> name_or_attr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "attr")); @@ -8692,7 +8947,7 @@ name_or_attr_rule(Parser *p) } { // NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> name_or_attr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); @@ -8711,7 +8966,7 @@ name_or_attr_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8719,16 +8974,19 @@ name_or_attr_rule(Parser *p) static pattern_ty group_pattern_rule(Parser *p) { - D(p->level++); - if (p->error_indicator) { - D(p->level--); - return NULL; + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; + return NULL; } pattern_ty _res = NULL; int _mark = p->mark; { // '(' pattern ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> group_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' pattern ')'")); @@ -8747,7 +9005,7 @@ group_pattern_rule(Parser *p) _res = pattern; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8758,7 +9016,7 @@ group_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8766,16 +9024,19 @@ group_pattern_rule(Parser *p) static pattern_ty sequence_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -8784,7 +9045,7 @@ sequence_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '[' maybe_sequence_pattern? ']' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> sequence_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'[' maybe_sequence_pattern? ']'")); @@ -8802,7 +9063,7 @@ sequence_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ sequence_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' maybe_sequence_pattern? ']'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -8812,7 +9073,7 @@ sequence_pattern_rule(Parser *p) _res = _PyAST_MatchSequence ( patterns , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8823,7 +9084,7 @@ sequence_pattern_rule(Parser *p) } { // '(' open_sequence_pattern? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> sequence_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' open_sequence_pattern? ')'")); @@ -8841,7 +9102,7 @@ sequence_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ sequence_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' open_sequence_pattern? ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -8851,7 +9112,7 @@ sequence_pattern_rule(Parser *p) _res = _PyAST_MatchSequence ( patterns , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8862,7 +9123,7 @@ sequence_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8870,16 +9131,19 @@ sequence_pattern_rule(Parser *p) static asdl_seq* open_sequence_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // maybe_star_pattern ',' maybe_sequence_pattern? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> open_sequence_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "maybe_star_pattern ',' maybe_sequence_pattern?")); @@ -8898,7 +9162,7 @@ open_sequence_pattern_rule(Parser *p) _res = _PyPegen_seq_insert_in_front ( p , pattern , patterns ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8909,7 +9173,7 @@ open_sequence_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8917,16 +9181,19 @@ open_sequence_pattern_rule(Parser *p) static asdl_seq* maybe_sequence_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // ','.maybe_star_pattern+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> maybe_sequence_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.maybe_star_pattern+ ','?")); @@ -8943,7 +9210,7 @@ maybe_sequence_pattern_rule(Parser *p) _res = patterns; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8954,7 +9221,7 @@ maybe_sequence_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8962,16 +9229,19 @@ maybe_sequence_pattern_rule(Parser *p) static pattern_ty maybe_star_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; { // star_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> maybe_star_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_pattern")); @@ -8990,7 +9260,7 @@ maybe_star_pattern_rule(Parser *p) } { // pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> maybe_star_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "pattern")); @@ -9009,7 +9279,7 @@ maybe_star_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9017,16 +9287,19 @@ maybe_star_pattern_rule(Parser *p) static pattern_ty star_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -9035,7 +9308,7 @@ star_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '*' pattern_capture_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' pattern_capture_target")); @@ -9050,7 +9323,7 @@ star_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ star_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' pattern_capture_target")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9060,7 +9333,7 @@ star_pattern_rule(Parser *p) _res = _PyAST_MatchStar ( target -> v . Name . id , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9071,7 +9344,7 @@ star_pattern_rule(Parser *p) } { // '*' wildcard_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' wildcard_pattern")); @@ -9086,7 +9359,7 @@ star_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ star_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' wildcard_pattern")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9096,7 +9369,7 @@ star_pattern_rule(Parser *p) _res = _PyAST_MatchStar ( NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9107,7 +9380,7 @@ star_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9119,16 +9392,19 @@ star_pattern_rule(Parser *p) static pattern_ty mapping_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -9137,7 +9413,7 @@ mapping_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '{' '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> mapping_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' '}'")); @@ -9152,7 +9428,7 @@ mapping_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ mapping_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9162,7 +9438,7 @@ mapping_pattern_rule(Parser *p) _res = _PyAST_MatchMapping ( NULL , NULL , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9173,7 +9449,7 @@ mapping_pattern_rule(Parser *p) } { // '{' double_star_pattern ','? '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> mapping_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' double_star_pattern ','? '}'")); @@ -9195,7 +9471,7 @@ mapping_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ mapping_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' double_star_pattern ','? '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9205,7 +9481,7 @@ mapping_pattern_rule(Parser *p) _res = _PyAST_MatchMapping ( NULL , NULL , rest -> v . Name . id , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9216,7 +9492,7 @@ mapping_pattern_rule(Parser *p) } { // '{' items_pattern ',' double_star_pattern ','? '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> mapping_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' items_pattern ',' double_star_pattern ','? '}'")); @@ -9244,7 +9520,7 @@ mapping_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ mapping_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' items_pattern ',' double_star_pattern ','? '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9254,7 +9530,7 @@ mapping_pattern_rule(Parser *p) _res = _PyAST_MatchMapping ( CHECK ( asdl_expr_seq* , _PyPegen_get_pattern_keys ( p , items ) ) , CHECK ( asdl_pattern_seq* , _PyPegen_get_patterns ( p , items ) ) , rest -> v . Name . id , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9265,7 +9541,7 @@ mapping_pattern_rule(Parser *p) } { // '{' items_pattern ','? '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> mapping_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' items_pattern ','? '}'")); @@ -9287,7 +9563,7 @@ mapping_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ mapping_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' items_pattern ','? '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9297,7 +9573,7 @@ mapping_pattern_rule(Parser *p) _res = _PyAST_MatchMapping ( CHECK ( asdl_expr_seq* , _PyPegen_get_pattern_keys ( p , items ) ) , CHECK ( asdl_pattern_seq* , _PyPegen_get_patterns ( p , items ) ) , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9308,7 +9584,7 @@ mapping_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9316,16 +9592,19 @@ mapping_pattern_rule(Parser *p) static asdl_seq* items_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // ','.key_value_pattern+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> items_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.key_value_pattern+")); @@ -9344,7 +9623,7 @@ items_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9352,16 +9631,19 @@ items_pattern_rule(Parser *p) static KeyPatternPair* key_value_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } KeyPatternPair* _res = NULL; int _mark = p->mark; { // (literal_expr | attr) ':' pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> key_value_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(literal_expr | attr) ':' pattern")); @@ -9380,7 +9662,7 @@ key_value_pattern_rule(Parser *p) _res = _PyPegen_key_pattern_pair ( p , key , pattern ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9391,7 +9673,7 @@ key_value_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9399,16 +9681,19 @@ key_value_pattern_rule(Parser *p) static expr_ty double_star_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // '**' pattern_capture_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> double_star_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' pattern_capture_target")); @@ -9424,7 +9709,7 @@ double_star_pattern_rule(Parser *p) _res = target; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9435,7 +9720,7 @@ double_star_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9448,16 +9733,19 @@ double_star_pattern_rule(Parser *p) static pattern_ty class_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -9466,7 +9754,7 @@ class_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // name_or_attr '(' ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' ')'")); @@ -9484,7 +9772,7 @@ class_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ class_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9494,7 +9782,7 @@ class_pattern_rule(Parser *p) _res = _PyAST_MatchClass ( cls , NULL , NULL , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9505,7 +9793,7 @@ class_pattern_rule(Parser *p) } { // name_or_attr '(' positional_patterns ','? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' positional_patterns ','? ')'")); @@ -9530,7 +9818,7 @@ class_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ class_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' positional_patterns ','? ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9540,7 +9828,7 @@ class_pattern_rule(Parser *p) _res = _PyAST_MatchClass ( cls , patterns , NULL , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9551,7 +9839,7 @@ class_pattern_rule(Parser *p) } { // name_or_attr '(' keyword_patterns ','? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' keyword_patterns ','? ')'")); @@ -9576,7 +9864,7 @@ class_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ class_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' keyword_patterns ','? ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9586,7 +9874,7 @@ class_pattern_rule(Parser *p) _res = _PyAST_MatchClass ( cls , NULL , CHECK ( asdl_identifier_seq* , _PyPegen_map_names_to_ids ( p , CHECK ( asdl_expr_seq* , _PyPegen_get_pattern_keys ( p , keywords ) ) ) ) , CHECK ( asdl_pattern_seq* , _PyPegen_get_patterns ( p , keywords ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9597,7 +9885,7 @@ class_pattern_rule(Parser *p) } { // name_or_attr '(' positional_patterns ',' keyword_patterns ','? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' positional_patterns ',' keyword_patterns ','? ')'")); @@ -9628,7 +9916,7 @@ class_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ class_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' positional_patterns ',' keyword_patterns ','? ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9638,7 +9926,7 @@ class_pattern_rule(Parser *p) _res = _PyAST_MatchClass ( cls , patterns , CHECK ( asdl_identifier_seq* , _PyPegen_map_names_to_ids ( p , CHECK ( asdl_expr_seq* , _PyPegen_get_pattern_keys ( p , keywords ) ) ) ) , CHECK ( asdl_pattern_seq* , _PyPegen_get_patterns ( p , keywords ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9649,7 +9937,7 @@ class_pattern_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_class_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_class_pattern")); @@ -9668,7 +9956,7 @@ class_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9676,16 +9964,19 @@ class_pattern_rule(Parser *p) static asdl_pattern_seq* positional_patterns_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_pattern_seq* _res = NULL; int _mark = p->mark; { // ','.pattern+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> positional_patterns[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.pattern+")); @@ -9698,7 +9989,7 @@ positional_patterns_rule(Parser *p) _res = args; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9709,7 +10000,7 @@ positional_patterns_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9717,16 +10008,19 @@ positional_patterns_rule(Parser *p) static asdl_seq* keyword_patterns_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // ','.keyword_pattern+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> keyword_patterns[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.keyword_pattern+")); @@ -9745,7 +10039,7 @@ keyword_patterns_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9753,16 +10047,19 @@ keyword_patterns_rule(Parser *p) static KeyPatternPair* keyword_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } KeyPatternPair* _res = NULL; int _mark = p->mark; { // NAME '=' pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> keyword_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '=' pattern")); @@ -9781,7 +10078,7 @@ keyword_pattern_rule(Parser *p) _res = _PyPegen_key_pattern_pair ( p , arg , value ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9792,7 +10089,7 @@ keyword_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9800,16 +10097,19 @@ keyword_pattern_rule(Parser *p) static expr_ty expressions_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -9818,7 +10118,7 @@ expressions_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // expression ((',' expression))+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ((',' expression))+ ','?")); @@ -9837,7 +10137,7 @@ expressions_rule(Parser *p) D(fprintf(stderr, "%*c+ expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ((',' expression))+ ','?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9847,7 +10147,7 @@ expressions_rule(Parser *p) _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq* , _PyPegen_seq_insert_in_front ( p , a , b ) ) , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9858,7 +10158,7 @@ expressions_rule(Parser *p) } { // expression ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ','")); @@ -9873,7 +10173,7 @@ expressions_rule(Parser *p) D(fprintf(stderr, "%*c+ expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ','")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9883,7 +10183,7 @@ expressions_rule(Parser *p) _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq* , _PyPegen_singleton_seq ( p , a ) ) , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9894,7 +10194,7 @@ expressions_rule(Parser *p) } { // expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression")); @@ -9913,7 +10213,7 @@ expressions_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9926,20 +10226,23 @@ expressions_rule(Parser *p) static expr_ty expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, expression_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -9948,7 +10251,7 @@ expression_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_expression")); @@ -9967,7 +10270,7 @@ expression_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_legacy_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_legacy_expression")); @@ -9986,7 +10289,7 @@ expression_rule(Parser *p) } { // disjunction 'if' disjunction 'else' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction 'else' expression")); @@ -10010,7 +10313,7 @@ expression_rule(Parser *p) D(fprintf(stderr, "%*c+ expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction 'else' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10020,7 +10323,7 @@ expression_rule(Parser *p) _res = _PyAST_IfExp ( b , a , c , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10031,7 +10334,7 @@ expression_rule(Parser *p) } { // disjunction if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "disjunction")); @@ -10050,7 +10353,7 @@ expression_rule(Parser *p) } { // lambdef if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambdef")); @@ -10070,7 +10373,7 @@ expression_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, expression_type, _res); - D(p->level--); + p->level--; return _res; } @@ -10078,16 +10381,19 @@ expression_rule(Parser *p) static expr_ty yield_expr_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -10096,7 +10402,7 @@ yield_expr_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'yield' 'from' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> yield_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'yield' 'from' expression")); @@ -10114,7 +10420,7 @@ yield_expr_rule(Parser *p) D(fprintf(stderr, "%*c+ yield_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'yield' 'from' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10124,7 +10430,7 @@ yield_expr_rule(Parser *p) _res = _PyAST_YieldFrom ( a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10135,7 +10441,7 @@ yield_expr_rule(Parser *p) } { // 'yield' star_expressions? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> yield_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'yield' star_expressions?")); @@ -10150,7 +10456,7 @@ yield_expr_rule(Parser *p) D(fprintf(stderr, "%*c+ yield_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'yield' star_expressions?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10160,7 +10466,7 @@ yield_expr_rule(Parser *p) _res = _PyAST_Yield ( a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10171,7 +10477,7 @@ yield_expr_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -10182,16 +10488,19 @@ yield_expr_rule(Parser *p) static expr_ty star_expressions_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -10200,7 +10509,7 @@ star_expressions_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // star_expression ((',' star_expression))+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expression ((',' star_expression))+ ','?")); @@ -10219,7 +10528,7 @@ star_expressions_rule(Parser *p) D(fprintf(stderr, "%*c+ star_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expression ((',' star_expression))+ ','?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10229,7 +10538,7 @@ star_expressions_rule(Parser *p) _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq* , _PyPegen_seq_insert_in_front ( p , a , b ) ) , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10240,7 +10549,7 @@ star_expressions_rule(Parser *p) } { // star_expression ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expression ','")); @@ -10255,7 +10564,7 @@ star_expressions_rule(Parser *p) D(fprintf(stderr, "%*c+ star_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expression ','")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10265,7 +10574,7 @@ star_expressions_rule(Parser *p) _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq* , _PyPegen_singleton_seq ( p , a ) ) , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10276,7 +10585,7 @@ star_expressions_rule(Parser *p) } { // star_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expression")); @@ -10295,7 +10604,7 @@ star_expressions_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -10303,20 +10612,23 @@ star_expressions_rule(Parser *p) static expr_ty star_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, star_expression_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -10325,7 +10637,7 @@ star_expression_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '*' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' bitwise_or")); @@ -10340,7 +10652,7 @@ star_expression_rule(Parser *p) D(fprintf(stderr, "%*c+ star_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' bitwise_or")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10350,7 +10662,7 @@ star_expression_rule(Parser *p) _res = _PyAST_Starred ( a , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10361,7 +10673,7 @@ star_expression_rule(Parser *p) } { // expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression")); @@ -10381,7 +10693,7 @@ star_expression_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, star_expression_type, _res); - D(p->level--); + p->level--; return _res; } @@ -10389,16 +10701,19 @@ star_expression_rule(Parser *p) static asdl_expr_seq* star_named_expressions_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_expr_seq* _res = NULL; int _mark = p->mark; { // ','.star_named_expression+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_named_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.star_named_expression+ ','?")); @@ -10415,7 +10730,7 @@ star_named_expressions_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10426,7 +10741,7 @@ star_named_expressions_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -10434,16 +10749,19 @@ star_named_expressions_rule(Parser *p) static expr_ty star_named_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -10452,7 +10770,7 @@ star_named_expression_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '*' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' bitwise_or")); @@ -10467,7 +10785,7 @@ star_named_expression_rule(Parser *p) D(fprintf(stderr, "%*c+ star_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' bitwise_or")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10477,7 +10795,7 @@ star_named_expression_rule(Parser *p) _res = _PyAST_Starred ( a , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10488,7 +10806,7 @@ star_named_expression_rule(Parser *p) } { // named_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression")); @@ -10507,7 +10825,7 @@ star_named_expression_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -10515,16 +10833,19 @@ star_named_expression_rule(Parser *p) static expr_ty assignment_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -10533,7 +10854,7 @@ assignment_expression_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME ':=' ~ expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> assignment_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME ':=' ~ expression")); @@ -10554,7 +10875,7 @@ assignment_expression_rule(Parser *p) D(fprintf(stderr, "%*c+ assignment_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME ':=' ~ expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10564,7 +10885,7 @@ assignment_expression_rule(Parser *p) _res = _PyAST_NamedExpr ( CHECK ( expr_ty , _PyPegen_set_expr_context ( p , a , Store ) ) , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10573,13 +10894,13 @@ assignment_expression_rule(Parser *p) D(fprintf(stderr, "%*c%s assignment_expression[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME ':=' ~ expression")); if (_cut_var) { - D(p->level--); + p->level--; return NULL; } } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -10587,16 +10908,19 @@ assignment_expression_rule(Parser *p) static expr_ty named_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // assignment_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); @@ -10615,7 +10939,7 @@ named_expression_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_named_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_named_expression")); @@ -10634,7 +10958,7 @@ named_expression_rule(Parser *p) } { // expression !':=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); @@ -10655,7 +10979,7 @@ named_expression_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -10663,20 +10987,23 @@ named_expression_rule(Parser *p) static expr_ty disjunction_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, disjunction_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -10685,7 +11012,7 @@ disjunction_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // conjunction (('or' conjunction))+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> disjunction[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "conjunction (('or' conjunction))+")); @@ -10700,7 +11027,7 @@ disjunction_rule(Parser *p) D(fprintf(stderr, "%*c+ disjunction[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "conjunction (('or' conjunction))+")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10710,7 +11037,7 @@ disjunction_rule(Parser *p) _res = _PyAST_BoolOp ( Or , CHECK ( asdl_expr_seq* , _PyPegen_seq_insert_in_front ( p , a , b ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10721,7 +11048,7 @@ disjunction_rule(Parser *p) } { // conjunction if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> disjunction[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "conjunction")); @@ -10741,7 +11068,7 @@ disjunction_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, disjunction_type, _res); - D(p->level--); + p->level--; return _res; } @@ -10749,20 +11076,23 @@ disjunction_rule(Parser *p) static expr_ty conjunction_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, conjunction_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -10771,7 +11101,7 @@ conjunction_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // inversion (('and' inversion))+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> conjunction[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "inversion (('and' inversion))+")); @@ -10786,7 +11116,7 @@ conjunction_rule(Parser *p) D(fprintf(stderr, "%*c+ conjunction[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "inversion (('and' inversion))+")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10796,7 +11126,7 @@ conjunction_rule(Parser *p) _res = _PyAST_BoolOp ( And , CHECK ( asdl_expr_seq* , _PyPegen_seq_insert_in_front ( p , a , b ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10807,7 +11137,7 @@ conjunction_rule(Parser *p) } { // inversion if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> conjunction[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "inversion")); @@ -10827,7 +11157,7 @@ conjunction_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, conjunction_type, _res); - D(p->level--); + p->level--; return _res; } @@ -10835,20 +11165,23 @@ conjunction_rule(Parser *p) static expr_ty inversion_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, inversion_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -10857,7 +11190,7 @@ inversion_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'not' inversion if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> inversion[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'not' inversion")); @@ -10872,7 +11205,7 @@ inversion_rule(Parser *p) D(fprintf(stderr, "%*c+ inversion[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'not' inversion")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10882,7 +11215,7 @@ inversion_rule(Parser *p) _res = _PyAST_UnaryOp ( Not , a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10893,7 +11226,7 @@ inversion_rule(Parser *p) } { // comparison if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> inversion[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "comparison")); @@ -10913,7 +11246,7 @@ inversion_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, inversion_type, _res); - D(p->level--); + p->level--; return _res; } @@ -10921,16 +11254,19 @@ inversion_rule(Parser *p) static expr_ty comparison_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -10939,7 +11275,7 @@ comparison_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // bitwise_or compare_op_bitwise_or_pair+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> comparison[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_or compare_op_bitwise_or_pair+")); @@ -10954,7 +11290,7 @@ comparison_rule(Parser *p) D(fprintf(stderr, "%*c+ comparison[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_or compare_op_bitwise_or_pair+")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10964,7 +11300,7 @@ comparison_rule(Parser *p) _res = _PyAST_Compare ( a , CHECK ( asdl_int_seq* , _PyPegen_get_cmpops ( p , b ) ) , CHECK ( asdl_expr_seq* , _PyPegen_get_exprs ( p , b ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10975,7 +11311,7 @@ comparison_rule(Parser *p) } { // bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> comparison[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_or")); @@ -10994,7 +11330,7 @@ comparison_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11012,16 +11348,19 @@ comparison_rule(Parser *p) static CmpopExprPair* compare_op_bitwise_or_pair_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // eq_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "eq_bitwise_or")); @@ -11040,7 +11379,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // noteq_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "noteq_bitwise_or")); @@ -11059,7 +11398,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // lte_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lte_bitwise_or")); @@ -11078,7 +11417,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // lt_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lt_bitwise_or")); @@ -11097,7 +11436,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // gte_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "gte_bitwise_or")); @@ -11116,7 +11455,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // gt_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "gt_bitwise_or")); @@ -11135,7 +11474,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // notin_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "notin_bitwise_or")); @@ -11154,7 +11493,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // in_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "in_bitwise_or")); @@ -11173,7 +11512,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // isnot_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "isnot_bitwise_or")); @@ -11192,7 +11531,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // is_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "is_bitwise_or")); @@ -11211,7 +11550,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11219,16 +11558,19 @@ compare_op_bitwise_or_pair_rule(Parser *p) static CmpopExprPair* eq_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // '==' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> eq_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'==' bitwise_or")); @@ -11244,7 +11586,7 @@ eq_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , Eq , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11255,7 +11597,7 @@ eq_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11263,16 +11605,19 @@ eq_bitwise_or_rule(Parser *p) static CmpopExprPair* noteq_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // ('!=') bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> noteq_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('!=') bitwise_or")); @@ -11288,7 +11633,7 @@ noteq_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , NotEq , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11299,7 +11644,7 @@ noteq_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11307,16 +11652,19 @@ noteq_bitwise_or_rule(Parser *p) static CmpopExprPair* lte_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // '<=' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lte_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'<=' bitwise_or")); @@ -11332,7 +11680,7 @@ lte_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , LtE , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11343,7 +11691,7 @@ lte_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11351,16 +11699,19 @@ lte_bitwise_or_rule(Parser *p) static CmpopExprPair* lt_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // '<' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lt_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'<' bitwise_or")); @@ -11376,7 +11727,7 @@ lt_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , Lt , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11387,7 +11738,7 @@ lt_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11395,16 +11746,19 @@ lt_bitwise_or_rule(Parser *p) static CmpopExprPair* gte_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // '>=' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> gte_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'>=' bitwise_or")); @@ -11420,7 +11774,7 @@ gte_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , GtE , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11431,7 +11785,7 @@ gte_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11439,16 +11793,19 @@ gte_bitwise_or_rule(Parser *p) static CmpopExprPair* gt_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // '>' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> gt_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'>' bitwise_or")); @@ -11464,7 +11821,7 @@ gt_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , Gt , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11475,7 +11832,7 @@ gt_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11483,16 +11840,19 @@ gt_bitwise_or_rule(Parser *p) static CmpopExprPair* notin_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // 'not' 'in' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> notin_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'not' 'in' bitwise_or")); @@ -11511,7 +11871,7 @@ notin_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , NotIn , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11522,7 +11882,7 @@ notin_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11530,16 +11890,19 @@ notin_bitwise_or_rule(Parser *p) static CmpopExprPair* in_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // 'in' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> in_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'in' bitwise_or")); @@ -11555,7 +11918,7 @@ in_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , In , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11566,7 +11929,7 @@ in_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11574,16 +11937,19 @@ in_bitwise_or_rule(Parser *p) static CmpopExprPair* isnot_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // 'is' 'not' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> isnot_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'is' 'not' bitwise_or")); @@ -11602,7 +11968,7 @@ isnot_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , IsNot , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11613,7 +11979,7 @@ isnot_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11621,16 +11987,19 @@ isnot_bitwise_or_rule(Parser *p) static CmpopExprPair* is_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // 'is' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> is_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'is' bitwise_or")); @@ -11646,7 +12015,7 @@ is_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , Is , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11657,7 +12026,7 @@ is_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11667,10 +12036,13 @@ static expr_ty bitwise_or_raw(Parser *); static expr_ty bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, bitwise_or_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -11678,37 +12050,42 @@ bitwise_or_rule(Parser *p) while (1) { int tmpvar_2 = _PyPegen_update_memo(p, _mark, bitwise_or_type, _res); if (tmpvar_2) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; p->in_raw_rule++; void *_raw = bitwise_or_raw(p); p->in_raw_rule--; - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty bitwise_or_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -11717,7 +12094,7 @@ bitwise_or_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // bitwise_or '|' bitwise_xor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_or '|' bitwise_xor")); @@ -11735,7 +12112,7 @@ bitwise_or_raw(Parser *p) D(fprintf(stderr, "%*c+ bitwise_or[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_or '|' bitwise_xor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -11745,7 +12122,7 @@ bitwise_or_raw(Parser *p) _res = _PyAST_BinOp ( a , BitOr , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11756,7 +12133,7 @@ bitwise_or_raw(Parser *p) } { // bitwise_xor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_xor")); @@ -11775,7 +12152,7 @@ bitwise_or_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11785,10 +12162,13 @@ static expr_ty bitwise_xor_raw(Parser *); static expr_ty bitwise_xor_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, bitwise_xor_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -11796,37 +12176,42 @@ bitwise_xor_rule(Parser *p) while (1) { int tmpvar_3 = _PyPegen_update_memo(p, _mark, bitwise_xor_type, _res); if (tmpvar_3) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; p->in_raw_rule++; void *_raw = bitwise_xor_raw(p); p->in_raw_rule--; - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty bitwise_xor_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -11835,7 +12220,7 @@ bitwise_xor_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // bitwise_xor '^' bitwise_and if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> bitwise_xor[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_xor '^' bitwise_and")); @@ -11853,7 +12238,7 @@ bitwise_xor_raw(Parser *p) D(fprintf(stderr, "%*c+ bitwise_xor[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_xor '^' bitwise_and")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -11863,7 +12248,7 @@ bitwise_xor_raw(Parser *p) _res = _PyAST_BinOp ( a , BitXor , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11874,7 +12259,7 @@ bitwise_xor_raw(Parser *p) } { // bitwise_and if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> bitwise_xor[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_and")); @@ -11893,7 +12278,7 @@ bitwise_xor_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11903,10 +12288,13 @@ static expr_ty bitwise_and_raw(Parser *); static expr_ty bitwise_and_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, bitwise_and_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -11914,37 +12302,42 @@ bitwise_and_rule(Parser *p) while (1) { int tmpvar_4 = _PyPegen_update_memo(p, _mark, bitwise_and_type, _res); if (tmpvar_4) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; p->in_raw_rule++; void *_raw = bitwise_and_raw(p); p->in_raw_rule--; - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty bitwise_and_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -11953,7 +12346,7 @@ bitwise_and_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // bitwise_and '&' shift_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> bitwise_and[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_and '&' shift_expr")); @@ -11971,7 +12364,7 @@ bitwise_and_raw(Parser *p) D(fprintf(stderr, "%*c+ bitwise_and[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_and '&' shift_expr")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -11981,7 +12374,7 @@ bitwise_and_raw(Parser *p) _res = _PyAST_BinOp ( a , BitAnd , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11992,7 +12385,7 @@ bitwise_and_raw(Parser *p) } { // shift_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> bitwise_and[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "shift_expr")); @@ -12011,7 +12404,7 @@ bitwise_and_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12021,10 +12414,13 @@ static expr_ty shift_expr_raw(Parser *); static expr_ty shift_expr_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, shift_expr_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -12032,37 +12428,42 @@ shift_expr_rule(Parser *p) while (1) { int tmpvar_5 = _PyPegen_update_memo(p, _mark, shift_expr_type, _res); if (tmpvar_5) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; p->in_raw_rule++; void *_raw = shift_expr_raw(p); p->in_raw_rule--; - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty shift_expr_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -12071,7 +12472,7 @@ shift_expr_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // shift_expr '<<' sum if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> shift_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "shift_expr '<<' sum")); @@ -12089,7 +12490,7 @@ shift_expr_raw(Parser *p) D(fprintf(stderr, "%*c+ shift_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "shift_expr '<<' sum")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12099,7 +12500,7 @@ shift_expr_raw(Parser *p) _res = _PyAST_BinOp ( a , LShift , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12110,7 +12511,7 @@ shift_expr_raw(Parser *p) } { // shift_expr '>>' sum if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> shift_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "shift_expr '>>' sum")); @@ -12128,7 +12529,7 @@ shift_expr_raw(Parser *p) D(fprintf(stderr, "%*c+ shift_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "shift_expr '>>' sum")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12138,7 +12539,7 @@ shift_expr_raw(Parser *p) _res = _PyAST_BinOp ( a , RShift , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12149,7 +12550,7 @@ shift_expr_raw(Parser *p) } { // sum if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> shift_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "sum")); @@ -12168,7 +12569,7 @@ shift_expr_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12178,10 +12579,13 @@ static expr_ty sum_raw(Parser *); static expr_ty sum_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, sum_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -12189,37 +12593,42 @@ sum_rule(Parser *p) while (1) { int tmpvar_6 = _PyPegen_update_memo(p, _mark, sum_type, _res); if (tmpvar_6) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; p->in_raw_rule++; void *_raw = sum_raw(p); p->in_raw_rule--; - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty sum_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -12228,7 +12637,7 @@ sum_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // sum '+' term if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> sum[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "sum '+' term")); @@ -12246,7 +12655,7 @@ sum_raw(Parser *p) D(fprintf(stderr, "%*c+ sum[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "sum '+' term")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12256,7 +12665,7 @@ sum_raw(Parser *p) _res = _PyAST_BinOp ( a , Add , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12267,7 +12676,7 @@ sum_raw(Parser *p) } { // sum '-' term if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> sum[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "sum '-' term")); @@ -12285,7 +12694,7 @@ sum_raw(Parser *p) D(fprintf(stderr, "%*c+ sum[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "sum '-' term")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12295,7 +12704,7 @@ sum_raw(Parser *p) _res = _PyAST_BinOp ( a , Sub , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12306,7 +12715,7 @@ sum_raw(Parser *p) } { // term if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> sum[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "term")); @@ -12325,7 +12734,7 @@ sum_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12341,10 +12750,13 @@ static expr_ty term_raw(Parser *); static expr_ty term_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, term_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -12352,37 +12764,42 @@ term_rule(Parser *p) while (1) { int tmpvar_7 = _PyPegen_update_memo(p, _mark, term_type, _res); if (tmpvar_7) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; p->in_raw_rule++; void *_raw = term_raw(p); p->in_raw_rule--; - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty term_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -12391,7 +12808,7 @@ term_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // term '*' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> term[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "term '*' factor")); @@ -12409,7 +12826,7 @@ term_raw(Parser *p) D(fprintf(stderr, "%*c+ term[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "term '*' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12419,7 +12836,7 @@ term_raw(Parser *p) _res = _PyAST_BinOp ( a , Mult , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12430,7 +12847,7 @@ term_raw(Parser *p) } { // term '/' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> term[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "term '/' factor")); @@ -12448,7 +12865,7 @@ term_raw(Parser *p) D(fprintf(stderr, "%*c+ term[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "term '/' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12458,7 +12875,7 @@ term_raw(Parser *p) _res = _PyAST_BinOp ( a , Div , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12469,7 +12886,7 @@ term_raw(Parser *p) } { // term '//' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> term[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "term '//' factor")); @@ -12487,7 +12904,7 @@ term_raw(Parser *p) D(fprintf(stderr, "%*c+ term[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "term '//' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12497,7 +12914,7 @@ term_raw(Parser *p) _res = _PyAST_BinOp ( a , FloorDiv , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12508,7 +12925,7 @@ term_raw(Parser *p) } { // term '%' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> term[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "term '%' factor")); @@ -12526,7 +12943,7 @@ term_raw(Parser *p) D(fprintf(stderr, "%*c+ term[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "term '%' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12536,7 +12953,7 @@ term_raw(Parser *p) _res = _PyAST_BinOp ( a , Mod , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12547,7 +12964,7 @@ term_raw(Parser *p) } { // term '@' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> term[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "term '@' factor")); @@ -12565,7 +12982,7 @@ term_raw(Parser *p) D(fprintf(stderr, "%*c+ term[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "term '@' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12575,7 +12992,7 @@ term_raw(Parser *p) _res = CHECK_VERSION ( expr_ty , 5 , "The '@' operator is" , _PyAST_BinOp ( a , MatMult , b , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12586,7 +13003,7 @@ term_raw(Parser *p) } { // factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> term[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "factor")); @@ -12605,7 +13022,7 @@ term_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12613,20 +13030,23 @@ term_raw(Parser *p) static expr_ty factor_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, factor_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -12635,7 +13055,7 @@ factor_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '+' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> factor[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+' factor")); @@ -12650,7 +13070,7 @@ factor_rule(Parser *p) D(fprintf(stderr, "%*c+ factor[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12660,7 +13080,7 @@ factor_rule(Parser *p) _res = _PyAST_UnaryOp ( UAdd , a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12671,7 +13091,7 @@ factor_rule(Parser *p) } { // '-' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> factor[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-' factor")); @@ -12686,7 +13106,7 @@ factor_rule(Parser *p) D(fprintf(stderr, "%*c+ factor[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12696,7 +13116,7 @@ factor_rule(Parser *p) _res = _PyAST_UnaryOp ( USub , a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12707,7 +13127,7 @@ factor_rule(Parser *p) } { // '~' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> factor[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'~' factor")); @@ -12722,7 +13142,7 @@ factor_rule(Parser *p) D(fprintf(stderr, "%*c+ factor[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'~' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12732,7 +13152,7 @@ factor_rule(Parser *p) _res = _PyAST_UnaryOp ( Invert , a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12743,7 +13163,7 @@ factor_rule(Parser *p) } { // power if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> factor[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "power")); @@ -12763,7 +13183,7 @@ factor_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, factor_type, _res); - D(p->level--); + p->level--; return _res; } @@ -12771,16 +13191,19 @@ factor_rule(Parser *p) static expr_ty power_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -12789,7 +13212,7 @@ power_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // await_primary '**' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> power[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "await_primary '**' factor")); @@ -12807,7 +13230,7 @@ power_rule(Parser *p) D(fprintf(stderr, "%*c+ power[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "await_primary '**' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12817,7 +13240,7 @@ power_rule(Parser *p) _res = _PyAST_BinOp ( a , Pow , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12828,7 +13251,7 @@ power_rule(Parser *p) } { // await_primary if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> power[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "await_primary")); @@ -12847,7 +13270,7 @@ power_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12855,20 +13278,23 @@ power_rule(Parser *p) static expr_ty await_primary_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, await_primary_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -12877,7 +13303,7 @@ await_primary_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // AWAIT primary if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> await_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "AWAIT primary")); @@ -12892,7 +13318,7 @@ await_primary_rule(Parser *p) D(fprintf(stderr, "%*c+ await_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "AWAIT primary")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12902,7 +13328,7 @@ await_primary_rule(Parser *p) _res = CHECK_VERSION ( expr_ty , 5 , "Await expressions are" , _PyAST_Await ( a , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12913,7 +13339,7 @@ await_primary_rule(Parser *p) } { // primary if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> await_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "primary")); @@ -12933,7 +13359,7 @@ await_primary_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, await_primary_type, _res); - D(p->level--); + p->level--; return _res; } @@ -12948,10 +13374,13 @@ static expr_ty primary_raw(Parser *); static expr_ty primary_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, primary_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -12959,37 +13388,42 @@ primary_rule(Parser *p) while (1) { int tmpvar_8 = _PyPegen_update_memo(p, _mark, primary_type, _res); if (tmpvar_8) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; p->in_raw_rule++; void *_raw = primary_raw(p); p->in_raw_rule--; - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty primary_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -12998,7 +13432,7 @@ primary_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // primary '.' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "primary '.' NAME")); @@ -13016,7 +13450,7 @@ primary_raw(Parser *p) D(fprintf(stderr, "%*c+ primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "primary '.' NAME")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13026,7 +13460,7 @@ primary_raw(Parser *p) _res = _PyAST_Attribute ( a , b -> v . Name . id , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13037,7 +13471,7 @@ primary_raw(Parser *p) } { // primary genexp if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "primary genexp")); @@ -13052,7 +13486,7 @@ primary_raw(Parser *p) D(fprintf(stderr, "%*c+ primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "primary genexp")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13062,7 +13496,7 @@ primary_raw(Parser *p) _res = _PyAST_Call ( a , CHECK ( asdl_expr_seq* , ( asdl_expr_seq* ) _PyPegen_singleton_seq ( p , b ) ) , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13073,7 +13507,7 @@ primary_raw(Parser *p) } { // primary '(' arguments? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "primary '(' arguments? ')'")); @@ -13094,7 +13528,7 @@ primary_raw(Parser *p) D(fprintf(stderr, "%*c+ primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "primary '(' arguments? ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13104,7 +13538,7 @@ primary_raw(Parser *p) _res = _PyAST_Call ( a , ( b ) ? ( ( expr_ty ) b ) -> v . Call . args : NULL , ( b ) ? ( ( expr_ty ) b ) -> v . Call . keywords : NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13115,7 +13549,7 @@ primary_raw(Parser *p) } { // primary '[' slices ']' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "primary '[' slices ']'")); @@ -13136,7 +13570,7 @@ primary_raw(Parser *p) D(fprintf(stderr, "%*c+ primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "primary '[' slices ']'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13146,7 +13580,7 @@ primary_raw(Parser *p) _res = _PyAST_Subscript ( a , b , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13157,7 +13591,7 @@ primary_raw(Parser *p) } { // atom if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "atom")); @@ -13176,7 +13610,7 @@ primary_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -13184,16 +13618,19 @@ primary_raw(Parser *p) static expr_ty slices_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -13202,7 +13639,7 @@ slices_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // slice !',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slices[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slice !','")); @@ -13217,7 +13654,7 @@ slices_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13228,7 +13665,7 @@ slices_rule(Parser *p) } { // ','.slice+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slices[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.slice+ ','?")); @@ -13244,7 +13681,7 @@ slices_rule(Parser *p) D(fprintf(stderr, "%*c+ slices[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.slice+ ','?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13254,7 +13691,7 @@ slices_rule(Parser *p) _res = _PyAST_Tuple ( a , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13265,7 +13702,7 @@ slices_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -13273,16 +13710,19 @@ slices_rule(Parser *p) static expr_ty slice_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -13291,7 +13731,7 @@ slice_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // expression? ':' expression? [':' expression?] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slice[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression? ':' expression? [':' expression?]")); @@ -13312,7 +13752,7 @@ slice_rule(Parser *p) D(fprintf(stderr, "%*c+ slice[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression? ':' expression? [':' expression?]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13322,7 +13762,7 @@ slice_rule(Parser *p) _res = _PyAST_Slice ( a , b , c , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13333,7 +13773,7 @@ slice_rule(Parser *p) } { // named_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slice[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression")); @@ -13346,7 +13786,7 @@ slice_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13357,7 +13797,7 @@ slice_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -13375,16 +13815,19 @@ slice_rule(Parser *p) static expr_ty atom_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -13393,7 +13836,7 @@ atom_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); @@ -13412,7 +13855,7 @@ atom_rule(Parser *p) } { // 'True' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); @@ -13424,7 +13867,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13434,7 +13877,7 @@ atom_rule(Parser *p) _res = _PyAST_Constant ( Py_True , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13445,7 +13888,7 @@ atom_rule(Parser *p) } { // 'False' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); @@ -13457,7 +13900,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13467,7 +13910,7 @@ atom_rule(Parser *p) _res = _PyAST_Constant ( Py_False , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13478,7 +13921,7 @@ atom_rule(Parser *p) } { // 'None' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); @@ -13490,7 +13933,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13500,7 +13943,7 @@ atom_rule(Parser *p) _res = _PyAST_Constant ( Py_None , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13511,7 +13954,7 @@ atom_rule(Parser *p) } { // &STRING strings if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&STRING strings")); @@ -13532,7 +13975,7 @@ atom_rule(Parser *p) } { // NUMBER if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NUMBER")); @@ -13551,7 +13994,7 @@ atom_rule(Parser *p) } { // &'(' (tuple | group | genexp) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'(' (tuple | group | genexp)")); @@ -13572,7 +14015,7 @@ atom_rule(Parser *p) } { // &'[' (list | listcomp) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'[' (list | listcomp)")); @@ -13593,7 +14036,7 @@ atom_rule(Parser *p) } { // &'{' (dict | set | dictcomp | setcomp) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'{' (dict | set | dictcomp | setcomp)")); @@ -13614,7 +14057,7 @@ atom_rule(Parser *p) } { // '...' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); @@ -13626,7 +14069,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13636,7 +14079,7 @@ atom_rule(Parser *p) _res = _PyAST_Constant ( Py_Ellipsis , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13647,7 +14090,7 @@ atom_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -13655,16 +14098,19 @@ atom_rule(Parser *p) static expr_ty group_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // '(' (yield_expr | named_expression) ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> group[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' (yield_expr | named_expression) ')'")); @@ -13683,7 +14129,7 @@ group_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13694,7 +14140,7 @@ group_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_group if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> group[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_group")); @@ -13713,7 +14159,7 @@ group_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -13721,16 +14167,19 @@ group_rule(Parser *p) static expr_ty lambdef_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -13739,7 +14188,7 @@ lambdef_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'lambda' lambda_params? ':' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambdef[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'lambda' lambda_params? ':' expression")); @@ -13760,7 +14209,7 @@ lambdef_rule(Parser *p) D(fprintf(stderr, "%*c+ lambdef[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'lambda' lambda_params? ':' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13770,7 +14219,7 @@ lambdef_rule(Parser *p) _res = _PyAST_Lambda ( ( a ) ? a : CHECK ( arguments_ty , _PyPegen_empty_arguments ( p ) ) , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13781,7 +14230,7 @@ lambdef_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -13789,16 +14238,19 @@ lambdef_rule(Parser *p) static arguments_ty lambda_params_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arguments_ty _res = NULL; int _mark = p->mark; if (p->call_invalid_rules) { // invalid_lambda_parameters if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_params[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_lambda_parameters")); @@ -13817,7 +14269,7 @@ lambda_params_rule(Parser *p) } { // lambda_parameters if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_params[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_parameters")); @@ -13836,7 +14288,7 @@ lambda_params_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -13849,16 +14301,19 @@ lambda_params_rule(Parser *p) static arguments_ty lambda_parameters_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arguments_ty _res = NULL; int _mark = p->mark; { // lambda_slash_no_default lambda_param_no_default* lambda_param_with_default* lambda_star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default lambda_param_no_default* lambda_param_with_default* lambda_star_etc?")); @@ -13880,7 +14335,7 @@ lambda_parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , a , NULL , b , c , d ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13891,7 +14346,7 @@ lambda_parameters_rule(Parser *p) } { // lambda_slash_with_default lambda_param_with_default* lambda_star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default lambda_param_with_default* lambda_star_etc?")); @@ -13910,7 +14365,7 @@ lambda_parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , NULL , a , NULL , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13921,7 +14376,7 @@ lambda_parameters_rule(Parser *p) } { // lambda_param_no_default+ lambda_param_with_default* lambda_star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default+ lambda_param_with_default* lambda_star_etc?")); @@ -13940,7 +14395,7 @@ lambda_parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , NULL , NULL , a , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13951,7 +14406,7 @@ lambda_parameters_rule(Parser *p) } { // lambda_param_with_default+ lambda_star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+ lambda_star_etc?")); @@ -13967,7 +14422,7 @@ lambda_parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , NULL , NULL , NULL , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13978,7 +14433,7 @@ lambda_parameters_rule(Parser *p) } { // lambda_star_etc if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_star_etc")); @@ -13991,7 +14446,7 @@ lambda_parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , NULL , NULL , NULL , NULL , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14002,7 +14457,7 @@ lambda_parameters_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14012,16 +14467,19 @@ lambda_parameters_rule(Parser *p) static asdl_arg_seq* lambda_slash_no_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_arg_seq* _res = NULL; int _mark = p->mark; { // lambda_param_no_default+ '/' ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_slash_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default+ '/' ','")); @@ -14040,7 +14498,7 @@ lambda_slash_no_default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14051,7 +14509,7 @@ lambda_slash_no_default_rule(Parser *p) } { // lambda_param_no_default+ '/' &':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_slash_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default+ '/' &':'")); @@ -14069,7 +14527,7 @@ lambda_slash_no_default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14080,7 +14538,7 @@ lambda_slash_no_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14090,16 +14548,19 @@ lambda_slash_no_default_rule(Parser *p) static SlashWithDefault* lambda_slash_with_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } SlashWithDefault* _res = NULL; int _mark = p->mark; { // lambda_param_no_default* lambda_param_with_default+ '/' ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_slash_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* lambda_param_with_default+ '/' ','")); @@ -14121,7 +14582,7 @@ lambda_slash_with_default_rule(Parser *p) _res = _PyPegen_slash_with_default ( p , ( asdl_arg_seq* ) a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14132,7 +14593,7 @@ lambda_slash_with_default_rule(Parser *p) } { // lambda_param_no_default* lambda_param_with_default+ '/' &':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_slash_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* lambda_param_with_default+ '/' &':'")); @@ -14153,7 +14614,7 @@ lambda_slash_with_default_rule(Parser *p) _res = _PyPegen_slash_with_default ( p , ( asdl_arg_seq* ) a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14164,7 +14625,7 @@ lambda_slash_with_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14176,16 +14637,19 @@ lambda_slash_with_default_rule(Parser *p) static StarEtc* lambda_star_etc_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } StarEtc* _res = NULL; int _mark = p->mark; { // '*' lambda_param_no_default lambda_param_maybe_default* lambda_kwds? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' lambda_param_no_default lambda_param_maybe_default* lambda_kwds?")); @@ -14207,7 +14671,7 @@ lambda_star_etc_rule(Parser *p) _res = _PyPegen_star_etc ( p , a , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14218,7 +14682,7 @@ lambda_star_etc_rule(Parser *p) } { // '*' ',' lambda_param_maybe_default+ lambda_kwds? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' ',' lambda_param_maybe_default+ lambda_kwds?")); @@ -14240,7 +14704,7 @@ lambda_star_etc_rule(Parser *p) _res = _PyPegen_star_etc ( p , NULL , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14251,7 +14715,7 @@ lambda_star_etc_rule(Parser *p) } { // lambda_kwds if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_kwds")); @@ -14264,7 +14728,7 @@ lambda_star_etc_rule(Parser *p) _res = _PyPegen_star_etc ( p , NULL , NULL , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14275,7 +14739,7 @@ lambda_star_etc_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_lambda_star_etc if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_lambda_star_etc")); @@ -14294,7 +14758,7 @@ lambda_star_etc_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14302,16 +14766,19 @@ lambda_star_etc_rule(Parser *p) static arg_ty lambda_kwds_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arg_ty _res = NULL; int _mark = p->mark; { // '**' lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_kwds[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' lambda_param_no_default")); @@ -14327,7 +14794,7 @@ lambda_kwds_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14338,7 +14805,7 @@ lambda_kwds_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14346,16 +14813,19 @@ lambda_kwds_rule(Parser *p) static arg_ty lambda_param_no_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arg_ty _res = NULL; int _mark = p->mark; { // lambda_param ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param ','")); @@ -14371,7 +14841,7 @@ lambda_param_no_default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14382,7 +14852,7 @@ lambda_param_no_default_rule(Parser *p) } { // lambda_param &':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param &':'")); @@ -14397,7 +14867,7 @@ lambda_param_no_default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14408,7 +14878,7 @@ lambda_param_no_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14416,16 +14886,19 @@ lambda_param_no_default_rule(Parser *p) static NameDefaultPair* lambda_param_with_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } NameDefaultPair* _res = NULL; int _mark = p->mark; { // lambda_param default ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param default ','")); @@ -14444,7 +14917,7 @@ lambda_param_with_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , NULL ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14455,7 +14928,7 @@ lambda_param_with_default_rule(Parser *p) } { // lambda_param default &':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param default &':'")); @@ -14473,7 +14946,7 @@ lambda_param_with_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , NULL ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14484,7 +14957,7 @@ lambda_param_with_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14492,16 +14965,19 @@ lambda_param_with_default_rule(Parser *p) static NameDefaultPair* lambda_param_maybe_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } NameDefaultPair* _res = NULL; int _mark = p->mark; { // lambda_param default? ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param_maybe_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param default? ','")); @@ -14520,7 +14996,7 @@ lambda_param_maybe_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , NULL ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14531,7 +15007,7 @@ lambda_param_maybe_default_rule(Parser *p) } { // lambda_param default? &':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param_maybe_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param default? &':'")); @@ -14549,7 +15025,7 @@ lambda_param_maybe_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , NULL ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14560,7 +15036,7 @@ lambda_param_maybe_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14568,16 +15044,19 @@ lambda_param_maybe_default_rule(Parser *p) static arg_ty lambda_param_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arg_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -14586,7 +15065,7 @@ lambda_param_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); @@ -14598,7 +15077,7 @@ lambda_param_rule(Parser *p) D(fprintf(stderr, "%*c+ lambda_param[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14608,7 +15087,7 @@ lambda_param_rule(Parser *p) _res = _PyAST_arg ( a -> v . Name . id , NULL , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14619,7 +15098,7 @@ lambda_param_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14627,20 +15106,23 @@ lambda_param_rule(Parser *p) static expr_ty strings_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, strings_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; { // STRING+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> strings[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "STRING+")); @@ -14653,7 +15135,7 @@ strings_rule(Parser *p) _res = _PyPegen_concatenate_strings ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14665,7 +15147,7 @@ strings_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, strings_type, _res); - D(p->level--); + p->level--; return _res; } @@ -14673,16 +15155,19 @@ strings_rule(Parser *p) static expr_ty list_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -14691,7 +15176,7 @@ list_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '[' star_named_expressions? ']' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> list[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'[' star_named_expressions? ']'")); @@ -14709,7 +15194,7 @@ list_rule(Parser *p) D(fprintf(stderr, "%*c+ list[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' star_named_expressions? ']'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14719,7 +15204,7 @@ list_rule(Parser *p) _res = _PyAST_List ( a , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14730,7 +15215,7 @@ list_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14738,16 +15223,19 @@ list_rule(Parser *p) static expr_ty tuple_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -14756,7 +15244,7 @@ tuple_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '(' [star_named_expression ',' star_named_expressions?] ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> tuple[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' [star_named_expression ',' star_named_expressions?] ')'")); @@ -14774,7 +15262,7 @@ tuple_rule(Parser *p) D(fprintf(stderr, "%*c+ tuple[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' [star_named_expression ',' star_named_expressions?] ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14784,7 +15272,7 @@ tuple_rule(Parser *p) _res = _PyAST_Tuple ( a , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14795,7 +15283,7 @@ tuple_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14803,16 +15291,19 @@ tuple_rule(Parser *p) static expr_ty set_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -14821,7 +15312,7 @@ set_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '{' star_named_expressions '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> set[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' star_named_expressions '}'")); @@ -14839,7 +15330,7 @@ set_rule(Parser *p) D(fprintf(stderr, "%*c+ set[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' star_named_expressions '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14849,7 +15340,7 @@ set_rule(Parser *p) _res = _PyAST_Set ( a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14860,7 +15351,7 @@ set_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14868,16 +15359,19 @@ set_rule(Parser *p) static expr_ty dict_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -14886,7 +15380,7 @@ dict_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '{' double_starred_kvpairs? '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dict[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' double_starred_kvpairs? '}'")); @@ -14904,7 +15398,7 @@ dict_rule(Parser *p) D(fprintf(stderr, "%*c+ dict[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' double_starred_kvpairs? '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14914,7 +15408,7 @@ dict_rule(Parser *p) _res = _PyAST_Dict ( CHECK ( asdl_expr_seq* , _PyPegen_get_keys ( p , a ) ) , CHECK ( asdl_expr_seq* , _PyPegen_get_values ( p , a ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14925,7 +15419,7 @@ dict_rule(Parser *p) } { // '{' invalid_double_starred_kvpairs '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dict[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' invalid_double_starred_kvpairs '}'")); @@ -14950,7 +15444,7 @@ dict_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14958,16 +15452,19 @@ dict_rule(Parser *p) static asdl_seq* double_starred_kvpairs_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // ','.double_starred_kvpair+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> double_starred_kvpairs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ','?")); @@ -14984,7 +15481,7 @@ double_starred_kvpairs_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14995,7 +15492,7 @@ double_starred_kvpairs_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15003,16 +15500,19 @@ double_starred_kvpairs_rule(Parser *p) static KeyValuePair* double_starred_kvpair_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } KeyValuePair* _res = NULL; int _mark = p->mark; { // '**' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> double_starred_kvpair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' bitwise_or")); @@ -15028,7 +15528,7 @@ double_starred_kvpair_rule(Parser *p) _res = _PyPegen_key_value_pair ( p , NULL , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15039,7 +15539,7 @@ double_starred_kvpair_rule(Parser *p) } { // kvpair if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> double_starred_kvpair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kvpair")); @@ -15058,7 +15558,7 @@ double_starred_kvpair_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15066,16 +15566,19 @@ double_starred_kvpair_rule(Parser *p) static KeyValuePair* kvpair_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } KeyValuePair* _res = NULL; int _mark = p->mark; { // expression ':' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kvpair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ':' expression")); @@ -15094,7 +15597,7 @@ kvpair_rule(Parser *p) _res = _PyPegen_key_value_pair ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15105,7 +15608,7 @@ kvpair_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15113,16 +15616,19 @@ kvpair_rule(Parser *p) static asdl_comprehension_seq* for_if_clauses_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_comprehension_seq* _res = NULL; int _mark = p->mark; { // for_if_clause+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_if_clauses[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "for_if_clause+")); @@ -15135,7 +15641,7 @@ for_if_clauses_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15146,7 +15652,7 @@ for_if_clauses_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15157,16 +15663,19 @@ for_if_clauses_rule(Parser *p) static comprehension_ty for_if_clause_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } comprehension_ty _res = NULL; int _mark = p->mark; { // ASYNC 'for' star_targets 'in' ~ disjunction (('if' disjunction))* if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_if_clause[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC 'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); @@ -15197,7 +15706,7 @@ for_if_clause_rule(Parser *p) _res = CHECK_VERSION ( comprehension_ty , 6 , "Async comprehensions are" , _PyAST_comprehension ( a , b , c , 1 , p -> arena ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15206,13 +15715,13 @@ for_if_clause_rule(Parser *p) D(fprintf(stderr, "%*c%s for_if_clause[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "ASYNC 'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); if (_cut_var) { - D(p->level--); + p->level--; return NULL; } } { // 'for' star_targets 'in' ~ disjunction (('if' disjunction))* if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_if_clause[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); @@ -15240,7 +15749,7 @@ for_if_clause_rule(Parser *p) _res = _PyAST_comprehension ( a , b , c , 0 , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15249,13 +15758,13 @@ for_if_clause_rule(Parser *p) D(fprintf(stderr, "%*c%s for_if_clause[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); if (_cut_var) { - D(p->level--); + p->level--; return NULL; } } if (p->call_invalid_rules) { // invalid_for_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_if_clause[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_for_target")); @@ -15274,7 +15783,7 @@ for_if_clause_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15282,16 +15791,19 @@ for_if_clause_rule(Parser *p) static expr_ty listcomp_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -15300,7 +15812,7 @@ listcomp_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '[' named_expression for_if_clauses ']' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> listcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'[' named_expression for_if_clauses ']'")); @@ -15321,7 +15833,7 @@ listcomp_rule(Parser *p) D(fprintf(stderr, "%*c+ listcomp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' named_expression for_if_clauses ']'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -15331,7 +15843,7 @@ listcomp_rule(Parser *p) _res = _PyAST_ListComp ( a , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15342,7 +15854,7 @@ listcomp_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_comprehension if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> listcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_comprehension")); @@ -15361,7 +15873,7 @@ listcomp_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15369,16 +15881,19 @@ listcomp_rule(Parser *p) static expr_ty setcomp_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -15387,7 +15902,7 @@ setcomp_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '{' named_expression for_if_clauses '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> setcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' named_expression for_if_clauses '}'")); @@ -15408,7 +15923,7 @@ setcomp_rule(Parser *p) D(fprintf(stderr, "%*c+ setcomp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' named_expression for_if_clauses '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -15418,7 +15933,7 @@ setcomp_rule(Parser *p) _res = _PyAST_SetComp ( a , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15429,7 +15944,7 @@ setcomp_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_comprehension if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> setcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_comprehension")); @@ -15448,7 +15963,7 @@ setcomp_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15458,16 +15973,19 @@ setcomp_rule(Parser *p) static expr_ty genexp_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -15476,7 +15994,7 @@ genexp_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '(' (assignment_expression | expression !':=') for_if_clauses ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> genexp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' (assignment_expression | expression !':=') for_if_clauses ')'")); @@ -15497,7 +16015,7 @@ genexp_rule(Parser *p) D(fprintf(stderr, "%*c+ genexp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' (assignment_expression | expression !':=') for_if_clauses ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -15507,7 +16025,7 @@ genexp_rule(Parser *p) _res = _PyAST_GeneratorExp ( a , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15518,7 +16036,7 @@ genexp_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_comprehension if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> genexp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_comprehension")); @@ -15537,7 +16055,7 @@ genexp_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15545,16 +16063,19 @@ genexp_rule(Parser *p) static expr_ty dictcomp_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -15563,7 +16084,7 @@ dictcomp_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '{' kvpair for_if_clauses '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dictcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' kvpair for_if_clauses '}'")); @@ -15584,7 +16105,7 @@ dictcomp_rule(Parser *p) D(fprintf(stderr, "%*c+ dictcomp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' kvpair for_if_clauses '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -15594,7 +16115,7 @@ dictcomp_rule(Parser *p) _res = _PyAST_DictComp ( a -> key , a -> value , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15605,7 +16126,7 @@ dictcomp_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_dict_comprehension if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dictcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_dict_comprehension")); @@ -15624,7 +16145,7 @@ dictcomp_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15632,20 +16153,23 @@ dictcomp_rule(Parser *p) static expr_ty arguments_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, arguments_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; { // args ','? &')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ','? &')'")); @@ -15664,7 +16188,7 @@ arguments_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15675,7 +16199,7 @@ arguments_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_arguments if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_arguments")); @@ -15695,7 +16219,7 @@ arguments_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, arguments_type, _res); - D(p->level--); + p->level--; return _res; } @@ -15705,16 +16229,19 @@ arguments_rule(Parser *p) static expr_ty args_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -15723,7 +16250,7 @@ args_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ [',' kwargs] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> args[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ [',' kwargs]")); @@ -15738,7 +16265,7 @@ args_rule(Parser *p) D(fprintf(stderr, "%*c+ args[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ [',' kwargs]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -15748,7 +16275,7 @@ args_rule(Parser *p) _res = _PyPegen_collect_call_seqs ( p , a , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15759,7 +16286,7 @@ args_rule(Parser *p) } { // kwargs if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> args[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwargs")); @@ -15771,7 +16298,7 @@ args_rule(Parser *p) D(fprintf(stderr, "%*c+ args[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwargs")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -15781,7 +16308,7 @@ args_rule(Parser *p) _res = _PyAST_Call ( _PyPegen_dummy_name ( p ) , CHECK_NULL_ALLOWED ( asdl_expr_seq* , _PyPegen_seq_extract_starred_exprs ( p , a ) ) , CHECK_NULL_ALLOWED ( asdl_keyword_seq* , _PyPegen_seq_delete_starred_exprs ( p , a ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15792,7 +16319,7 @@ args_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15803,16 +16330,19 @@ args_rule(Parser *p) static asdl_seq* kwargs_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // ','.kwarg_or_starred+ ',' ','.kwarg_or_double_starred+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwargs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+ ',' ','.kwarg_or_double_starred+")); @@ -15831,7 +16361,7 @@ kwargs_rule(Parser *p) _res = _PyPegen_join_sequences ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15842,7 +16372,7 @@ kwargs_rule(Parser *p) } { // ','.kwarg_or_starred+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwargs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+")); @@ -15861,7 +16391,7 @@ kwargs_rule(Parser *p) } { // ','.kwarg_or_double_starred+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwargs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_double_starred+")); @@ -15880,7 +16410,7 @@ kwargs_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15888,16 +16418,19 @@ kwargs_rule(Parser *p) static expr_ty starred_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -15906,7 +16439,7 @@ starred_expression_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '*' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> starred_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' expression")); @@ -15921,7 +16454,7 @@ starred_expression_rule(Parser *p) D(fprintf(stderr, "%*c+ starred_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -15931,7 +16464,7 @@ starred_expression_rule(Parser *p) _res = _PyAST_Starred ( a , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15942,7 +16475,7 @@ starred_expression_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15950,16 +16483,19 @@ starred_expression_rule(Parser *p) static KeywordOrStarred* kwarg_or_starred_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } KeywordOrStarred* _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -15968,7 +16504,7 @@ kwarg_or_starred_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_kwarg if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwarg_or_starred[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_kwarg")); @@ -15987,7 +16523,7 @@ kwarg_or_starred_rule(Parser *p) } { // NAME '=' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwarg_or_starred[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '=' expression")); @@ -16005,7 +16541,7 @@ kwarg_or_starred_rule(Parser *p) D(fprintf(stderr, "%*c+ kwarg_or_starred[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16015,7 +16551,7 @@ kwarg_or_starred_rule(Parser *p) _res = _PyPegen_keyword_or_starred ( p , CHECK ( keyword_ty , _PyAST_keyword ( a -> v . Name . id , b , EXTRA ) ) , 1 ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16026,7 +16562,7 @@ kwarg_or_starred_rule(Parser *p) } { // starred_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwarg_or_starred[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); @@ -16039,7 +16575,7 @@ kwarg_or_starred_rule(Parser *p) _res = _PyPegen_keyword_or_starred ( p , a , 0 ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16050,7 +16586,7 @@ kwarg_or_starred_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16058,16 +16594,19 @@ kwarg_or_starred_rule(Parser *p) static KeywordOrStarred* kwarg_or_double_starred_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } KeywordOrStarred* _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -16076,7 +16615,7 @@ kwarg_or_double_starred_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_kwarg if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwarg_or_double_starred[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_kwarg")); @@ -16095,7 +16634,7 @@ kwarg_or_double_starred_rule(Parser *p) } { // NAME '=' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwarg_or_double_starred[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '=' expression")); @@ -16113,7 +16652,7 @@ kwarg_or_double_starred_rule(Parser *p) D(fprintf(stderr, "%*c+ kwarg_or_double_starred[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16123,7 +16662,7 @@ kwarg_or_double_starred_rule(Parser *p) _res = _PyPegen_keyword_or_starred ( p , CHECK ( keyword_ty , _PyAST_keyword ( a -> v . Name . id , b , EXTRA ) ) , 1 ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16134,7 +16673,7 @@ kwarg_or_double_starred_rule(Parser *p) } { // '**' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwarg_or_double_starred[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' expression")); @@ -16149,7 +16688,7 @@ kwarg_or_double_starred_rule(Parser *p) D(fprintf(stderr, "%*c+ kwarg_or_double_starred[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16159,7 +16698,7 @@ kwarg_or_double_starred_rule(Parser *p) _res = _PyPegen_keyword_or_starred ( p , CHECK ( keyword_ty , _PyAST_keyword ( NULL , a , EXTRA ) ) , 1 ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16170,7 +16709,7 @@ kwarg_or_double_starred_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16178,16 +16717,19 @@ kwarg_or_double_starred_rule(Parser *p) static expr_ty star_targets_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -16196,7 +16738,7 @@ star_targets_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // star_target !',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target !','")); @@ -16211,7 +16753,7 @@ star_targets_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16222,7 +16764,7 @@ star_targets_rule(Parser *p) } { // star_target ((',' star_target))* ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target ((',' star_target))* ','?")); @@ -16241,7 +16783,7 @@ star_targets_rule(Parser *p) D(fprintf(stderr, "%*c+ star_targets[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target ((',' star_target))* ','?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16251,7 +16793,7 @@ star_targets_rule(Parser *p) _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq* , _PyPegen_seq_insert_in_front ( p , a , b ) ) , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16262,7 +16804,7 @@ star_targets_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16270,16 +16812,19 @@ star_targets_rule(Parser *p) static asdl_expr_seq* star_targets_list_seq_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_expr_seq* _res = NULL; int _mark = p->mark; { // ','.star_target+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_targets_list_seq[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.star_target+ ','?")); @@ -16296,7 +16841,7 @@ star_targets_list_seq_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16307,7 +16852,7 @@ star_targets_list_seq_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16315,16 +16860,19 @@ star_targets_list_seq_rule(Parser *p) static asdl_expr_seq* star_targets_tuple_seq_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_expr_seq* _res = NULL; int _mark = p->mark; { // star_target ((',' star_target))+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_targets_tuple_seq[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target ((',' star_target))+ ','?")); @@ -16344,7 +16892,7 @@ star_targets_tuple_seq_rule(Parser *p) _res = ( asdl_expr_seq* ) _PyPegen_seq_insert_in_front ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16355,7 +16903,7 @@ star_targets_tuple_seq_rule(Parser *p) } { // star_target ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_targets_tuple_seq[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target ','")); @@ -16371,7 +16919,7 @@ star_targets_tuple_seq_rule(Parser *p) _res = ( asdl_expr_seq* ) _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16382,7 +16930,7 @@ star_targets_tuple_seq_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16390,20 +16938,23 @@ star_targets_tuple_seq_rule(Parser *p) static expr_ty star_target_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, star_target_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -16412,7 +16963,7 @@ star_target_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '*' (!'*' star_target) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (!'*' star_target)")); @@ -16427,7 +16978,7 @@ star_target_rule(Parser *p) D(fprintf(stderr, "%*c+ star_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (!'*' star_target)")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16437,7 +16988,7 @@ star_target_rule(Parser *p) _res = _PyAST_Starred ( CHECK ( expr_ty , _PyPegen_set_expr_context ( p , a , Store ) ) , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16448,7 +16999,7 @@ star_target_rule(Parser *p) } { // target_with_star_atom if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "target_with_star_atom")); @@ -16468,7 +17019,7 @@ star_target_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, star_target_type, _res); - D(p->level--); + p->level--; return _res; } @@ -16479,20 +17030,23 @@ star_target_rule(Parser *p) static expr_ty target_with_star_atom_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, target_with_star_atom_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -16501,7 +17055,7 @@ target_with_star_atom_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // t_primary '.' NAME !t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> target_with_star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); @@ -16521,7 +17075,7 @@ target_with_star_atom_rule(Parser *p) D(fprintf(stderr, "%*c+ target_with_star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16531,7 +17085,7 @@ target_with_star_atom_rule(Parser *p) _res = _PyAST_Attribute ( a , b -> v . Name . id , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16542,7 +17096,7 @@ target_with_star_atom_rule(Parser *p) } { // t_primary '[' slices ']' !t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> target_with_star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); @@ -16565,7 +17119,7 @@ target_with_star_atom_rule(Parser *p) D(fprintf(stderr, "%*c+ target_with_star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16575,7 +17129,7 @@ target_with_star_atom_rule(Parser *p) _res = _PyAST_Subscript ( a , b , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16586,7 +17140,7 @@ target_with_star_atom_rule(Parser *p) } { // star_atom if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> target_with_star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_atom")); @@ -16606,7 +17160,7 @@ target_with_star_atom_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, target_with_star_atom_type, _res); - D(p->level--); + p->level--; return _res; } @@ -16618,16 +17172,19 @@ target_with_star_atom_rule(Parser *p) static expr_ty star_atom_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -16636,7 +17193,7 @@ star_atom_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); @@ -16649,7 +17206,7 @@ star_atom_rule(Parser *p) _res = _PyPegen_set_expr_context ( p , a , Store ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16660,7 +17217,7 @@ star_atom_rule(Parser *p) } { // '(' target_with_star_atom ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' target_with_star_atom ')'")); @@ -16679,7 +17236,7 @@ star_atom_rule(Parser *p) _res = _PyPegen_set_expr_context ( p , a , Store ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16690,7 +17247,7 @@ star_atom_rule(Parser *p) } { // '(' star_targets_tuple_seq? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' star_targets_tuple_seq? ')'")); @@ -16708,7 +17265,7 @@ star_atom_rule(Parser *p) D(fprintf(stderr, "%*c+ star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' star_targets_tuple_seq? ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16718,7 +17275,7 @@ star_atom_rule(Parser *p) _res = _PyAST_Tuple ( a , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16729,7 +17286,7 @@ star_atom_rule(Parser *p) } { // '[' star_targets_list_seq? ']' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'[' star_targets_list_seq? ']'")); @@ -16747,7 +17304,7 @@ star_atom_rule(Parser *p) D(fprintf(stderr, "%*c+ star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' star_targets_list_seq? ']'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16757,7 +17314,7 @@ star_atom_rule(Parser *p) _res = _PyAST_List ( a , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16768,7 +17325,7 @@ star_atom_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16776,16 +17333,19 @@ star_atom_rule(Parser *p) static expr_ty single_target_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // single_subscript_attribute_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> single_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "single_subscript_attribute_target")); @@ -16804,7 +17364,7 @@ single_target_rule(Parser *p) } { // NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> single_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); @@ -16817,7 +17377,7 @@ single_target_rule(Parser *p) _res = _PyPegen_set_expr_context ( p , a , Store ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16828,7 +17388,7 @@ single_target_rule(Parser *p) } { // '(' single_target ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> single_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' single_target ')'")); @@ -16847,7 +17407,7 @@ single_target_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16858,7 +17418,7 @@ single_target_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16868,16 +17428,19 @@ single_target_rule(Parser *p) static expr_ty single_subscript_attribute_target_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -16886,7 +17449,7 @@ single_subscript_attribute_target_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // t_primary '.' NAME !t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> single_subscript_attribute_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); @@ -16906,7 +17469,7 @@ single_subscript_attribute_target_rule(Parser *p) D(fprintf(stderr, "%*c+ single_subscript_attribute_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16916,7 +17479,7 @@ single_subscript_attribute_target_rule(Parser *p) _res = _PyAST_Attribute ( a , b -> v . Name . id , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16927,7 +17490,7 @@ single_subscript_attribute_target_rule(Parser *p) } { // t_primary '[' slices ']' !t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> single_subscript_attribute_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); @@ -16950,7 +17513,7 @@ single_subscript_attribute_target_rule(Parser *p) D(fprintf(stderr, "%*c+ single_subscript_attribute_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16960,7 +17523,7 @@ single_subscript_attribute_target_rule(Parser *p) _res = _PyAST_Subscript ( a , b , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16971,7 +17534,7 @@ single_subscript_attribute_target_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16986,10 +17549,13 @@ static expr_ty t_primary_raw(Parser *); static expr_ty t_primary_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, t_primary_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -16997,37 +17563,42 @@ t_primary_rule(Parser *p) while (1) { int tmpvar_9 = _PyPegen_update_memo(p, _mark, t_primary_type, _res); if (tmpvar_9) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; p->in_raw_rule++; void *_raw = t_primary_raw(p); p->in_raw_rule--; - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty t_primary_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -17036,7 +17607,7 @@ t_primary_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // t_primary '.' NAME &t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME &t_lookahead")); @@ -17056,7 +17627,7 @@ t_primary_raw(Parser *p) D(fprintf(stderr, "%*c+ t_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME &t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17066,7 +17637,7 @@ t_primary_raw(Parser *p) _res = _PyAST_Attribute ( a , b -> v . Name . id , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17077,7 +17648,7 @@ t_primary_raw(Parser *p) } { // t_primary '[' slices ']' &t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' &t_lookahead")); @@ -17100,7 +17671,7 @@ t_primary_raw(Parser *p) D(fprintf(stderr, "%*c+ t_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' &t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17110,7 +17681,7 @@ t_primary_raw(Parser *p) _res = _PyAST_Subscript ( a , b , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17121,7 +17692,7 @@ t_primary_raw(Parser *p) } { // t_primary genexp &t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary genexp &t_lookahead")); @@ -17138,7 +17709,7 @@ t_primary_raw(Parser *p) D(fprintf(stderr, "%*c+ t_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary genexp &t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17148,7 +17719,7 @@ t_primary_raw(Parser *p) _res = _PyAST_Call ( a , CHECK ( asdl_expr_seq* , ( asdl_expr_seq* ) _PyPegen_singleton_seq ( p , b ) ) , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17159,7 +17730,7 @@ t_primary_raw(Parser *p) } { // t_primary '(' arguments? ')' &t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '(' arguments? ')' &t_lookahead")); @@ -17182,7 +17753,7 @@ t_primary_raw(Parser *p) D(fprintf(stderr, "%*c+ t_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '(' arguments? ')' &t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17192,7 +17763,7 @@ t_primary_raw(Parser *p) _res = _PyAST_Call ( a , ( b ) ? ( ( expr_ty ) b ) -> v . Call . args : NULL , ( b ) ? ( ( expr_ty ) b ) -> v . Call . keywords : NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17203,7 +17774,7 @@ t_primary_raw(Parser *p) } { // atom &t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "atom &t_lookahead")); @@ -17218,7 +17789,7 @@ t_primary_raw(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17229,7 +17800,7 @@ t_primary_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -17237,16 +17808,19 @@ t_primary_raw(Parser *p) static void * t_lookahead_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '(' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_lookahead[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); @@ -17265,7 +17839,7 @@ t_lookahead_rule(Parser *p) } { // '[' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_lookahead[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); @@ -17284,7 +17858,7 @@ t_lookahead_rule(Parser *p) } { // '.' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_lookahead[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); @@ -17303,7 +17877,7 @@ t_lookahead_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -17311,16 +17885,19 @@ t_lookahead_rule(Parser *p) static asdl_expr_seq* del_targets_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_expr_seq* _res = NULL; int _mark = p->mark; { // ','.del_target+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.del_target+ ','?")); @@ -17337,7 +17914,7 @@ del_targets_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17348,7 +17925,7 @@ del_targets_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -17359,20 +17936,23 @@ del_targets_rule(Parser *p) static expr_ty del_target_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, del_target_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -17381,7 +17961,7 @@ del_target_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // t_primary '.' NAME !t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); @@ -17401,7 +17981,7 @@ del_target_rule(Parser *p) D(fprintf(stderr, "%*c+ del_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17411,7 +17991,7 @@ del_target_rule(Parser *p) _res = _PyAST_Attribute ( a , b -> v . Name . id , Del , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17422,7 +18002,7 @@ del_target_rule(Parser *p) } { // t_primary '[' slices ']' !t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); @@ -17445,7 +18025,7 @@ del_target_rule(Parser *p) D(fprintf(stderr, "%*c+ del_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17455,7 +18035,7 @@ del_target_rule(Parser *p) _res = _PyAST_Subscript ( a , b , Del , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17466,7 +18046,7 @@ del_target_rule(Parser *p) } { // del_t_atom if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "del_t_atom")); @@ -17486,7 +18066,7 @@ del_target_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, del_target_type, _res); - D(p->level--); + p->level--; return _res; } @@ -17494,16 +18074,19 @@ del_target_rule(Parser *p) static expr_ty del_t_atom_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -17512,7 +18095,7 @@ del_t_atom_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_t_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); @@ -17525,7 +18108,7 @@ del_t_atom_rule(Parser *p) _res = _PyPegen_set_expr_context ( p , a , Del ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17536,7 +18119,7 @@ del_t_atom_rule(Parser *p) } { // '(' del_target ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_t_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' del_target ')'")); @@ -17555,7 +18138,7 @@ del_t_atom_rule(Parser *p) _res = _PyPegen_set_expr_context ( p , a , Del ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17566,7 +18149,7 @@ del_t_atom_rule(Parser *p) } { // '(' del_targets? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_t_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' del_targets? ')'")); @@ -17584,7 +18167,7 @@ del_t_atom_rule(Parser *p) D(fprintf(stderr, "%*c+ del_t_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' del_targets? ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17594,7 +18177,7 @@ del_t_atom_rule(Parser *p) _res = _PyAST_Tuple ( a , Del , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17605,7 +18188,7 @@ del_t_atom_rule(Parser *p) } { // '[' del_targets? ']' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_t_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'[' del_targets? ']'")); @@ -17623,7 +18206,7 @@ del_t_atom_rule(Parser *p) D(fprintf(stderr, "%*c+ del_t_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' del_targets? ']'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17633,7 +18216,7 @@ del_t_atom_rule(Parser *p) _res = _PyAST_List ( a , Del , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17644,7 +18227,7 @@ del_t_atom_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -17659,16 +18242,19 @@ del_t_atom_rule(Parser *p) static asdl_expr_seq* type_expressions_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_expr_seq* _res = NULL; int _mark = p->mark; { // ','.expression+ ',' '*' expression ',' '**' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.expression+ ',' '*' expression ',' '**' expression")); @@ -17699,7 +18285,7 @@ type_expressions_rule(Parser *p) _res = ( asdl_expr_seq* ) _PyPegen_seq_append_to_end ( p , CHECK ( asdl_seq* , _PyPegen_seq_append_to_end ( p , a , b ) ) , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17710,7 +18296,7 @@ type_expressions_rule(Parser *p) } { // ','.expression+ ',' '*' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.expression+ ',' '*' expression")); @@ -17732,7 +18318,7 @@ type_expressions_rule(Parser *p) _res = ( asdl_expr_seq* ) _PyPegen_seq_append_to_end ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17743,7 +18329,7 @@ type_expressions_rule(Parser *p) } { // ','.expression+ ',' '**' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.expression+ ',' '**' expression")); @@ -17765,7 +18351,7 @@ type_expressions_rule(Parser *p) _res = ( asdl_expr_seq* ) _PyPegen_seq_append_to_end ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17776,7 +18362,7 @@ type_expressions_rule(Parser *p) } { // '*' expression ',' '**' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' expression ',' '**' expression")); @@ -17801,7 +18387,7 @@ type_expressions_rule(Parser *p) _res = ( asdl_expr_seq* ) _PyPegen_seq_append_to_end ( p , CHECK ( asdl_seq* , _PyPegen_singleton_seq ( p , a ) ) , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17812,7 +18398,7 @@ type_expressions_rule(Parser *p) } { // '*' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' expression")); @@ -17828,7 +18414,7 @@ type_expressions_rule(Parser *p) _res = ( asdl_expr_seq* ) _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17839,7 +18425,7 @@ type_expressions_rule(Parser *p) } { // '**' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' expression")); @@ -17855,7 +18441,7 @@ type_expressions_rule(Parser *p) _res = ( asdl_expr_seq* ) _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17866,7 +18452,7 @@ type_expressions_rule(Parser *p) } { // ','.expression+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.expression+")); @@ -17879,7 +18465,7 @@ type_expressions_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17890,7 +18476,7 @@ type_expressions_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -17901,16 +18487,19 @@ type_expressions_rule(Parser *p) static Token* func_type_comment_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } Token* _res = NULL; int _mark = p->mark; { // NEWLINE TYPE_COMMENT &(NEWLINE INDENT) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> func_type_comment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE TYPE_COMMENT &(NEWLINE INDENT)")); @@ -17928,7 +18517,7 @@ func_type_comment_rule(Parser *p) _res = t; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17939,7 +18528,7 @@ func_type_comment_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_double_type_comments if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> func_type_comment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_double_type_comments")); @@ -17958,7 +18547,7 @@ func_type_comment_rule(Parser *p) } { // TYPE_COMMENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> func_type_comment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "TYPE_COMMENT")); @@ -17977,7 +18566,7 @@ func_type_comment_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -17991,16 +18580,19 @@ func_type_comment_rule(Parser *p) static void * invalid_arguments_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // args ',' '*' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ',' '*'")); @@ -18019,7 +18611,7 @@ invalid_arguments_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "iterable argument unpacking follows keyword argument unpacking" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18030,7 +18622,7 @@ invalid_arguments_rule(Parser *p) } { // expression for_if_clauses ',' [args | expression for_if_clauses] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses ',' [args | expression for_if_clauses]")); @@ -18053,7 +18645,7 @@ invalid_arguments_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , PyPegen_last_item ( b , comprehension_ty ) -> target , "Generator expression must be parenthesized" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18064,7 +18656,7 @@ invalid_arguments_rule(Parser *p) } { // NAME '=' expression for_if_clauses if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '=' expression for_if_clauses")); @@ -18086,7 +18678,7 @@ invalid_arguments_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Maybe you meant '==' or ':=' instead of '='?" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18097,7 +18689,7 @@ invalid_arguments_rule(Parser *p) } { // args for_if_clauses if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args for_if_clauses")); @@ -18113,7 +18705,7 @@ invalid_arguments_rule(Parser *p) _res = _PyPegen_nonparen_genexp_in_call ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18124,7 +18716,7 @@ invalid_arguments_rule(Parser *p) } { // args ',' expression for_if_clauses if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ',' expression for_if_clauses")); @@ -18146,7 +18738,7 @@ invalid_arguments_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , asdl_seq_GET ( b , b -> size - 1 ) -> target , "Generator expression must be parenthesized" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18157,7 +18749,7 @@ invalid_arguments_rule(Parser *p) } { // args ',' args if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ',' args")); @@ -18176,7 +18768,7 @@ invalid_arguments_rule(Parser *p) _res = _PyPegen_arguments_parsing_error ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18187,7 +18779,7 @@ invalid_arguments_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18198,16 +18790,19 @@ invalid_arguments_rule(Parser *p) static void * invalid_kwarg_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ('True' | 'False' | 'None') '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_kwarg[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('True' | 'False' | 'None') '='")); @@ -18223,7 +18818,7 @@ invalid_kwarg_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot assign to %s" , PyBytes_AS_STRING ( a -> bytes ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18234,7 +18829,7 @@ invalid_kwarg_rule(Parser *p) } { // NAME '=' expression for_if_clauses if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_kwarg[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '=' expression for_if_clauses")); @@ -18256,7 +18851,7 @@ invalid_kwarg_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Maybe you meant '==' or ':=' instead of '='?" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18267,7 +18862,7 @@ invalid_kwarg_rule(Parser *p) } { // !(NAME '=') expression '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_kwarg[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!(NAME '=') expression '='")); @@ -18285,7 +18880,7 @@ invalid_kwarg_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "expression cannot contain assignment, perhaps you meant \"==\"?" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18296,7 +18891,7 @@ invalid_kwarg_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18307,16 +18902,19 @@ invalid_kwarg_rule(Parser *p) static expr_ty expression_without_invalid_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -18325,7 +18923,7 @@ expression_without_invalid_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // disjunction 'if' disjunction 'else' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expression_without_invalid[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction 'else' expression")); @@ -18349,7 +18947,7 @@ expression_without_invalid_rule(Parser *p) D(fprintf(stderr, "%*c+ expression_without_invalid[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction 'else' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -18359,7 +18957,7 @@ expression_without_invalid_rule(Parser *p) _res = _PyAST_IfExp ( b , a , c , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18370,7 +18968,7 @@ expression_without_invalid_rule(Parser *p) } { // disjunction if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expression_without_invalid[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "disjunction")); @@ -18389,7 +18987,7 @@ expression_without_invalid_rule(Parser *p) } { // lambdef if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expression_without_invalid[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambdef")); @@ -18408,7 +19006,7 @@ expression_without_invalid_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18416,16 +19014,19 @@ expression_without_invalid_rule(Parser *p) static void * invalid_legacy_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // NAME !'(' star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_legacy_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME !'(' star_expressions")); @@ -18443,7 +19044,7 @@ invalid_legacy_expression_rule(Parser *p) _res = _PyPegen_check_legacy_stmt ( p , a ) ? RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "Missing parentheses in call to '%U'. Did you mean %U(...)?" , a -> v . Name . id , a -> v . Name . id ) : NULL; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18454,7 +19055,7 @@ invalid_legacy_expression_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18464,16 +19065,19 @@ invalid_legacy_expression_rule(Parser *p) static void * invalid_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // !(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid")); @@ -18491,7 +19095,7 @@ invalid_expression_rule(Parser *p) _res = _PyPegen_check_legacy_stmt ( p , a ) ? NULL : p -> tokens [p -> mark - 1] -> level == 0 ? NULL : RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Perhaps you forgot a comma?" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18502,7 +19106,7 @@ invalid_expression_rule(Parser *p) } { // disjunction 'if' disjunction !('else' | ':') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction !('else' | ':')")); @@ -18523,7 +19127,7 @@ invalid_expression_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "expected 'else' after 'if' expression" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18534,7 +19138,7 @@ invalid_expression_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18545,16 +19149,19 @@ invalid_expression_rule(Parser *p) static void * invalid_named_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // expression ':=' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ':=' expression")); @@ -18573,7 +19180,7 @@ invalid_named_expression_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use assignment expressions with %s" , _PyPegen_get_expr_name ( a ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18584,7 +19191,7 @@ invalid_named_expression_rule(Parser *p) } { // NAME '=' bitwise_or !('=' | ':=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '=' bitwise_or !('=' | ':=')")); @@ -18605,7 +19212,7 @@ invalid_named_expression_rule(Parser *p) _res = p -> in_raw_rule ? NULL : RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Maybe you meant '==' or ':=' instead of '='?" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18616,7 +19223,7 @@ invalid_named_expression_rule(Parser *p) } { // !(list | tuple | genexp | 'True' | 'None' | 'False') bitwise_or '=' bitwise_or !('=' | ':=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!(list | tuple | genexp | 'True' | 'None' | 'False') bitwise_or '=' bitwise_or !('=' | ':=')")); @@ -18639,7 +19246,7 @@ invalid_named_expression_rule(Parser *p) _res = p -> in_raw_rule ? NULL : RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot assign to %s here. Maybe you meant '==' instead of '='?" , _PyPegen_get_expr_name ( a ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18650,7 +19257,7 @@ invalid_named_expression_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18664,16 +19271,19 @@ invalid_named_expression_rule(Parser *p) static void * invalid_assignment_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // invalid_ann_assign_target ':' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_ann_assign_target ':' expression")); @@ -18692,7 +19302,7 @@ invalid_assignment_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "only single target (not %s) can be annotated" , _PyPegen_get_expr_name ( a ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18703,7 +19313,7 @@ invalid_assignment_rule(Parser *p) } { // star_named_expression ',' star_named_expressions* ':' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions* ':' expression")); @@ -18728,7 +19338,7 @@ invalid_assignment_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "only single target (not tuple) can be annotated" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18739,7 +19349,7 @@ invalid_assignment_rule(Parser *p) } { // expression ':' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ':' expression")); @@ -18758,7 +19368,7 @@ invalid_assignment_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "illegal target for annotation" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18769,7 +19379,7 @@ invalid_assignment_rule(Parser *p) } { // ((star_targets '='))* star_expressions '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* star_expressions '='")); @@ -18788,7 +19398,7 @@ invalid_assignment_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( STAR_TARGETS , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18799,7 +19409,7 @@ invalid_assignment_rule(Parser *p) } { // ((star_targets '='))* yield_expr '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* yield_expr '='")); @@ -18818,7 +19428,7 @@ invalid_assignment_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "assignment to yield expression not possible" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18829,7 +19439,7 @@ invalid_assignment_rule(Parser *p) } { // star_expressions augassign (yield_expr | star_expressions) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions augassign (yield_expr | star_expressions)")); @@ -18848,7 +19458,7 @@ invalid_assignment_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "'%s' is an illegal expression for augmented assignment" , _PyPegen_get_expr_name ( a ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18859,7 +19469,7 @@ invalid_assignment_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18867,16 +19477,19 @@ invalid_assignment_rule(Parser *p) static expr_ty invalid_ann_assign_target_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // list if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_ann_assign_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); @@ -18895,7 +19508,7 @@ invalid_ann_assign_target_rule(Parser *p) } { // tuple if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_ann_assign_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); @@ -18914,7 +19527,7 @@ invalid_ann_assign_target_rule(Parser *p) } { // '(' invalid_ann_assign_target ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_ann_assign_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' invalid_ann_assign_target ')'")); @@ -18933,7 +19546,7 @@ invalid_ann_assign_target_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18944,7 +19557,7 @@ invalid_ann_assign_target_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18952,16 +19565,19 @@ invalid_ann_assign_target_rule(Parser *p) static void * invalid_del_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'del' star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_del_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'del' star_expressions")); @@ -18977,7 +19593,7 @@ invalid_del_stmt_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( DEL_TARGETS , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18988,7 +19604,7 @@ invalid_del_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18996,16 +19612,19 @@ invalid_del_stmt_rule(Parser *p) static void * invalid_block_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE !INDENT")); @@ -19020,7 +19639,7 @@ invalid_block_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19031,7 +19650,7 @@ invalid_block_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19042,16 +19661,19 @@ invalid_block_rule(Parser *p) static void * invalid_comprehension_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ('[' | '(' | '{') starred_expression for_if_clauses if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '(' | '{') starred_expression for_if_clauses")); @@ -19070,7 +19692,7 @@ invalid_comprehension_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "iterable unpacking cannot be used in comprehension" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19081,7 +19703,7 @@ invalid_comprehension_rule(Parser *p) } { // ('[' | '{') star_named_expression ',' star_named_expressions for_if_clauses if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '{') star_named_expression ',' star_named_expressions for_if_clauses")); @@ -19106,7 +19728,7 @@ invalid_comprehension_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , PyPegen_last_item ( b , expr_ty ) , "did you forget parentheses around the comprehension target?" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19117,7 +19739,7 @@ invalid_comprehension_rule(Parser *p) } { // ('[' | '{') star_named_expression ',' for_if_clauses if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '{') star_named_expression ',' for_if_clauses")); @@ -19139,7 +19761,7 @@ invalid_comprehension_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "did you forget parentheses around the comprehension target?" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19150,7 +19772,7 @@ invalid_comprehension_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19158,16 +19780,19 @@ invalid_comprehension_rule(Parser *p) static void * invalid_dict_comprehension_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '{' '**' bitwise_or for_if_clauses '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_dict_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' '**' bitwise_or for_if_clauses '}'")); @@ -19192,7 +19817,7 @@ invalid_dict_comprehension_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "dict unpacking cannot be used in dict comprehension" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19203,7 +19828,7 @@ invalid_dict_comprehension_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19213,16 +19838,19 @@ invalid_dict_comprehension_rule(Parser *p) static void * invalid_parameters_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // param_no_default* invalid_parameters_helper param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default* invalid_parameters_helper param_no_default")); @@ -19241,7 +19869,7 @@ invalid_parameters_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "non-default argument follows default argument" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19252,7 +19880,7 @@ invalid_parameters_rule(Parser *p) } { // param_no_default* '(' param_no_default+ ','? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default* '(' param_no_default+ ','? ')'")); @@ -19278,7 +19906,7 @@ invalid_parameters_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "Function parameters cannot be parenthesized" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19289,7 +19917,7 @@ invalid_parameters_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19297,16 +19925,19 @@ invalid_parameters_rule(Parser *p) static void * invalid_parameters_helper_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // slash_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default")); @@ -19319,7 +19950,7 @@ invalid_parameters_helper_rule(Parser *p) _res = _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19330,7 +19961,7 @@ invalid_parameters_helper_rule(Parser *p) } { // param_with_default+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default+")); @@ -19349,7 +19980,7 @@ invalid_parameters_helper_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19359,16 +19990,19 @@ invalid_parameters_helper_rule(Parser *p) static void * invalid_lambda_parameters_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // lambda_param_no_default* invalid_lambda_parameters_helper lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* invalid_lambda_parameters_helper lambda_param_no_default")); @@ -19387,7 +20021,7 @@ invalid_lambda_parameters_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "non-default argument follows default argument" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19398,7 +20032,7 @@ invalid_lambda_parameters_rule(Parser *p) } { // lambda_param_no_default* '(' ','.lambda_param+ ','? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* '(' ','.lambda_param+ ','? ')'")); @@ -19424,7 +20058,7 @@ invalid_lambda_parameters_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "Lambda expression parameters cannot be parenthesized" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19435,7 +20069,7 @@ invalid_lambda_parameters_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19445,16 +20079,19 @@ invalid_lambda_parameters_rule(Parser *p) static void * invalid_lambda_parameters_helper_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // lambda_slash_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); @@ -19467,7 +20104,7 @@ invalid_lambda_parameters_helper_rule(Parser *p) _res = _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19478,7 +20115,7 @@ invalid_lambda_parameters_helper_rule(Parser *p) } { // lambda_param_with_default+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+")); @@ -19497,7 +20134,7 @@ invalid_lambda_parameters_helper_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19505,16 +20142,19 @@ invalid_lambda_parameters_helper_rule(Parser *p) static void * invalid_star_etc_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '*' (')' | ',' (')' | '**')) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))")); @@ -19530,7 +20170,7 @@ invalid_star_etc_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "named arguments must follow bare *" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19541,7 +20181,7 @@ invalid_star_etc_rule(Parser *p) } { // '*' ',' TYPE_COMMENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' ',' TYPE_COMMENT")); @@ -19560,7 +20200,7 @@ invalid_star_etc_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "bare * has associated type comment" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19571,7 +20211,7 @@ invalid_star_etc_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19579,16 +20219,19 @@ invalid_star_etc_rule(Parser *p) static void * invalid_lambda_star_etc_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '*' (':' | ',' (':' | '**')) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))")); @@ -19604,7 +20247,7 @@ invalid_lambda_star_etc_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "named arguments must follow bare *" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19615,7 +20258,7 @@ invalid_lambda_star_etc_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19623,16 +20266,19 @@ invalid_lambda_star_etc_rule(Parser *p) static void * invalid_double_type_comments_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // TYPE_COMMENT NEWLINE TYPE_COMMENT NEWLINE INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_double_type_comments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "TYPE_COMMENT NEWLINE TYPE_COMMENT NEWLINE INDENT")); @@ -19657,7 +20303,7 @@ invalid_double_type_comments_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "Cannot have two type comments on def" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19668,7 +20314,7 @@ invalid_double_type_comments_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19676,16 +20322,19 @@ invalid_double_type_comments_rule(Parser *p) static void * invalid_with_item_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // expression 'as' expression &(',' | ')' | ':') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_with_item[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression 'as' expression &(',' | ')' | ':')")); @@ -19706,7 +20355,7 @@ invalid_with_item_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( STAR_TARGETS , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19717,7 +20366,7 @@ invalid_with_item_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19725,16 +20374,19 @@ invalid_with_item_rule(Parser *p) static void * invalid_for_target_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ASYNC? 'for' star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_for_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'for' star_expressions")); @@ -19754,7 +20406,7 @@ invalid_for_target_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( FOR_TARGETS , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19765,7 +20417,7 @@ invalid_for_target_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19773,16 +20425,19 @@ invalid_for_target_rule(Parser *p) static void * invalid_group_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '(' starred_expression ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_group[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' starred_expression ')'")); @@ -19801,7 +20456,7 @@ invalid_group_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use starred expression here" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19812,7 +20467,7 @@ invalid_group_rule(Parser *p) } { // '(' '**' expression ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_group[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' '**' expression ')'")); @@ -19834,7 +20489,7 @@ invalid_group_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use double starred expression here" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19845,7 +20500,7 @@ invalid_group_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19853,16 +20508,19 @@ invalid_group_rule(Parser *p) static void * invalid_import_from_targets_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // import_from_as_names ',' NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_import_from_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "import_from_as_names ',' NEWLINE")); @@ -19881,7 +20539,7 @@ invalid_import_from_targets_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "trailing comma not allowed without surrounding parentheses" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19892,7 +20550,7 @@ invalid_import_from_targets_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19902,16 +20560,19 @@ invalid_import_from_targets_rule(Parser *p) static void * invalid_with_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ASYNC? 'with' ','.(expression ['as' star_target])+ &&':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' ','.(expression ['as' star_target])+ &&':'")); @@ -19940,7 +20601,7 @@ invalid_with_stmt_rule(Parser *p) } { // ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' &&':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' &&':'")); @@ -19979,7 +20640,7 @@ invalid_with_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19989,16 +20650,19 @@ invalid_with_stmt_rule(Parser *p) static void * invalid_with_stmt_indent_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ASYNC? 'with' ','.(expression ['as' star_target])+ ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' ','.(expression ['as' star_target])+ ':' NEWLINE !INDENT")); @@ -20026,7 +20690,7 @@ invalid_with_stmt_indent_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'with' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20037,7 +20701,7 @@ invalid_with_stmt_indent_rule(Parser *p) } { // ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' ':' NEWLINE !INDENT")); @@ -20075,7 +20739,7 @@ invalid_with_stmt_indent_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'with' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20086,7 +20750,7 @@ invalid_with_stmt_indent_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20097,16 +20761,19 @@ invalid_with_stmt_indent_rule(Parser *p) static void * invalid_try_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'try' ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_try_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'try' ':' NEWLINE !INDENT")); @@ -20127,7 +20794,7 @@ invalid_try_stmt_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'try' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20138,7 +20805,7 @@ invalid_try_stmt_rule(Parser *p) } { // 'try' ':' block !('except' | 'finally') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_try_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'try' ':' block !('except' | 'finally')")); @@ -20159,7 +20826,7 @@ invalid_try_stmt_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "expected 'except' or 'finally' block" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20170,7 +20837,7 @@ invalid_try_stmt_rule(Parser *p) } { // 'try' ':' block* ((except_block+ except_star_block) | (except_star_block+ except_block)) block* if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_try_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'try' ':' block* ((except_block+ except_star_block) | (except_star_block+ except_block)) block*")); @@ -20195,7 +20862,7 @@ invalid_try_stmt_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "cannot have both 'except' and 'except*' on the same 'try'" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20206,7 +20873,7 @@ invalid_try_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20218,16 +20885,19 @@ invalid_try_stmt_rule(Parser *p) static void * invalid_except_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'except' '*'? expression ',' expressions ['as' NAME] ':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_except_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' '*'? expression ',' expressions ['as' NAME] ':'")); @@ -20260,7 +20930,7 @@ invalid_except_stmt_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( a , "multiple exception types must be parenthesized" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20271,7 +20941,7 @@ invalid_except_stmt_rule(Parser *p) } { // 'except' '*'? expression ['as' NAME] NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_except_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' '*'? expression ['as' NAME] NEWLINE")); @@ -20298,7 +20968,7 @@ invalid_except_stmt_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20309,7 +20979,7 @@ invalid_except_stmt_rule(Parser *p) } { // 'except' NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_except_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' NEWLINE")); @@ -20325,7 +20995,7 @@ invalid_except_stmt_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20336,7 +21006,7 @@ invalid_except_stmt_rule(Parser *p) } { // 'except' '*' (NEWLINE | ':') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_except_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' '*' (NEWLINE | ':')")); @@ -20355,7 +21025,7 @@ invalid_except_stmt_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "expected one or more exception types" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20366,7 +21036,7 @@ invalid_except_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20374,16 +21044,19 @@ invalid_except_stmt_rule(Parser *p) static void * invalid_finally_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'finally' ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_finally_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally' ':' NEWLINE !INDENT")); @@ -20404,7 +21077,7 @@ invalid_finally_stmt_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'finally' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20415,7 +21088,7 @@ invalid_finally_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20425,16 +21098,19 @@ invalid_finally_stmt_rule(Parser *p) static void * invalid_except_stmt_indent_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'except' expression ['as' NAME] ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_except_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' expression ['as' NAME] ':' NEWLINE !INDENT")); @@ -20462,7 +21138,7 @@ invalid_except_stmt_indent_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'except' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20473,7 +21149,7 @@ invalid_except_stmt_indent_rule(Parser *p) } { // 'except' ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_except_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' ':' NEWLINE !INDENT")); @@ -20494,7 +21170,7 @@ invalid_except_stmt_indent_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "expected an indented block after except statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20505,7 +21181,7 @@ invalid_except_stmt_indent_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20514,16 +21190,19 @@ invalid_except_stmt_indent_rule(Parser *p) static void * invalid_except_star_stmt_indent_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'except' '*' expression ['as' NAME] ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_except_star_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' '*' expression ['as' NAME] ':' NEWLINE !INDENT")); @@ -20554,7 +21233,7 @@ invalid_except_star_stmt_indent_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'except*' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20565,7 +21244,7 @@ invalid_except_star_stmt_indent_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20575,16 +21254,19 @@ invalid_except_star_stmt_indent_rule(Parser *p) static void * invalid_match_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // "match" subject_expr !':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_match_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"match\" subject_expr !':'")); @@ -20602,7 +21284,7 @@ invalid_match_stmt_rule(Parser *p) _res = CHECK_VERSION ( void* , 10 , "Pattern matching is" , RAISE_SYNTAX_ERROR ( "expected ':'" ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20613,7 +21295,7 @@ invalid_match_stmt_rule(Parser *p) } { // "match" subject_expr ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_match_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"match\" subject_expr ':' NEWLINE !INDENT")); @@ -20637,7 +21319,7 @@ invalid_match_stmt_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'match' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20648,7 +21330,7 @@ invalid_match_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20658,16 +21340,19 @@ invalid_match_stmt_rule(Parser *p) static void * invalid_case_block_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // "case" patterns guard? !':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_case_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"case\" patterns guard? !':'")); @@ -20689,7 +21374,7 @@ invalid_case_block_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20700,7 +21385,7 @@ invalid_case_block_rule(Parser *p) } { // "case" patterns guard? ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_case_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"case\" patterns guard? ':' NEWLINE !INDENT")); @@ -20728,7 +21413,7 @@ invalid_case_block_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'case' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20739,7 +21424,7 @@ invalid_case_block_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20747,16 +21432,19 @@ invalid_case_block_rule(Parser *p) static void * invalid_as_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // or_pattern 'as' "_" if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_as_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "or_pattern 'as' \"_\"")); @@ -20775,7 +21463,7 @@ invalid_as_pattern_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use '_' as a target" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20786,7 +21474,7 @@ invalid_as_pattern_rule(Parser *p) } { // or_pattern 'as' !NAME expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_as_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "or_pattern 'as' !NAME expression")); @@ -20807,7 +21495,7 @@ invalid_as_pattern_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "invalid pattern target" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20818,7 +21506,7 @@ invalid_as_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20826,16 +21514,19 @@ invalid_as_pattern_rule(Parser *p) static void * invalid_class_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // name_or_attr '(' invalid_class_argument_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_class_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' invalid_class_argument_pattern")); @@ -20854,7 +21545,7 @@ invalid_class_pattern_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( PyPegen_first_item ( a , pattern_ty ) , PyPegen_last_item ( a , pattern_ty ) , "positional patterns follow keyword patterns" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20865,7 +21556,7 @@ invalid_class_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20874,16 +21565,19 @@ invalid_class_pattern_rule(Parser *p) static asdl_pattern_seq* invalid_class_argument_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_pattern_seq* _res = NULL; int _mark = p->mark; { // [positional_patterns ','] keyword_patterns ',' positional_patterns if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_class_argument_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "[positional_patterns ','] keyword_patterns ',' positional_patterns")); @@ -20906,7 +21600,7 @@ invalid_class_argument_pattern_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20917,7 +21611,7 @@ invalid_class_argument_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20927,16 +21621,19 @@ invalid_class_argument_pattern_rule(Parser *p) static void * invalid_if_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'if' named_expression NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_if_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' named_expression NEWLINE")); @@ -20955,7 +21652,7 @@ invalid_if_stmt_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20966,7 +21663,7 @@ invalid_if_stmt_rule(Parser *p) } { // 'if' named_expression ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_if_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' named_expression ':' NEWLINE !INDENT")); @@ -20990,7 +21687,7 @@ invalid_if_stmt_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'if' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -21001,7 +21698,7 @@ invalid_if_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21011,16 +21708,19 @@ invalid_if_stmt_rule(Parser *p) static void * invalid_elif_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'elif' named_expression NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_elif_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'elif' named_expression NEWLINE")); @@ -21039,7 +21739,7 @@ invalid_elif_stmt_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -21050,7 +21750,7 @@ invalid_elif_stmt_rule(Parser *p) } { // 'elif' named_expression ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_elif_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'elif' named_expression ':' NEWLINE !INDENT")); @@ -21074,7 +21774,7 @@ invalid_elif_stmt_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'elif' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -21085,7 +21785,7 @@ invalid_elif_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21093,16 +21793,19 @@ invalid_elif_stmt_rule(Parser *p) static void * invalid_else_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'else' ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_else_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else' ':' NEWLINE !INDENT")); @@ -21123,7 +21826,7 @@ invalid_else_stmt_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'else' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -21134,7 +21837,7 @@ invalid_else_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21144,16 +21847,19 @@ invalid_else_stmt_rule(Parser *p) static void * invalid_while_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'while' named_expression NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_while_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'while' named_expression NEWLINE")); @@ -21172,7 +21878,7 @@ invalid_while_stmt_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -21183,7 +21889,7 @@ invalid_while_stmt_rule(Parser *p) } { // 'while' named_expression ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_while_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'while' named_expression ':' NEWLINE !INDENT")); @@ -21207,7 +21913,7 @@ invalid_while_stmt_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'while' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -21218,7 +21924,7 @@ invalid_while_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21226,16 +21932,19 @@ invalid_while_stmt_rule(Parser *p) static void * invalid_for_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ASYNC? 'for' star_targets 'in' star_expressions ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_for_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'for' star_targets 'in' star_expressions ':' NEWLINE !INDENT")); @@ -21269,7 +21978,7 @@ invalid_for_stmt_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'for' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -21280,7 +21989,7 @@ invalid_for_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21289,16 +21998,19 @@ invalid_for_stmt_rule(Parser *p) static void * invalid_def_raw_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ASYNC? 'def' NAME '(' params? ')' ['->' expression] ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'def' NAME '(' params? ')' ['->' expression] ':' NEWLINE !INDENT")); @@ -21340,7 +22052,7 @@ invalid_def_raw_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after function definition on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -21351,7 +22063,7 @@ invalid_def_raw_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21359,16 +22071,19 @@ invalid_def_raw_rule(Parser *p) static void * invalid_class_def_raw_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'class' NAME ['(' arguments? ')'] ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_class_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class' NAME ['(' arguments? ')'] ':' NEWLINE !INDENT")); @@ -21396,7 +22111,7 @@ invalid_class_def_raw_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after class definition on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -21407,7 +22122,7 @@ invalid_class_def_raw_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21418,16 +22133,19 @@ invalid_class_def_raw_rule(Parser *p) static void * invalid_double_starred_kvpairs_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ','.double_starred_kvpair+ ',' invalid_kvpair if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_double_starred_kvpairs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ',' invalid_kvpair")); @@ -21452,7 +22170,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) } { // expression ':' '*' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_double_starred_kvpairs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ':' '*' bitwise_or")); @@ -21474,7 +22192,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( a , "cannot use a starred expression in a dictionary value" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -21485,7 +22203,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) } { // expression ':' &('}' | ',') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_double_starred_kvpairs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ':' &('}' | ',')")); @@ -21503,7 +22221,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "expression expected after dictionary key and ':'" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -21514,7 +22232,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21522,16 +22240,19 @@ invalid_double_starred_kvpairs_rule(Parser *p) static void * invalid_kvpair_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // expression !(':') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_kvpair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !(':')")); @@ -21546,7 +22267,7 @@ invalid_kvpair_rule(Parser *p) _res = RAISE_ERROR_KNOWN_LOCATION ( p , PyExc_SyntaxError , a -> lineno , a -> end_col_offset - 1 , a -> end_lineno , - 1 , "':' expected after dictionary key" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -21557,7 +22278,7 @@ invalid_kvpair_rule(Parser *p) } { // expression ':' '*' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_kvpair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ':' '*' bitwise_or")); @@ -21579,7 +22300,7 @@ invalid_kvpair_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( a , "cannot use a starred expression in a dictionary value" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -21590,7 +22311,7 @@ invalid_kvpair_rule(Parser *p) } { // expression ':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_kvpair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ':'")); @@ -21606,7 +22327,7 @@ invalid_kvpair_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "expression expected after dictionary key and ':'" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -21617,7 +22338,7 @@ invalid_kvpair_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21625,9 +22346,12 @@ invalid_kvpair_rule(Parser *p) static asdl_seq * _loop0_1_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -21637,14 +22361,14 @@ _loop0_1_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_1[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); @@ -21660,7 +22384,7 @@ _loop0_1_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -21677,13 +22401,13 @@ _loop0_1_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_1_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -21691,9 +22415,12 @@ _loop0_1_rule(Parser *p) static asdl_seq * _loop0_2_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -21703,14 +22430,14 @@ _loop0_2_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_2[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); @@ -21726,7 +22453,7 @@ _loop0_2_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -21743,13 +22470,13 @@ _loop0_2_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_2_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -21757,9 +22484,12 @@ _loop0_2_rule(Parser *p) static asdl_seq * _loop1_3_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -21769,14 +22499,14 @@ _loop1_3_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // statement if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_3[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "statement")); @@ -21792,7 +22522,7 @@ _loop1_3_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -21806,7 +22536,7 @@ _loop1_3_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -21814,13 +22544,13 @@ _loop1_3_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_3_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -21828,9 +22558,12 @@ _loop1_3_rule(Parser *p) static asdl_seq * _loop0_5_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -21840,14 +22573,14 @@ _loop0_5_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ';' simple_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_5[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "';' simple_stmt")); @@ -21863,7 +22596,7 @@ _loop0_5_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -21872,7 +22605,7 @@ _loop0_5_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -21889,13 +22622,13 @@ _loop0_5_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_5_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -21903,16 +22636,19 @@ _loop0_5_rule(Parser *p) static asdl_seq * _gather_4_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // simple_stmt _loop0_5 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_4[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "simple_stmt _loop0_5")); @@ -21934,7 +22670,7 @@ _gather_4_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21942,16 +22678,19 @@ _gather_4_rule(Parser *p) static void * _tmp_6_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'import' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_6[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'import'")); @@ -21970,7 +22709,7 @@ _tmp_6_rule(Parser *p) } { // 'from' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_6[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from'")); @@ -21989,7 +22728,7 @@ _tmp_6_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21997,16 +22736,19 @@ _tmp_6_rule(Parser *p) static void * _tmp_7_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'def' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_7[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'def'")); @@ -22025,7 +22767,7 @@ _tmp_7_rule(Parser *p) } { // '@' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_7[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@'")); @@ -22044,7 +22786,7 @@ _tmp_7_rule(Parser *p) } { // ASYNC if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_7[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC")); @@ -22063,7 +22805,7 @@ _tmp_7_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22071,16 +22813,19 @@ _tmp_7_rule(Parser *p) static void * _tmp_8_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'class' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_8[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class'")); @@ -22099,7 +22844,7 @@ _tmp_8_rule(Parser *p) } { // '@' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_8[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@'")); @@ -22118,7 +22863,7 @@ _tmp_8_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22126,16 +22871,19 @@ _tmp_8_rule(Parser *p) static void * _tmp_9_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'with' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_9[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'with'")); @@ -22154,7 +22902,7 @@ _tmp_9_rule(Parser *p) } { // ASYNC if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_9[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC")); @@ -22173,7 +22921,7 @@ _tmp_9_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22181,16 +22929,19 @@ _tmp_9_rule(Parser *p) static void * _tmp_10_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'for' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_10[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'for'")); @@ -22209,7 +22960,7 @@ _tmp_10_rule(Parser *p) } { // ASYNC if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_10[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC")); @@ -22228,7 +22979,7 @@ _tmp_10_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22236,16 +22987,19 @@ _tmp_10_rule(Parser *p) static void * _tmp_11_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '=' annotated_rhs if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_11[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'=' annotated_rhs")); @@ -22261,7 +23015,7 @@ _tmp_11_rule(Parser *p) _res = d; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -22272,7 +23026,7 @@ _tmp_11_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22280,16 +23034,19 @@ _tmp_11_rule(Parser *p) static void * _tmp_12_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '(' single_target ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_12[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' single_target ')'")); @@ -22308,7 +23065,7 @@ _tmp_12_rule(Parser *p) _res = b; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -22319,7 +23076,7 @@ _tmp_12_rule(Parser *p) } { // single_subscript_attribute_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_12[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "single_subscript_attribute_target")); @@ -22338,7 +23095,7 @@ _tmp_12_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22346,16 +23103,19 @@ _tmp_12_rule(Parser *p) static void * _tmp_13_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '=' annotated_rhs if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_13[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'=' annotated_rhs")); @@ -22371,7 +23131,7 @@ _tmp_13_rule(Parser *p) _res = d; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -22382,7 +23142,7 @@ _tmp_13_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22390,9 +23150,12 @@ _tmp_13_rule(Parser *p) static asdl_seq * _loop1_14_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -22402,14 +23165,14 @@ _loop1_14_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // (star_targets '=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_14[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); @@ -22425,7 +23188,7 @@ _loop1_14_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -22439,7 +23202,7 @@ _loop1_14_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -22447,13 +23210,13 @@ _loop1_14_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_14_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -22461,16 +23224,19 @@ _loop1_14_rule(Parser *p) static void * _tmp_15_rule(Parser *p) { - D(p->level++); - if (p->error_indicator) { - D(p->level--); - return NULL; + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; + return NULL; } void * _res = NULL; int _mark = p->mark; { // yield_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_15[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); @@ -22489,7 +23255,7 @@ _tmp_15_rule(Parser *p) } { // star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_15[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); @@ -22508,7 +23274,7 @@ _tmp_15_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22516,16 +23282,19 @@ _tmp_15_rule(Parser *p) static void * _tmp_16_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // yield_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_16[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); @@ -22544,7 +23313,7 @@ _tmp_16_rule(Parser *p) } { // star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_16[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); @@ -22563,7 +23332,7 @@ _tmp_16_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22571,16 +23340,19 @@ _tmp_16_rule(Parser *p) static void * _tmp_17_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'from' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_17[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from' expression")); @@ -22596,7 +23368,7 @@ _tmp_17_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -22607,7 +23379,7 @@ _tmp_17_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22615,9 +23387,12 @@ _tmp_17_rule(Parser *p) static asdl_seq * _loop0_19_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -22627,14 +23402,14 @@ _loop0_19_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_19[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' NAME")); @@ -22650,7 +23425,7 @@ _loop0_19_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -22659,7 +23434,7 @@ _loop0_19_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -22676,13 +23451,13 @@ _loop0_19_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_19_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -22690,16 +23465,19 @@ _loop0_19_rule(Parser *p) static asdl_seq * _gather_18_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // NAME _loop0_19 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_18[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME _loop0_19")); @@ -22721,7 +23499,7 @@ _gather_18_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22729,9 +23507,12 @@ _gather_18_rule(Parser *p) static asdl_seq * _loop0_21_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -22741,14 +23522,14 @@ _loop0_21_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_21[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' NAME")); @@ -22764,7 +23545,7 @@ _loop0_21_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -22773,7 +23554,7 @@ _loop0_21_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -22790,13 +23571,13 @@ _loop0_21_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_21_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -22804,16 +23585,19 @@ _loop0_21_rule(Parser *p) static asdl_seq * _gather_20_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // NAME _loop0_21 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_20[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME _loop0_21")); @@ -22835,7 +23619,7 @@ _gather_20_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22843,16 +23627,19 @@ _gather_20_rule(Parser *p) static void * _tmp_22_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ';' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_22[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "';'")); @@ -22871,7 +23658,7 @@ _tmp_22_rule(Parser *p) } { // NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_22[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); @@ -22890,7 +23677,7 @@ _tmp_22_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22898,16 +23685,19 @@ _tmp_22_rule(Parser *p) static void * _tmp_23_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_23[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); @@ -22923,7 +23713,7 @@ _tmp_23_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -22934,7 +23724,7 @@ _tmp_23_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22942,9 +23732,12 @@ _tmp_23_rule(Parser *p) static asdl_seq * _loop0_24_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -22954,14 +23747,14 @@ _loop0_24_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ('.' | '...') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_24[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); @@ -22977,7 +23770,7 @@ _loop0_24_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -22994,13 +23787,13 @@ _loop0_24_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_24_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23008,9 +23801,12 @@ _loop0_24_rule(Parser *p) static asdl_seq * _loop1_25_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23020,14 +23816,14 @@ _loop1_25_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ('.' | '...') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_25[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); @@ -23043,7 +23839,7 @@ _loop1_25_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23057,7 +23853,7 @@ _loop1_25_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -23065,13 +23861,13 @@ _loop1_25_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_25_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23079,9 +23875,12 @@ _loop1_25_rule(Parser *p) static asdl_seq * _loop0_27_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23091,14 +23890,14 @@ _loop0_27_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' import_from_as_name if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_27[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' import_from_as_name")); @@ -23114,7 +23913,7 @@ _loop0_27_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -23123,7 +23922,7 @@ _loop0_27_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23140,13 +23939,13 @@ _loop0_27_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_27_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23154,16 +23953,19 @@ _loop0_27_rule(Parser *p) static asdl_seq * _gather_26_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // import_from_as_name _loop0_27 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_26[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "import_from_as_name _loop0_27")); @@ -23185,7 +23987,7 @@ _gather_26_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23193,16 +23995,19 @@ _gather_26_rule(Parser *p) static void * _tmp_28_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_28[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); @@ -23218,7 +24023,7 @@ _tmp_28_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -23229,7 +24034,7 @@ _tmp_28_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23237,9 +24042,12 @@ _tmp_28_rule(Parser *p) static asdl_seq * _loop0_30_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23249,14 +24057,14 @@ _loop0_30_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' dotted_as_name if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_30[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' dotted_as_name")); @@ -23272,7 +24080,7 @@ _loop0_30_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -23281,7 +24089,7 @@ _loop0_30_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23298,13 +24106,13 @@ _loop0_30_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_30_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23312,16 +24120,19 @@ _loop0_30_rule(Parser *p) static asdl_seq * _gather_29_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // dotted_as_name _loop0_30 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_29[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dotted_as_name _loop0_30")); @@ -23343,7 +24154,7 @@ _gather_29_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23351,16 +24162,19 @@ _gather_29_rule(Parser *p) static void * _tmp_31_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_31[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); @@ -23376,7 +24190,7 @@ _tmp_31_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -23387,7 +24201,7 @@ _tmp_31_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23395,9 +24209,12 @@ _tmp_31_rule(Parser *p) static asdl_seq * _loop1_32_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23407,14 +24224,14 @@ _loop1_32_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ('@' named_expression NEWLINE) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_32[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('@' named_expression NEWLINE)")); @@ -23430,7 +24247,7 @@ _loop1_32_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23444,7 +24261,7 @@ _loop1_32_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -23452,13 +24269,13 @@ _loop1_32_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_32_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23466,16 +24283,19 @@ _loop1_32_rule(Parser *p) static void * _tmp_33_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '(' arguments? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_33[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); @@ -23494,7 +24314,7 @@ _tmp_33_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -23505,7 +24325,7 @@ _tmp_33_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23513,16 +24333,19 @@ _tmp_33_rule(Parser *p) static void * _tmp_34_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '->' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_34[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); @@ -23538,7 +24361,7 @@ _tmp_34_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -23549,7 +24372,7 @@ _tmp_34_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23557,16 +24380,19 @@ _tmp_34_rule(Parser *p) static void * _tmp_35_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '->' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_35[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); @@ -23582,7 +24408,7 @@ _tmp_35_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -23593,7 +24419,7 @@ _tmp_35_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23601,9 +24427,12 @@ _tmp_35_rule(Parser *p) static asdl_seq * _loop0_36_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23613,14 +24442,14 @@ _loop0_36_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_36[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -23636,7 +24465,7 @@ _loop0_36_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23653,13 +24482,13 @@ _loop0_36_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_36_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23667,9 +24496,12 @@ _loop0_36_rule(Parser *p) static asdl_seq * _loop0_37_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23679,14 +24511,14 @@ _loop0_37_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_37[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); @@ -23702,7 +24534,7 @@ _loop0_37_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23719,13 +24551,13 @@ _loop0_37_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_37_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23733,9 +24565,12 @@ _loop0_37_rule(Parser *p) static asdl_seq * _loop0_38_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23745,14 +24580,14 @@ _loop0_38_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_38[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); @@ -23768,7 +24603,7 @@ _loop0_38_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23785,13 +24620,13 @@ _loop0_38_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_38_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23799,9 +24634,12 @@ _loop0_38_rule(Parser *p) static asdl_seq * _loop1_39_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23811,14 +24649,14 @@ _loop1_39_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_39[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -23834,7 +24672,7 @@ _loop1_39_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23848,7 +24686,7 @@ _loop1_39_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -23856,13 +24694,13 @@ _loop1_39_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_39_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23870,9 +24708,12 @@ _loop1_39_rule(Parser *p) static asdl_seq * _loop0_40_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23882,14 +24723,14 @@ _loop0_40_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_40[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); @@ -23905,7 +24746,7 @@ _loop0_40_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23922,13 +24763,13 @@ _loop0_40_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_40_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23936,9 +24777,12 @@ _loop0_40_rule(Parser *p) static asdl_seq * _loop1_41_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23948,14 +24792,14 @@ _loop1_41_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_41[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); @@ -23971,7 +24815,7 @@ _loop1_41_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23985,7 +24829,7 @@ _loop1_41_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -23993,13 +24837,13 @@ _loop1_41_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_41_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -24007,9 +24851,12 @@ _loop1_41_rule(Parser *p) static asdl_seq * _loop1_42_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -24019,14 +24866,14 @@ _loop1_42_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_42[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -24042,7 +24889,7 @@ _loop1_42_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -24056,7 +24903,7 @@ _loop1_42_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -24064,13 +24911,13 @@ _loop1_42_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_42_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -24078,9 +24925,12 @@ _loop1_42_rule(Parser *p) static asdl_seq * _loop1_43_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -24090,14 +24940,14 @@ _loop1_43_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_43[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -24113,7 +24963,7 @@ _loop1_43_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -24127,7 +24977,7 @@ _loop1_43_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -24135,13 +24985,13 @@ _loop1_43_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_43_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -24149,9 +24999,12 @@ _loop1_43_rule(Parser *p) static asdl_seq * _loop0_44_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -24161,14 +25014,14 @@ _loop0_44_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_44[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -24184,7 +25037,7 @@ _loop0_44_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -24201,13 +25054,13 @@ _loop0_44_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_44_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -24215,9 +25068,12 @@ _loop0_44_rule(Parser *p) static asdl_seq * _loop1_45_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -24227,14 +25083,14 @@ _loop1_45_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_45[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); @@ -24250,7 +25106,7 @@ _loop1_45_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -24264,7 +25120,7 @@ _loop1_45_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -24272,13 +25128,13 @@ _loop1_45_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_45_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -24286,9 +25142,12 @@ _loop1_45_rule(Parser *p) static asdl_seq * _loop0_46_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -24298,14 +25157,14 @@ _loop0_46_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_46[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -24321,7 +25180,7 @@ _loop0_46_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -24338,13 +25197,13 @@ _loop0_46_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_46_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -24352,9 +25211,12 @@ _loop0_46_rule(Parser *p) static asdl_seq * _loop1_47_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -24364,14 +25226,14 @@ _loop1_47_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_47[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); @@ -24387,7 +25249,7 @@ _loop1_47_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -24401,7 +25263,7 @@ _loop1_47_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -24409,13 +25271,13 @@ _loop1_47_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_47_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -24423,9 +25285,12 @@ _loop1_47_rule(Parser *p) static asdl_seq * _loop0_48_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -24435,14 +25300,14 @@ _loop0_48_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_maybe_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_48[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); @@ -24458,7 +25323,7 @@ _loop0_48_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -24475,13 +25340,13 @@ _loop0_48_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_48_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -24489,9 +25354,12 @@ _loop0_48_rule(Parser *p) static asdl_seq * _loop1_49_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -24501,14 +25369,14 @@ _loop1_49_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_maybe_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_49[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); @@ -24524,7 +25392,7 @@ _loop1_49_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -24538,7 +25406,7 @@ _loop1_49_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -24546,13 +25414,13 @@ _loop1_49_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_49_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -24560,9 +25428,12 @@ _loop1_49_rule(Parser *p) static asdl_seq * _loop0_51_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -24572,14 +25443,14 @@ _loop0_51_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' with_item if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_51[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); @@ -24595,7 +25466,7 @@ _loop0_51_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -24604,7 +25475,7 @@ _loop0_51_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -24621,13 +25492,13 @@ _loop0_51_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_51_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -24635,16 +25506,19 @@ _loop0_51_rule(Parser *p) static asdl_seq * _gather_50_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // with_item _loop0_51 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_50[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_51")); @@ -24666,7 +25540,7 @@ _gather_50_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24674,9 +25548,12 @@ _gather_50_rule(Parser *p) static asdl_seq * _loop0_53_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -24686,14 +25563,14 @@ _loop0_53_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' with_item if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_53[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); @@ -24709,7 +25586,7 @@ _loop0_53_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -24718,7 +25595,7 @@ _loop0_53_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -24735,13 +25612,13 @@ _loop0_53_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_53_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -24749,16 +25626,19 @@ _loop0_53_rule(Parser *p) static asdl_seq * _gather_52_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // with_item _loop0_53 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_52[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_53")); @@ -24780,7 +25660,7 @@ _gather_52_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24788,9 +25668,12 @@ _gather_52_rule(Parser *p) static asdl_seq * _loop0_55_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -24800,14 +25683,14 @@ _loop0_55_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' with_item if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_55[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); @@ -24823,7 +25706,7 @@ _loop0_55_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -24832,7 +25715,7 @@ _loop0_55_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -24849,13 +25732,13 @@ _loop0_55_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_55_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -24863,16 +25746,19 @@ _loop0_55_rule(Parser *p) static asdl_seq * _gather_54_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // with_item _loop0_55 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_54[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_55")); @@ -24894,7 +25780,7 @@ _gather_54_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24902,9 +25788,12 @@ _gather_54_rule(Parser *p) static asdl_seq * _loop0_57_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -24914,14 +25803,14 @@ _loop0_57_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' with_item if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_57[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); @@ -24937,7 +25826,7 @@ _loop0_57_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -24946,7 +25835,7 @@ _loop0_57_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -24963,13 +25852,13 @@ _loop0_57_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_57_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -24977,16 +25866,19 @@ _loop0_57_rule(Parser *p) static asdl_seq * _gather_56_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // with_item _loop0_57 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_56[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_57")); @@ -25008,7 +25900,7 @@ _gather_56_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -25016,16 +25908,19 @@ _gather_56_rule(Parser *p) static void * _tmp_58_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_58[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); @@ -25044,7 +25939,7 @@ _tmp_58_rule(Parser *p) } { // ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_58[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); @@ -25063,7 +25958,7 @@ _tmp_58_rule(Parser *p) } { // ':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_58[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); @@ -25082,7 +25977,7 @@ _tmp_58_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -25090,9 +25985,12 @@ _tmp_58_rule(Parser *p) static asdl_seq * _loop1_59_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25102,14 +26000,14 @@ _loop1_59_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // except_block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_59[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_block")); @@ -25125,7 +26023,7 @@ _loop1_59_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25139,7 +26037,7 @@ _loop1_59_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -25147,13 +26045,13 @@ _loop1_59_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_59_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25161,9 +26059,12 @@ _loop1_59_rule(Parser *p) static asdl_seq * _loop1_60_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25173,14 +26074,14 @@ _loop1_60_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // except_star_block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_60[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_star_block")); @@ -25196,7 +26097,7 @@ _loop1_60_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25210,7 +26111,7 @@ _loop1_60_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -25218,13 +26119,13 @@ _loop1_60_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_60_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25232,16 +26133,19 @@ _loop1_60_rule(Parser *p) static void * _tmp_61_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_61[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); @@ -25257,7 +26161,7 @@ _tmp_61_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -25268,7 +26172,7 @@ _tmp_61_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -25276,16 +26180,19 @@ _tmp_61_rule(Parser *p) static void * _tmp_62_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_62[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); @@ -25301,7 +26208,7 @@ _tmp_62_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -25312,7 +26219,7 @@ _tmp_62_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -25320,9 +26227,12 @@ _tmp_62_rule(Parser *p) static asdl_seq * _loop1_63_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25332,14 +26242,14 @@ _loop1_63_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // case_block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_63[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "case_block")); @@ -25355,7 +26265,7 @@ _loop1_63_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25369,7 +26279,7 @@ _loop1_63_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -25377,13 +26287,13 @@ _loop1_63_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_63_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25391,9 +26301,12 @@ _loop1_63_rule(Parser *p) static asdl_seq * _loop0_65_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25403,14 +26316,14 @@ _loop0_65_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // '|' closed_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_65[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'|' closed_pattern")); @@ -25426,7 +26339,7 @@ _loop0_65_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -25435,7 +26348,7 @@ _loop0_65_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25452,13 +26365,13 @@ _loop0_65_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_65_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25466,16 +26379,19 @@ _loop0_65_rule(Parser *p) static asdl_seq * _gather_64_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // closed_pattern _loop0_65 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_64[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "closed_pattern _loop0_65")); @@ -25497,7 +26413,7 @@ _gather_64_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -25505,16 +26421,19 @@ _gather_64_rule(Parser *p) static void * _tmp_66_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '+' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_66[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); @@ -25533,7 +26452,7 @@ _tmp_66_rule(Parser *p) } { // '-' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_66[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); @@ -25552,7 +26471,7 @@ _tmp_66_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -25560,16 +26479,19 @@ _tmp_66_rule(Parser *p) static void * _tmp_67_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '+' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_67[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); @@ -25588,7 +26510,7 @@ _tmp_67_rule(Parser *p) } { // '-' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_67[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); @@ -25607,7 +26529,7 @@ _tmp_67_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -25615,16 +26537,19 @@ _tmp_67_rule(Parser *p) static void * _tmp_68_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '.' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_68[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); @@ -25643,7 +26568,7 @@ _tmp_68_rule(Parser *p) } { // '(' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_68[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); @@ -25662,7 +26587,7 @@ _tmp_68_rule(Parser *p) } { // '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_68[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); @@ -25681,7 +26606,7 @@ _tmp_68_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -25689,16 +26614,19 @@ _tmp_68_rule(Parser *p) static void * _tmp_69_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '.' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_69[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); @@ -25717,7 +26645,7 @@ _tmp_69_rule(Parser *p) } { // '(' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_69[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); @@ -25736,7 +26664,7 @@ _tmp_69_rule(Parser *p) } { // '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_69[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); @@ -25755,7 +26683,7 @@ _tmp_69_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -25763,9 +26691,12 @@ _tmp_69_rule(Parser *p) static asdl_seq * _loop0_71_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25775,14 +26706,14 @@ _loop0_71_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' maybe_star_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_71[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' maybe_star_pattern")); @@ -25798,7 +26729,7 @@ _loop0_71_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -25807,7 +26738,7 @@ _loop0_71_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25824,13 +26755,13 @@ _loop0_71_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_71_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25838,16 +26769,19 @@ _loop0_71_rule(Parser *p) static asdl_seq * _gather_70_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // maybe_star_pattern _loop0_71 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_70[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "maybe_star_pattern _loop0_71")); @@ -25869,7 +26803,7 @@ _gather_70_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -25877,9 +26811,12 @@ _gather_70_rule(Parser *p) static asdl_seq * _loop0_73_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25889,14 +26826,14 @@ _loop0_73_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' key_value_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_73[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' key_value_pattern")); @@ -25912,7 +26849,7 @@ _loop0_73_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -25921,7 +26858,7 @@ _loop0_73_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25938,13 +26875,13 @@ _loop0_73_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_73_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25952,16 +26889,19 @@ _loop0_73_rule(Parser *p) static asdl_seq * _gather_72_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // key_value_pattern _loop0_73 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_72[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "key_value_pattern _loop0_73")); @@ -25983,7 +26923,7 @@ _gather_72_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -25991,16 +26931,19 @@ _gather_72_rule(Parser *p) static void * _tmp_74_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // literal_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_74[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "literal_expr")); @@ -26019,7 +26962,7 @@ _tmp_74_rule(Parser *p) } { // attr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_74[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "attr")); @@ -26038,7 +26981,7 @@ _tmp_74_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -26046,9 +26989,12 @@ _tmp_74_rule(Parser *p) static asdl_seq * _loop0_76_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26058,14 +27004,14 @@ _loop0_76_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_76[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' pattern")); @@ -26081,7 +27027,7 @@ _loop0_76_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -26090,7 +27036,7 @@ _loop0_76_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26107,13 +27053,13 @@ _loop0_76_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_76_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26121,16 +27067,19 @@ _loop0_76_rule(Parser *p) static asdl_seq * _gather_75_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // pattern _loop0_76 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_75[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "pattern _loop0_76")); @@ -26152,7 +27101,7 @@ _gather_75_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -26160,9 +27109,12 @@ _gather_75_rule(Parser *p) static asdl_seq * _loop0_78_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26172,14 +27124,14 @@ _loop0_78_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' keyword_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_78[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' keyword_pattern")); @@ -26195,7 +27147,7 @@ _loop0_78_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -26204,7 +27156,7 @@ _loop0_78_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26221,13 +27173,13 @@ _loop0_78_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_78_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26235,16 +27187,19 @@ _loop0_78_rule(Parser *p) static asdl_seq * _gather_77_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // keyword_pattern _loop0_78 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_77[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "keyword_pattern _loop0_78")); @@ -26266,7 +27221,7 @@ _gather_77_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -26274,9 +27229,12 @@ _gather_77_rule(Parser *p) static asdl_seq * _loop1_79_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26286,14 +27244,14 @@ _loop1_79_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // (',' expression) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_79[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' expression)")); @@ -26309,7 +27267,7 @@ _loop1_79_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26323,7 +27281,7 @@ _loop1_79_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26331,13 +27289,13 @@ _loop1_79_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_79_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26345,9 +27303,12 @@ _loop1_79_rule(Parser *p) static asdl_seq * _loop1_80_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26357,14 +27318,14 @@ _loop1_80_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // (',' star_expression) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_80[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_expression)")); @@ -26380,7 +27341,7 @@ _loop1_80_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26394,7 +27355,7 @@ _loop1_80_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26402,13 +27363,13 @@ _loop1_80_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_80_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26416,9 +27377,12 @@ _loop1_80_rule(Parser *p) static asdl_seq * _loop0_82_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26428,14 +27392,14 @@ _loop0_82_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' star_named_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_82[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_named_expression")); @@ -26451,7 +27415,7 @@ _loop0_82_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -26460,7 +27424,7 @@ _loop0_82_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26477,13 +27441,13 @@ _loop0_82_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_82_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26491,16 +27455,19 @@ _loop0_82_rule(Parser *p) static asdl_seq * _gather_81_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // star_named_expression _loop0_82 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_81[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression _loop0_82")); @@ -26522,7 +27489,7 @@ _gather_81_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -26530,9 +27497,12 @@ _gather_81_rule(Parser *p) static asdl_seq * _loop1_83_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26542,14 +27512,14 @@ _loop1_83_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ('or' conjunction) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_83[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('or' conjunction)")); @@ -26565,7 +27535,7 @@ _loop1_83_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26579,7 +27549,7 @@ _loop1_83_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26587,13 +27557,13 @@ _loop1_83_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_83_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26601,9 +27571,12 @@ _loop1_83_rule(Parser *p) static asdl_seq * _loop1_84_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26613,14 +27586,14 @@ _loop1_84_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ('and' inversion) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_84[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('and' inversion)")); @@ -26636,7 +27609,7 @@ _loop1_84_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26650,7 +27623,7 @@ _loop1_84_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26658,13 +27631,13 @@ _loop1_84_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_84_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26672,9 +27645,12 @@ _loop1_84_rule(Parser *p) static asdl_seq * _loop1_85_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26684,14 +27660,14 @@ _loop1_85_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // compare_op_bitwise_or_pair if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_85[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "compare_op_bitwise_or_pair")); @@ -26707,7 +27683,7 @@ _loop1_85_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26721,7 +27697,7 @@ _loop1_85_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26729,13 +27705,13 @@ _loop1_85_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_85_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26743,16 +27719,19 @@ _loop1_85_rule(Parser *p) static void * _tmp_86_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '!=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_86[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!='")); @@ -26765,7 +27744,7 @@ _tmp_86_rule(Parser *p) _res = _PyPegen_check_barry_as_flufl ( p , tok ) ? NULL : tok; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -26776,7 +27755,7 @@ _tmp_86_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -26784,9 +27763,12 @@ _tmp_86_rule(Parser *p) static asdl_seq * _loop0_88_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26796,14 +27778,14 @@ _loop0_88_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' slice if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_88[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' slice")); @@ -26819,7 +27801,7 @@ _loop0_88_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -26828,7 +27810,7 @@ _loop0_88_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26845,13 +27827,13 @@ _loop0_88_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_88_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26859,16 +27841,19 @@ _loop0_88_rule(Parser *p) static asdl_seq * _gather_87_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // slice _loop0_88 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_87[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slice _loop0_88")); @@ -26890,7 +27875,7 @@ _gather_87_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -26898,16 +27883,19 @@ _gather_87_rule(Parser *p) static void * _tmp_89_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ':' expression? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_89[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':' expression?")); @@ -26923,7 +27911,7 @@ _tmp_89_rule(Parser *p) _res = d; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -26934,7 +27922,7 @@ _tmp_89_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -26942,16 +27930,19 @@ _tmp_89_rule(Parser *p) static void * _tmp_90_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // tuple if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_90[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); @@ -26970,7 +27961,7 @@ _tmp_90_rule(Parser *p) } { // group if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_90[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "group")); @@ -26989,7 +27980,7 @@ _tmp_90_rule(Parser *p) } { // genexp if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_90[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); @@ -27008,7 +27999,7 @@ _tmp_90_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -27016,16 +28007,19 @@ _tmp_90_rule(Parser *p) static void * _tmp_91_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // list if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_91[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); @@ -27044,7 +28038,7 @@ _tmp_91_rule(Parser *p) } { // listcomp if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_91[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "listcomp")); @@ -27063,7 +28057,7 @@ _tmp_91_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -27071,16 +28065,19 @@ _tmp_91_rule(Parser *p) static void * _tmp_92_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // dict if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_92[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dict")); @@ -27099,7 +28096,7 @@ _tmp_92_rule(Parser *p) } { // set if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_92[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "set")); @@ -27118,7 +28115,7 @@ _tmp_92_rule(Parser *p) } { // dictcomp if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_92[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dictcomp")); @@ -27137,7 +28134,7 @@ _tmp_92_rule(Parser *p) } { // setcomp if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_92[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "setcomp")); @@ -27156,7 +28153,7 @@ _tmp_92_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -27164,16 +28161,19 @@ _tmp_92_rule(Parser *p) static void * _tmp_93_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // yield_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_93[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); @@ -27192,7 +28192,7 @@ _tmp_93_rule(Parser *p) } { // named_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_93[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression")); @@ -27211,7 +28211,7 @@ _tmp_93_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -27219,9 +28219,12 @@ _tmp_93_rule(Parser *p) static asdl_seq * _loop0_94_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27231,14 +28234,14 @@ _loop0_94_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_94[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -27254,7 +28257,7 @@ _loop0_94_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27271,13 +28274,13 @@ _loop0_94_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_94_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27285,9 +28288,12 @@ _loop0_94_rule(Parser *p) static asdl_seq * _loop0_95_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27297,14 +28303,14 @@ _loop0_95_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_95[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); @@ -27320,7 +28326,7 @@ _loop0_95_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27337,13 +28343,13 @@ _loop0_95_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_95_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27351,9 +28357,12 @@ _loop0_95_rule(Parser *p) static asdl_seq * _loop0_96_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27363,14 +28372,14 @@ _loop0_96_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_96[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); @@ -27386,7 +28395,7 @@ _loop0_96_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27403,13 +28412,13 @@ _loop0_96_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_96_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27417,9 +28426,12 @@ _loop0_96_rule(Parser *p) static asdl_seq * _loop1_97_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27429,14 +28441,14 @@ _loop1_97_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -27452,7 +28464,7 @@ _loop1_97_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27466,7 +28478,7 @@ _loop1_97_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27474,13 +28486,13 @@ _loop1_97_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_97_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27488,9 +28500,12 @@ _loop1_97_rule(Parser *p) static asdl_seq * _loop0_98_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27500,14 +28515,14 @@ _loop0_98_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_98[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); @@ -27523,7 +28538,7 @@ _loop0_98_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27540,13 +28555,13 @@ _loop0_98_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_98_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27554,10 +28569,13 @@ _loop0_98_rule(Parser *p) static asdl_seq * _loop1_99_rule(Parser *p) { - D(p->level++); - if (p->error_indicator) { - D(p->level--); - return NULL; + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; + return NULL; } void *_res = NULL; int _mark = p->mark; @@ -27566,14 +28584,14 @@ _loop1_99_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_99[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); @@ -27589,7 +28607,7 @@ _loop1_99_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27603,7 +28621,7 @@ _loop1_99_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27611,13 +28629,13 @@ _loop1_99_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_99_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27625,9 +28643,12 @@ _loop1_99_rule(Parser *p) static asdl_seq * _loop1_100_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27637,14 +28658,14 @@ _loop1_100_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_100[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -27660,7 +28681,7 @@ _loop1_100_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27674,7 +28695,7 @@ _loop1_100_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27682,13 +28703,13 @@ _loop1_100_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_100_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27696,9 +28717,12 @@ _loop1_100_rule(Parser *p) static asdl_seq * _loop1_101_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27708,14 +28732,14 @@ _loop1_101_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_101[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -27731,7 +28755,7 @@ _loop1_101_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27745,7 +28769,7 @@ _loop1_101_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27753,13 +28777,13 @@ _loop1_101_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_101_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27767,9 +28791,12 @@ _loop1_101_rule(Parser *p) static asdl_seq * _loop0_102_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27779,14 +28806,14 @@ _loop0_102_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_102[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -27802,7 +28829,7 @@ _loop0_102_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27819,13 +28846,13 @@ _loop0_102_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_102_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27833,9 +28860,12 @@ _loop0_102_rule(Parser *p) static asdl_seq * _loop1_103_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27845,14 +28875,14 @@ _loop1_103_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_103[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); @@ -27868,7 +28898,7 @@ _loop1_103_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27882,7 +28912,7 @@ _loop1_103_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27890,13 +28920,13 @@ _loop1_103_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_103_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27904,9 +28934,12 @@ _loop1_103_rule(Parser *p) static asdl_seq * _loop0_104_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27916,14 +28949,14 @@ _loop0_104_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_104[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -27939,7 +28972,7 @@ _loop0_104_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27956,13 +28989,13 @@ _loop0_104_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_104_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27970,9 +29003,12 @@ _loop0_104_rule(Parser *p) static asdl_seq * _loop1_105_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27982,14 +29018,14 @@ _loop1_105_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_105[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); @@ -28005,7 +29041,7 @@ _loop1_105_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28019,7 +29055,7 @@ _loop1_105_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28027,13 +29063,13 @@ _loop1_105_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_105_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -28041,9 +29077,12 @@ _loop1_105_rule(Parser *p) static asdl_seq * _loop0_106_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -28053,14 +29092,14 @@ _loop0_106_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_maybe_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_106[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); @@ -28076,7 +29115,7 @@ _loop0_106_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28093,13 +29132,13 @@ _loop0_106_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_106_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -28107,9 +29146,12 @@ _loop0_106_rule(Parser *p) static asdl_seq * _loop1_107_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -28119,14 +29161,14 @@ _loop1_107_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_maybe_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_107[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); @@ -28142,7 +29184,7 @@ _loop1_107_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28156,7 +29198,7 @@ _loop1_107_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28164,13 +29206,13 @@ _loop1_107_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_107_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -28178,9 +29220,12 @@ _loop1_107_rule(Parser *p) static asdl_seq * _loop1_108_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -28190,14 +29235,14 @@ _loop1_108_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // STRING if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_108[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "STRING")); @@ -28213,7 +29258,7 @@ _loop1_108_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28227,7 +29272,7 @@ _loop1_108_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28235,13 +29280,13 @@ _loop1_108_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_108_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -28249,16 +29294,19 @@ _loop1_108_rule(Parser *p) static void * _tmp_109_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // star_named_expression ',' star_named_expressions? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_109[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?")); @@ -28277,7 +29325,7 @@ _tmp_109_rule(Parser *p) _res = _PyPegen_seq_insert_in_front ( p , y , z ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -28288,7 +29336,7 @@ _tmp_109_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -28296,9 +29344,12 @@ _tmp_109_rule(Parser *p) static asdl_seq * _loop0_111_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -28308,14 +29359,14 @@ _loop0_111_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' double_starred_kvpair if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_111[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); @@ -28331,7 +29382,7 @@ _loop0_111_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -28340,7 +29391,7 @@ _loop0_111_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28357,13 +29408,13 @@ _loop0_111_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_111_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -28371,16 +29422,19 @@ _loop0_111_rule(Parser *p) static asdl_seq * _gather_110_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // double_starred_kvpair _loop0_111 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_110[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_111")); @@ -28402,7 +29456,7 @@ _gather_110_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -28410,9 +29464,12 @@ _gather_110_rule(Parser *p) static asdl_seq * _loop1_112_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -28422,14 +29479,14 @@ _loop1_112_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // for_if_clause if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "for_if_clause")); @@ -28445,7 +29502,7 @@ _loop1_112_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28459,7 +29516,7 @@ _loop1_112_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28467,13 +29524,13 @@ _loop1_112_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_112_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -28481,9 +29538,12 @@ _loop1_112_rule(Parser *p) static asdl_seq * _loop0_113_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -28493,14 +29553,14 @@ _loop0_113_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ('if' disjunction) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); @@ -28516,7 +29576,7 @@ _loop0_113_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28533,13 +29593,13 @@ _loop0_113_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_113_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -28547,9 +29607,12 @@ _loop0_113_rule(Parser *p) static asdl_seq * _loop0_114_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -28559,14 +29622,14 @@ _loop0_114_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ('if' disjunction) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); @@ -28582,7 +29645,7 @@ _loop0_114_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28599,13 +29662,13 @@ _loop0_114_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_114_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -28613,16 +29676,19 @@ _loop0_114_rule(Parser *p) static void * _tmp_115_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // assignment_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_115[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); @@ -28641,7 +29707,7 @@ _tmp_115_rule(Parser *p) } { // expression !':=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_115[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); @@ -28662,7 +29728,7 @@ _tmp_115_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -28670,9 +29736,12 @@ _tmp_115_rule(Parser *p) static asdl_seq * _loop0_117_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -28682,14 +29751,14 @@ _loop0_117_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' (starred_expression | (assignment_expression | expression !':=') !'=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); @@ -28705,7 +29774,7 @@ _loop0_117_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -28714,7 +29783,7 @@ _loop0_117_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28731,13 +29800,13 @@ _loop0_117_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_117_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -28746,16 +29815,19 @@ _loop0_117_rule(Parser *p) static asdl_seq * _gather_116_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_117 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_116[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_117")); @@ -28777,7 +29849,7 @@ _gather_116_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -28785,16 +29857,19 @@ _gather_116_rule(Parser *p) static void * _tmp_118_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' kwargs if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_118[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwargs")); @@ -28810,7 +29885,7 @@ _tmp_118_rule(Parser *p) _res = k; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -28821,7 +29896,7 @@ _tmp_118_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -28829,9 +29904,12 @@ _tmp_118_rule(Parser *p) static asdl_seq * _loop0_120_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -28841,14 +29919,14 @@ _loop0_120_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' kwarg_or_starred if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_120[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); @@ -28864,7 +29942,7 @@ _loop0_120_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -28873,7 +29951,7 @@ _loop0_120_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28890,13 +29968,13 @@ _loop0_120_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_120_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -28904,16 +29982,19 @@ _loop0_120_rule(Parser *p) static asdl_seq * _gather_119_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // kwarg_or_starred _loop0_120 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_119[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_120")); @@ -28935,7 +30016,7 @@ _gather_119_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -28943,9 +30024,12 @@ _gather_119_rule(Parser *p) static asdl_seq * _loop0_122_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -28955,14 +30039,14 @@ _loop0_122_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' kwarg_or_double_starred if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); @@ -28978,7 +30062,7 @@ _loop0_122_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -28987,7 +30071,7 @@ _loop0_122_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -29004,13 +30088,13 @@ _loop0_122_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_122_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -29018,16 +30102,19 @@ _loop0_122_rule(Parser *p) static asdl_seq * _gather_121_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // kwarg_or_double_starred _loop0_122 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_121[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_122")); @@ -29049,7 +30136,7 @@ _gather_121_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -29057,9 +30144,12 @@ _gather_121_rule(Parser *p) static asdl_seq * _loop0_124_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -29069,14 +30159,14 @@ _loop0_124_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' kwarg_or_starred if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); @@ -29092,7 +30182,7 @@ _loop0_124_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -29101,7 +30191,7 @@ _loop0_124_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -29118,13 +30208,13 @@ _loop0_124_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_124_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -29132,16 +30222,19 @@ _loop0_124_rule(Parser *p) static asdl_seq * _gather_123_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // kwarg_or_starred _loop0_124 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_124")); @@ -29163,7 +30256,7 @@ _gather_123_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -29171,9 +30264,12 @@ _gather_123_rule(Parser *p) static asdl_seq * _loop0_126_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -29183,14 +30279,14 @@ _loop0_126_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' kwarg_or_double_starred if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_126[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); @@ -29206,7 +30302,7 @@ _loop0_126_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -29215,7 +30311,7 @@ _loop0_126_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -29232,13 +30328,13 @@ _loop0_126_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_126_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -29246,16 +30342,19 @@ _loop0_126_rule(Parser *p) static asdl_seq * _gather_125_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // kwarg_or_double_starred _loop0_126 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_126")); @@ -29277,7 +30376,7 @@ _gather_125_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -29285,9 +30384,12 @@ _gather_125_rule(Parser *p) static asdl_seq * _loop0_127_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -29297,14 +30399,14 @@ _loop0_127_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // (',' star_target) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_127[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); @@ -29320,7 +30422,7 @@ _loop0_127_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -29337,13 +30439,13 @@ _loop0_127_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_127_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -29351,9 +30453,12 @@ _loop0_127_rule(Parser *p) static asdl_seq * _loop0_129_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -29363,14 +30468,14 @@ _loop0_129_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); @@ -29386,7 +30491,7 @@ _loop0_129_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -29395,7 +30500,7 @@ _loop0_129_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -29412,13 +30517,13 @@ _loop0_129_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_129_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -29426,16 +30531,19 @@ _loop0_129_rule(Parser *p) static asdl_seq * _gather_128_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // star_target _loop0_129 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target _loop0_129")); @@ -29457,7 +30565,7 @@ _gather_128_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -29465,9 +30573,12 @@ _gather_128_rule(Parser *p) static asdl_seq * _loop1_130_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -29477,14 +30588,14 @@ _loop1_130_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // (',' star_target) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); @@ -29500,7 +30611,7 @@ _loop1_130_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -29514,7 +30625,7 @@ _loop1_130_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -29522,13 +30633,13 @@ _loop1_130_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_130_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -29536,16 +30647,19 @@ _loop1_130_rule(Parser *p) static void * _tmp_131_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // !'*' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); @@ -29566,7 +30680,7 @@ _tmp_131_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -29574,9 +30688,12 @@ _tmp_131_rule(Parser *p) static asdl_seq * _loop0_133_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -29586,14 +30703,14 @@ _loop0_133_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' del_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_133[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' del_target")); @@ -29609,7 +30726,7 @@ _loop0_133_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -29618,7 +30735,7 @@ _loop0_133_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -29635,13 +30752,13 @@ _loop0_133_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_133_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -29649,16 +30766,19 @@ _loop0_133_rule(Parser *p) static asdl_seq * _gather_132_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // del_target _loop0_133 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "del_target _loop0_133")); @@ -29680,7 +30800,7 @@ _gather_132_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -29688,9 +30808,12 @@ _gather_132_rule(Parser *p) static asdl_seq * _loop0_135_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -29700,14 +30823,14 @@ _loop0_135_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); @@ -29723,7 +30846,7 @@ _loop0_135_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -29732,7 +30855,7 @@ _loop0_135_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -29749,13 +30872,13 @@ _loop0_135_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_135_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -29763,16 +30886,19 @@ _loop0_135_rule(Parser *p) static asdl_seq * _gather_134_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // expression _loop0_135 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_135")); @@ -29794,7 +30920,7 @@ _gather_134_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -29802,9 +30928,12 @@ _gather_134_rule(Parser *p) static asdl_seq * _loop0_137_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -29814,14 +30943,14 @@ _loop0_137_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); @@ -29837,7 +30966,7 @@ _loop0_137_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -29846,7 +30975,7 @@ _loop0_137_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -29863,13 +30992,13 @@ _loop0_137_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_137_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -29877,16 +31006,19 @@ _loop0_137_rule(Parser *p) static asdl_seq * _gather_136_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // expression _loop0_137 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_137")); @@ -29908,7 +31040,7 @@ _gather_136_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -29916,9 +31048,12 @@ _gather_136_rule(Parser *p) static asdl_seq * _loop0_139_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -29928,14 +31063,14 @@ _loop0_139_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); @@ -29951,7 +31086,7 @@ _loop0_139_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -29960,7 +31095,7 @@ _loop0_139_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -29977,13 +31112,13 @@ _loop0_139_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_139_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -29991,16 +31126,19 @@ _loop0_139_rule(Parser *p) static asdl_seq * _gather_138_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // expression _loop0_139 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_139")); @@ -30022,7 +31160,7 @@ _gather_138_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -30030,9 +31168,12 @@ _gather_138_rule(Parser *p) static asdl_seq * _loop0_141_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -30042,14 +31183,14 @@ _loop0_141_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); @@ -30065,7 +31206,7 @@ _loop0_141_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -30074,7 +31215,7 @@ _loop0_141_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -30091,13 +31232,13 @@ _loop0_141_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_141_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -30105,16 +31246,19 @@ _loop0_141_rule(Parser *p) static asdl_seq * _gather_140_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // expression _loop0_141 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_141")); @@ -30136,7 +31280,7 @@ _gather_140_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -30144,16 +31288,19 @@ _gather_140_rule(Parser *p) static void * _tmp_142_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // NEWLINE INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT")); @@ -30175,7 +31322,7 @@ _tmp_142_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -30183,16 +31330,19 @@ _tmp_142_rule(Parser *p) static void * _tmp_143_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // args if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args")); @@ -30211,7 +31361,7 @@ _tmp_143_rule(Parser *p) } { // expression for_if_clauses if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); @@ -30233,7 +31383,7 @@ _tmp_143_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -30241,16 +31391,19 @@ _tmp_143_rule(Parser *p) static void * _tmp_144_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'True' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); @@ -30269,7 +31422,7 @@ _tmp_144_rule(Parser *p) } { // 'False' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); @@ -30288,7 +31441,7 @@ _tmp_144_rule(Parser *p) } { // 'None' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); @@ -30307,7 +31460,7 @@ _tmp_144_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -30315,16 +31468,19 @@ _tmp_144_rule(Parser *p) static void * _tmp_145_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // NAME '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '='")); @@ -30346,7 +31502,7 @@ _tmp_145_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -30354,16 +31510,19 @@ _tmp_145_rule(Parser *p) static void * _tmp_146_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // NAME STRING if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME STRING")); @@ -30385,7 +31544,7 @@ _tmp_146_rule(Parser *p) } { // SOFT_KEYWORD if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); @@ -30404,7 +31563,7 @@ _tmp_146_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -30412,16 +31571,19 @@ _tmp_146_rule(Parser *p) static void * _tmp_147_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'else' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else'")); @@ -30440,7 +31602,7 @@ _tmp_147_rule(Parser *p) } { // ':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); @@ -30459,7 +31621,7 @@ _tmp_147_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -30467,16 +31629,19 @@ _tmp_147_rule(Parser *p) static void * _tmp_148_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); @@ -30495,7 +31660,7 @@ _tmp_148_rule(Parser *p) } { // ':=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); @@ -30514,7 +31679,7 @@ _tmp_148_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -30522,16 +31687,19 @@ _tmp_148_rule(Parser *p) static void * _tmp_149_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // list if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); @@ -30550,7 +31718,7 @@ _tmp_149_rule(Parser *p) } { // tuple if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); @@ -30569,7 +31737,7 @@ _tmp_149_rule(Parser *p) } { // genexp if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); @@ -30588,7 +31756,7 @@ _tmp_149_rule(Parser *p) } { // 'True' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); @@ -30607,7 +31775,7 @@ _tmp_149_rule(Parser *p) } { // 'None' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); @@ -30626,7 +31794,7 @@ _tmp_149_rule(Parser *p) } { // 'False' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); @@ -30645,7 +31813,7 @@ _tmp_149_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -30653,16 +31821,19 @@ _tmp_149_rule(Parser *p) static void * _tmp_150_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); @@ -30681,7 +31852,7 @@ _tmp_150_rule(Parser *p) } { // ':=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); @@ -30700,7 +31871,7 @@ _tmp_150_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -30708,9 +31879,12 @@ _tmp_150_rule(Parser *p) static asdl_seq * _loop0_151_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -30720,14 +31894,14 @@ _loop0_151_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // star_named_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expressions")); @@ -30743,7 +31917,7 @@ _loop0_151_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -30760,13 +31934,13 @@ _loop0_151_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_151_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -30774,9 +31948,12 @@ _loop0_151_rule(Parser *p) static asdl_seq * _loop0_152_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -30786,14 +31963,14 @@ _loop0_152_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // (star_targets '=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); @@ -30809,7 +31986,7 @@ _loop0_152_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -30826,13 +32003,13 @@ _loop0_152_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_152_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -30840,9 +32017,12 @@ _loop0_152_rule(Parser *p) static asdl_seq * _loop0_153_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -30852,14 +32032,14 @@ _loop0_153_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // (star_targets '=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); @@ -30875,7 +32055,7 @@ _loop0_153_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -30892,13 +32072,13 @@ _loop0_153_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_153_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -30906,16 +32086,19 @@ _loop0_153_rule(Parser *p) static void * _tmp_154_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // yield_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); @@ -30934,7 +32117,7 @@ _tmp_154_rule(Parser *p) } { // star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); @@ -30953,7 +32136,7 @@ _tmp_154_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -30961,16 +32144,19 @@ _tmp_154_rule(Parser *p) static void * _tmp_155_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '[' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); @@ -30989,7 +32175,7 @@ _tmp_155_rule(Parser *p) } { // '(' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); @@ -31008,7 +32194,7 @@ _tmp_155_rule(Parser *p) } { // '{' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); @@ -31027,7 +32213,7 @@ _tmp_155_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -31035,16 +32221,19 @@ _tmp_155_rule(Parser *p) static void * _tmp_156_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '[' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); @@ -31063,7 +32252,7 @@ _tmp_156_rule(Parser *p) } { // '{' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); @@ -31082,7 +32271,7 @@ _tmp_156_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -31090,16 +32279,19 @@ _tmp_156_rule(Parser *p) static void * _tmp_157_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '[' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); @@ -31118,7 +32310,7 @@ _tmp_157_rule(Parser *p) } { // '{' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); @@ -31137,7 +32329,7 @@ _tmp_157_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -31145,9 +32337,12 @@ _tmp_157_rule(Parser *p) static asdl_seq * _loop0_158_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -31157,14 +32352,14 @@ _loop0_158_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_158[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -31180,7 +32375,7 @@ _loop0_158_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -31197,13 +32392,13 @@ _loop0_158_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_158_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -31211,9 +32406,12 @@ _loop0_158_rule(Parser *p) static asdl_seq * _loop0_159_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -31223,14 +32421,14 @@ _loop0_159_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -31246,7 +32444,7 @@ _loop0_159_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -31263,13 +32461,13 @@ _loop0_159_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_159_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -31277,9 +32475,12 @@ _loop0_159_rule(Parser *p) static asdl_seq * _loop1_160_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -31289,14 +32490,14 @@ _loop1_160_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -31312,7 +32513,7 @@ _loop1_160_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -31326,7 +32527,7 @@ _loop1_160_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31334,13 +32535,13 @@ _loop1_160_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_160_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -31348,9 +32549,12 @@ _loop1_160_rule(Parser *p) static asdl_seq * _loop1_161_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -31360,14 +32564,14 @@ _loop1_161_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); @@ -31383,7 +32587,7 @@ _loop1_161_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -31397,7 +32601,7 @@ _loop1_161_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31405,13 +32609,13 @@ _loop1_161_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_161_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -31419,9 +32623,12 @@ _loop1_161_rule(Parser *p) static asdl_seq * _loop0_162_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -31431,14 +32638,14 @@ _loop0_162_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -31454,7 +32661,7 @@ _loop0_162_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -31471,13 +32678,13 @@ _loop0_162_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_162_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -31485,9 +32692,12 @@ _loop0_162_rule(Parser *p) static asdl_seq * _loop0_163_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -31497,14 +32707,14 @@ _loop0_163_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_163[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -31520,7 +32730,7 @@ _loop0_163_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -31537,13 +32747,13 @@ _loop0_163_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_163_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -31551,9 +32761,12 @@ _loop0_163_rule(Parser *p) static asdl_seq * _loop0_165_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -31563,14 +32776,14 @@ _loop0_165_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' lambda_param if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' lambda_param")); @@ -31586,7 +32799,7 @@ _loop0_165_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -31595,7 +32808,7 @@ _loop0_165_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -31612,13 +32825,13 @@ _loop0_165_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_165_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -31626,16 +32839,19 @@ _loop0_165_rule(Parser *p) static asdl_seq * _gather_164_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // lambda_param _loop0_165 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_164[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param _loop0_165")); @@ -31657,7 +32873,7 @@ _gather_164_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -31665,9 +32881,12 @@ _gather_164_rule(Parser *p) static asdl_seq * _loop1_166_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -31677,14 +32896,14 @@ _loop1_166_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); @@ -31700,7 +32919,7 @@ _loop1_166_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -31714,7 +32933,7 @@ _loop1_166_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31722,13 +32941,13 @@ _loop1_166_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_166_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -31736,16 +32955,19 @@ _loop1_166_rule(Parser *p) static void * _tmp_167_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); @@ -31764,7 +32986,7 @@ _tmp_167_rule(Parser *p) } { // ',' (')' | '**') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); @@ -31786,7 +33008,7 @@ _tmp_167_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -31794,16 +33016,19 @@ _tmp_167_rule(Parser *p) static void * _tmp_168_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); @@ -31822,7 +33047,7 @@ _tmp_168_rule(Parser *p) } { // ',' (':' | '**') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); @@ -31844,7 +33069,7 @@ _tmp_168_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -31852,16 +33077,19 @@ _tmp_168_rule(Parser *p) static void * _tmp_169_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); @@ -31880,7 +33108,7 @@ _tmp_169_rule(Parser *p) } { // ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); @@ -31899,7 +33127,7 @@ _tmp_169_rule(Parser *p) } { // ':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); @@ -31918,7 +33146,7 @@ _tmp_169_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -31926,9 +33154,12 @@ _tmp_169_rule(Parser *p) static asdl_seq * _loop0_171_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -31938,14 +33169,14 @@ _loop0_171_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' (expression ['as' star_target]) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_171[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); @@ -31961,7 +33192,7 @@ _loop0_171_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -31970,7 +33201,7 @@ _loop0_171_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -31987,13 +33218,13 @@ _loop0_171_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_171_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -32001,16 +33232,19 @@ _loop0_171_rule(Parser *p) static asdl_seq * _gather_170_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // (expression ['as' star_target]) _loop0_171 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_170[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_171")); @@ -32032,7 +33266,7 @@ _gather_170_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32040,9 +33274,12 @@ _gather_170_rule(Parser *p) static asdl_seq * _loop0_173_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -32052,14 +33289,14 @@ _loop0_173_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' (expressions ['as' star_target]) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_173[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); @@ -32075,7 +33312,7 @@ _loop0_173_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -32084,7 +33321,7 @@ _loop0_173_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -32101,13 +33338,13 @@ _loop0_173_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_173_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -32115,16 +33352,19 @@ _loop0_173_rule(Parser *p) static asdl_seq * _gather_172_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // (expressions ['as' star_target]) _loop0_173 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_172[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_173")); @@ -32146,7 +33386,7 @@ _gather_172_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32154,9 +33394,12 @@ _gather_172_rule(Parser *p) static asdl_seq * _loop0_175_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -32166,14 +33409,14 @@ _loop0_175_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' (expression ['as' star_target]) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_175[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); @@ -32189,7 +33432,7 @@ _loop0_175_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -32198,7 +33441,7 @@ _loop0_175_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -32215,13 +33458,13 @@ _loop0_175_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_175_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -32229,16 +33472,19 @@ _loop0_175_rule(Parser *p) static asdl_seq * _gather_174_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // (expression ['as' star_target]) _loop0_175 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_174[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_175")); @@ -32260,7 +33506,7 @@ _gather_174_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32268,9 +33514,12 @@ _gather_174_rule(Parser *p) static asdl_seq * _loop0_177_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -32280,14 +33529,14 @@ _loop0_177_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' (expressions ['as' star_target]) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_177[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); @@ -32303,7 +33552,7 @@ _loop0_177_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -32312,7 +33561,7 @@ _loop0_177_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -32329,13 +33578,13 @@ _loop0_177_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_177_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -32343,16 +33592,19 @@ _loop0_177_rule(Parser *p) static asdl_seq * _gather_176_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // (expressions ['as' star_target]) _loop0_177 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_176[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_177")); @@ -32374,7 +33626,7 @@ _gather_176_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32382,16 +33634,19 @@ _gather_176_rule(Parser *p) static void * _tmp_178_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'except' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_178[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except'")); @@ -32410,7 +33665,7 @@ _tmp_178_rule(Parser *p) } { // 'finally' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_178[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally'")); @@ -32429,7 +33684,7 @@ _tmp_178_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32437,9 +33692,12 @@ _tmp_178_rule(Parser *p) static asdl_seq * _loop0_179_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -32449,14 +33707,14 @@ _loop0_179_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "block")); @@ -32472,7 +33730,7 @@ _loop0_179_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -32489,13 +33747,13 @@ _loop0_179_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_179_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -32503,16 +33761,19 @@ _loop0_179_rule(Parser *p) static void * _tmp_180_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // (except_block+ except_star_block) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(except_block+ except_star_block)")); @@ -32531,7 +33792,7 @@ _tmp_180_rule(Parser *p) } { // (except_star_block+ except_block) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(except_star_block+ except_block)")); @@ -32550,7 +33811,7 @@ _tmp_180_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32558,9 +33819,12 @@ _tmp_180_rule(Parser *p) static asdl_seq * _loop0_181_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -32570,14 +33834,14 @@ _loop0_181_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_181[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "block")); @@ -32593,7 +33857,7 @@ _loop0_181_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -32610,13 +33874,13 @@ _loop0_181_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_181_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -32624,16 +33888,19 @@ _loop0_181_rule(Parser *p) static void * _tmp_182_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); @@ -32655,7 +33922,7 @@ _tmp_182_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32663,16 +33930,19 @@ _tmp_182_rule(Parser *p) static void * _tmp_183_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); @@ -32694,7 +33964,7 @@ _tmp_183_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32702,16 +33972,19 @@ _tmp_183_rule(Parser *p) static void * _tmp_184_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_184[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); @@ -32730,7 +34003,7 @@ _tmp_184_rule(Parser *p) } { // ':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_184[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); @@ -32749,7 +34022,7 @@ _tmp_184_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32757,16 +34030,19 @@ _tmp_184_rule(Parser *p) static void * _tmp_185_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_185[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); @@ -32788,7 +34064,7 @@ _tmp_185_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32796,16 +34072,19 @@ _tmp_185_rule(Parser *p) static void * _tmp_186_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_186[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); @@ -32827,7 +34106,7 @@ _tmp_186_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32835,16 +34114,19 @@ _tmp_186_rule(Parser *p) static void * _tmp_187_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // positional_patterns ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_187[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); @@ -32866,7 +34148,7 @@ _tmp_187_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32874,16 +34156,19 @@ _tmp_187_rule(Parser *p) static void * _tmp_188_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '->' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_188[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); @@ -32905,7 +34190,7 @@ _tmp_188_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32913,16 +34198,19 @@ _tmp_188_rule(Parser *p) static void * _tmp_189_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '(' arguments? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_189[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); @@ -32948,7 +34236,7 @@ _tmp_189_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32956,9 +34244,12 @@ _tmp_189_rule(Parser *p) static asdl_seq * _loop0_191_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -32968,14 +34259,14 @@ _loop0_191_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' double_starred_kvpair if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_191[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); @@ -32991,7 +34282,7 @@ _loop0_191_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -33000,7 +34291,7 @@ _loop0_191_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -33017,13 +34308,13 @@ _loop0_191_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_191_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -33031,16 +34322,19 @@ _loop0_191_rule(Parser *p) static asdl_seq * _gather_190_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // double_starred_kvpair _loop0_191 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_190[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_191")); @@ -33062,7 +34356,7 @@ _gather_190_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -33070,16 +34364,19 @@ _gather_190_rule(Parser *p) static void * _tmp_192_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_192[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); @@ -33098,7 +34395,7 @@ _tmp_192_rule(Parser *p) } { // ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_192[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); @@ -33117,7 +34414,7 @@ _tmp_192_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -33125,16 +34422,19 @@ _tmp_192_rule(Parser *p) static void * _tmp_193_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // star_targets '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_193[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); @@ -33150,7 +34450,7 @@ _tmp_193_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -33161,7 +34461,7 @@ _tmp_193_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -33169,16 +34469,19 @@ _tmp_193_rule(Parser *p) static void * _tmp_194_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '.' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_194[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); @@ -33197,7 +34500,7 @@ _tmp_194_rule(Parser *p) } { // '...' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_194[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); @@ -33216,7 +34519,7 @@ _tmp_194_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -33224,16 +34527,19 @@ _tmp_194_rule(Parser *p) static void * _tmp_195_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '.' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_195[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); @@ -33252,7 +34558,7 @@ _tmp_195_rule(Parser *p) } { // '...' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_195[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); @@ -33271,7 +34577,7 @@ _tmp_195_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -33279,16 +34585,19 @@ _tmp_195_rule(Parser *p) static void * _tmp_196_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '@' named_expression NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); @@ -33307,7 +34616,7 @@ _tmp_196_rule(Parser *p) _res = f; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -33318,7 +34627,7 @@ _tmp_196_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -33326,16 +34635,19 @@ _tmp_196_rule(Parser *p) static void * _tmp_197_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); @@ -33351,7 +34663,7 @@ _tmp_197_rule(Parser *p) _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -33362,7 +34674,7 @@ _tmp_197_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -33370,16 +34682,19 @@ _tmp_197_rule(Parser *p) static void * _tmp_198_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' star_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_198[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression")); @@ -33395,7 +34710,7 @@ _tmp_198_rule(Parser *p) _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -33406,7 +34721,7 @@ _tmp_198_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -33414,16 +34729,19 @@ _tmp_198_rule(Parser *p) static void * _tmp_199_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'or' conjunction if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_199[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); @@ -33439,7 +34757,7 @@ _tmp_199_rule(Parser *p) _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -33450,7 +34768,7 @@ _tmp_199_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -33458,16 +34776,19 @@ _tmp_199_rule(Parser *p) static void * _tmp_200_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'and' inversion if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_200[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion")); @@ -33483,7 +34804,7 @@ _tmp_200_rule(Parser *p) _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -33494,7 +34815,7 @@ _tmp_200_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -33502,16 +34823,19 @@ _tmp_200_rule(Parser *p) static void * _tmp_201_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'if' disjunction if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); @@ -33527,7 +34851,7 @@ _tmp_201_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -33538,7 +34862,7 @@ _tmp_201_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -33546,16 +34870,19 @@ _tmp_201_rule(Parser *p) static void * _tmp_202_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'if' disjunction if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); @@ -33571,7 +34898,7 @@ _tmp_202_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -33582,7 +34909,7 @@ _tmp_202_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -33590,16 +34917,19 @@ _tmp_202_rule(Parser *p) static void * _tmp_203_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // starred_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_203[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); @@ -33618,7 +34948,7 @@ _tmp_203_rule(Parser *p) } { // (assignment_expression | expression !':=') !'=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_203[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); @@ -33639,7 +34969,7 @@ _tmp_203_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -33647,16 +34977,19 @@ _tmp_203_rule(Parser *p) static void * _tmp_204_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_204[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); @@ -33672,7 +35005,7 @@ _tmp_204_rule(Parser *p) _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -33683,7 +35016,7 @@ _tmp_204_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -33691,16 +35024,19 @@ _tmp_204_rule(Parser *p) static void * _tmp_205_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_205[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); @@ -33716,7 +35052,7 @@ _tmp_205_rule(Parser *p) _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -33727,7 +35063,7 @@ _tmp_205_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -33735,16 +35071,19 @@ _tmp_205_rule(Parser *p) static void * _tmp_206_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // star_targets '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_206[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); @@ -33766,7 +35105,7 @@ _tmp_206_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -33774,16 +35113,19 @@ _tmp_206_rule(Parser *p) static void * _tmp_207_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // star_targets '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_207[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); @@ -33805,7 +35147,7 @@ _tmp_207_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -33813,16 +35155,19 @@ _tmp_207_rule(Parser *p) static void * _tmp_208_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_208[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); @@ -33841,7 +35186,7 @@ _tmp_208_rule(Parser *p) } { // '**' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_208[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); @@ -33860,7 +35205,7 @@ _tmp_208_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -33868,16 +35213,19 @@ _tmp_208_rule(Parser *p) static void * _tmp_209_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_209[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); @@ -33896,7 +35244,7 @@ _tmp_209_rule(Parser *p) } { // '**' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_209[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); @@ -33915,7 +35263,7 @@ _tmp_209_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -33923,16 +35271,19 @@ _tmp_209_rule(Parser *p) static void * _tmp_210_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // expression ['as' star_target] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_210[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); @@ -33955,7 +35306,7 @@ _tmp_210_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -33963,16 +35314,19 @@ _tmp_210_rule(Parser *p) static void * _tmp_211_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // expressions ['as' star_target] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_211[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); @@ -33995,7 +35349,7 @@ _tmp_211_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -34003,16 +35357,19 @@ _tmp_211_rule(Parser *p) static void * _tmp_212_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // expression ['as' star_target] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_212[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); @@ -34035,7 +35392,7 @@ _tmp_212_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -34043,16 +35400,19 @@ _tmp_212_rule(Parser *p) static void * _tmp_213_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // expressions ['as' star_target] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_213[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); @@ -34075,7 +35435,7 @@ _tmp_213_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -34083,16 +35443,19 @@ _tmp_213_rule(Parser *p) static void * _tmp_214_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // except_block+ except_star_block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_214[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_block+ except_star_block")); @@ -34114,7 +35477,7 @@ _tmp_214_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -34122,16 +35485,19 @@ _tmp_214_rule(Parser *p) static void * _tmp_215_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // except_star_block+ except_block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_215[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_star_block+ except_block")); @@ -34153,7 +35519,7 @@ _tmp_215_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -34161,16 +35527,19 @@ _tmp_215_rule(Parser *p) static void * _tmp_216_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // assignment_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_216[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); @@ -34189,7 +35558,7 @@ _tmp_216_rule(Parser *p) } { // expression !':=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_216[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); @@ -34210,7 +35579,7 @@ _tmp_216_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -34218,16 +35587,19 @@ _tmp_216_rule(Parser *p) static void * _tmp_217_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_217[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); @@ -34249,7 +35621,7 @@ _tmp_217_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -34257,16 +35629,19 @@ _tmp_217_rule(Parser *p) static void * _tmp_218_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_218[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); @@ -34288,7 +35663,7 @@ _tmp_218_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -34296,16 +35671,19 @@ _tmp_218_rule(Parser *p) static void * _tmp_219_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_219[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); @@ -34327,7 +35705,7 @@ _tmp_219_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -34335,16 +35713,19 @@ _tmp_219_rule(Parser *p) static void * _tmp_220_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_220[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); @@ -34366,7 +35747,7 @@ _tmp_220_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -34374,9 +35755,12 @@ _tmp_220_rule(Parser *p) static asdl_seq * _loop1_221_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -34386,14 +35770,14 @@ _loop1_221_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // except_block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_221[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_block")); @@ -34409,7 +35793,7 @@ _loop1_221_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -34423,7 +35807,7 @@ _loop1_221_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -34431,13 +35815,13 @@ _loop1_221_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_221_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -34445,9 +35829,12 @@ _loop1_221_rule(Parser *p) static asdl_seq * _loop1_222_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -34457,14 +35844,14 @@ _loop1_222_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // except_star_block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_222[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_star_block")); @@ -34480,7 +35867,7 @@ _loop1_222_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -34494,7 +35881,7 @@ _loop1_222_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -34502,13 +35889,13 @@ _loop1_222_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_222_type, _seq); - D(p->level--); + p->level--; return _seq; } diff --git a/Parser/pegen.c b/Parser/pegen.c index 870085e7285e3..cfea1c87199b2 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -815,6 +815,7 @@ void * _PyPegen_run_parser(Parser *p) { void *res = _PyPegen_parse(p); + assert(p->level == 0); if (res == NULL) { if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_SyntaxError)) { return NULL; diff --git a/Tools/peg_generator/pegen/c_generator.py b/Tools/peg_generator/pegen/c_generator.py index 9cfbf38b40a77..ee255c8016386 100644 --- a/Tools/peg_generator/pegen/c_generator.py +++ b/Tools/peg_generator/pegen/c_generator.py @@ -37,6 +37,8 @@ # define D(x) #endif +# define MAXSTACK 6000 + """ @@ -364,10 +366,14 @@ def __init__( self.skip_actions = skip_actions def add_level(self) -> None: - self.print("D(p->level++);") + self.print("if (p->level++ == MAXSTACK) {") + with self.indent(): + self.print("p->error_indicator = 1;") + self.print("PyErr_NoMemory();") + self.print("}") def remove_level(self) -> None: - self.print("D(p->level--);") + self.print("p->level--;") def add_return(self, ret_val: str) -> None: self.remove_level() @@ -544,9 +550,10 @@ def _set_up_rule_memoization(self, node: Rule, result_type: str) -> None: self.print("p->in_raw_rule++;") self.print(f"void *_raw = {node.name}_raw(p);") self.print("p->in_raw_rule--;") - self.print("if (p->error_indicator)") + self.print("if (p->error_indicator) {") with self.indent(): - self.print("return NULL;") + self.add_return("NULL") + self.print("}") self.print("if (_raw == NULL || p->mark <= _resmark)") with self.indent(): self.print("break;") From webhook-mailer at python.org Mon Dec 20 11:23:50 2021 From: webhook-mailer at python.org (pablogsal) Date: Mon, 20 Dec 2021 16:23:50 -0000 Subject: [Python-checkins] [3.10] bpo-46110: Add a recursion check to avoid stack overflow in the PEG parser (GH-30177) (GH-30214) Message-ID: https://github.com/python/cpython/commit/dc73199a212a44553578eb4952631e5ba9e5f292 commit: dc73199a212a44553578eb4952631e5ba9e5f292 branch: 3.10 author: Pablo Galindo Salgado committer: pablogsal date: 2021-12-20T16:23:37Z summary: [3.10] bpo-46110: Add a recursion check to avoid stack overflow in the PEG parser (GH-30177) (GH-30214) Co-authored-by: Batuhan Taskaya . (cherry picked from commit e9898bf153d26059261ffef11f7643ae991e2a4c) Co-authored-by: Pablo Galindo Salgado files: A Misc/NEWS.d/next/Core and Builtins/2021-12-18-02-37-07.bpo-46110.B6hAfu.rst M Lib/test/test_syntax.py M Parser/parser.c M Parser/pegen.c M Tools/peg_generator/pegen/c_generator.py diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 8f961c6bfdbba..b5bebb3d0bdfa 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -1576,6 +1576,14 @@ def test_syntax_error_on_deeply_nested_blocks(self): """ self._check_error(source, "too many statically nested blocks") + @support.cpython_only + def test_error_on_parser_stack_overflow(self): + source = "-" * 100000 + "4" + for mode in ["exec", "eval", "single"]: + with self.subTest(mode=mode): + with self.assertRaises(MemoryError): + compile(source, "", mode) + def test_main(): support.run_unittest(SyntaxTestCase) diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-18-02-37-07.bpo-46110.B6hAfu.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-18-02-37-07.bpo-46110.B6hAfu.rst new file mode 100644 index 0000000000000..593d2855972c4 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-18-02-37-07.bpo-46110.B6hAfu.rst @@ -0,0 +1,2 @@ +Add a maximum recursion check to the PEG parser to avoid stack overflow. +Patch by Pablo Galindo diff --git a/Parser/parser.c b/Parser/parser.c index 67515ecc6f145..7e6f04898e1e3 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -6,6 +6,8 @@ #else # define D(x) #endif + +# define MAXSTACK 6000 static const int n_keyword_lists = 9; static KeywordToken *reserved_keywords[] = { (KeywordToken[]) {{NULL, -1}}, @@ -932,16 +934,19 @@ static void *_tmp_206_rule(Parser *p); static mod_ty file_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } mod_ty _res = NULL; int _mark = p->mark; { // statements? $ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> file[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "statements? $")); @@ -957,7 +962,7 @@ file_rule(Parser *p) _res = _PyPegen_make_module ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -968,7 +973,7 @@ file_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -976,16 +981,19 @@ file_rule(Parser *p) static mod_ty interactive_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } mod_ty _res = NULL; int _mark = p->mark; { // statement_newline if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> interactive[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "statement_newline")); @@ -998,7 +1006,7 @@ interactive_rule(Parser *p) _res = _PyAST_Interactive ( a , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1009,7 +1017,7 @@ interactive_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1017,16 +1025,19 @@ interactive_rule(Parser *p) static mod_ty eval_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } mod_ty _res = NULL; int _mark = p->mark; { // expressions NEWLINE* $ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> eval[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions NEWLINE* $")); @@ -1045,7 +1056,7 @@ eval_rule(Parser *p) _res = _PyAST_Expression ( a , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1056,7 +1067,7 @@ eval_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1064,16 +1075,19 @@ eval_rule(Parser *p) static mod_ty func_type_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } mod_ty _res = NULL; int _mark = p->mark; { // '(' type_expressions? ')' '->' expression NEWLINE* $ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> func_type[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' type_expressions? ')' '->' expression NEWLINE* $")); @@ -1104,7 +1118,7 @@ func_type_rule(Parser *p) _res = _PyAST_FunctionType ( a , b , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1115,7 +1129,7 @@ func_type_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1123,16 +1137,19 @@ func_type_rule(Parser *p) static expr_ty fstring_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> fstring[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); @@ -1151,7 +1168,7 @@ fstring_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1166,16 +1183,19 @@ fstring_rule(Parser *p) static asdl_expr_seq* type_expressions_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_expr_seq* _res = NULL; int _mark = p->mark; { // ','.expression+ ',' '*' expression ',' '**' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.expression+ ',' '*' expression ',' '**' expression")); @@ -1206,7 +1226,7 @@ type_expressions_rule(Parser *p) _res = ( asdl_expr_seq * ) _PyPegen_seq_append_to_end ( p , CHECK ( asdl_seq * , _PyPegen_seq_append_to_end ( p , a , b ) ) , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1217,7 +1237,7 @@ type_expressions_rule(Parser *p) } { // ','.expression+ ',' '*' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.expression+ ',' '*' expression")); @@ -1239,7 +1259,7 @@ type_expressions_rule(Parser *p) _res = ( asdl_expr_seq * ) _PyPegen_seq_append_to_end ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1250,7 +1270,7 @@ type_expressions_rule(Parser *p) } { // ','.expression+ ',' '**' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.expression+ ',' '**' expression")); @@ -1272,7 +1292,7 @@ type_expressions_rule(Parser *p) _res = ( asdl_expr_seq * ) _PyPegen_seq_append_to_end ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1283,7 +1303,7 @@ type_expressions_rule(Parser *p) } { // '*' expression ',' '**' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' expression ',' '**' expression")); @@ -1308,7 +1328,7 @@ type_expressions_rule(Parser *p) _res = ( asdl_expr_seq * ) _PyPegen_seq_append_to_end ( p , CHECK ( asdl_seq * , _PyPegen_singleton_seq ( p , a ) ) , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1319,7 +1339,7 @@ type_expressions_rule(Parser *p) } { // '*' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' expression")); @@ -1335,7 +1355,7 @@ type_expressions_rule(Parser *p) _res = ( asdl_expr_seq * ) _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1346,7 +1366,7 @@ type_expressions_rule(Parser *p) } { // '**' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' expression")); @@ -1362,7 +1382,7 @@ type_expressions_rule(Parser *p) _res = ( asdl_expr_seq * ) _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1373,7 +1393,7 @@ type_expressions_rule(Parser *p) } { // ','.expression+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.expression+")); @@ -1386,7 +1406,7 @@ type_expressions_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1397,7 +1417,7 @@ type_expressions_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1405,16 +1425,19 @@ type_expressions_rule(Parser *p) static asdl_stmt_seq* statements_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_stmt_seq* _res = NULL; int _mark = p->mark; { // statement+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statements[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "statement+")); @@ -1427,7 +1450,7 @@ statements_rule(Parser *p) _res = ( asdl_stmt_seq * ) _PyPegen_seq_flatten ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1438,7 +1461,7 @@ statements_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1446,16 +1469,19 @@ statements_rule(Parser *p) static asdl_stmt_seq* statement_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_stmt_seq* _res = NULL; int _mark = p->mark; { // compound_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statement[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "compound_stmt")); @@ -1468,7 +1494,7 @@ statement_rule(Parser *p) _res = ( asdl_stmt_seq * ) _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1479,7 +1505,7 @@ statement_rule(Parser *p) } { // simple_stmts if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statement[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "simple_stmts")); @@ -1492,7 +1518,7 @@ statement_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1503,7 +1529,7 @@ statement_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1511,16 +1537,19 @@ statement_rule(Parser *p) static asdl_stmt_seq* statement_newline_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_stmt_seq* _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -1529,7 +1558,7 @@ statement_newline_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // compound_stmt NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statement_newline[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "compound_stmt NEWLINE")); @@ -1545,7 +1574,7 @@ statement_newline_rule(Parser *p) _res = ( asdl_stmt_seq * ) _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1556,7 +1585,7 @@ statement_newline_rule(Parser *p) } { // simple_stmts if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statement_newline[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "simple_stmts")); @@ -1575,7 +1604,7 @@ statement_newline_rule(Parser *p) } { // NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statement_newline[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); @@ -1587,7 +1616,7 @@ statement_newline_rule(Parser *p) D(fprintf(stderr, "%*c+ statement_newline[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -1597,7 +1626,7 @@ statement_newline_rule(Parser *p) _res = ( asdl_stmt_seq * ) _PyPegen_singleton_seq ( p , CHECK ( stmt_ty , _PyAST_Pass ( EXTRA ) ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1608,7 +1637,7 @@ statement_newline_rule(Parser *p) } { // $ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statement_newline[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "$")); @@ -1621,7 +1650,7 @@ statement_newline_rule(Parser *p) _res = _PyPegen_interactive_exit ( p ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1632,7 +1661,7 @@ statement_newline_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1640,16 +1669,19 @@ statement_newline_rule(Parser *p) static asdl_stmt_seq* simple_stmts_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_stmt_seq* _res = NULL; int _mark = p->mark; { // simple_stmt !';' NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmts[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "simple_stmt !';' NEWLINE")); @@ -1667,7 +1699,7 @@ simple_stmts_rule(Parser *p) _res = ( asdl_stmt_seq * ) _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1678,7 +1710,7 @@ simple_stmts_rule(Parser *p) } { // ';'.simple_stmt+ ';'? NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmts[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "';'.simple_stmt+ ';'? NEWLINE")); @@ -1698,7 +1730,7 @@ simple_stmts_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1709,7 +1741,7 @@ simple_stmts_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1730,20 +1762,23 @@ simple_stmts_rule(Parser *p) static stmt_ty simple_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; if (_PyPegen_is_memoized(p, simple_stmt_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -1752,7 +1787,7 @@ simple_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // assignment if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment")); @@ -1771,7 +1806,7 @@ simple_stmt_rule(Parser *p) } { // star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); @@ -1783,7 +1818,7 @@ simple_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ simple_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -1793,7 +1828,7 @@ simple_stmt_rule(Parser *p) _res = _PyAST_Expr ( e , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1804,7 +1839,7 @@ simple_stmt_rule(Parser *p) } { // &'return' return_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'return' return_stmt")); @@ -1825,7 +1860,7 @@ simple_stmt_rule(Parser *p) } { // &('import' | 'from') import_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('import' | 'from') import_stmt")); @@ -1846,7 +1881,7 @@ simple_stmt_rule(Parser *p) } { // &'raise' raise_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'raise' raise_stmt")); @@ -1867,7 +1902,7 @@ simple_stmt_rule(Parser *p) } { // 'pass' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'pass'")); @@ -1879,7 +1914,7 @@ simple_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ simple_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'pass'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -1889,7 +1924,7 @@ simple_stmt_rule(Parser *p) _res = _PyAST_Pass ( EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1900,7 +1935,7 @@ simple_stmt_rule(Parser *p) } { // &'del' del_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'del' del_stmt")); @@ -1921,7 +1956,7 @@ simple_stmt_rule(Parser *p) } { // &'yield' yield_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'yield' yield_stmt")); @@ -1942,7 +1977,7 @@ simple_stmt_rule(Parser *p) } { // &'assert' assert_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'assert' assert_stmt")); @@ -1963,7 +1998,7 @@ simple_stmt_rule(Parser *p) } { // 'break' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'break'")); @@ -1975,7 +2010,7 @@ simple_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ simple_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'break'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -1985,7 +2020,7 @@ simple_stmt_rule(Parser *p) _res = _PyAST_Break ( EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1996,7 +2031,7 @@ simple_stmt_rule(Parser *p) } { // 'continue' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'continue'")); @@ -2008,7 +2043,7 @@ simple_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ simple_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'continue'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2018,7 +2053,7 @@ simple_stmt_rule(Parser *p) _res = _PyAST_Continue ( EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2029,7 +2064,7 @@ simple_stmt_rule(Parser *p) } { // &'global' global_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'global' global_stmt")); @@ -2050,7 +2085,7 @@ simple_stmt_rule(Parser *p) } { // &'nonlocal' nonlocal_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'nonlocal' nonlocal_stmt")); @@ -2072,7 +2107,7 @@ simple_stmt_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, simple_stmt_type, _res); - D(p->level--); + p->level--; return _res; } @@ -2088,16 +2123,19 @@ simple_stmt_rule(Parser *p) static stmt_ty compound_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; { // &('def' | '@' | ASYNC) function_def if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('def' | '@' | ASYNC) function_def")); @@ -2118,7 +2156,7 @@ compound_stmt_rule(Parser *p) } { // &'if' if_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'if' if_stmt")); @@ -2139,7 +2177,7 @@ compound_stmt_rule(Parser *p) } { // &('class' | '@') class_def if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('class' | '@') class_def")); @@ -2160,7 +2198,7 @@ compound_stmt_rule(Parser *p) } { // &('with' | ASYNC) with_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('with' | ASYNC) with_stmt")); @@ -2181,7 +2219,7 @@ compound_stmt_rule(Parser *p) } { // &('for' | ASYNC) for_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('for' | ASYNC) for_stmt")); @@ -2202,7 +2240,7 @@ compound_stmt_rule(Parser *p) } { // &'try' try_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'try' try_stmt")); @@ -2223,7 +2261,7 @@ compound_stmt_rule(Parser *p) } { // &'while' while_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'while' while_stmt")); @@ -2244,7 +2282,7 @@ compound_stmt_rule(Parser *p) } { // match_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "match_stmt")); @@ -2263,7 +2301,7 @@ compound_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -2276,16 +2314,19 @@ compound_stmt_rule(Parser *p) static stmt_ty assignment_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -2294,7 +2335,7 @@ assignment_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME ':' expression ['=' annotated_rhs] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME ':' expression ['=' annotated_rhs]")); @@ -2315,7 +2356,7 @@ assignment_rule(Parser *p) D(fprintf(stderr, "%*c+ assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME ':' expression ['=' annotated_rhs]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2325,7 +2366,7 @@ assignment_rule(Parser *p) _res = CHECK_VERSION ( stmt_ty , 6 , "Variable annotation syntax is" , _PyAST_AnnAssign ( CHECK ( expr_ty , _PyPegen_set_expr_context ( p , a , Store ) ) , b , c , 1 , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2336,7 +2377,7 @@ assignment_rule(Parser *p) } { // ('(' single_target ')' | single_subscript_attribute_target) ':' expression ['=' annotated_rhs] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('(' single_target ')' | single_subscript_attribute_target) ':' expression ['=' annotated_rhs]")); @@ -2357,7 +2398,7 @@ assignment_rule(Parser *p) D(fprintf(stderr, "%*c+ assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "('(' single_target ')' | single_subscript_attribute_target) ':' expression ['=' annotated_rhs]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2367,7 +2408,7 @@ assignment_rule(Parser *p) _res = CHECK_VERSION ( stmt_ty , 6 , "Variable annotations syntax is" , _PyAST_AnnAssign ( a , b , c , 0 , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2378,7 +2419,7 @@ assignment_rule(Parser *p) } { // ((star_targets '='))+ (yield_expr | star_expressions) !'=' TYPE_COMMENT? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))+ (yield_expr | star_expressions) !'=' TYPE_COMMENT?")); @@ -2398,7 +2439,7 @@ assignment_rule(Parser *p) D(fprintf(stderr, "%*c+ assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "((star_targets '='))+ (yield_expr | star_expressions) !'=' TYPE_COMMENT?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2408,7 +2449,7 @@ assignment_rule(Parser *p) _res = _PyAST_Assign ( a , b , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2419,7 +2460,7 @@ assignment_rule(Parser *p) } { // single_target augassign ~ (yield_expr | star_expressions) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "single_target augassign ~ (yield_expr | star_expressions)")); @@ -2440,7 +2481,7 @@ assignment_rule(Parser *p) D(fprintf(stderr, "%*c+ assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "single_target augassign ~ (yield_expr | star_expressions)")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2450,7 +2491,7 @@ assignment_rule(Parser *p) _res = _PyAST_AugAssign ( a , b -> kind , c , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2459,13 +2500,13 @@ assignment_rule(Parser *p) D(fprintf(stderr, "%*c%s assignment[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "single_target augassign ~ (yield_expr | star_expressions)")); if (_cut_var) { - D(p->level--); + p->level--; return NULL; } } if (p->call_invalid_rules) { // invalid_assignment if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_assignment")); @@ -2484,7 +2525,7 @@ assignment_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -2505,16 +2546,19 @@ assignment_rule(Parser *p) static AugOperator* augassign_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } AugOperator* _res = NULL; int _mark = p->mark; { // '+=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+='")); @@ -2527,7 +2571,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , Add ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2538,7 +2582,7 @@ augassign_rule(Parser *p) } { // '-=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-='")); @@ -2551,7 +2595,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , Sub ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2562,7 +2606,7 @@ augassign_rule(Parser *p) } { // '*=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*='")); @@ -2575,7 +2619,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , Mult ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2586,7 +2630,7 @@ augassign_rule(Parser *p) } { // '@=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@='")); @@ -2599,7 +2643,7 @@ augassign_rule(Parser *p) _res = CHECK_VERSION ( AugOperator * , 5 , "The '@' operator is" , _PyPegen_augoperator ( p , MatMult ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2610,7 +2654,7 @@ augassign_rule(Parser *p) } { // '/=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'/='")); @@ -2623,7 +2667,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , Div ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2634,7 +2678,7 @@ augassign_rule(Parser *p) } { // '%=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'%='")); @@ -2647,7 +2691,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , Mod ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2658,7 +2702,7 @@ augassign_rule(Parser *p) } { // '&=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'&='")); @@ -2671,7 +2715,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , BitAnd ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2682,7 +2726,7 @@ augassign_rule(Parser *p) } { // '|=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'|='")); @@ -2695,7 +2739,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , BitOr ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2706,7 +2750,7 @@ augassign_rule(Parser *p) } { // '^=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'^='")); @@ -2719,7 +2763,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , BitXor ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2730,7 +2774,7 @@ augassign_rule(Parser *p) } { // '<<=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'<<='")); @@ -2743,7 +2787,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , LShift ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2754,7 +2798,7 @@ augassign_rule(Parser *p) } { // '>>=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'>>='")); @@ -2767,7 +2811,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , RShift ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2778,7 +2822,7 @@ augassign_rule(Parser *p) } { // '**=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**='")); @@ -2791,7 +2835,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , Pow ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2802,7 +2846,7 @@ augassign_rule(Parser *p) } { // '//=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'//='")); @@ -2815,7 +2859,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , FloorDiv ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2826,7 +2870,7 @@ augassign_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -2834,16 +2878,19 @@ augassign_rule(Parser *p) static stmt_ty global_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -2852,7 +2899,7 @@ global_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'global' ','.NAME+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> global_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'global' ','.NAME+")); @@ -2867,7 +2914,7 @@ global_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ global_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'global' ','.NAME+")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2877,7 +2924,7 @@ global_stmt_rule(Parser *p) _res = _PyAST_Global ( CHECK ( asdl_identifier_seq * , _PyPegen_map_names_to_ids ( p , a ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2888,7 +2935,7 @@ global_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -2896,16 +2943,19 @@ global_stmt_rule(Parser *p) static stmt_ty nonlocal_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -2914,7 +2964,7 @@ nonlocal_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'nonlocal' ','.NAME+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> nonlocal_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'nonlocal' ','.NAME+")); @@ -2929,7 +2979,7 @@ nonlocal_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ nonlocal_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'nonlocal' ','.NAME+")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2939,7 +2989,7 @@ nonlocal_stmt_rule(Parser *p) _res = _PyAST_Nonlocal ( CHECK ( asdl_identifier_seq * , _PyPegen_map_names_to_ids ( p , a ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2950,7 +3000,7 @@ nonlocal_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -2958,16 +3008,19 @@ nonlocal_stmt_rule(Parser *p) static stmt_ty yield_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -2976,7 +3029,7 @@ yield_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // yield_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> yield_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); @@ -2988,7 +3041,7 @@ yield_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ yield_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2998,7 +3051,7 @@ yield_stmt_rule(Parser *p) _res = _PyAST_Expr ( y , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3009,7 +3062,7 @@ yield_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3017,16 +3070,19 @@ yield_stmt_rule(Parser *p) static stmt_ty assert_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3035,7 +3091,7 @@ assert_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'assert' expression [',' expression] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> assert_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'assert' expression [',' expression]")); @@ -3053,7 +3109,7 @@ assert_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ assert_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'assert' expression [',' expression]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3063,7 +3119,7 @@ assert_stmt_rule(Parser *p) _res = _PyAST_Assert ( a , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3074,7 +3130,7 @@ assert_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3082,16 +3138,19 @@ assert_stmt_rule(Parser *p) static stmt_ty del_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3100,7 +3159,7 @@ del_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'del' del_targets &(';' | NEWLINE) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'del' del_targets &(';' | NEWLINE)")); @@ -3117,7 +3176,7 @@ del_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ del_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'del' del_targets &(';' | NEWLINE)")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3127,7 +3186,7 @@ del_stmt_rule(Parser *p) _res = _PyAST_Delete ( a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3138,7 +3197,7 @@ del_stmt_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_del_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_del_stmt")); @@ -3157,7 +3216,7 @@ del_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3165,16 +3224,19 @@ del_stmt_rule(Parser *p) static stmt_ty import_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; { // import_name if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "import_name")); @@ -3193,7 +3255,7 @@ import_stmt_rule(Parser *p) } { // import_from if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "import_from")); @@ -3212,7 +3274,7 @@ import_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3220,16 +3282,19 @@ import_stmt_rule(Parser *p) static stmt_ty import_name_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3238,7 +3303,7 @@ import_name_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'import' dotted_as_names if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_name[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'import' dotted_as_names")); @@ -3253,7 +3318,7 @@ import_name_rule(Parser *p) D(fprintf(stderr, "%*c+ import_name[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'import' dotted_as_names")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3263,7 +3328,7 @@ import_name_rule(Parser *p) _res = _PyAST_Import ( a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3274,7 +3339,7 @@ import_name_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3284,16 +3349,19 @@ import_name_rule(Parser *p) static stmt_ty import_from_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3302,7 +3370,7 @@ import_from_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'from' (('.' | '...'))* dotted_name 'import' import_from_targets if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from' (('.' | '...'))* dotted_name 'import' import_from_targets")); @@ -3326,7 +3394,7 @@ import_from_rule(Parser *p) D(fprintf(stderr, "%*c+ import_from[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'from' (('.' | '...'))* dotted_name 'import' import_from_targets")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3336,7 +3404,7 @@ import_from_rule(Parser *p) _res = _PyAST_ImportFrom ( b -> v . Name . id , c , _PyPegen_seq_count_dots ( a ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3347,7 +3415,7 @@ import_from_rule(Parser *p) } { // 'from' (('.' | '...'))+ 'import' import_from_targets if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from' (('.' | '...'))+ 'import' import_from_targets")); @@ -3368,7 +3436,7 @@ import_from_rule(Parser *p) D(fprintf(stderr, "%*c+ import_from[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'from' (('.' | '...'))+ 'import' import_from_targets")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3378,7 +3446,7 @@ import_from_rule(Parser *p) _res = _PyAST_ImportFrom ( NULL , b , _PyPegen_seq_count_dots ( a ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3389,7 +3457,7 @@ import_from_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3401,16 +3469,19 @@ import_from_rule(Parser *p) static asdl_alias_seq* import_from_targets_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_alias_seq* _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3419,7 +3490,7 @@ import_from_targets_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '(' import_from_as_names ','? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' import_from_as_names ','? ')'")); @@ -3442,7 +3513,7 @@ import_from_targets_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3453,7 +3524,7 @@ import_from_targets_rule(Parser *p) } { // import_from_as_names !',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "import_from_as_names !','")); @@ -3474,7 +3545,7 @@ import_from_targets_rule(Parser *p) } { // '*' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*'")); @@ -3486,7 +3557,7 @@ import_from_targets_rule(Parser *p) D(fprintf(stderr, "%*c+ import_from_targets[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3496,7 +3567,7 @@ import_from_targets_rule(Parser *p) _res = ( asdl_alias_seq * ) _PyPegen_singleton_seq ( p , CHECK ( alias_ty , _PyPegen_alias_for_star ( p , EXTRA ) ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3507,7 +3578,7 @@ import_from_targets_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_import_from_targets if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_import_from_targets")); @@ -3526,7 +3597,7 @@ import_from_targets_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3534,16 +3605,19 @@ import_from_targets_rule(Parser *p) static asdl_alias_seq* import_from_as_names_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_alias_seq* _res = NULL; int _mark = p->mark; { // ','.import_from_as_name+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from_as_names[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.import_from_as_name+")); @@ -3556,7 +3630,7 @@ import_from_as_names_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3567,7 +3641,7 @@ import_from_as_names_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3575,16 +3649,19 @@ import_from_as_names_rule(Parser *p) static alias_ty import_from_as_name_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } alias_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3593,7 +3670,7 @@ import_from_as_name_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME ['as' NAME] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from_as_name[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME ['as' NAME]")); @@ -3608,7 +3685,7 @@ import_from_as_name_rule(Parser *p) D(fprintf(stderr, "%*c+ import_from_as_name[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME ['as' NAME]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3618,7 +3695,7 @@ import_from_as_name_rule(Parser *p) _res = _PyAST_alias ( a -> v . Name . id , ( b ) ? ( ( expr_ty ) b ) -> v . Name . id : NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3629,7 +3706,7 @@ import_from_as_name_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3637,16 +3714,19 @@ import_from_as_name_rule(Parser *p) static asdl_alias_seq* dotted_as_names_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_alias_seq* _res = NULL; int _mark = p->mark; { // ','.dotted_as_name+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dotted_as_names[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.dotted_as_name+")); @@ -3659,7 +3739,7 @@ dotted_as_names_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3670,7 +3750,7 @@ dotted_as_names_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3678,16 +3758,19 @@ dotted_as_names_rule(Parser *p) static alias_ty dotted_as_name_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } alias_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3696,7 +3779,7 @@ dotted_as_name_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // dotted_name ['as' NAME] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dotted_as_name[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dotted_name ['as' NAME]")); @@ -3711,7 +3794,7 @@ dotted_as_name_rule(Parser *p) D(fprintf(stderr, "%*c+ dotted_as_name[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dotted_name ['as' NAME]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3721,7 +3804,7 @@ dotted_as_name_rule(Parser *p) _res = _PyAST_alias ( a -> v . Name . id , ( b ) ? ( ( expr_ty ) b ) -> v . Name . id : NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3732,7 +3815,7 @@ dotted_as_name_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3742,10 +3825,13 @@ static expr_ty dotted_name_raw(Parser *); static expr_ty dotted_name_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, dotted_name_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -3753,37 +3839,42 @@ dotted_name_rule(Parser *p) while (1) { int tmpvar_0 = _PyPegen_update_memo(p, _mark, dotted_name_type, _res); if (tmpvar_0) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; p->in_raw_rule++; void *_raw = dotted_name_raw(p); p->in_raw_rule--; - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty dotted_name_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // dotted_name '.' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dotted_name[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dotted_name '.' NAME")); @@ -3802,7 +3893,7 @@ dotted_name_raw(Parser *p) _res = _PyPegen_join_names_with_dot ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3813,7 +3904,7 @@ dotted_name_raw(Parser *p) } { // NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dotted_name[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); @@ -3832,7 +3923,7 @@ dotted_name_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3843,16 +3934,19 @@ dotted_name_raw(Parser *p) static stmt_ty if_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3861,7 +3955,7 @@ if_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_if_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> if_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_if_stmt")); @@ -3880,7 +3974,7 @@ if_stmt_rule(Parser *p) } { // 'if' named_expression ':' block elif_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> if_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' named_expression ':' block elif_stmt")); @@ -3904,7 +3998,7 @@ if_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ if_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' named_expression ':' block elif_stmt")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3914,7 +4008,7 @@ if_stmt_rule(Parser *p) _res = _PyAST_If ( a , b , CHECK ( asdl_stmt_seq * , _PyPegen_singleton_seq ( p , c ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3925,7 +4019,7 @@ if_stmt_rule(Parser *p) } { // 'if' named_expression ':' block else_block? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> if_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' named_expression ':' block else_block?")); @@ -3949,7 +4043,7 @@ if_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ if_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' named_expression ':' block else_block?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3959,7 +4053,7 @@ if_stmt_rule(Parser *p) _res = _PyAST_If ( a , b , c , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3970,7 +4064,7 @@ if_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3981,16 +4075,19 @@ if_stmt_rule(Parser *p) static stmt_ty elif_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3999,7 +4096,7 @@ elif_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_elif_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> elif_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_elif_stmt")); @@ -4018,7 +4115,7 @@ elif_stmt_rule(Parser *p) } { // 'elif' named_expression ':' block elif_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> elif_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'elif' named_expression ':' block elif_stmt")); @@ -4042,7 +4139,7 @@ elif_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ elif_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'elif' named_expression ':' block elif_stmt")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4052,7 +4149,7 @@ elif_stmt_rule(Parser *p) _res = _PyAST_If ( a , b , CHECK ( asdl_stmt_seq * , _PyPegen_singleton_seq ( p , c ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4063,7 +4160,7 @@ elif_stmt_rule(Parser *p) } { // 'elif' named_expression ':' block else_block? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> elif_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'elif' named_expression ':' block else_block?")); @@ -4087,7 +4184,7 @@ elif_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ elif_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'elif' named_expression ':' block else_block?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4097,7 +4194,7 @@ elif_stmt_rule(Parser *p) _res = _PyAST_If ( a , b , c , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4108,7 +4205,7 @@ elif_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4116,16 +4213,19 @@ elif_stmt_rule(Parser *p) static asdl_stmt_seq* else_block_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_stmt_seq* _res = NULL; int _mark = p->mark; if (p->call_invalid_rules) { // invalid_else_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> else_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_else_stmt")); @@ -4144,7 +4244,7 @@ else_block_rule(Parser *p) } { // 'else' &&':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> else_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else' &&':' block")); @@ -4163,7 +4263,7 @@ else_block_rule(Parser *p) _res = b; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4174,7 +4274,7 @@ else_block_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4182,16 +4282,19 @@ else_block_rule(Parser *p) static stmt_ty while_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -4200,7 +4303,7 @@ while_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_while_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> while_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_while_stmt")); @@ -4219,7 +4322,7 @@ while_stmt_rule(Parser *p) } { // 'while' named_expression ':' block else_block? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> while_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'while' named_expression ':' block else_block?")); @@ -4243,7 +4346,7 @@ while_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ while_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'while' named_expression ':' block else_block?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4253,7 +4356,7 @@ while_stmt_rule(Parser *p) _res = _PyAST_While ( a , b , c , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4264,7 +4367,7 @@ while_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4276,16 +4379,19 @@ while_stmt_rule(Parser *p) static stmt_ty for_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -4294,7 +4400,7 @@ for_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_for_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_for_stmt")); @@ -4313,7 +4419,7 @@ for_stmt_rule(Parser *p) } { // 'for' star_targets 'in' ~ star_expressions &&':' TYPE_COMMENT? block else_block? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'for' star_targets 'in' ~ star_expressions &&':' TYPE_COMMENT? block else_block?")); @@ -4349,7 +4455,7 @@ for_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ for_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'for' star_targets 'in' ~ star_expressions &&':' TYPE_COMMENT? block else_block?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4359,7 +4465,7 @@ for_stmt_rule(Parser *p) _res = _PyAST_For ( t , ex , b , el , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4368,13 +4474,13 @@ for_stmt_rule(Parser *p) D(fprintf(stderr, "%*c%s for_stmt[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'for' star_targets 'in' ~ star_expressions &&':' TYPE_COMMENT? block else_block?")); if (_cut_var) { - D(p->level--); + p->level--; return NULL; } } { // ASYNC 'for' star_targets 'in' ~ star_expressions &&':' TYPE_COMMENT? block else_block? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC 'for' star_targets 'in' ~ star_expressions &&':' TYPE_COMMENT? block else_block?")); @@ -4413,7 +4519,7 @@ for_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ for_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC 'for' star_targets 'in' ~ star_expressions &&':' TYPE_COMMENT? block else_block?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4423,7 +4529,7 @@ for_stmt_rule(Parser *p) _res = CHECK_VERSION ( stmt_ty , 5 , "Async for loops are" , _PyAST_AsyncFor ( t , ex , b , el , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4432,13 +4538,13 @@ for_stmt_rule(Parser *p) D(fprintf(stderr, "%*c%s for_stmt[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "ASYNC 'for' star_targets 'in' ~ star_expressions &&':' TYPE_COMMENT? block else_block?")); if (_cut_var) { - D(p->level--); + p->level--; return NULL; } } if (p->call_invalid_rules) { // invalid_for_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_for_target")); @@ -4457,7 +4563,7 @@ for_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4471,16 +4577,19 @@ for_stmt_rule(Parser *p) static stmt_ty with_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -4489,7 +4598,7 @@ with_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_with_stmt_indent if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_with_stmt_indent")); @@ -4508,7 +4617,7 @@ with_stmt_rule(Parser *p) } { // 'with' '(' ','.with_item+ ','? ')' ':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'with' '(' ','.with_item+ ','? ')' ':' block")); @@ -4539,7 +4648,7 @@ with_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'with' '(' ','.with_item+ ','? ')' ':' block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4549,7 +4658,7 @@ with_stmt_rule(Parser *p) _res = _PyAST_With ( a , b , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4560,7 +4669,7 @@ with_stmt_rule(Parser *p) } { // 'with' ','.with_item+ ':' TYPE_COMMENT? block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'with' ','.with_item+ ':' TYPE_COMMENT? block")); @@ -4584,7 +4693,7 @@ with_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'with' ','.with_item+ ':' TYPE_COMMENT? block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4594,7 +4703,7 @@ with_stmt_rule(Parser *p) _res = _PyAST_With ( a , b , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4605,7 +4714,7 @@ with_stmt_rule(Parser *p) } { // ASYNC 'with' '(' ','.with_item+ ','? ')' ':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC 'with' '(' ','.with_item+ ','? ')' ':' block")); @@ -4639,7 +4748,7 @@ with_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC 'with' '(' ','.with_item+ ','? ')' ':' block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4649,7 +4758,7 @@ with_stmt_rule(Parser *p) _res = CHECK_VERSION ( stmt_ty , 5 , "Async with statements are" , _PyAST_AsyncWith ( a , b , NULL , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4660,7 +4769,7 @@ with_stmt_rule(Parser *p) } { // ASYNC 'with' ','.with_item+ ':' TYPE_COMMENT? block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC 'with' ','.with_item+ ':' TYPE_COMMENT? block")); @@ -4687,7 +4796,7 @@ with_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC 'with' ','.with_item+ ':' TYPE_COMMENT? block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4697,7 +4806,7 @@ with_stmt_rule(Parser *p) _res = CHECK_VERSION ( stmt_ty , 5 , "Async with statements are" , _PyAST_AsyncWith ( a , b , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4708,7 +4817,7 @@ with_stmt_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_with_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_with_stmt")); @@ -4727,7 +4836,7 @@ with_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4738,16 +4847,19 @@ with_stmt_rule(Parser *p) static withitem_ty with_item_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } withitem_ty _res = NULL; int _mark = p->mark; { // expression 'as' star_target &(',' | ')' | ':') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_item[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression 'as' star_target &(',' | ')' | ':')")); @@ -4768,7 +4880,7 @@ with_item_rule(Parser *p) _res = _PyAST_withitem ( e , t , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4779,7 +4891,7 @@ with_item_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_with_item if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_item[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_with_item")); @@ -4798,7 +4910,7 @@ with_item_rule(Parser *p) } { // expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_item[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression")); @@ -4811,7 +4923,7 @@ with_item_rule(Parser *p) _res = _PyAST_withitem ( e , NULL , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4822,7 +4934,7 @@ with_item_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4833,16 +4945,19 @@ with_item_rule(Parser *p) static stmt_ty try_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -4851,7 +4966,7 @@ try_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_try_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> try_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_try_stmt")); @@ -4870,7 +4985,7 @@ try_stmt_rule(Parser *p) } { // 'try' &&':' block finally_block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> try_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'try' &&':' block finally_block")); @@ -4891,7 +5006,7 @@ try_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' &&':' block finally_block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4901,7 +5016,7 @@ try_stmt_rule(Parser *p) _res = _PyAST_Try ( b , NULL , NULL , f , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4912,7 +5027,7 @@ try_stmt_rule(Parser *p) } { // 'try' &&':' block except_block+ else_block? finally_block? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> try_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'try' &&':' block except_block+ else_block? finally_block?")); @@ -4939,7 +5054,7 @@ try_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' &&':' block except_block+ else_block? finally_block?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4949,7 +5064,7 @@ try_stmt_rule(Parser *p) _res = _PyAST_Try ( b , ex , el , f , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4960,7 +5075,7 @@ try_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4972,16 +5087,19 @@ try_stmt_rule(Parser *p) static excepthandler_ty except_block_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } excepthandler_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -4990,7 +5108,7 @@ except_block_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_except_stmt_indent if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> except_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_except_stmt_indent")); @@ -5009,7 +5127,7 @@ except_block_rule(Parser *p) } { // 'except' expression ['as' NAME] ':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> except_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' expression ['as' NAME] ':' block")); @@ -5033,7 +5151,7 @@ except_block_rule(Parser *p) D(fprintf(stderr, "%*c+ except_block[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' expression ['as' NAME] ':' block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -5043,7 +5161,7 @@ except_block_rule(Parser *p) _res = _PyAST_ExceptHandler ( e , ( t ) ? ( ( expr_ty ) t ) -> v . Name . id : NULL , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5054,7 +5172,7 @@ except_block_rule(Parser *p) } { // 'except' ':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> except_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' ':' block")); @@ -5072,7 +5190,7 @@ except_block_rule(Parser *p) D(fprintf(stderr, "%*c+ except_block[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' ':' block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -5082,7 +5200,7 @@ except_block_rule(Parser *p) _res = _PyAST_ExceptHandler ( NULL , NULL , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5093,7 +5211,7 @@ except_block_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_except_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> except_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_except_stmt")); @@ -5112,7 +5230,7 @@ except_block_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5120,16 +5238,19 @@ except_block_rule(Parser *p) static asdl_stmt_seq* finally_block_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_stmt_seq* _res = NULL; int _mark = p->mark; if (p->call_invalid_rules) { // invalid_finally_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> finally_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_finally_stmt")); @@ -5148,7 +5269,7 @@ finally_block_rule(Parser *p) } { // 'finally' &&':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> finally_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally' &&':' block")); @@ -5167,7 +5288,7 @@ finally_block_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5178,7 +5299,7 @@ finally_block_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5188,16 +5309,19 @@ finally_block_rule(Parser *p) static stmt_ty match_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -5206,7 +5330,7 @@ match_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // "match" subject_expr ':' NEWLINE INDENT case_block+ DEDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> match_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"match\" subject_expr ':' NEWLINE INDENT case_block+ DEDENT")); @@ -5236,7 +5360,7 @@ match_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ match_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"match\" subject_expr ':' NEWLINE INDENT case_block+ DEDENT")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -5246,7 +5370,7 @@ match_stmt_rule(Parser *p) _res = CHECK_VERSION ( stmt_ty , 10 , "Pattern matching is" , _PyAST_Match ( subject , cases , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5257,7 +5381,7 @@ match_stmt_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_match_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> match_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_match_stmt")); @@ -5276,7 +5400,7 @@ match_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5284,16 +5408,19 @@ match_stmt_rule(Parser *p) static expr_ty subject_expr_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -5302,7 +5429,7 @@ subject_expr_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // star_named_expression ',' star_named_expressions? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> subject_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?")); @@ -5320,7 +5447,7 @@ subject_expr_rule(Parser *p) D(fprintf(stderr, "%*c+ subject_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -5330,7 +5457,7 @@ subject_expr_rule(Parser *p) _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq * , _PyPegen_seq_insert_in_front ( p , value , values ) ) , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5341,7 +5468,7 @@ subject_expr_rule(Parser *p) } { // named_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> subject_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression")); @@ -5360,7 +5487,7 @@ subject_expr_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5368,16 +5495,19 @@ subject_expr_rule(Parser *p) static match_case_ty case_block_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } match_case_ty _res = NULL; int _mark = p->mark; if (p->call_invalid_rules) { // invalid_case_block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> case_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_case_block")); @@ -5396,7 +5526,7 @@ case_block_rule(Parser *p) } { // "case" patterns guard? ':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> case_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"case\" patterns guard? ':' block")); @@ -5421,7 +5551,7 @@ case_block_rule(Parser *p) _res = _PyAST_match_case ( pattern , guard , body , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5432,7 +5562,7 @@ case_block_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5440,16 +5570,19 @@ case_block_rule(Parser *p) static expr_ty guard_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // 'if' named_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> guard[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' named_expression")); @@ -5465,7 +5598,7 @@ guard_rule(Parser *p) _res = guard; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5476,7 +5609,7 @@ guard_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5484,16 +5617,19 @@ guard_rule(Parser *p) static pattern_ty patterns_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -5502,7 +5638,7 @@ patterns_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // open_sequence_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> patterns[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "open_sequence_pattern")); @@ -5514,7 +5650,7 @@ patterns_rule(Parser *p) D(fprintf(stderr, "%*c+ patterns[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "open_sequence_pattern")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -5524,7 +5660,7 @@ patterns_rule(Parser *p) _res = _PyAST_MatchSequence ( patterns , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5535,7 +5671,7 @@ patterns_rule(Parser *p) } { // pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> patterns[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "pattern")); @@ -5554,7 +5690,7 @@ patterns_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5562,16 +5698,19 @@ patterns_rule(Parser *p) static pattern_ty pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; { // as_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "as_pattern")); @@ -5590,7 +5729,7 @@ pattern_rule(Parser *p) } { // or_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "or_pattern")); @@ -5609,7 +5748,7 @@ pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5617,16 +5756,19 @@ pattern_rule(Parser *p) static pattern_ty as_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -5635,7 +5777,7 @@ as_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // or_pattern 'as' pattern_capture_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> as_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "or_pattern 'as' pattern_capture_target")); @@ -5653,7 +5795,7 @@ as_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ as_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "or_pattern 'as' pattern_capture_target")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -5663,7 +5805,7 @@ as_pattern_rule(Parser *p) _res = _PyAST_MatchAs ( pattern , target -> v . Name . id , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5674,7 +5816,7 @@ as_pattern_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_as_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> as_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_as_pattern")); @@ -5693,7 +5835,7 @@ as_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5701,16 +5843,19 @@ as_pattern_rule(Parser *p) static pattern_ty or_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -5719,7 +5864,7 @@ or_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '|'.closed_pattern+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> or_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'|'.closed_pattern+")); @@ -5731,7 +5876,7 @@ or_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ or_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'|'.closed_pattern+")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -5741,7 +5886,7 @@ or_pattern_rule(Parser *p) _res = asdl_seq_LEN ( patterns ) == 1 ? asdl_seq_GET ( patterns , 0 ) : _PyAST_MatchOr ( patterns , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5752,7 +5897,7 @@ or_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5768,16 +5913,19 @@ or_pattern_rule(Parser *p) static pattern_ty closed_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; { // literal_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> closed_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "literal_pattern")); @@ -5796,7 +5944,7 @@ closed_pattern_rule(Parser *p) } { // capture_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> closed_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "capture_pattern")); @@ -5815,7 +5963,7 @@ closed_pattern_rule(Parser *p) } { // wildcard_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> closed_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "wildcard_pattern")); @@ -5834,7 +5982,7 @@ closed_pattern_rule(Parser *p) } { // value_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> closed_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "value_pattern")); @@ -5853,7 +6001,7 @@ closed_pattern_rule(Parser *p) } { // group_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> closed_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "group_pattern")); @@ -5872,7 +6020,7 @@ closed_pattern_rule(Parser *p) } { // sequence_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> closed_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "sequence_pattern")); @@ -5891,7 +6039,7 @@ closed_pattern_rule(Parser *p) } { // mapping_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> closed_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "mapping_pattern")); @@ -5910,7 +6058,7 @@ closed_pattern_rule(Parser *p) } { // class_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> closed_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "class_pattern")); @@ -5929,7 +6077,7 @@ closed_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5943,16 +6091,19 @@ closed_pattern_rule(Parser *p) static pattern_ty literal_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -5961,7 +6112,7 @@ literal_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // signed_number !('+' | '-') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "signed_number !('+' | '-')")); @@ -5975,7 +6126,7 @@ literal_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "signed_number !('+' | '-')")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -5985,7 +6136,7 @@ literal_pattern_rule(Parser *p) _res = _PyAST_MatchValue ( value , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5996,7 +6147,7 @@ literal_pattern_rule(Parser *p) } { // complex_number if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "complex_number")); @@ -6008,7 +6159,7 @@ literal_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "complex_number")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6018,7 +6169,7 @@ literal_pattern_rule(Parser *p) _res = _PyAST_MatchValue ( value , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6029,7 +6180,7 @@ literal_pattern_rule(Parser *p) } { // strings if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "strings")); @@ -6041,7 +6192,7 @@ literal_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "strings")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6051,7 +6202,7 @@ literal_pattern_rule(Parser *p) _res = _PyAST_MatchValue ( value , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6062,7 +6213,7 @@ literal_pattern_rule(Parser *p) } { // 'None' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); @@ -6074,7 +6225,7 @@ literal_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6084,7 +6235,7 @@ literal_pattern_rule(Parser *p) _res = _PyAST_MatchSingleton ( Py_None , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6095,7 +6246,7 @@ literal_pattern_rule(Parser *p) } { // 'True' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); @@ -6107,7 +6258,7 @@ literal_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6117,7 +6268,7 @@ literal_pattern_rule(Parser *p) _res = _PyAST_MatchSingleton ( Py_True , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6128,7 +6279,7 @@ literal_pattern_rule(Parser *p) } { // 'False' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); @@ -6140,7 +6291,7 @@ literal_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6150,7 +6301,7 @@ literal_pattern_rule(Parser *p) _res = _PyAST_MatchSingleton ( Py_False , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6161,7 +6312,7 @@ literal_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6175,16 +6326,19 @@ literal_pattern_rule(Parser *p) static expr_ty literal_expr_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6193,7 +6347,7 @@ literal_expr_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // signed_number !('+' | '-') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "signed_number !('+' | '-')")); @@ -6214,7 +6368,7 @@ literal_expr_rule(Parser *p) } { // complex_number if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "complex_number")); @@ -6233,7 +6387,7 @@ literal_expr_rule(Parser *p) } { // strings if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "strings")); @@ -6252,7 +6406,7 @@ literal_expr_rule(Parser *p) } { // 'None' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); @@ -6264,7 +6418,7 @@ literal_expr_rule(Parser *p) D(fprintf(stderr, "%*c+ literal_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6274,7 +6428,7 @@ literal_expr_rule(Parser *p) _res = _PyAST_Constant ( Py_None , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6285,7 +6439,7 @@ literal_expr_rule(Parser *p) } { // 'True' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); @@ -6297,7 +6451,7 @@ literal_expr_rule(Parser *p) D(fprintf(stderr, "%*c+ literal_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6307,7 +6461,7 @@ literal_expr_rule(Parser *p) _res = _PyAST_Constant ( Py_True , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6318,7 +6472,7 @@ literal_expr_rule(Parser *p) } { // 'False' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); @@ -6330,7 +6484,7 @@ literal_expr_rule(Parser *p) D(fprintf(stderr, "%*c+ literal_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6340,7 +6494,7 @@ literal_expr_rule(Parser *p) _res = _PyAST_Constant ( Py_False , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6351,7 +6505,7 @@ literal_expr_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6361,16 +6515,19 @@ literal_expr_rule(Parser *p) static expr_ty complex_number_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6379,7 +6536,7 @@ complex_number_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // signed_real_number '+' imaginary_number if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> complex_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "signed_real_number '+' imaginary_number")); @@ -6397,7 +6554,7 @@ complex_number_rule(Parser *p) D(fprintf(stderr, "%*c+ complex_number[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "signed_real_number '+' imaginary_number")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6407,7 +6564,7 @@ complex_number_rule(Parser *p) _res = _PyAST_BinOp ( real , Add , imag , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6418,7 +6575,7 @@ complex_number_rule(Parser *p) } { // signed_real_number '-' imaginary_number if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> complex_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "signed_real_number '-' imaginary_number")); @@ -6436,7 +6593,7 @@ complex_number_rule(Parser *p) D(fprintf(stderr, "%*c+ complex_number[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "signed_real_number '-' imaginary_number")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6446,7 +6603,7 @@ complex_number_rule(Parser *p) _res = _PyAST_BinOp ( real , Sub , imag , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6457,7 +6614,7 @@ complex_number_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6465,16 +6622,19 @@ complex_number_rule(Parser *p) static expr_ty signed_number_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6483,7 +6643,7 @@ signed_number_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NUMBER if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> signed_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NUMBER")); @@ -6502,7 +6662,7 @@ signed_number_rule(Parser *p) } { // '-' NUMBER if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> signed_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-' NUMBER")); @@ -6517,7 +6677,7 @@ signed_number_rule(Parser *p) D(fprintf(stderr, "%*c+ signed_number[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-' NUMBER")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6527,7 +6687,7 @@ signed_number_rule(Parser *p) _res = _PyAST_UnaryOp ( USub , number , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6538,7 +6698,7 @@ signed_number_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6546,16 +6706,19 @@ signed_number_rule(Parser *p) static expr_ty signed_real_number_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6564,7 +6727,7 @@ signed_real_number_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // real_number if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> signed_real_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "real_number")); @@ -6583,7 +6746,7 @@ signed_real_number_rule(Parser *p) } { // '-' real_number if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> signed_real_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-' real_number")); @@ -6598,7 +6761,7 @@ signed_real_number_rule(Parser *p) D(fprintf(stderr, "%*c+ signed_real_number[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-' real_number")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6608,7 +6771,7 @@ signed_real_number_rule(Parser *p) _res = _PyAST_UnaryOp ( USub , real , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6619,7 +6782,7 @@ signed_real_number_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6627,16 +6790,19 @@ signed_real_number_rule(Parser *p) static expr_ty real_number_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // NUMBER if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> real_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NUMBER")); @@ -6649,7 +6815,7 @@ real_number_rule(Parser *p) _res = _PyPegen_ensure_real ( p , real ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6660,7 +6826,7 @@ real_number_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6668,16 +6834,19 @@ real_number_rule(Parser *p) static expr_ty imaginary_number_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // NUMBER if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> imaginary_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NUMBER")); @@ -6690,7 +6859,7 @@ imaginary_number_rule(Parser *p) _res = _PyPegen_ensure_imaginary ( p , imag ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6701,7 +6870,7 @@ imaginary_number_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6709,16 +6878,19 @@ imaginary_number_rule(Parser *p) static pattern_ty capture_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6727,7 +6899,7 @@ capture_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // pattern_capture_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> capture_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "pattern_capture_target")); @@ -6739,7 +6911,7 @@ capture_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ capture_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "pattern_capture_target")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6749,7 +6921,7 @@ capture_pattern_rule(Parser *p) _res = _PyAST_MatchAs ( NULL , target -> v . Name . id , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6760,7 +6932,7 @@ capture_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6768,16 +6940,19 @@ capture_pattern_rule(Parser *p) static expr_ty pattern_capture_target_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // !"_" NAME !('.' | '(' | '=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> pattern_capture_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!\"_\" NAME !('.' | '(' | '=')")); @@ -6794,7 +6969,7 @@ pattern_capture_target_rule(Parser *p) _res = _PyPegen_set_expr_context ( p , name , Store ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6805,7 +6980,7 @@ pattern_capture_target_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6813,16 +6988,19 @@ pattern_capture_target_rule(Parser *p) static pattern_ty wildcard_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6831,7 +7009,7 @@ wildcard_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // "_" if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> wildcard_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"_\"")); @@ -6843,7 +7021,7 @@ wildcard_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ wildcard_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"_\"")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6853,7 +7031,7 @@ wildcard_pattern_rule(Parser *p) _res = _PyAST_MatchAs ( NULL , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6864,7 +7042,7 @@ wildcard_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6872,16 +7050,19 @@ wildcard_pattern_rule(Parser *p) static pattern_ty value_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6890,7 +7071,7 @@ value_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // attr !('.' | '(' | '=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> value_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "attr !('.' | '(' | '=')")); @@ -6904,7 +7085,7 @@ value_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ value_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "attr !('.' | '(' | '=')")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6914,7 +7095,7 @@ value_pattern_rule(Parser *p) _res = _PyAST_MatchValue ( attr , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6925,7 +7106,7 @@ value_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6935,10 +7116,13 @@ static expr_ty attr_raw(Parser *); static expr_ty attr_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, attr_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -6946,37 +7130,42 @@ attr_rule(Parser *p) while (1) { int tmpvar_1 = _PyPegen_update_memo(p, _mark, attr_type, _res); if (tmpvar_1) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; p->in_raw_rule++; void *_raw = attr_raw(p); p->in_raw_rule--; - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty attr_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6985,7 +7174,7 @@ attr_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // name_or_attr '.' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> attr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "name_or_attr '.' NAME")); @@ -7003,7 +7192,7 @@ attr_raw(Parser *p) D(fprintf(stderr, "%*c+ attr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "name_or_attr '.' NAME")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7013,7 +7202,7 @@ attr_raw(Parser *p) _res = _PyAST_Attribute ( value , attr -> v . Name . id , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7024,7 +7213,7 @@ attr_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7033,16 +7222,19 @@ attr_raw(Parser *p) static expr_ty name_or_attr_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // attr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> name_or_attr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "attr")); @@ -7061,7 +7253,7 @@ name_or_attr_rule(Parser *p) } { // NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> name_or_attr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); @@ -7080,7 +7272,7 @@ name_or_attr_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7088,16 +7280,19 @@ name_or_attr_rule(Parser *p) static pattern_ty group_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; { // '(' pattern ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> group_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' pattern ')'")); @@ -7116,7 +7311,7 @@ group_pattern_rule(Parser *p) _res = pattern; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7127,7 +7322,7 @@ group_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7135,16 +7330,19 @@ group_pattern_rule(Parser *p) static pattern_ty sequence_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -7153,7 +7351,7 @@ sequence_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '[' maybe_sequence_pattern? ']' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> sequence_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'[' maybe_sequence_pattern? ']'")); @@ -7171,7 +7369,7 @@ sequence_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ sequence_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' maybe_sequence_pattern? ']'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7181,7 +7379,7 @@ sequence_pattern_rule(Parser *p) _res = _PyAST_MatchSequence ( patterns , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7192,7 +7390,7 @@ sequence_pattern_rule(Parser *p) } { // '(' open_sequence_pattern? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> sequence_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' open_sequence_pattern? ')'")); @@ -7210,7 +7408,7 @@ sequence_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ sequence_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' open_sequence_pattern? ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7220,7 +7418,7 @@ sequence_pattern_rule(Parser *p) _res = _PyAST_MatchSequence ( patterns , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7231,7 +7429,7 @@ sequence_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7239,16 +7437,19 @@ sequence_pattern_rule(Parser *p) static asdl_seq* open_sequence_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // maybe_star_pattern ',' maybe_sequence_pattern? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> open_sequence_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "maybe_star_pattern ',' maybe_sequence_pattern?")); @@ -7267,7 +7468,7 @@ open_sequence_pattern_rule(Parser *p) _res = _PyPegen_seq_insert_in_front ( p , pattern , patterns ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7278,7 +7479,7 @@ open_sequence_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7286,16 +7487,19 @@ open_sequence_pattern_rule(Parser *p) static asdl_seq* maybe_sequence_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // ','.maybe_star_pattern+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> maybe_sequence_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.maybe_star_pattern+ ','?")); @@ -7312,7 +7516,7 @@ maybe_sequence_pattern_rule(Parser *p) _res = patterns; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7323,7 +7527,7 @@ maybe_sequence_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7331,16 +7535,19 @@ maybe_sequence_pattern_rule(Parser *p) static pattern_ty maybe_star_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; { // star_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> maybe_star_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_pattern")); @@ -7359,7 +7566,7 @@ maybe_star_pattern_rule(Parser *p) } { // pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> maybe_star_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "pattern")); @@ -7378,7 +7585,7 @@ maybe_star_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7386,16 +7593,19 @@ maybe_star_pattern_rule(Parser *p) static pattern_ty star_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -7404,7 +7614,7 @@ star_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '*' pattern_capture_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' pattern_capture_target")); @@ -7419,7 +7629,7 @@ star_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ star_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' pattern_capture_target")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7429,7 +7639,7 @@ star_pattern_rule(Parser *p) _res = _PyAST_MatchStar ( target -> v . Name . id , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7440,7 +7650,7 @@ star_pattern_rule(Parser *p) } { // '*' wildcard_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' wildcard_pattern")); @@ -7455,7 +7665,7 @@ star_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ star_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' wildcard_pattern")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7465,7 +7675,7 @@ star_pattern_rule(Parser *p) _res = _PyAST_MatchStar ( NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7476,7 +7686,7 @@ star_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7488,16 +7698,19 @@ star_pattern_rule(Parser *p) static pattern_ty mapping_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -7506,7 +7719,7 @@ mapping_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '{' '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> mapping_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' '}'")); @@ -7521,7 +7734,7 @@ mapping_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ mapping_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7531,7 +7744,7 @@ mapping_pattern_rule(Parser *p) _res = _PyAST_MatchMapping ( NULL , NULL , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7542,7 +7755,7 @@ mapping_pattern_rule(Parser *p) } { // '{' double_star_pattern ','? '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> mapping_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' double_star_pattern ','? '}'")); @@ -7564,7 +7777,7 @@ mapping_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ mapping_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' double_star_pattern ','? '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7574,7 +7787,7 @@ mapping_pattern_rule(Parser *p) _res = _PyAST_MatchMapping ( NULL , NULL , rest -> v . Name . id , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7585,7 +7798,7 @@ mapping_pattern_rule(Parser *p) } { // '{' items_pattern ',' double_star_pattern ','? '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> mapping_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' items_pattern ',' double_star_pattern ','? '}'")); @@ -7613,7 +7826,7 @@ mapping_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ mapping_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' items_pattern ',' double_star_pattern ','? '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7623,7 +7836,7 @@ mapping_pattern_rule(Parser *p) _res = _PyAST_MatchMapping ( CHECK ( asdl_expr_seq * , _PyPegen_get_pattern_keys ( p , items ) ) , CHECK ( asdl_pattern_seq * , _PyPegen_get_patterns ( p , items ) ) , rest -> v . Name . id , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7634,7 +7847,7 @@ mapping_pattern_rule(Parser *p) } { // '{' items_pattern ','? '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> mapping_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' items_pattern ','? '}'")); @@ -7656,7 +7869,7 @@ mapping_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ mapping_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' items_pattern ','? '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7666,7 +7879,7 @@ mapping_pattern_rule(Parser *p) _res = _PyAST_MatchMapping ( CHECK ( asdl_expr_seq * , _PyPegen_get_pattern_keys ( p , items ) ) , CHECK ( asdl_pattern_seq * , _PyPegen_get_patterns ( p , items ) ) , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7677,7 +7890,7 @@ mapping_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7685,16 +7898,19 @@ mapping_pattern_rule(Parser *p) static asdl_seq* items_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // ','.key_value_pattern+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> items_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.key_value_pattern+")); @@ -7713,7 +7929,7 @@ items_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7721,16 +7937,19 @@ items_pattern_rule(Parser *p) static KeyPatternPair* key_value_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } KeyPatternPair* _res = NULL; int _mark = p->mark; { // (literal_expr | attr) ':' pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> key_value_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(literal_expr | attr) ':' pattern")); @@ -7749,7 +7968,7 @@ key_value_pattern_rule(Parser *p) _res = _PyPegen_key_pattern_pair ( p , key , pattern ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7760,7 +7979,7 @@ key_value_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7768,16 +7987,19 @@ key_value_pattern_rule(Parser *p) static expr_ty double_star_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // '**' pattern_capture_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> double_star_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' pattern_capture_target")); @@ -7793,7 +8015,7 @@ double_star_pattern_rule(Parser *p) _res = target; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7804,7 +8026,7 @@ double_star_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7817,16 +8039,19 @@ double_star_pattern_rule(Parser *p) static pattern_ty class_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -7835,7 +8060,7 @@ class_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // name_or_attr '(' ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' ')'")); @@ -7853,7 +8078,7 @@ class_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ class_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7863,7 +8088,7 @@ class_pattern_rule(Parser *p) _res = _PyAST_MatchClass ( cls , NULL , NULL , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7874,7 +8099,7 @@ class_pattern_rule(Parser *p) } { // name_or_attr '(' positional_patterns ','? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' positional_patterns ','? ')'")); @@ -7899,7 +8124,7 @@ class_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ class_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' positional_patterns ','? ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7909,7 +8134,7 @@ class_pattern_rule(Parser *p) _res = _PyAST_MatchClass ( cls , patterns , NULL , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7920,7 +8145,7 @@ class_pattern_rule(Parser *p) } { // name_or_attr '(' keyword_patterns ','? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' keyword_patterns ','? ')'")); @@ -7945,7 +8170,7 @@ class_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ class_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' keyword_patterns ','? ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7955,7 +8180,7 @@ class_pattern_rule(Parser *p) _res = _PyAST_MatchClass ( cls , NULL , CHECK ( asdl_identifier_seq * , _PyPegen_map_names_to_ids ( p , CHECK ( asdl_expr_seq * , _PyPegen_get_pattern_keys ( p , keywords ) ) ) ) , CHECK ( asdl_pattern_seq * , _PyPegen_get_patterns ( p , keywords ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7966,7 +8191,7 @@ class_pattern_rule(Parser *p) } { // name_or_attr '(' positional_patterns ',' keyword_patterns ','? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' positional_patterns ',' keyword_patterns ','? ')'")); @@ -7997,7 +8222,7 @@ class_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ class_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' positional_patterns ',' keyword_patterns ','? ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -8007,7 +8232,7 @@ class_pattern_rule(Parser *p) _res = _PyAST_MatchClass ( cls , patterns , CHECK ( asdl_identifier_seq * , _PyPegen_map_names_to_ids ( p , CHECK ( asdl_expr_seq * , _PyPegen_get_pattern_keys ( p , keywords ) ) ) ) , CHECK ( asdl_pattern_seq * , _PyPegen_get_patterns ( p , keywords ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8018,7 +8243,7 @@ class_pattern_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_class_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_class_pattern")); @@ -8037,7 +8262,7 @@ class_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8045,16 +8270,19 @@ class_pattern_rule(Parser *p) static asdl_pattern_seq* positional_patterns_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_pattern_seq* _res = NULL; int _mark = p->mark; { // ','.pattern+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> positional_patterns[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.pattern+")); @@ -8067,7 +8295,7 @@ positional_patterns_rule(Parser *p) _res = args; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8078,7 +8306,7 @@ positional_patterns_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8086,16 +8314,19 @@ positional_patterns_rule(Parser *p) static asdl_seq* keyword_patterns_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // ','.keyword_pattern+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> keyword_patterns[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.keyword_pattern+")); @@ -8114,7 +8345,7 @@ keyword_patterns_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8122,16 +8353,19 @@ keyword_patterns_rule(Parser *p) static KeyPatternPair* keyword_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } KeyPatternPair* _res = NULL; int _mark = p->mark; { // NAME '=' pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> keyword_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '=' pattern")); @@ -8150,7 +8384,7 @@ keyword_pattern_rule(Parser *p) _res = _PyPegen_key_pattern_pair ( p , arg , value ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8161,7 +8395,7 @@ keyword_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8169,16 +8403,19 @@ keyword_pattern_rule(Parser *p) static stmt_ty return_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -8187,7 +8424,7 @@ return_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'return' star_expressions? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> return_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'return' star_expressions?")); @@ -8202,7 +8439,7 @@ return_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ return_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'return' star_expressions?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -8212,7 +8449,7 @@ return_stmt_rule(Parser *p) _res = _PyAST_Return ( a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8223,7 +8460,7 @@ return_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8231,16 +8468,19 @@ return_stmt_rule(Parser *p) static stmt_ty raise_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -8249,7 +8489,7 @@ raise_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'raise' expression ['from' expression] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> raise_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'raise' expression ['from' expression]")); @@ -8267,7 +8507,7 @@ raise_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ raise_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'raise' expression ['from' expression]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -8277,7 +8517,7 @@ raise_stmt_rule(Parser *p) _res = _PyAST_Raise ( a , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8288,7 +8528,7 @@ raise_stmt_rule(Parser *p) } { // 'raise' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> raise_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'raise'")); @@ -8300,7 +8540,7 @@ raise_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ raise_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'raise'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -8310,7 +8550,7 @@ raise_stmt_rule(Parser *p) _res = _PyAST_Raise ( NULL , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8321,7 +8561,7 @@ raise_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8329,16 +8569,19 @@ raise_stmt_rule(Parser *p) static stmt_ty function_def_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; { // decorators function_def_raw if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> function_def[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "decorators function_def_raw")); @@ -8354,7 +8597,7 @@ function_def_rule(Parser *p) _res = _PyPegen_function_def_decorators ( p , d , f ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8365,7 +8608,7 @@ function_def_rule(Parser *p) } { // function_def_raw if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> function_def[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "function_def_raw")); @@ -8384,7 +8627,7 @@ function_def_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8395,16 +8638,19 @@ function_def_rule(Parser *p) static stmt_ty function_def_raw_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -8413,7 +8659,7 @@ function_def_raw_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_def_raw if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> function_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_def_raw")); @@ -8432,7 +8678,7 @@ function_def_raw_rule(Parser *p) } { // 'def' NAME '(' params? ')' ['->' expression] &&':' func_type_comment? block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> function_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'def' NAME '(' params? ')' ['->' expression] &&':' func_type_comment? block")); @@ -8468,7 +8714,7 @@ function_def_raw_rule(Parser *p) D(fprintf(stderr, "%*c+ function_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'def' NAME '(' params? ')' ['->' expression] &&':' func_type_comment? block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -8478,7 +8724,7 @@ function_def_raw_rule(Parser *p) _res = _PyAST_FunctionDef ( n -> v . Name . id , ( params ) ? params : CHECK ( arguments_ty , _PyPegen_empty_arguments ( p ) ) , b , NULL , a , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8489,7 +8735,7 @@ function_def_raw_rule(Parser *p) } { // ASYNC 'def' NAME '(' params? ')' ['->' expression] &&':' func_type_comment? block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> function_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC 'def' NAME '(' params? ')' ['->' expression] &&':' func_type_comment? block")); @@ -8528,7 +8774,7 @@ function_def_raw_rule(Parser *p) D(fprintf(stderr, "%*c+ function_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC 'def' NAME '(' params? ')' ['->' expression] &&':' func_type_comment? block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -8538,7 +8784,7 @@ function_def_raw_rule(Parser *p) _res = CHECK_VERSION ( stmt_ty , 5 , "Async functions are" , _PyAST_AsyncFunctionDef ( n -> v . Name . id , ( params ) ? params : CHECK ( arguments_ty , _PyPegen_empty_arguments ( p ) ) , b , NULL , a , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8549,7 +8795,7 @@ function_def_raw_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8560,16 +8806,19 @@ function_def_raw_rule(Parser *p) static Token* func_type_comment_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } Token* _res = NULL; int _mark = p->mark; { // NEWLINE TYPE_COMMENT &(NEWLINE INDENT) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> func_type_comment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE TYPE_COMMENT &(NEWLINE INDENT)")); @@ -8587,7 +8836,7 @@ func_type_comment_rule(Parser *p) _res = t; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8598,7 +8847,7 @@ func_type_comment_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_double_type_comments if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> func_type_comment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_double_type_comments")); @@ -8617,7 +8866,7 @@ func_type_comment_rule(Parser *p) } { // TYPE_COMMENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> func_type_comment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "TYPE_COMMENT")); @@ -8636,7 +8885,7 @@ func_type_comment_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8644,16 +8893,19 @@ func_type_comment_rule(Parser *p) static arguments_ty params_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arguments_ty _res = NULL; int _mark = p->mark; if (p->call_invalid_rules) { // invalid_parameters if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> params[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_parameters")); @@ -8672,7 +8924,7 @@ params_rule(Parser *p) } { // parameters if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> params[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "parameters")); @@ -8691,7 +8943,7 @@ params_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8704,16 +8956,19 @@ params_rule(Parser *p) static arguments_ty parameters_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arguments_ty _res = NULL; int _mark = p->mark; { // slash_no_default param_no_default* param_with_default* star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_no_default param_no_default* param_with_default* star_etc?")); @@ -8735,7 +8990,7 @@ parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , a , NULL , b , c , d ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8746,7 +9001,7 @@ parameters_rule(Parser *p) } { // slash_with_default param_with_default* star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default param_with_default* star_etc?")); @@ -8765,7 +9020,7 @@ parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , NULL , a , NULL , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8776,7 +9031,7 @@ parameters_rule(Parser *p) } { // param_no_default+ param_with_default* star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default+ param_with_default* star_etc?")); @@ -8795,7 +9050,7 @@ parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , NULL , NULL , a , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8806,7 +9061,7 @@ parameters_rule(Parser *p) } { // param_with_default+ star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default+ star_etc?")); @@ -8822,7 +9077,7 @@ parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , NULL , NULL , NULL , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8833,7 +9088,7 @@ parameters_rule(Parser *p) } { // star_etc if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_etc")); @@ -8846,7 +9101,7 @@ parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , NULL , NULL , NULL , NULL , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8857,7 +9112,7 @@ parameters_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8865,16 +9120,19 @@ parameters_rule(Parser *p) static asdl_arg_seq* slash_no_default_rule(Parser *p) { - D(p->level++); - if (p->error_indicator) { - D(p->level--); - return NULL; + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; + return NULL; } asdl_arg_seq* _res = NULL; int _mark = p->mark; { // param_no_default+ '/' ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slash_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default+ '/' ','")); @@ -8893,7 +9151,7 @@ slash_no_default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8904,7 +9162,7 @@ slash_no_default_rule(Parser *p) } { // param_no_default+ '/' &')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slash_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default+ '/' &')'")); @@ -8922,7 +9180,7 @@ slash_no_default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8933,7 +9191,7 @@ slash_no_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8943,16 +9201,19 @@ slash_no_default_rule(Parser *p) static SlashWithDefault* slash_with_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } SlashWithDefault* _res = NULL; int _mark = p->mark; { // param_no_default* param_with_default+ '/' ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slash_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default* param_with_default+ '/' ','")); @@ -8974,7 +9235,7 @@ slash_with_default_rule(Parser *p) _res = _PyPegen_slash_with_default ( p , ( asdl_arg_seq * ) a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8985,7 +9246,7 @@ slash_with_default_rule(Parser *p) } { // param_no_default* param_with_default+ '/' &')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slash_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default* param_with_default+ '/' &')'")); @@ -9006,7 +9267,7 @@ slash_with_default_rule(Parser *p) _res = _PyPegen_slash_with_default ( p , ( asdl_arg_seq * ) a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9017,7 +9278,7 @@ slash_with_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9029,16 +9290,19 @@ slash_with_default_rule(Parser *p) static StarEtc* star_etc_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } StarEtc* _res = NULL; int _mark = p->mark; { // '*' param_no_default param_maybe_default* kwds? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' param_no_default param_maybe_default* kwds?")); @@ -9060,7 +9324,7 @@ star_etc_rule(Parser *p) _res = _PyPegen_star_etc ( p , a , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9071,7 +9335,7 @@ star_etc_rule(Parser *p) } { // '*' ',' param_maybe_default+ kwds? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' ',' param_maybe_default+ kwds?")); @@ -9093,7 +9357,7 @@ star_etc_rule(Parser *p) _res = _PyPegen_star_etc ( p , NULL , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9104,7 +9368,7 @@ star_etc_rule(Parser *p) } { // kwds if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwds")); @@ -9117,7 +9381,7 @@ star_etc_rule(Parser *p) _res = _PyPegen_star_etc ( p , NULL , NULL , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9128,7 +9392,7 @@ star_etc_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_star_etc if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_star_etc")); @@ -9147,7 +9411,7 @@ star_etc_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9155,16 +9419,19 @@ star_etc_rule(Parser *p) static arg_ty kwds_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arg_ty _res = NULL; int _mark = p->mark; { // '**' param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwds[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' param_no_default")); @@ -9180,7 +9447,7 @@ kwds_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9191,7 +9458,7 @@ kwds_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9199,16 +9466,19 @@ kwds_rule(Parser *p) static arg_ty param_no_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arg_ty _res = NULL; int _mark = p->mark; { // param ',' TYPE_COMMENT? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param ',' TYPE_COMMENT?")); @@ -9227,7 +9497,7 @@ param_no_default_rule(Parser *p) _res = _PyPegen_add_type_comment_to_arg ( p , a , tc ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9238,7 +9508,7 @@ param_no_default_rule(Parser *p) } { // param TYPE_COMMENT? &')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param TYPE_COMMENT? &')'")); @@ -9256,7 +9526,7 @@ param_no_default_rule(Parser *p) _res = _PyPegen_add_type_comment_to_arg ( p , a , tc ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9267,7 +9537,7 @@ param_no_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9275,16 +9545,19 @@ param_no_default_rule(Parser *p) static NameDefaultPair* param_with_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } NameDefaultPair* _res = NULL; int _mark = p->mark; { // param default ',' TYPE_COMMENT? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param default ',' TYPE_COMMENT?")); @@ -9306,7 +9579,7 @@ param_with_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , tc ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9317,7 +9590,7 @@ param_with_default_rule(Parser *p) } { // param default TYPE_COMMENT? &')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param default TYPE_COMMENT? &')'")); @@ -9338,7 +9611,7 @@ param_with_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , tc ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9349,7 +9622,7 @@ param_with_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9359,16 +9632,19 @@ param_with_default_rule(Parser *p) static NameDefaultPair* param_maybe_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } NameDefaultPair* _res = NULL; int _mark = p->mark; { // param default? ',' TYPE_COMMENT? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param_maybe_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param default? ',' TYPE_COMMENT?")); @@ -9390,7 +9666,7 @@ param_maybe_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , tc ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9401,7 +9677,7 @@ param_maybe_default_rule(Parser *p) } { // param default? TYPE_COMMENT? &')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param_maybe_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param default? TYPE_COMMENT? &')'")); @@ -9422,7 +9698,7 @@ param_maybe_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , tc ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9433,7 +9709,7 @@ param_maybe_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9441,16 +9717,19 @@ param_maybe_default_rule(Parser *p) static arg_ty param_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arg_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -9459,7 +9738,7 @@ param_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME annotation? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME annotation?")); @@ -9474,7 +9753,7 @@ param_rule(Parser *p) D(fprintf(stderr, "%*c+ param[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME annotation?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9484,7 +9763,7 @@ param_rule(Parser *p) _res = _PyAST_arg ( a -> v . Name . id , b , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9495,7 +9774,7 @@ param_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9503,16 +9782,19 @@ param_rule(Parser *p) static expr_ty annotation_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // ':' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> annotation[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':' expression")); @@ -9528,7 +9810,7 @@ annotation_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9539,7 +9821,7 @@ annotation_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9547,16 +9829,19 @@ annotation_rule(Parser *p) static expr_ty default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // '=' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'=' expression")); @@ -9572,7 +9857,7 @@ default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9583,7 +9868,7 @@ default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9591,16 +9876,19 @@ default_rule(Parser *p) static asdl_expr_seq* decorators_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_expr_seq* _res = NULL; int _mark = p->mark; { // (('@' named_expression NEWLINE))+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> decorators[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(('@' named_expression NEWLINE))+")); @@ -9613,7 +9901,7 @@ decorators_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9624,7 +9912,7 @@ decorators_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9632,16 +9920,19 @@ decorators_rule(Parser *p) static stmt_ty class_def_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; { // decorators class_def_raw if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_def[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "decorators class_def_raw")); @@ -9657,7 +9948,7 @@ class_def_rule(Parser *p) _res = _PyPegen_class_def_decorators ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9668,7 +9959,7 @@ class_def_rule(Parser *p) } { // class_def_raw if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_def[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "class_def_raw")); @@ -9687,7 +9978,7 @@ class_def_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9695,16 +9986,19 @@ class_def_rule(Parser *p) static stmt_ty class_def_raw_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -9713,7 +10007,7 @@ class_def_raw_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_class_def_raw if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_class_def_raw")); @@ -9732,7 +10026,7 @@ class_def_raw_rule(Parser *p) } { // 'class' NAME ['(' arguments? ')'] &&':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class' NAME ['(' arguments? ')'] &&':' block")); @@ -9756,7 +10050,7 @@ class_def_raw_rule(Parser *p) D(fprintf(stderr, "%*c+ class_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'class' NAME ['(' arguments? ')'] &&':' block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9766,7 +10060,7 @@ class_def_raw_rule(Parser *p) _res = _PyAST_ClassDef ( a -> v . Name . id , ( b ) ? ( ( expr_ty ) b ) -> v . Call . args : NULL , ( b ) ? ( ( expr_ty ) b ) -> v . Call . keywords : NULL , c , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9777,7 +10071,7 @@ class_def_raw_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9785,20 +10079,23 @@ class_def_raw_rule(Parser *p) static asdl_stmt_seq* block_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_stmt_seq* _res = NULL; if (_PyPegen_is_memoized(p, block_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; { // NEWLINE INDENT statements DEDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT statements DEDENT")); @@ -9820,7 +10117,7 @@ block_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9831,7 +10128,7 @@ block_rule(Parser *p) } { // simple_stmts if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "simple_stmts")); @@ -9850,7 +10147,7 @@ block_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_block")); @@ -9870,7 +10167,7 @@ block_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, block_type, _res); - D(p->level--); + p->level--; return _res; } @@ -9881,16 +10178,19 @@ block_rule(Parser *p) static expr_ty star_expressions_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -9899,7 +10199,7 @@ star_expressions_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // star_expression ((',' star_expression))+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expression ((',' star_expression))+ ','?")); @@ -9918,7 +10218,7 @@ star_expressions_rule(Parser *p) D(fprintf(stderr, "%*c+ star_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expression ((',' star_expression))+ ','?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9928,7 +10228,7 @@ star_expressions_rule(Parser *p) _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq * , _PyPegen_seq_insert_in_front ( p , a , b ) ) , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9939,7 +10239,7 @@ star_expressions_rule(Parser *p) } { // star_expression ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expression ','")); @@ -9954,7 +10254,7 @@ star_expressions_rule(Parser *p) D(fprintf(stderr, "%*c+ star_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expression ','")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9964,7 +10264,7 @@ star_expressions_rule(Parser *p) _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq * , _PyPegen_singleton_seq ( p , a ) ) , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9975,7 +10275,7 @@ star_expressions_rule(Parser *p) } { // star_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expression")); @@ -9994,7 +10294,7 @@ star_expressions_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -10002,20 +10302,23 @@ star_expressions_rule(Parser *p) static expr_ty star_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, star_expression_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -10024,7 +10327,7 @@ star_expression_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '*' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' bitwise_or")); @@ -10039,7 +10342,7 @@ star_expression_rule(Parser *p) D(fprintf(stderr, "%*c+ star_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' bitwise_or")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10049,7 +10352,7 @@ star_expression_rule(Parser *p) _res = _PyAST_Starred ( a , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10060,7 +10363,7 @@ star_expression_rule(Parser *p) } { // expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression")); @@ -10080,7 +10383,7 @@ star_expression_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, star_expression_type, _res); - D(p->level--); + p->level--; return _res; } @@ -10088,16 +10391,19 @@ star_expression_rule(Parser *p) static asdl_expr_seq* star_named_expressions_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_expr_seq* _res = NULL; int _mark = p->mark; { // ','.star_named_expression+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_named_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.star_named_expression+ ','?")); @@ -10114,7 +10420,7 @@ star_named_expressions_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10125,7 +10431,7 @@ star_named_expressions_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -10133,16 +10439,19 @@ star_named_expressions_rule(Parser *p) static expr_ty star_named_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -10151,7 +10460,7 @@ star_named_expression_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '*' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' bitwise_or")); @@ -10166,7 +10475,7 @@ star_named_expression_rule(Parser *p) D(fprintf(stderr, "%*c+ star_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' bitwise_or")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10176,7 +10485,7 @@ star_named_expression_rule(Parser *p) _res = _PyAST_Starred ( a , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10187,7 +10496,7 @@ star_named_expression_rule(Parser *p) } { // named_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression")); @@ -10206,7 +10515,7 @@ star_named_expression_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -10214,16 +10523,19 @@ star_named_expression_rule(Parser *p) static expr_ty assignment_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -10232,7 +10544,7 @@ assignment_expression_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME ':=' ~ expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> assignment_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME ':=' ~ expression")); @@ -10253,7 +10565,7 @@ assignment_expression_rule(Parser *p) D(fprintf(stderr, "%*c+ assignment_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME ':=' ~ expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10263,7 +10575,7 @@ assignment_expression_rule(Parser *p) _res = _PyAST_NamedExpr ( CHECK ( expr_ty , _PyPegen_set_expr_context ( p , a , Store ) ) , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10272,13 +10584,13 @@ assignment_expression_rule(Parser *p) D(fprintf(stderr, "%*c%s assignment_expression[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME ':=' ~ expression")); if (_cut_var) { - D(p->level--); + p->level--; return NULL; } } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -10286,16 +10598,19 @@ assignment_expression_rule(Parser *p) static expr_ty named_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // assignment_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); @@ -10314,7 +10629,7 @@ named_expression_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_named_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_named_expression")); @@ -10333,7 +10648,7 @@ named_expression_rule(Parser *p) } { // expression !':=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); @@ -10354,7 +10669,7 @@ named_expression_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -10362,16 +10677,19 @@ named_expression_rule(Parser *p) static expr_ty annotated_rhs_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // yield_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> annotated_rhs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); @@ -10390,7 +10708,7 @@ annotated_rhs_rule(Parser *p) } { // star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> annotated_rhs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); @@ -10409,7 +10727,7 @@ annotated_rhs_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -10417,16 +10735,19 @@ annotated_rhs_rule(Parser *p) static expr_ty expressions_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -10435,7 +10756,7 @@ expressions_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // expression ((',' expression))+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ((',' expression))+ ','?")); @@ -10454,7 +10775,7 @@ expressions_rule(Parser *p) D(fprintf(stderr, "%*c+ expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ((',' expression))+ ','?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10464,7 +10785,7 @@ expressions_rule(Parser *p) _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq * , _PyPegen_seq_insert_in_front ( p , a , b ) ) , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10475,7 +10796,7 @@ expressions_rule(Parser *p) } { // expression ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ','")); @@ -10490,7 +10811,7 @@ expressions_rule(Parser *p) D(fprintf(stderr, "%*c+ expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ','")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10500,7 +10821,7 @@ expressions_rule(Parser *p) _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq * , _PyPegen_singleton_seq ( p , a ) ) , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10511,7 +10832,7 @@ expressions_rule(Parser *p) } { // expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression")); @@ -10530,7 +10851,7 @@ expressions_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -10543,20 +10864,23 @@ expressions_rule(Parser *p) static expr_ty expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, expression_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -10565,7 +10889,7 @@ expression_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_expression")); @@ -10584,7 +10908,7 @@ expression_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_legacy_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_legacy_expression")); @@ -10603,7 +10927,7 @@ expression_rule(Parser *p) } { // disjunction 'if' disjunction 'else' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction 'else' expression")); @@ -10627,7 +10951,7 @@ expression_rule(Parser *p) D(fprintf(stderr, "%*c+ expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction 'else' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10637,7 +10961,7 @@ expression_rule(Parser *p) _res = _PyAST_IfExp ( b , a , c , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10648,7 +10972,7 @@ expression_rule(Parser *p) } { // disjunction if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "disjunction")); @@ -10667,7 +10991,7 @@ expression_rule(Parser *p) } { // lambdef if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambdef")); @@ -10687,7 +11011,7 @@ expression_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, expression_type, _res); - D(p->level--); + p->level--; return _res; } @@ -10695,16 +11019,19 @@ expression_rule(Parser *p) static expr_ty lambdef_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -10713,7 +11040,7 @@ lambdef_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'lambda' lambda_params? ':' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambdef[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'lambda' lambda_params? ':' expression")); @@ -10734,7 +11061,7 @@ lambdef_rule(Parser *p) D(fprintf(stderr, "%*c+ lambdef[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'lambda' lambda_params? ':' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10744,7 +11071,7 @@ lambdef_rule(Parser *p) _res = _PyAST_Lambda ( ( a ) ? a : CHECK ( arguments_ty , _PyPegen_empty_arguments ( p ) ) , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10755,7 +11082,7 @@ lambdef_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -10763,16 +11090,19 @@ lambdef_rule(Parser *p) static arguments_ty lambda_params_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arguments_ty _res = NULL; int _mark = p->mark; if (p->call_invalid_rules) { // invalid_lambda_parameters if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_params[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_lambda_parameters")); @@ -10791,7 +11121,7 @@ lambda_params_rule(Parser *p) } { // lambda_parameters if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_params[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_parameters")); @@ -10810,7 +11140,7 @@ lambda_params_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -10823,16 +11153,19 @@ lambda_params_rule(Parser *p) static arguments_ty lambda_parameters_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arguments_ty _res = NULL; int _mark = p->mark; { // lambda_slash_no_default lambda_param_no_default* lambda_param_with_default* lambda_star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default lambda_param_no_default* lambda_param_with_default* lambda_star_etc?")); @@ -10854,7 +11187,7 @@ lambda_parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , a , NULL , b , c , d ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10865,7 +11198,7 @@ lambda_parameters_rule(Parser *p) } { // lambda_slash_with_default lambda_param_with_default* lambda_star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default lambda_param_with_default* lambda_star_etc?")); @@ -10884,7 +11217,7 @@ lambda_parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , NULL , a , NULL , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10895,7 +11228,7 @@ lambda_parameters_rule(Parser *p) } { // lambda_param_no_default+ lambda_param_with_default* lambda_star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default+ lambda_param_with_default* lambda_star_etc?")); @@ -10914,7 +11247,7 @@ lambda_parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , NULL , NULL , a , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10925,7 +11258,7 @@ lambda_parameters_rule(Parser *p) } { // lambda_param_with_default+ lambda_star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+ lambda_star_etc?")); @@ -10941,7 +11274,7 @@ lambda_parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , NULL , NULL , NULL , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10952,7 +11285,7 @@ lambda_parameters_rule(Parser *p) } { // lambda_star_etc if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_star_etc")); @@ -10965,7 +11298,7 @@ lambda_parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , NULL , NULL , NULL , NULL , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10976,7 +11309,7 @@ lambda_parameters_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -10986,16 +11319,19 @@ lambda_parameters_rule(Parser *p) static asdl_arg_seq* lambda_slash_no_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_arg_seq* _res = NULL; int _mark = p->mark; { // lambda_param_no_default+ '/' ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_slash_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default+ '/' ','")); @@ -11014,7 +11350,7 @@ lambda_slash_no_default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11025,7 +11361,7 @@ lambda_slash_no_default_rule(Parser *p) } { // lambda_param_no_default+ '/' &':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_slash_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default+ '/' &':'")); @@ -11043,7 +11379,7 @@ lambda_slash_no_default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11054,7 +11390,7 @@ lambda_slash_no_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11064,16 +11400,19 @@ lambda_slash_no_default_rule(Parser *p) static SlashWithDefault* lambda_slash_with_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } SlashWithDefault* _res = NULL; int _mark = p->mark; { // lambda_param_no_default* lambda_param_with_default+ '/' ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_slash_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* lambda_param_with_default+ '/' ','")); @@ -11095,7 +11434,7 @@ lambda_slash_with_default_rule(Parser *p) _res = _PyPegen_slash_with_default ( p , ( asdl_arg_seq * ) a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11106,7 +11445,7 @@ lambda_slash_with_default_rule(Parser *p) } { // lambda_param_no_default* lambda_param_with_default+ '/' &':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_slash_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* lambda_param_with_default+ '/' &':'")); @@ -11127,7 +11466,7 @@ lambda_slash_with_default_rule(Parser *p) _res = _PyPegen_slash_with_default ( p , ( asdl_arg_seq * ) a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11138,7 +11477,7 @@ lambda_slash_with_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11150,16 +11489,19 @@ lambda_slash_with_default_rule(Parser *p) static StarEtc* lambda_star_etc_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } StarEtc* _res = NULL; int _mark = p->mark; { // '*' lambda_param_no_default lambda_param_maybe_default* lambda_kwds? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' lambda_param_no_default lambda_param_maybe_default* lambda_kwds?")); @@ -11181,7 +11523,7 @@ lambda_star_etc_rule(Parser *p) _res = _PyPegen_star_etc ( p , a , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11192,7 +11534,7 @@ lambda_star_etc_rule(Parser *p) } { // '*' ',' lambda_param_maybe_default+ lambda_kwds? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' ',' lambda_param_maybe_default+ lambda_kwds?")); @@ -11214,7 +11556,7 @@ lambda_star_etc_rule(Parser *p) _res = _PyPegen_star_etc ( p , NULL , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11225,7 +11567,7 @@ lambda_star_etc_rule(Parser *p) } { // lambda_kwds if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_kwds")); @@ -11238,7 +11580,7 @@ lambda_star_etc_rule(Parser *p) _res = _PyPegen_star_etc ( p , NULL , NULL , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11249,7 +11591,7 @@ lambda_star_etc_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_lambda_star_etc if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_lambda_star_etc")); @@ -11268,7 +11610,7 @@ lambda_star_etc_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11276,16 +11618,19 @@ lambda_star_etc_rule(Parser *p) static arg_ty lambda_kwds_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arg_ty _res = NULL; int _mark = p->mark; { // '**' lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_kwds[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' lambda_param_no_default")); @@ -11301,7 +11646,7 @@ lambda_kwds_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11312,7 +11657,7 @@ lambda_kwds_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11320,16 +11665,19 @@ lambda_kwds_rule(Parser *p) static arg_ty lambda_param_no_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arg_ty _res = NULL; int _mark = p->mark; { // lambda_param ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param ','")); @@ -11345,7 +11693,7 @@ lambda_param_no_default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11356,7 +11704,7 @@ lambda_param_no_default_rule(Parser *p) } { // lambda_param &':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param &':'")); @@ -11371,7 +11719,7 @@ lambda_param_no_default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11382,7 +11730,7 @@ lambda_param_no_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11390,16 +11738,19 @@ lambda_param_no_default_rule(Parser *p) static NameDefaultPair* lambda_param_with_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } NameDefaultPair* _res = NULL; int _mark = p->mark; { // lambda_param default ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param default ','")); @@ -11418,7 +11769,7 @@ lambda_param_with_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , NULL ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11429,7 +11780,7 @@ lambda_param_with_default_rule(Parser *p) } { // lambda_param default &':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param default &':'")); @@ -11447,7 +11798,7 @@ lambda_param_with_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , NULL ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11458,7 +11809,7 @@ lambda_param_with_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11466,16 +11817,19 @@ lambda_param_with_default_rule(Parser *p) static NameDefaultPair* lambda_param_maybe_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } NameDefaultPair* _res = NULL; int _mark = p->mark; { // lambda_param default? ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param_maybe_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param default? ','")); @@ -11494,7 +11848,7 @@ lambda_param_maybe_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , NULL ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11505,7 +11859,7 @@ lambda_param_maybe_default_rule(Parser *p) } { // lambda_param default? &':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param_maybe_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param default? &':'")); @@ -11523,7 +11877,7 @@ lambda_param_maybe_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , NULL ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11534,7 +11888,7 @@ lambda_param_maybe_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11542,16 +11896,19 @@ lambda_param_maybe_default_rule(Parser *p) static arg_ty lambda_param_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arg_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -11560,7 +11917,7 @@ lambda_param_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); @@ -11572,7 +11929,7 @@ lambda_param_rule(Parser *p) D(fprintf(stderr, "%*c+ lambda_param[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -11582,7 +11939,7 @@ lambda_param_rule(Parser *p) _res = _PyAST_arg ( a -> v . Name . id , NULL , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11593,7 +11950,7 @@ lambda_param_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11601,20 +11958,23 @@ lambda_param_rule(Parser *p) static expr_ty disjunction_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, disjunction_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -11623,7 +11983,7 @@ disjunction_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // conjunction (('or' conjunction))+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> disjunction[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "conjunction (('or' conjunction))+")); @@ -11638,7 +11998,7 @@ disjunction_rule(Parser *p) D(fprintf(stderr, "%*c+ disjunction[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "conjunction (('or' conjunction))+")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -11648,7 +12008,7 @@ disjunction_rule(Parser *p) _res = _PyAST_BoolOp ( Or , CHECK ( asdl_expr_seq * , _PyPegen_seq_insert_in_front ( p , a , b ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11659,7 +12019,7 @@ disjunction_rule(Parser *p) } { // conjunction if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> disjunction[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "conjunction")); @@ -11679,7 +12039,7 @@ disjunction_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, disjunction_type, _res); - D(p->level--); + p->level--; return _res; } @@ -11687,20 +12047,23 @@ disjunction_rule(Parser *p) static expr_ty conjunction_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, conjunction_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -11709,7 +12072,7 @@ conjunction_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // inversion (('and' inversion))+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> conjunction[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "inversion (('and' inversion))+")); @@ -11724,7 +12087,7 @@ conjunction_rule(Parser *p) D(fprintf(stderr, "%*c+ conjunction[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "inversion (('and' inversion))+")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -11734,7 +12097,7 @@ conjunction_rule(Parser *p) _res = _PyAST_BoolOp ( And , CHECK ( asdl_expr_seq * , _PyPegen_seq_insert_in_front ( p , a , b ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11745,7 +12108,7 @@ conjunction_rule(Parser *p) } { // inversion if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> conjunction[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "inversion")); @@ -11765,7 +12128,7 @@ conjunction_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, conjunction_type, _res); - D(p->level--); + p->level--; return _res; } @@ -11773,20 +12136,23 @@ conjunction_rule(Parser *p) static expr_ty inversion_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, inversion_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -11795,7 +12161,7 @@ inversion_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'not' inversion if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> inversion[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'not' inversion")); @@ -11810,7 +12176,7 @@ inversion_rule(Parser *p) D(fprintf(stderr, "%*c+ inversion[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'not' inversion")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -11820,7 +12186,7 @@ inversion_rule(Parser *p) _res = _PyAST_UnaryOp ( Not , a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11831,7 +12197,7 @@ inversion_rule(Parser *p) } { // comparison if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> inversion[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "comparison")); @@ -11851,7 +12217,7 @@ inversion_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, inversion_type, _res); - D(p->level--); + p->level--; return _res; } @@ -11859,16 +12225,19 @@ inversion_rule(Parser *p) static expr_ty comparison_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -11877,7 +12246,7 @@ comparison_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // bitwise_or compare_op_bitwise_or_pair+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> comparison[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_or compare_op_bitwise_or_pair+")); @@ -11892,7 +12261,7 @@ comparison_rule(Parser *p) D(fprintf(stderr, "%*c+ comparison[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_or compare_op_bitwise_or_pair+")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -11902,7 +12271,7 @@ comparison_rule(Parser *p) _res = _PyAST_Compare ( a , CHECK ( asdl_int_seq * , _PyPegen_get_cmpops ( p , b ) ) , CHECK ( asdl_expr_seq * , _PyPegen_get_exprs ( p , b ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11913,7 +12282,7 @@ comparison_rule(Parser *p) } { // bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> comparison[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_or")); @@ -11932,7 +12301,7 @@ comparison_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11950,16 +12319,19 @@ comparison_rule(Parser *p) static CmpopExprPair* compare_op_bitwise_or_pair_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // eq_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "eq_bitwise_or")); @@ -11978,7 +12350,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // noteq_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "noteq_bitwise_or")); @@ -11997,7 +12369,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // lte_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lte_bitwise_or")); @@ -12016,7 +12388,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // lt_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lt_bitwise_or")); @@ -12035,7 +12407,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // gte_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "gte_bitwise_or")); @@ -12054,7 +12426,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // gt_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "gt_bitwise_or")); @@ -12073,7 +12445,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // notin_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "notin_bitwise_or")); @@ -12092,7 +12464,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // in_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "in_bitwise_or")); @@ -12111,7 +12483,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // isnot_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "isnot_bitwise_or")); @@ -12130,7 +12502,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // is_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "is_bitwise_or")); @@ -12149,7 +12521,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12157,16 +12529,19 @@ compare_op_bitwise_or_pair_rule(Parser *p) static CmpopExprPair* eq_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // '==' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> eq_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'==' bitwise_or")); @@ -12182,7 +12557,7 @@ eq_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , Eq , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12193,7 +12568,7 @@ eq_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12201,16 +12576,19 @@ eq_bitwise_or_rule(Parser *p) static CmpopExprPair* noteq_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // ('!=') bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> noteq_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('!=') bitwise_or")); @@ -12226,7 +12604,7 @@ noteq_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , NotEq , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12237,7 +12615,7 @@ noteq_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12245,16 +12623,19 @@ noteq_bitwise_or_rule(Parser *p) static CmpopExprPair* lte_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // '<=' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lte_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'<=' bitwise_or")); @@ -12270,7 +12651,7 @@ lte_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , LtE , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12281,7 +12662,7 @@ lte_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12289,16 +12670,19 @@ lte_bitwise_or_rule(Parser *p) static CmpopExprPair* lt_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // '<' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lt_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'<' bitwise_or")); @@ -12314,7 +12698,7 @@ lt_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , Lt , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12325,7 +12709,7 @@ lt_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12333,16 +12717,19 @@ lt_bitwise_or_rule(Parser *p) static CmpopExprPair* gte_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // '>=' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> gte_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'>=' bitwise_or")); @@ -12358,7 +12745,7 @@ gte_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , GtE , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12369,7 +12756,7 @@ gte_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12377,16 +12764,19 @@ gte_bitwise_or_rule(Parser *p) static CmpopExprPair* gt_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // '>' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> gt_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'>' bitwise_or")); @@ -12402,7 +12792,7 @@ gt_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , Gt , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12413,7 +12803,7 @@ gt_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12421,16 +12811,19 @@ gt_bitwise_or_rule(Parser *p) static CmpopExprPair* notin_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // 'not' 'in' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> notin_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'not' 'in' bitwise_or")); @@ -12449,7 +12842,7 @@ notin_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , NotIn , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12460,7 +12853,7 @@ notin_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12468,16 +12861,19 @@ notin_bitwise_or_rule(Parser *p) static CmpopExprPair* in_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // 'in' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> in_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'in' bitwise_or")); @@ -12493,7 +12889,7 @@ in_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , In , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12504,7 +12900,7 @@ in_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12512,16 +12908,19 @@ in_bitwise_or_rule(Parser *p) static CmpopExprPair* isnot_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // 'is' 'not' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> isnot_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'is' 'not' bitwise_or")); @@ -12540,7 +12939,7 @@ isnot_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , IsNot , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12551,7 +12950,7 @@ isnot_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12559,16 +12958,19 @@ isnot_bitwise_or_rule(Parser *p) static CmpopExprPair* is_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // 'is' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> is_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'is' bitwise_or")); @@ -12584,7 +12986,7 @@ is_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , Is , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12595,7 +12997,7 @@ is_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12605,10 +13007,13 @@ static expr_ty bitwise_or_raw(Parser *); static expr_ty bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, bitwise_or_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -12616,37 +13021,42 @@ bitwise_or_rule(Parser *p) while (1) { int tmpvar_2 = _PyPegen_update_memo(p, _mark, bitwise_or_type, _res); if (tmpvar_2) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; p->in_raw_rule++; void *_raw = bitwise_or_raw(p); p->in_raw_rule--; - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty bitwise_or_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -12655,7 +13065,7 @@ bitwise_or_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // bitwise_or '|' bitwise_xor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_or '|' bitwise_xor")); @@ -12673,7 +13083,7 @@ bitwise_or_raw(Parser *p) D(fprintf(stderr, "%*c+ bitwise_or[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_or '|' bitwise_xor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12683,7 +13093,7 @@ bitwise_or_raw(Parser *p) _res = _PyAST_BinOp ( a , BitOr , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12694,7 +13104,7 @@ bitwise_or_raw(Parser *p) } { // bitwise_xor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_xor")); @@ -12713,7 +13123,7 @@ bitwise_or_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12723,10 +13133,13 @@ static expr_ty bitwise_xor_raw(Parser *); static expr_ty bitwise_xor_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, bitwise_xor_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -12734,37 +13147,42 @@ bitwise_xor_rule(Parser *p) while (1) { int tmpvar_3 = _PyPegen_update_memo(p, _mark, bitwise_xor_type, _res); if (tmpvar_3) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; p->in_raw_rule++; void *_raw = bitwise_xor_raw(p); p->in_raw_rule--; - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty bitwise_xor_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -12773,7 +13191,7 @@ bitwise_xor_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // bitwise_xor '^' bitwise_and if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> bitwise_xor[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_xor '^' bitwise_and")); @@ -12791,7 +13209,7 @@ bitwise_xor_raw(Parser *p) D(fprintf(stderr, "%*c+ bitwise_xor[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_xor '^' bitwise_and")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12801,7 +13219,7 @@ bitwise_xor_raw(Parser *p) _res = _PyAST_BinOp ( a , BitXor , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12812,7 +13230,7 @@ bitwise_xor_raw(Parser *p) } { // bitwise_and if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> bitwise_xor[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_and")); @@ -12831,7 +13249,7 @@ bitwise_xor_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12841,10 +13259,13 @@ static expr_ty bitwise_and_raw(Parser *); static expr_ty bitwise_and_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, bitwise_and_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -12852,37 +13273,42 @@ bitwise_and_rule(Parser *p) while (1) { int tmpvar_4 = _PyPegen_update_memo(p, _mark, bitwise_and_type, _res); if (tmpvar_4) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; p->in_raw_rule++; void *_raw = bitwise_and_raw(p); p->in_raw_rule--; - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty bitwise_and_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -12891,7 +13317,7 @@ bitwise_and_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // bitwise_and '&' shift_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> bitwise_and[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_and '&' shift_expr")); @@ -12909,7 +13335,7 @@ bitwise_and_raw(Parser *p) D(fprintf(stderr, "%*c+ bitwise_and[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_and '&' shift_expr")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12919,7 +13345,7 @@ bitwise_and_raw(Parser *p) _res = _PyAST_BinOp ( a , BitAnd , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12930,7 +13356,7 @@ bitwise_and_raw(Parser *p) } { // shift_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> bitwise_and[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "shift_expr")); @@ -12949,7 +13375,7 @@ bitwise_and_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12959,10 +13385,13 @@ static expr_ty shift_expr_raw(Parser *); static expr_ty shift_expr_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, shift_expr_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -12970,37 +13399,42 @@ shift_expr_rule(Parser *p) while (1) { int tmpvar_5 = _PyPegen_update_memo(p, _mark, shift_expr_type, _res); if (tmpvar_5) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; p->in_raw_rule++; void *_raw = shift_expr_raw(p); p->in_raw_rule--; - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty shift_expr_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -13009,7 +13443,7 @@ shift_expr_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // shift_expr '<<' sum if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> shift_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "shift_expr '<<' sum")); @@ -13027,7 +13461,7 @@ shift_expr_raw(Parser *p) D(fprintf(stderr, "%*c+ shift_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "shift_expr '<<' sum")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13037,7 +13471,7 @@ shift_expr_raw(Parser *p) _res = _PyAST_BinOp ( a , LShift , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13048,7 +13482,7 @@ shift_expr_raw(Parser *p) } { // shift_expr '>>' sum if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> shift_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "shift_expr '>>' sum")); @@ -13066,7 +13500,7 @@ shift_expr_raw(Parser *p) D(fprintf(stderr, "%*c+ shift_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "shift_expr '>>' sum")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13076,7 +13510,7 @@ shift_expr_raw(Parser *p) _res = _PyAST_BinOp ( a , RShift , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13087,7 +13521,7 @@ shift_expr_raw(Parser *p) } { // sum if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> shift_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "sum")); @@ -13106,7 +13540,7 @@ shift_expr_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -13116,10 +13550,13 @@ static expr_ty sum_raw(Parser *); static expr_ty sum_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, sum_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -13127,37 +13564,42 @@ sum_rule(Parser *p) while (1) { int tmpvar_6 = _PyPegen_update_memo(p, _mark, sum_type, _res); if (tmpvar_6) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; p->in_raw_rule++; void *_raw = sum_raw(p); p->in_raw_rule--; - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty sum_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -13166,7 +13608,7 @@ sum_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // sum '+' term if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> sum[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "sum '+' term")); @@ -13184,7 +13626,7 @@ sum_raw(Parser *p) D(fprintf(stderr, "%*c+ sum[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "sum '+' term")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13194,7 +13636,7 @@ sum_raw(Parser *p) _res = _PyAST_BinOp ( a , Add , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13205,7 +13647,7 @@ sum_raw(Parser *p) } { // sum '-' term if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> sum[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "sum '-' term")); @@ -13223,7 +13665,7 @@ sum_raw(Parser *p) D(fprintf(stderr, "%*c+ sum[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "sum '-' term")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13233,7 +13675,7 @@ sum_raw(Parser *p) _res = _PyAST_BinOp ( a , Sub , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13244,7 +13686,7 @@ sum_raw(Parser *p) } { // term if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> sum[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "term")); @@ -13263,7 +13705,7 @@ sum_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -13279,10 +13721,13 @@ static expr_ty term_raw(Parser *); static expr_ty term_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, term_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -13290,37 +13735,42 @@ term_rule(Parser *p) while (1) { int tmpvar_7 = _PyPegen_update_memo(p, _mark, term_type, _res); if (tmpvar_7) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; p->in_raw_rule++; void *_raw = term_raw(p); p->in_raw_rule--; - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty term_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -13329,7 +13779,7 @@ term_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // term '*' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> term[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "term '*' factor")); @@ -13347,7 +13797,7 @@ term_raw(Parser *p) D(fprintf(stderr, "%*c+ term[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "term '*' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13357,7 +13807,7 @@ term_raw(Parser *p) _res = _PyAST_BinOp ( a , Mult , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13368,7 +13818,7 @@ term_raw(Parser *p) } { // term '/' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> term[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "term '/' factor")); @@ -13386,7 +13836,7 @@ term_raw(Parser *p) D(fprintf(stderr, "%*c+ term[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "term '/' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13396,7 +13846,7 @@ term_raw(Parser *p) _res = _PyAST_BinOp ( a , Div , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13407,7 +13857,7 @@ term_raw(Parser *p) } { // term '//' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> term[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "term '//' factor")); @@ -13425,7 +13875,7 @@ term_raw(Parser *p) D(fprintf(stderr, "%*c+ term[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "term '//' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13435,7 +13885,7 @@ term_raw(Parser *p) _res = _PyAST_BinOp ( a , FloorDiv , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13446,7 +13896,7 @@ term_raw(Parser *p) } { // term '%' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> term[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "term '%' factor")); @@ -13464,7 +13914,7 @@ term_raw(Parser *p) D(fprintf(stderr, "%*c+ term[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "term '%' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13474,7 +13924,7 @@ term_raw(Parser *p) _res = _PyAST_BinOp ( a , Mod , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13485,7 +13935,7 @@ term_raw(Parser *p) } { // term '@' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> term[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "term '@' factor")); @@ -13503,7 +13953,7 @@ term_raw(Parser *p) D(fprintf(stderr, "%*c+ term[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "term '@' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13513,7 +13963,7 @@ term_raw(Parser *p) _res = CHECK_VERSION ( expr_ty , 5 , "The '@' operator is" , _PyAST_BinOp ( a , MatMult , b , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13524,7 +13974,7 @@ term_raw(Parser *p) } { // factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> term[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "factor")); @@ -13543,7 +13993,7 @@ term_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -13551,20 +14001,23 @@ term_raw(Parser *p) static expr_ty factor_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, factor_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -13573,7 +14026,7 @@ factor_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '+' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> factor[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+' factor")); @@ -13588,7 +14041,7 @@ factor_rule(Parser *p) D(fprintf(stderr, "%*c+ factor[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13598,7 +14051,7 @@ factor_rule(Parser *p) _res = _PyAST_UnaryOp ( UAdd , a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13609,7 +14062,7 @@ factor_rule(Parser *p) } { // '-' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> factor[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-' factor")); @@ -13624,7 +14077,7 @@ factor_rule(Parser *p) D(fprintf(stderr, "%*c+ factor[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13634,7 +14087,7 @@ factor_rule(Parser *p) _res = _PyAST_UnaryOp ( USub , a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13645,7 +14098,7 @@ factor_rule(Parser *p) } { // '~' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> factor[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'~' factor")); @@ -13660,7 +14113,7 @@ factor_rule(Parser *p) D(fprintf(stderr, "%*c+ factor[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'~' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13670,7 +14123,7 @@ factor_rule(Parser *p) _res = _PyAST_UnaryOp ( Invert , a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13681,7 +14134,7 @@ factor_rule(Parser *p) } { // power if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> factor[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "power")); @@ -13701,7 +14154,7 @@ factor_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, factor_type, _res); - D(p->level--); + p->level--; return _res; } @@ -13709,16 +14162,19 @@ factor_rule(Parser *p) static expr_ty power_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -13727,7 +14183,7 @@ power_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // await_primary '**' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> power[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "await_primary '**' factor")); @@ -13745,7 +14201,7 @@ power_rule(Parser *p) D(fprintf(stderr, "%*c+ power[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "await_primary '**' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13755,7 +14211,7 @@ power_rule(Parser *p) _res = _PyAST_BinOp ( a , Pow , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13766,7 +14222,7 @@ power_rule(Parser *p) } { // await_primary if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> power[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "await_primary")); @@ -13785,7 +14241,7 @@ power_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -13793,20 +14249,23 @@ power_rule(Parser *p) static expr_ty await_primary_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, await_primary_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -13815,7 +14274,7 @@ await_primary_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // AWAIT primary if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> await_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "AWAIT primary")); @@ -13830,7 +14289,7 @@ await_primary_rule(Parser *p) D(fprintf(stderr, "%*c+ await_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "AWAIT primary")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13840,7 +14299,7 @@ await_primary_rule(Parser *p) _res = CHECK_VERSION ( expr_ty , 5 , "Await expressions are" , _PyAST_Await ( a , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13851,7 +14310,7 @@ await_primary_rule(Parser *p) } { // primary if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> await_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "primary")); @@ -13871,7 +14330,7 @@ await_primary_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, await_primary_type, _res); - D(p->level--); + p->level--; return _res; } @@ -13886,10 +14345,13 @@ static expr_ty primary_raw(Parser *); static expr_ty primary_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, primary_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -13897,37 +14359,42 @@ primary_rule(Parser *p) while (1) { int tmpvar_8 = _PyPegen_update_memo(p, _mark, primary_type, _res); if (tmpvar_8) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; p->in_raw_rule++; void *_raw = primary_raw(p); p->in_raw_rule--; - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty primary_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -13936,7 +14403,7 @@ primary_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // primary '.' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "primary '.' NAME")); @@ -13954,7 +14421,7 @@ primary_raw(Parser *p) D(fprintf(stderr, "%*c+ primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "primary '.' NAME")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13964,7 +14431,7 @@ primary_raw(Parser *p) _res = _PyAST_Attribute ( a , b -> v . Name . id , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13975,7 +14442,7 @@ primary_raw(Parser *p) } { // primary genexp if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "primary genexp")); @@ -13990,7 +14457,7 @@ primary_raw(Parser *p) D(fprintf(stderr, "%*c+ primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "primary genexp")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14000,7 +14467,7 @@ primary_raw(Parser *p) _res = _PyAST_Call ( a , CHECK ( asdl_expr_seq * , ( asdl_expr_seq * ) _PyPegen_singleton_seq ( p , b ) ) , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14011,7 +14478,7 @@ primary_raw(Parser *p) } { // primary '(' arguments? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "primary '(' arguments? ')'")); @@ -14032,7 +14499,7 @@ primary_raw(Parser *p) D(fprintf(stderr, "%*c+ primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "primary '(' arguments? ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14042,7 +14509,7 @@ primary_raw(Parser *p) _res = _PyAST_Call ( a , ( b ) ? ( ( expr_ty ) b ) -> v . Call . args : NULL , ( b ) ? ( ( expr_ty ) b ) -> v . Call . keywords : NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14053,7 +14520,7 @@ primary_raw(Parser *p) } { // primary '[' slices ']' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "primary '[' slices ']'")); @@ -14074,7 +14541,7 @@ primary_raw(Parser *p) D(fprintf(stderr, "%*c+ primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "primary '[' slices ']'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14084,7 +14551,7 @@ primary_raw(Parser *p) _res = _PyAST_Subscript ( a , b , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14095,7 +14562,7 @@ primary_raw(Parser *p) } { // atom if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "atom")); @@ -14114,7 +14581,7 @@ primary_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14122,16 +14589,19 @@ primary_raw(Parser *p) static expr_ty slices_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -14140,7 +14610,7 @@ slices_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // slice !',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slices[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slice !','")); @@ -14155,7 +14625,7 @@ slices_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14166,7 +14636,7 @@ slices_rule(Parser *p) } { // ','.slice+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slices[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.slice+ ','?")); @@ -14182,7 +14652,7 @@ slices_rule(Parser *p) D(fprintf(stderr, "%*c+ slices[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.slice+ ','?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14192,7 +14662,7 @@ slices_rule(Parser *p) _res = _PyAST_Tuple ( a , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14203,7 +14673,7 @@ slices_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14211,16 +14681,19 @@ slices_rule(Parser *p) static expr_ty slice_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -14229,7 +14702,7 @@ slice_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // expression? ':' expression? [':' expression?] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slice[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression? ':' expression? [':' expression?]")); @@ -14250,7 +14723,7 @@ slice_rule(Parser *p) D(fprintf(stderr, "%*c+ slice[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression? ':' expression? [':' expression?]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14260,7 +14733,7 @@ slice_rule(Parser *p) _res = _PyAST_Slice ( a , b , c , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14271,7 +14744,7 @@ slice_rule(Parser *p) } { // named_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slice[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression")); @@ -14284,7 +14757,7 @@ slice_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14295,7 +14768,7 @@ slice_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14313,16 +14786,19 @@ slice_rule(Parser *p) static expr_ty atom_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -14331,7 +14807,7 @@ atom_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); @@ -14350,7 +14826,7 @@ atom_rule(Parser *p) } { // 'True' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); @@ -14362,7 +14838,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14372,7 +14848,7 @@ atom_rule(Parser *p) _res = _PyAST_Constant ( Py_True , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14383,7 +14859,7 @@ atom_rule(Parser *p) } { // 'False' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); @@ -14395,7 +14871,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14405,7 +14881,7 @@ atom_rule(Parser *p) _res = _PyAST_Constant ( Py_False , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14416,7 +14892,7 @@ atom_rule(Parser *p) } { // 'None' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); @@ -14428,7 +14904,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14438,7 +14914,7 @@ atom_rule(Parser *p) _res = _PyAST_Constant ( Py_None , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14449,7 +14925,7 @@ atom_rule(Parser *p) } { // &STRING strings if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&STRING strings")); @@ -14470,7 +14946,7 @@ atom_rule(Parser *p) } { // NUMBER if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NUMBER")); @@ -14489,7 +14965,7 @@ atom_rule(Parser *p) } { // &'(' (tuple | group | genexp) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'(' (tuple | group | genexp)")); @@ -14510,7 +14986,7 @@ atom_rule(Parser *p) } { // &'[' (list | listcomp) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'[' (list | listcomp)")); @@ -14531,7 +15007,7 @@ atom_rule(Parser *p) } { // &'{' (dict | set | dictcomp | setcomp) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'{' (dict | set | dictcomp | setcomp)")); @@ -14552,7 +15028,7 @@ atom_rule(Parser *p) } { // '...' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); @@ -14564,7 +15040,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14574,7 +15050,7 @@ atom_rule(Parser *p) _res = _PyAST_Constant ( Py_Ellipsis , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14585,7 +15061,7 @@ atom_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14593,20 +15069,23 @@ atom_rule(Parser *p) static expr_ty strings_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, strings_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; { // STRING+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> strings[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "STRING+")); @@ -14619,7 +15098,7 @@ strings_rule(Parser *p) _res = _PyPegen_concatenate_strings ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14631,7 +15110,7 @@ strings_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, strings_type, _res); - D(p->level--); + p->level--; return _res; } @@ -14639,16 +15118,19 @@ strings_rule(Parser *p) static expr_ty list_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -14657,7 +15139,7 @@ list_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '[' star_named_expressions? ']' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> list[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'[' star_named_expressions? ']'")); @@ -14675,7 +15157,7 @@ list_rule(Parser *p) D(fprintf(stderr, "%*c+ list[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' star_named_expressions? ']'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14685,7 +15167,7 @@ list_rule(Parser *p) _res = _PyAST_List ( a , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14696,7 +15178,7 @@ list_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14704,16 +15186,19 @@ list_rule(Parser *p) static expr_ty listcomp_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -14722,7 +15207,7 @@ listcomp_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '[' named_expression for_if_clauses ']' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> listcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'[' named_expression for_if_clauses ']'")); @@ -14743,7 +15228,7 @@ listcomp_rule(Parser *p) D(fprintf(stderr, "%*c+ listcomp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' named_expression for_if_clauses ']'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14753,7 +15238,7 @@ listcomp_rule(Parser *p) _res = _PyAST_ListComp ( a , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14764,7 +15249,7 @@ listcomp_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_comprehension if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> listcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_comprehension")); @@ -14783,7 +15268,7 @@ listcomp_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14791,16 +15276,19 @@ listcomp_rule(Parser *p) static expr_ty tuple_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -14809,7 +15297,7 @@ tuple_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '(' [star_named_expression ',' star_named_expressions?] ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> tuple[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' [star_named_expression ',' star_named_expressions?] ')'")); @@ -14827,7 +15315,7 @@ tuple_rule(Parser *p) D(fprintf(stderr, "%*c+ tuple[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' [star_named_expression ',' star_named_expressions?] ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14837,7 +15325,7 @@ tuple_rule(Parser *p) _res = _PyAST_Tuple ( a , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14848,7 +15336,7 @@ tuple_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14856,16 +15344,19 @@ tuple_rule(Parser *p) static expr_ty group_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // '(' (yield_expr | named_expression) ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> group[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' (yield_expr | named_expression) ')'")); @@ -14884,7 +15375,7 @@ group_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14895,7 +15386,7 @@ group_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_group if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> group[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_group")); @@ -14914,7 +15405,7 @@ group_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14924,16 +15415,19 @@ group_rule(Parser *p) static expr_ty genexp_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -14942,7 +15436,7 @@ genexp_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '(' (assignment_expression | expression !':=') for_if_clauses ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> genexp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' (assignment_expression | expression !':=') for_if_clauses ')'")); @@ -14963,7 +15457,7 @@ genexp_rule(Parser *p) D(fprintf(stderr, "%*c+ genexp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' (assignment_expression | expression !':=') for_if_clauses ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14973,7 +15467,7 @@ genexp_rule(Parser *p) _res = _PyAST_GeneratorExp ( a , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14984,7 +15478,7 @@ genexp_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_comprehension if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> genexp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_comprehension")); @@ -15003,7 +15497,7 @@ genexp_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15011,16 +15505,19 @@ genexp_rule(Parser *p) static expr_ty set_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -15029,7 +15526,7 @@ set_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '{' star_named_expressions '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> set[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' star_named_expressions '}'")); @@ -15047,7 +15544,7 @@ set_rule(Parser *p) D(fprintf(stderr, "%*c+ set[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' star_named_expressions '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -15057,7 +15554,7 @@ set_rule(Parser *p) _res = _PyAST_Set ( a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15068,7 +15565,7 @@ set_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15076,16 +15573,19 @@ set_rule(Parser *p) static expr_ty setcomp_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -15094,7 +15594,7 @@ setcomp_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '{' named_expression for_if_clauses '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> setcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' named_expression for_if_clauses '}'")); @@ -15115,7 +15615,7 @@ setcomp_rule(Parser *p) D(fprintf(stderr, "%*c+ setcomp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' named_expression for_if_clauses '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -15125,7 +15625,7 @@ setcomp_rule(Parser *p) _res = _PyAST_SetComp ( a , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15136,7 +15636,7 @@ setcomp_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_comprehension if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> setcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_comprehension")); @@ -15155,7 +15655,7 @@ setcomp_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15163,16 +15663,19 @@ setcomp_rule(Parser *p) static expr_ty dict_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -15181,7 +15684,7 @@ dict_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '{' double_starred_kvpairs? '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dict[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' double_starred_kvpairs? '}'")); @@ -15199,7 +15702,7 @@ dict_rule(Parser *p) D(fprintf(stderr, "%*c+ dict[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' double_starred_kvpairs? '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -15209,7 +15712,7 @@ dict_rule(Parser *p) _res = _PyAST_Dict ( CHECK ( asdl_expr_seq * , _PyPegen_get_keys ( p , a ) ) , CHECK ( asdl_expr_seq * , _PyPegen_get_values ( p , a ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15220,7 +15723,7 @@ dict_rule(Parser *p) } { // '{' invalid_double_starred_kvpairs '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dict[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' invalid_double_starred_kvpairs '}'")); @@ -15245,7 +15748,7 @@ dict_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15253,16 +15756,19 @@ dict_rule(Parser *p) static expr_ty dictcomp_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -15271,7 +15777,7 @@ dictcomp_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '{' kvpair for_if_clauses '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dictcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' kvpair for_if_clauses '}'")); @@ -15292,7 +15798,7 @@ dictcomp_rule(Parser *p) D(fprintf(stderr, "%*c+ dictcomp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' kvpair for_if_clauses '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -15302,7 +15808,7 @@ dictcomp_rule(Parser *p) _res = _PyAST_DictComp ( a -> key , a -> value , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15313,7 +15819,7 @@ dictcomp_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_dict_comprehension if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dictcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_dict_comprehension")); @@ -15332,7 +15838,7 @@ dictcomp_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15340,16 +15846,19 @@ dictcomp_rule(Parser *p) static asdl_seq* double_starred_kvpairs_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // ','.double_starred_kvpair+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> double_starred_kvpairs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ','?")); @@ -15366,7 +15875,7 @@ double_starred_kvpairs_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15377,7 +15886,7 @@ double_starred_kvpairs_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15385,16 +15894,19 @@ double_starred_kvpairs_rule(Parser *p) static KeyValuePair* double_starred_kvpair_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } KeyValuePair* _res = NULL; int _mark = p->mark; { // '**' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> double_starred_kvpair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' bitwise_or")); @@ -15410,7 +15922,7 @@ double_starred_kvpair_rule(Parser *p) _res = _PyPegen_key_value_pair ( p , NULL , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15421,7 +15933,7 @@ double_starred_kvpair_rule(Parser *p) } { // kvpair if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> double_starred_kvpair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kvpair")); @@ -15440,7 +15952,7 @@ double_starred_kvpair_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15448,16 +15960,19 @@ double_starred_kvpair_rule(Parser *p) static KeyValuePair* kvpair_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } KeyValuePair* _res = NULL; int _mark = p->mark; { // expression ':' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kvpair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ':' expression")); @@ -15476,7 +15991,7 @@ kvpair_rule(Parser *p) _res = _PyPegen_key_value_pair ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15487,7 +16002,7 @@ kvpair_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15495,16 +16010,19 @@ kvpair_rule(Parser *p) static asdl_comprehension_seq* for_if_clauses_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_comprehension_seq* _res = NULL; int _mark = p->mark; { // for_if_clause+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_if_clauses[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "for_if_clause+")); @@ -15517,7 +16035,7 @@ for_if_clauses_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15528,7 +16046,7 @@ for_if_clauses_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15539,16 +16057,19 @@ for_if_clauses_rule(Parser *p) static comprehension_ty for_if_clause_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } comprehension_ty _res = NULL; int _mark = p->mark; { // ASYNC 'for' star_targets 'in' ~ disjunction (('if' disjunction))* if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_if_clause[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC 'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); @@ -15579,7 +16100,7 @@ for_if_clause_rule(Parser *p) _res = CHECK_VERSION ( comprehension_ty , 6 , "Async comprehensions are" , _PyAST_comprehension ( a , b , c , 1 , p -> arena ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15588,13 +16109,13 @@ for_if_clause_rule(Parser *p) D(fprintf(stderr, "%*c%s for_if_clause[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "ASYNC 'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); if (_cut_var) { - D(p->level--); + p->level--; return NULL; } } { // 'for' star_targets 'in' ~ disjunction (('if' disjunction))* if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_if_clause[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); @@ -15622,7 +16143,7 @@ for_if_clause_rule(Parser *p) _res = _PyAST_comprehension ( a , b , c , 0 , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15631,13 +16152,13 @@ for_if_clause_rule(Parser *p) D(fprintf(stderr, "%*c%s for_if_clause[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); if (_cut_var) { - D(p->level--); + p->level--; return NULL; } } if (p->call_invalid_rules) { // invalid_for_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_if_clause[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_for_target")); @@ -15656,7 +16177,7 @@ for_if_clause_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15664,16 +16185,19 @@ for_if_clause_rule(Parser *p) static expr_ty yield_expr_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -15682,7 +16206,7 @@ yield_expr_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'yield' 'from' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> yield_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'yield' 'from' expression")); @@ -15700,7 +16224,7 @@ yield_expr_rule(Parser *p) D(fprintf(stderr, "%*c+ yield_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'yield' 'from' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -15710,7 +16234,7 @@ yield_expr_rule(Parser *p) _res = _PyAST_YieldFrom ( a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15721,7 +16245,7 @@ yield_expr_rule(Parser *p) } { // 'yield' star_expressions? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> yield_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'yield' star_expressions?")); @@ -15736,7 +16260,7 @@ yield_expr_rule(Parser *p) D(fprintf(stderr, "%*c+ yield_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'yield' star_expressions?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -15746,7 +16270,7 @@ yield_expr_rule(Parser *p) _res = _PyAST_Yield ( a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15757,7 +16281,7 @@ yield_expr_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15765,20 +16289,23 @@ yield_expr_rule(Parser *p) static expr_ty arguments_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, arguments_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; { // args ','? &')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ','? &')'")); @@ -15797,7 +16324,7 @@ arguments_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15808,7 +16335,7 @@ arguments_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_arguments if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_arguments")); @@ -15828,7 +16355,7 @@ arguments_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, arguments_type, _res); - D(p->level--); + p->level--; return _res; } @@ -15838,16 +16365,19 @@ arguments_rule(Parser *p) static expr_ty args_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -15856,7 +16386,7 @@ args_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ [',' kwargs] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> args[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ [',' kwargs]")); @@ -15871,7 +16401,7 @@ args_rule(Parser *p) D(fprintf(stderr, "%*c+ args[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ [',' kwargs]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -15881,7 +16411,7 @@ args_rule(Parser *p) _res = _PyPegen_collect_call_seqs ( p , a , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15892,7 +16422,7 @@ args_rule(Parser *p) } { // kwargs if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> args[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwargs")); @@ -15904,7 +16434,7 @@ args_rule(Parser *p) D(fprintf(stderr, "%*c+ args[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwargs")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -15914,7 +16444,7 @@ args_rule(Parser *p) _res = _PyAST_Call ( _PyPegen_dummy_name ( p ) , CHECK_NULL_ALLOWED ( asdl_expr_seq * , _PyPegen_seq_extract_starred_exprs ( p , a ) ) , CHECK_NULL_ALLOWED ( asdl_keyword_seq * , _PyPegen_seq_delete_starred_exprs ( p , a ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15925,7 +16455,7 @@ args_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15936,16 +16466,19 @@ args_rule(Parser *p) static asdl_seq* kwargs_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // ','.kwarg_or_starred+ ',' ','.kwarg_or_double_starred+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwargs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+ ',' ','.kwarg_or_double_starred+")); @@ -15964,7 +16497,7 @@ kwargs_rule(Parser *p) _res = _PyPegen_join_sequences ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15975,7 +16508,7 @@ kwargs_rule(Parser *p) } { // ','.kwarg_or_starred+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwargs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+")); @@ -15994,7 +16527,7 @@ kwargs_rule(Parser *p) } { // ','.kwarg_or_double_starred+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwargs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_double_starred+")); @@ -16013,7 +16546,7 @@ kwargs_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16021,16 +16554,19 @@ kwargs_rule(Parser *p) static expr_ty starred_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -16039,7 +16575,7 @@ starred_expression_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '*' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> starred_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' expression")); @@ -16054,7 +16590,7 @@ starred_expression_rule(Parser *p) D(fprintf(stderr, "%*c+ starred_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16064,7 +16600,7 @@ starred_expression_rule(Parser *p) _res = _PyAST_Starred ( a , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16075,7 +16611,7 @@ starred_expression_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16083,16 +16619,19 @@ starred_expression_rule(Parser *p) static KeywordOrStarred* kwarg_or_starred_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } KeywordOrStarred* _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -16101,7 +16640,7 @@ kwarg_or_starred_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_kwarg if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwarg_or_starred[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_kwarg")); @@ -16120,7 +16659,7 @@ kwarg_or_starred_rule(Parser *p) } { // NAME '=' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwarg_or_starred[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '=' expression")); @@ -16138,7 +16677,7 @@ kwarg_or_starred_rule(Parser *p) D(fprintf(stderr, "%*c+ kwarg_or_starred[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16148,7 +16687,7 @@ kwarg_or_starred_rule(Parser *p) _res = _PyPegen_keyword_or_starred ( p , CHECK ( keyword_ty , _PyAST_keyword ( a -> v . Name . id , b , EXTRA ) ) , 1 ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16159,7 +16698,7 @@ kwarg_or_starred_rule(Parser *p) } { // starred_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwarg_or_starred[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); @@ -16172,7 +16711,7 @@ kwarg_or_starred_rule(Parser *p) _res = _PyPegen_keyword_or_starred ( p , a , 0 ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16183,7 +16722,7 @@ kwarg_or_starred_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16191,16 +16730,19 @@ kwarg_or_starred_rule(Parser *p) static KeywordOrStarred* kwarg_or_double_starred_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } KeywordOrStarred* _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -16209,7 +16751,7 @@ kwarg_or_double_starred_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_kwarg if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwarg_or_double_starred[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_kwarg")); @@ -16228,7 +16770,7 @@ kwarg_or_double_starred_rule(Parser *p) } { // NAME '=' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwarg_or_double_starred[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '=' expression")); @@ -16246,7 +16788,7 @@ kwarg_or_double_starred_rule(Parser *p) D(fprintf(stderr, "%*c+ kwarg_or_double_starred[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16256,7 +16798,7 @@ kwarg_or_double_starred_rule(Parser *p) _res = _PyPegen_keyword_or_starred ( p , CHECK ( keyword_ty , _PyAST_keyword ( a -> v . Name . id , b , EXTRA ) ) , 1 ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16267,7 +16809,7 @@ kwarg_or_double_starred_rule(Parser *p) } { // '**' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwarg_or_double_starred[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' expression")); @@ -16282,7 +16824,7 @@ kwarg_or_double_starred_rule(Parser *p) D(fprintf(stderr, "%*c+ kwarg_or_double_starred[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16292,7 +16834,7 @@ kwarg_or_double_starred_rule(Parser *p) _res = _PyPegen_keyword_or_starred ( p , CHECK ( keyword_ty , _PyAST_keyword ( NULL , a , EXTRA ) ) , 1 ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16303,7 +16845,7 @@ kwarg_or_double_starred_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16311,16 +16853,19 @@ kwarg_or_double_starred_rule(Parser *p) static expr_ty star_targets_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -16329,7 +16874,7 @@ star_targets_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // star_target !',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target !','")); @@ -16344,7 +16889,7 @@ star_targets_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16355,7 +16900,7 @@ star_targets_rule(Parser *p) } { // star_target ((',' star_target))* ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target ((',' star_target))* ','?")); @@ -16374,7 +16919,7 @@ star_targets_rule(Parser *p) D(fprintf(stderr, "%*c+ star_targets[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target ((',' star_target))* ','?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16384,7 +16929,7 @@ star_targets_rule(Parser *p) _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq * , _PyPegen_seq_insert_in_front ( p , a , b ) ) , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16395,7 +16940,7 @@ star_targets_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16403,16 +16948,19 @@ star_targets_rule(Parser *p) static asdl_expr_seq* star_targets_list_seq_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_expr_seq* _res = NULL; int _mark = p->mark; { // ','.star_target+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_targets_list_seq[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.star_target+ ','?")); @@ -16429,7 +16977,7 @@ star_targets_list_seq_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16440,7 +16988,7 @@ star_targets_list_seq_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16448,16 +16996,19 @@ star_targets_list_seq_rule(Parser *p) static asdl_expr_seq* star_targets_tuple_seq_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_expr_seq* _res = NULL; int _mark = p->mark; { // star_target ((',' star_target))+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_targets_tuple_seq[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target ((',' star_target))+ ','?")); @@ -16477,7 +17028,7 @@ star_targets_tuple_seq_rule(Parser *p) _res = ( asdl_expr_seq * ) _PyPegen_seq_insert_in_front ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16488,7 +17039,7 @@ star_targets_tuple_seq_rule(Parser *p) } { // star_target ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_targets_tuple_seq[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target ','")); @@ -16504,7 +17055,7 @@ star_targets_tuple_seq_rule(Parser *p) _res = ( asdl_expr_seq * ) _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16515,7 +17066,7 @@ star_targets_tuple_seq_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16523,20 +17074,23 @@ star_targets_tuple_seq_rule(Parser *p) static expr_ty star_target_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, star_target_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -16545,7 +17099,7 @@ star_target_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '*' (!'*' star_target) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (!'*' star_target)")); @@ -16560,7 +17114,7 @@ star_target_rule(Parser *p) D(fprintf(stderr, "%*c+ star_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (!'*' star_target)")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16570,7 +17124,7 @@ star_target_rule(Parser *p) _res = _PyAST_Starred ( CHECK ( expr_ty , _PyPegen_set_expr_context ( p , a , Store ) ) , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16581,7 +17135,7 @@ star_target_rule(Parser *p) } { // target_with_star_atom if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "target_with_star_atom")); @@ -16601,7 +17155,7 @@ star_target_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, star_target_type, _res); - D(p->level--); + p->level--; return _res; } @@ -16612,20 +17166,23 @@ star_target_rule(Parser *p) static expr_ty target_with_star_atom_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, target_with_star_atom_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -16634,7 +17191,7 @@ target_with_star_atom_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // t_primary '.' NAME !t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> target_with_star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); @@ -16654,7 +17211,7 @@ target_with_star_atom_rule(Parser *p) D(fprintf(stderr, "%*c+ target_with_star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16664,7 +17221,7 @@ target_with_star_atom_rule(Parser *p) _res = _PyAST_Attribute ( a , b -> v . Name . id , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16675,7 +17232,7 @@ target_with_star_atom_rule(Parser *p) } { // t_primary '[' slices ']' !t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> target_with_star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); @@ -16698,7 +17255,7 @@ target_with_star_atom_rule(Parser *p) D(fprintf(stderr, "%*c+ target_with_star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16708,7 +17265,7 @@ target_with_star_atom_rule(Parser *p) _res = _PyAST_Subscript ( a , b , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16719,7 +17276,7 @@ target_with_star_atom_rule(Parser *p) } { // star_atom if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> target_with_star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_atom")); @@ -16739,7 +17296,7 @@ target_with_star_atom_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, target_with_star_atom_type, _res); - D(p->level--); + p->level--; return _res; } @@ -16751,16 +17308,19 @@ target_with_star_atom_rule(Parser *p) static expr_ty star_atom_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -16769,7 +17329,7 @@ star_atom_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); @@ -16782,7 +17342,7 @@ star_atom_rule(Parser *p) _res = _PyPegen_set_expr_context ( p , a , Store ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16793,7 +17353,7 @@ star_atom_rule(Parser *p) } { // '(' target_with_star_atom ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' target_with_star_atom ')'")); @@ -16812,7 +17372,7 @@ star_atom_rule(Parser *p) _res = _PyPegen_set_expr_context ( p , a , Store ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16823,7 +17383,7 @@ star_atom_rule(Parser *p) } { // '(' star_targets_tuple_seq? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' star_targets_tuple_seq? ')'")); @@ -16841,7 +17401,7 @@ star_atom_rule(Parser *p) D(fprintf(stderr, "%*c+ star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' star_targets_tuple_seq? ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16851,7 +17411,7 @@ star_atom_rule(Parser *p) _res = _PyAST_Tuple ( a , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16862,7 +17422,7 @@ star_atom_rule(Parser *p) } { // '[' star_targets_list_seq? ']' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'[' star_targets_list_seq? ']'")); @@ -16880,7 +17440,7 @@ star_atom_rule(Parser *p) D(fprintf(stderr, "%*c+ star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' star_targets_list_seq? ']'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16890,7 +17450,7 @@ star_atom_rule(Parser *p) _res = _PyAST_List ( a , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16901,7 +17461,7 @@ star_atom_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16909,16 +17469,19 @@ star_atom_rule(Parser *p) static expr_ty single_target_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // single_subscript_attribute_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> single_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "single_subscript_attribute_target")); @@ -16937,7 +17500,7 @@ single_target_rule(Parser *p) } { // NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> single_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); @@ -16950,7 +17513,7 @@ single_target_rule(Parser *p) _res = _PyPegen_set_expr_context ( p , a , Store ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16961,7 +17524,7 @@ single_target_rule(Parser *p) } { // '(' single_target ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> single_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' single_target ')'")); @@ -16980,7 +17543,7 @@ single_target_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16991,7 +17554,7 @@ single_target_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -17001,16 +17564,19 @@ single_target_rule(Parser *p) static expr_ty single_subscript_attribute_target_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -17019,7 +17585,7 @@ single_subscript_attribute_target_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // t_primary '.' NAME !t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> single_subscript_attribute_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); @@ -17039,7 +17605,7 @@ single_subscript_attribute_target_rule(Parser *p) D(fprintf(stderr, "%*c+ single_subscript_attribute_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17049,7 +17615,7 @@ single_subscript_attribute_target_rule(Parser *p) _res = _PyAST_Attribute ( a , b -> v . Name . id , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17060,7 +17626,7 @@ single_subscript_attribute_target_rule(Parser *p) } { // t_primary '[' slices ']' !t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> single_subscript_attribute_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); @@ -17083,7 +17649,7 @@ single_subscript_attribute_target_rule(Parser *p) D(fprintf(stderr, "%*c+ single_subscript_attribute_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17093,7 +17659,7 @@ single_subscript_attribute_target_rule(Parser *p) _res = _PyAST_Subscript ( a , b , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17104,7 +17670,7 @@ single_subscript_attribute_target_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -17112,16 +17678,19 @@ single_subscript_attribute_target_rule(Parser *p) static asdl_expr_seq* del_targets_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_expr_seq* _res = NULL; int _mark = p->mark; { // ','.del_target+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.del_target+ ','?")); @@ -17138,7 +17707,7 @@ del_targets_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17149,7 +17718,7 @@ del_targets_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -17160,20 +17729,23 @@ del_targets_rule(Parser *p) static expr_ty del_target_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, del_target_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -17182,7 +17754,7 @@ del_target_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // t_primary '.' NAME !t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); @@ -17202,7 +17774,7 @@ del_target_rule(Parser *p) D(fprintf(stderr, "%*c+ del_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17212,7 +17784,7 @@ del_target_rule(Parser *p) _res = _PyAST_Attribute ( a , b -> v . Name . id , Del , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17223,7 +17795,7 @@ del_target_rule(Parser *p) } { // t_primary '[' slices ']' !t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); @@ -17246,7 +17818,7 @@ del_target_rule(Parser *p) D(fprintf(stderr, "%*c+ del_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17256,7 +17828,7 @@ del_target_rule(Parser *p) _res = _PyAST_Subscript ( a , b , Del , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17267,7 +17839,7 @@ del_target_rule(Parser *p) } { // del_t_atom if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "del_t_atom")); @@ -17287,7 +17859,7 @@ del_target_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, del_target_type, _res); - D(p->level--); + p->level--; return _res; } @@ -17295,16 +17867,19 @@ del_target_rule(Parser *p) static expr_ty del_t_atom_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -17313,7 +17888,7 @@ del_t_atom_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_t_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); @@ -17326,7 +17901,7 @@ del_t_atom_rule(Parser *p) _res = _PyPegen_set_expr_context ( p , a , Del ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17337,7 +17912,7 @@ del_t_atom_rule(Parser *p) } { // '(' del_target ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_t_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' del_target ')'")); @@ -17356,7 +17931,7 @@ del_t_atom_rule(Parser *p) _res = _PyPegen_set_expr_context ( p , a , Del ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17367,7 +17942,7 @@ del_t_atom_rule(Parser *p) } { // '(' del_targets? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_t_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' del_targets? ')'")); @@ -17385,7 +17960,7 @@ del_t_atom_rule(Parser *p) D(fprintf(stderr, "%*c+ del_t_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' del_targets? ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17395,7 +17970,7 @@ del_t_atom_rule(Parser *p) _res = _PyAST_Tuple ( a , Del , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17406,7 +17981,7 @@ del_t_atom_rule(Parser *p) } { // '[' del_targets? ']' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_t_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'[' del_targets? ']'")); @@ -17424,7 +17999,7 @@ del_t_atom_rule(Parser *p) D(fprintf(stderr, "%*c+ del_t_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' del_targets? ']'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17434,7 +18009,7 @@ del_t_atom_rule(Parser *p) _res = _PyAST_List ( a , Del , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17445,7 +18020,7 @@ del_t_atom_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -17460,10 +18035,13 @@ static expr_ty t_primary_raw(Parser *); static expr_ty t_primary_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, t_primary_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -17471,37 +18049,42 @@ t_primary_rule(Parser *p) while (1) { int tmpvar_9 = _PyPegen_update_memo(p, _mark, t_primary_type, _res); if (tmpvar_9) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; p->in_raw_rule++; void *_raw = t_primary_raw(p); p->in_raw_rule--; - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty t_primary_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -17510,7 +18093,7 @@ t_primary_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // t_primary '.' NAME &t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME &t_lookahead")); @@ -17530,7 +18113,7 @@ t_primary_raw(Parser *p) D(fprintf(stderr, "%*c+ t_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME &t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17540,7 +18123,7 @@ t_primary_raw(Parser *p) _res = _PyAST_Attribute ( a , b -> v . Name . id , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17551,7 +18134,7 @@ t_primary_raw(Parser *p) } { // t_primary '[' slices ']' &t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' &t_lookahead")); @@ -17574,7 +18157,7 @@ t_primary_raw(Parser *p) D(fprintf(stderr, "%*c+ t_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' &t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17584,7 +18167,7 @@ t_primary_raw(Parser *p) _res = _PyAST_Subscript ( a , b , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17595,7 +18178,7 @@ t_primary_raw(Parser *p) } { // t_primary genexp &t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary genexp &t_lookahead")); @@ -17612,7 +18195,7 @@ t_primary_raw(Parser *p) D(fprintf(stderr, "%*c+ t_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary genexp &t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17622,7 +18205,7 @@ t_primary_raw(Parser *p) _res = _PyAST_Call ( a , CHECK ( asdl_expr_seq * , ( asdl_expr_seq * ) _PyPegen_singleton_seq ( p , b ) ) , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17633,7 +18216,7 @@ t_primary_raw(Parser *p) } { // t_primary '(' arguments? ')' &t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '(' arguments? ')' &t_lookahead")); @@ -17656,7 +18239,7 @@ t_primary_raw(Parser *p) D(fprintf(stderr, "%*c+ t_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '(' arguments? ')' &t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17666,7 +18249,7 @@ t_primary_raw(Parser *p) _res = _PyAST_Call ( a , ( b ) ? ( ( expr_ty ) b ) -> v . Call . args : NULL , ( b ) ? ( ( expr_ty ) b ) -> v . Call . keywords : NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17677,7 +18260,7 @@ t_primary_raw(Parser *p) } { // atom &t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "atom &t_lookahead")); @@ -17692,7 +18275,7 @@ t_primary_raw(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17703,7 +18286,7 @@ t_primary_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -17711,16 +18294,19 @@ t_primary_raw(Parser *p) static void * t_lookahead_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '(' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_lookahead[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); @@ -17739,7 +18325,7 @@ t_lookahead_rule(Parser *p) } { // '[' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_lookahead[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); @@ -17758,7 +18344,7 @@ t_lookahead_rule(Parser *p) } { // '.' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_lookahead[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); @@ -17777,7 +18363,7 @@ t_lookahead_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -17791,16 +18377,19 @@ t_lookahead_rule(Parser *p) static void * invalid_arguments_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // args ',' '*' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ',' '*'")); @@ -17819,7 +18408,7 @@ invalid_arguments_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "iterable argument unpacking follows keyword argument unpacking" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17830,7 +18419,7 @@ invalid_arguments_rule(Parser *p) } { // expression for_if_clauses ',' [args | expression for_if_clauses] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses ',' [args | expression for_if_clauses]")); @@ -17853,7 +18442,7 @@ invalid_arguments_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , PyPegen_last_item ( b , comprehension_ty ) -> target , "Generator expression must be parenthesized" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17864,7 +18453,7 @@ invalid_arguments_rule(Parser *p) } { // NAME '=' expression for_if_clauses if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '=' expression for_if_clauses")); @@ -17886,7 +18475,7 @@ invalid_arguments_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Maybe you meant '==' or ':=' instead of '='?" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17897,7 +18486,7 @@ invalid_arguments_rule(Parser *p) } { // args for_if_clauses if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args for_if_clauses")); @@ -17913,7 +18502,7 @@ invalid_arguments_rule(Parser *p) _res = _PyPegen_nonparen_genexp_in_call ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17924,7 +18513,7 @@ invalid_arguments_rule(Parser *p) } { // args ',' expression for_if_clauses if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ',' expression for_if_clauses")); @@ -17946,7 +18535,7 @@ invalid_arguments_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , asdl_seq_GET ( b , b -> size - 1 ) -> target , "Generator expression must be parenthesized" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17957,7 +18546,7 @@ invalid_arguments_rule(Parser *p) } { // args ',' args if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ',' args")); @@ -17976,7 +18565,7 @@ invalid_arguments_rule(Parser *p) _res = _PyPegen_arguments_parsing_error ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17987,7 +18576,7 @@ invalid_arguments_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -17998,16 +18587,19 @@ invalid_arguments_rule(Parser *p) static void * invalid_kwarg_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ('True' | 'False' | 'None') '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_kwarg[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('True' | 'False' | 'None') '='")); @@ -18023,7 +18615,7 @@ invalid_kwarg_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot assign to %s" , PyBytes_AS_STRING ( a -> bytes ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18034,7 +18626,7 @@ invalid_kwarg_rule(Parser *p) } { // NAME '=' expression for_if_clauses if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_kwarg[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '=' expression for_if_clauses")); @@ -18056,7 +18648,7 @@ invalid_kwarg_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Maybe you meant '==' or ':=' instead of '='?" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18067,7 +18659,7 @@ invalid_kwarg_rule(Parser *p) } { // !(NAME '=') expression '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_kwarg[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!(NAME '=') expression '='")); @@ -18085,7 +18677,7 @@ invalid_kwarg_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "expression cannot contain assignment, perhaps you meant \"==\"?" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18096,7 +18688,7 @@ invalid_kwarg_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18107,16 +18699,19 @@ invalid_kwarg_rule(Parser *p) static expr_ty expression_without_invalid_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -18125,7 +18720,7 @@ expression_without_invalid_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // disjunction 'if' disjunction 'else' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expression_without_invalid[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction 'else' expression")); @@ -18149,7 +18744,7 @@ expression_without_invalid_rule(Parser *p) D(fprintf(stderr, "%*c+ expression_without_invalid[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction 'else' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -18159,7 +18754,7 @@ expression_without_invalid_rule(Parser *p) _res = _PyAST_IfExp ( b , a , c , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18170,7 +18765,7 @@ expression_without_invalid_rule(Parser *p) } { // disjunction if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expression_without_invalid[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "disjunction")); @@ -18189,7 +18784,7 @@ expression_without_invalid_rule(Parser *p) } { // lambdef if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expression_without_invalid[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambdef")); @@ -18208,7 +18803,7 @@ expression_without_invalid_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18216,16 +18811,19 @@ expression_without_invalid_rule(Parser *p) static void * invalid_legacy_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // NAME !'(' star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_legacy_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME !'(' star_expressions")); @@ -18243,7 +18841,7 @@ invalid_legacy_expression_rule(Parser *p) _res = _PyPegen_check_legacy_stmt ( p , a ) ? RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "Missing parentheses in call to '%U'. Did you mean %U(...)?" , a -> v . Name . id , a -> v . Name . id ) : NULL; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18254,7 +18852,7 @@ invalid_legacy_expression_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18264,16 +18862,19 @@ invalid_legacy_expression_rule(Parser *p) static void * invalid_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // !(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid")); @@ -18291,7 +18892,7 @@ invalid_expression_rule(Parser *p) _res = _PyPegen_check_legacy_stmt ( p , a ) ? NULL : p -> tokens [ p -> mark - 1 ] -> level == 0 ? NULL : RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Perhaps you forgot a comma?" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18302,7 +18903,7 @@ invalid_expression_rule(Parser *p) } { // disjunction 'if' disjunction !('else' | ':') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction !('else' | ':')")); @@ -18323,7 +18924,7 @@ invalid_expression_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "expected 'else' after 'if' expression" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18334,7 +18935,7 @@ invalid_expression_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18345,16 +18946,19 @@ invalid_expression_rule(Parser *p) static void * invalid_named_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // expression ':=' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ':=' expression")); @@ -18373,7 +18977,7 @@ invalid_named_expression_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use assignment expressions with %s" , _PyPegen_get_expr_name ( a ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18384,7 +18988,7 @@ invalid_named_expression_rule(Parser *p) } { // NAME '=' bitwise_or !('=' | ':=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '=' bitwise_or !('=' | ':=')")); @@ -18405,7 +19009,7 @@ invalid_named_expression_rule(Parser *p) _res = p -> in_raw_rule ? NULL : RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Maybe you meant '==' or ':=' instead of '='?" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18416,7 +19020,7 @@ invalid_named_expression_rule(Parser *p) } { // !(list | tuple | genexp | 'True' | 'None' | 'False') bitwise_or '=' bitwise_or !('=' | ':=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!(list | tuple | genexp | 'True' | 'None' | 'False') bitwise_or '=' bitwise_or !('=' | ':=')")); @@ -18439,7 +19043,7 @@ invalid_named_expression_rule(Parser *p) _res = p -> in_raw_rule ? NULL : RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot assign to %s here. Maybe you meant '==' instead of '='?" , _PyPegen_get_expr_name ( a ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18450,7 +19054,7 @@ invalid_named_expression_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18464,16 +19068,19 @@ invalid_named_expression_rule(Parser *p) static void * invalid_assignment_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // invalid_ann_assign_target ':' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_ann_assign_target ':' expression")); @@ -18492,7 +19099,7 @@ invalid_assignment_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "only single target (not %s) can be annotated" , _PyPegen_get_expr_name ( a ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18503,7 +19110,7 @@ invalid_assignment_rule(Parser *p) } { // star_named_expression ',' star_named_expressions* ':' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions* ':' expression")); @@ -18528,7 +19135,7 @@ invalid_assignment_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "only single target (not tuple) can be annotated" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18539,7 +19146,7 @@ invalid_assignment_rule(Parser *p) } { // expression ':' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ':' expression")); @@ -18558,7 +19165,7 @@ invalid_assignment_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "illegal target for annotation" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18569,7 +19176,7 @@ invalid_assignment_rule(Parser *p) } { // ((star_targets '='))* star_expressions '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* star_expressions '='")); @@ -18588,7 +19195,7 @@ invalid_assignment_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( STAR_TARGETS , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18599,7 +19206,7 @@ invalid_assignment_rule(Parser *p) } { // ((star_targets '='))* yield_expr '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* yield_expr '='")); @@ -18618,7 +19225,7 @@ invalid_assignment_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "assignment to yield expression not possible" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18629,7 +19236,7 @@ invalid_assignment_rule(Parser *p) } { // star_expressions augassign (yield_expr | star_expressions) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions augassign (yield_expr | star_expressions)")); @@ -18648,7 +19255,7 @@ invalid_assignment_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "'%s' is an illegal expression for augmented assignment" , _PyPegen_get_expr_name ( a ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18659,7 +19266,7 @@ invalid_assignment_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18667,16 +19274,19 @@ invalid_assignment_rule(Parser *p) static expr_ty invalid_ann_assign_target_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // list if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_ann_assign_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); @@ -18695,7 +19305,7 @@ invalid_ann_assign_target_rule(Parser *p) } { // tuple if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_ann_assign_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); @@ -18714,7 +19324,7 @@ invalid_ann_assign_target_rule(Parser *p) } { // '(' invalid_ann_assign_target ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_ann_assign_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' invalid_ann_assign_target ')'")); @@ -18733,7 +19343,7 @@ invalid_ann_assign_target_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18744,7 +19354,7 @@ invalid_ann_assign_target_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18752,16 +19362,19 @@ invalid_ann_assign_target_rule(Parser *p) static void * invalid_del_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'del' star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_del_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'del' star_expressions")); @@ -18777,7 +19390,7 @@ invalid_del_stmt_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( DEL_TARGETS , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18788,7 +19401,7 @@ invalid_del_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18796,16 +19409,19 @@ invalid_del_stmt_rule(Parser *p) static void * invalid_block_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE !INDENT")); @@ -18820,7 +19436,7 @@ invalid_block_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18831,7 +19447,7 @@ invalid_block_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18842,16 +19458,19 @@ invalid_block_rule(Parser *p) static void * invalid_comprehension_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ('[' | '(' | '{') starred_expression for_if_clauses if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '(' | '{') starred_expression for_if_clauses")); @@ -18870,7 +19489,7 @@ invalid_comprehension_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "iterable unpacking cannot be used in comprehension" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18881,7 +19500,7 @@ invalid_comprehension_rule(Parser *p) } { // ('[' | '{') star_named_expression ',' star_named_expressions for_if_clauses if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '{') star_named_expression ',' star_named_expressions for_if_clauses")); @@ -18906,7 +19525,7 @@ invalid_comprehension_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , PyPegen_last_item ( b , expr_ty ) , "did you forget parentheses around the comprehension target?" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18917,7 +19536,7 @@ invalid_comprehension_rule(Parser *p) } { // ('[' | '{') star_named_expression ',' for_if_clauses if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '{') star_named_expression ',' for_if_clauses")); @@ -18939,7 +19558,7 @@ invalid_comprehension_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "did you forget parentheses around the comprehension target?" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18950,7 +19569,7 @@ invalid_comprehension_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18958,16 +19577,19 @@ invalid_comprehension_rule(Parser *p) static void * invalid_dict_comprehension_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '{' '**' bitwise_or for_if_clauses '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_dict_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' '**' bitwise_or for_if_clauses '}'")); @@ -18992,7 +19614,7 @@ invalid_dict_comprehension_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "dict unpacking cannot be used in dict comprehension" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19003,7 +19625,7 @@ invalid_dict_comprehension_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19011,16 +19633,19 @@ invalid_dict_comprehension_rule(Parser *p) static void * invalid_parameters_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // param_no_default* invalid_parameters_helper param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default* invalid_parameters_helper param_no_default")); @@ -19039,7 +19664,7 @@ invalid_parameters_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "non-default argument follows default argument" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19050,7 +19675,7 @@ invalid_parameters_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19058,16 +19683,19 @@ invalid_parameters_rule(Parser *p) static void * invalid_parameters_helper_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // slash_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default")); @@ -19080,7 +19708,7 @@ invalid_parameters_helper_rule(Parser *p) _res = _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19091,7 +19719,7 @@ invalid_parameters_helper_rule(Parser *p) } { // param_with_default+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default+")); @@ -19110,7 +19738,7 @@ invalid_parameters_helper_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19119,16 +19747,19 @@ invalid_parameters_helper_rule(Parser *p) static void * invalid_lambda_parameters_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // lambda_param_no_default* invalid_lambda_parameters_helper lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* invalid_lambda_parameters_helper lambda_param_no_default")); @@ -19147,7 +19778,7 @@ invalid_lambda_parameters_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "non-default argument follows default argument" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19158,7 +19789,7 @@ invalid_lambda_parameters_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19168,16 +19799,19 @@ invalid_lambda_parameters_rule(Parser *p) static void * invalid_lambda_parameters_helper_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // lambda_slash_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); @@ -19190,7 +19824,7 @@ invalid_lambda_parameters_helper_rule(Parser *p) _res = _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19201,7 +19835,7 @@ invalid_lambda_parameters_helper_rule(Parser *p) } { // lambda_param_with_default+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+")); @@ -19220,7 +19854,7 @@ invalid_lambda_parameters_helper_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19228,16 +19862,19 @@ invalid_lambda_parameters_helper_rule(Parser *p) static void * invalid_star_etc_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '*' (')' | ',' (')' | '**')) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))")); @@ -19253,7 +19890,7 @@ invalid_star_etc_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "named arguments must follow bare *" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19264,7 +19901,7 @@ invalid_star_etc_rule(Parser *p) } { // '*' ',' TYPE_COMMENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' ',' TYPE_COMMENT")); @@ -19283,7 +19920,7 @@ invalid_star_etc_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "bare * has associated type comment" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19294,7 +19931,7 @@ invalid_star_etc_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19302,16 +19939,19 @@ invalid_star_etc_rule(Parser *p) static void * invalid_lambda_star_etc_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '*' (':' | ',' (':' | '**')) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))")); @@ -19327,7 +19967,7 @@ invalid_lambda_star_etc_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "named arguments must follow bare *" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19338,7 +19978,7 @@ invalid_lambda_star_etc_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19346,16 +19986,19 @@ invalid_lambda_star_etc_rule(Parser *p) static void * invalid_double_type_comments_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // TYPE_COMMENT NEWLINE TYPE_COMMENT NEWLINE INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_double_type_comments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "TYPE_COMMENT NEWLINE TYPE_COMMENT NEWLINE INDENT")); @@ -19380,7 +20023,7 @@ invalid_double_type_comments_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "Cannot have two type comments on def" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19391,7 +20034,7 @@ invalid_double_type_comments_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19399,16 +20042,19 @@ invalid_double_type_comments_rule(Parser *p) static void * invalid_with_item_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // expression 'as' expression &(',' | ')' | ':') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_with_item[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression 'as' expression &(',' | ')' | ':')")); @@ -19429,7 +20075,7 @@ invalid_with_item_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( STAR_TARGETS , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19440,7 +20086,7 @@ invalid_with_item_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19448,16 +20094,19 @@ invalid_with_item_rule(Parser *p) static void * invalid_for_target_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ASYNC? 'for' star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_for_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'for' star_expressions")); @@ -19477,7 +20126,7 @@ invalid_for_target_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( FOR_TARGETS , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19488,7 +20137,7 @@ invalid_for_target_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19496,16 +20145,19 @@ invalid_for_target_rule(Parser *p) static void * invalid_group_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '(' starred_expression ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_group[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' starred_expression ')'")); @@ -19524,7 +20176,7 @@ invalid_group_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use starred expression here" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19535,7 +20187,7 @@ invalid_group_rule(Parser *p) } { // '(' '**' expression ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_group[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' '**' expression ')'")); @@ -19557,7 +20209,7 @@ invalid_group_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use double starred expression here" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19568,7 +20220,7 @@ invalid_group_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19576,16 +20228,19 @@ invalid_group_rule(Parser *p) static void * invalid_import_from_targets_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // import_from_as_names ',' NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_import_from_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "import_from_as_names ',' NEWLINE")); @@ -19604,7 +20259,7 @@ invalid_import_from_targets_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "trailing comma not allowed without surrounding parentheses" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19615,7 +20270,7 @@ invalid_import_from_targets_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19625,16 +20280,19 @@ invalid_import_from_targets_rule(Parser *p) static void * invalid_with_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ASYNC? 'with' ','.(expression ['as' star_target])+ &&':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' ','.(expression ['as' star_target])+ &&':'")); @@ -19663,7 +20321,7 @@ invalid_with_stmt_rule(Parser *p) } { // ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' &&':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' &&':'")); @@ -19702,7 +20360,7 @@ invalid_with_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19712,16 +20370,19 @@ invalid_with_stmt_rule(Parser *p) static void * invalid_with_stmt_indent_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ASYNC? 'with' ','.(expression ['as' star_target])+ ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' ','.(expression ['as' star_target])+ ':' NEWLINE !INDENT")); @@ -19749,7 +20410,7 @@ invalid_with_stmt_indent_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'with' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19760,7 +20421,7 @@ invalid_with_stmt_indent_rule(Parser *p) } { // ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' ':' NEWLINE !INDENT")); @@ -19798,7 +20459,7 @@ invalid_with_stmt_indent_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'with' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19809,7 +20470,7 @@ invalid_with_stmt_indent_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19817,16 +20478,19 @@ invalid_with_stmt_indent_rule(Parser *p) static void * invalid_try_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'try' ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_try_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'try' ':' NEWLINE !INDENT")); @@ -19847,7 +20511,7 @@ invalid_try_stmt_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'try' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19858,7 +20522,7 @@ invalid_try_stmt_rule(Parser *p) } { // 'try' ':' block !('except' | 'finally') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_try_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'try' ':' block !('except' | 'finally')")); @@ -19879,7 +20543,7 @@ invalid_try_stmt_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "expected 'except' or 'finally' block" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19890,7 +20554,7 @@ invalid_try_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19901,16 +20565,19 @@ invalid_try_stmt_rule(Parser *p) static void * invalid_except_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'except' expression ',' expressions ['as' NAME] ':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_except_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' expression ',' expressions ['as' NAME] ':'")); @@ -19939,7 +20606,7 @@ invalid_except_stmt_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( a , "multiple exception types must be parenthesized" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19950,7 +20617,7 @@ invalid_except_stmt_rule(Parser *p) } { // 'except' expression ['as' NAME] NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_except_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' expression ['as' NAME] NEWLINE")); @@ -19973,7 +20640,7 @@ invalid_except_stmt_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19984,7 +20651,7 @@ invalid_except_stmt_rule(Parser *p) } { // 'except' NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_except_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' NEWLINE")); @@ -20000,7 +20667,7 @@ invalid_except_stmt_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20011,7 +20678,7 @@ invalid_except_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20019,16 +20686,19 @@ invalid_except_stmt_rule(Parser *p) static void * invalid_finally_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'finally' ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_finally_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally' ':' NEWLINE !INDENT")); @@ -20049,7 +20719,7 @@ invalid_finally_stmt_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'finally' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20060,7 +20730,7 @@ invalid_finally_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20070,16 +20740,19 @@ invalid_finally_stmt_rule(Parser *p) static void * invalid_except_stmt_indent_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'except' expression ['as' NAME] ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_except_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' expression ['as' NAME] ':' NEWLINE !INDENT")); @@ -20107,7 +20780,7 @@ invalid_except_stmt_indent_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'except' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20118,7 +20791,7 @@ invalid_except_stmt_indent_rule(Parser *p) } { // 'except' ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_except_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' ':' NEWLINE !INDENT")); @@ -20139,7 +20812,7 @@ invalid_except_stmt_indent_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "expected an indented block after except statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20150,7 +20823,7 @@ invalid_except_stmt_indent_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20160,16 +20833,19 @@ invalid_except_stmt_indent_rule(Parser *p) static void * invalid_match_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // "match" subject_expr !':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_match_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"match\" subject_expr !':'")); @@ -20187,7 +20863,7 @@ invalid_match_stmt_rule(Parser *p) _res = CHECK_VERSION ( void * , 10 , "Pattern matching is" , RAISE_SYNTAX_ERROR ( "expected ':'" ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20198,7 +20874,7 @@ invalid_match_stmt_rule(Parser *p) } { // "match" subject_expr ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_match_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"match\" subject_expr ':' NEWLINE !INDENT")); @@ -20222,7 +20898,7 @@ invalid_match_stmt_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'match' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20233,7 +20909,7 @@ invalid_match_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20243,16 +20919,19 @@ invalid_match_stmt_rule(Parser *p) static void * invalid_case_block_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // "case" patterns guard? !':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_case_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"case\" patterns guard? !':'")); @@ -20274,7 +20953,7 @@ invalid_case_block_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20285,7 +20964,7 @@ invalid_case_block_rule(Parser *p) } { // "case" patterns guard? ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_case_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"case\" patterns guard? ':' NEWLINE !INDENT")); @@ -20313,7 +20992,7 @@ invalid_case_block_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'case' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20324,7 +21003,7 @@ invalid_case_block_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20332,16 +21011,19 @@ invalid_case_block_rule(Parser *p) static void * invalid_as_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // or_pattern 'as' "_" if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_as_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "or_pattern 'as' \"_\"")); @@ -20360,7 +21042,7 @@ invalid_as_pattern_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use '_' as a target" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20371,7 +21053,7 @@ invalid_as_pattern_rule(Parser *p) } { // or_pattern 'as' !NAME expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_as_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "or_pattern 'as' !NAME expression")); @@ -20392,7 +21074,7 @@ invalid_as_pattern_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "invalid pattern target" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20403,7 +21085,7 @@ invalid_as_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20411,16 +21093,19 @@ invalid_as_pattern_rule(Parser *p) static void * invalid_class_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // name_or_attr '(' invalid_class_argument_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_class_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' invalid_class_argument_pattern")); @@ -20439,7 +21124,7 @@ invalid_class_pattern_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( PyPegen_first_item ( a , pattern_ty ) , PyPegen_last_item ( a , pattern_ty ) , "positional patterns follow keyword patterns" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20450,7 +21135,7 @@ invalid_class_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20459,16 +21144,19 @@ invalid_class_pattern_rule(Parser *p) static asdl_pattern_seq* invalid_class_argument_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_pattern_seq* _res = NULL; int _mark = p->mark; { // [positional_patterns ','] keyword_patterns ',' positional_patterns if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_class_argument_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "[positional_patterns ','] keyword_patterns ',' positional_patterns")); @@ -20491,7 +21179,7 @@ invalid_class_argument_pattern_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20502,7 +21190,7 @@ invalid_class_argument_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20512,16 +21200,19 @@ invalid_class_argument_pattern_rule(Parser *p) static void * invalid_if_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'if' named_expression NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_if_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' named_expression NEWLINE")); @@ -20540,7 +21231,7 @@ invalid_if_stmt_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20551,7 +21242,7 @@ invalid_if_stmt_rule(Parser *p) } { // 'if' named_expression ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_if_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' named_expression ':' NEWLINE !INDENT")); @@ -20575,7 +21266,7 @@ invalid_if_stmt_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'if' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20586,7 +21277,7 @@ invalid_if_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20596,16 +21287,19 @@ invalid_if_stmt_rule(Parser *p) static void * invalid_elif_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'elif' named_expression NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_elif_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'elif' named_expression NEWLINE")); @@ -20624,7 +21318,7 @@ invalid_elif_stmt_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20635,7 +21329,7 @@ invalid_elif_stmt_rule(Parser *p) } { // 'elif' named_expression ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_elif_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'elif' named_expression ':' NEWLINE !INDENT")); @@ -20659,7 +21353,7 @@ invalid_elif_stmt_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'elif' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20670,7 +21364,7 @@ invalid_elif_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20678,16 +21372,19 @@ invalid_elif_stmt_rule(Parser *p) static void * invalid_else_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'else' ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_else_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else' ':' NEWLINE !INDENT")); @@ -20708,7 +21405,7 @@ invalid_else_stmt_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'else' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20719,7 +21416,7 @@ invalid_else_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20729,16 +21426,19 @@ invalid_else_stmt_rule(Parser *p) static void * invalid_while_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'while' named_expression NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_while_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'while' named_expression NEWLINE")); @@ -20757,7 +21457,7 @@ invalid_while_stmt_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20768,7 +21468,7 @@ invalid_while_stmt_rule(Parser *p) } { // 'while' named_expression ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_while_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'while' named_expression ':' NEWLINE !INDENT")); @@ -20792,7 +21492,7 @@ invalid_while_stmt_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'while' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20803,7 +21503,7 @@ invalid_while_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20811,16 +21511,19 @@ invalid_while_stmt_rule(Parser *p) static void * invalid_for_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ASYNC? 'for' star_targets 'in' star_expressions ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_for_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'for' star_targets 'in' star_expressions ':' NEWLINE !INDENT")); @@ -20854,7 +21557,7 @@ invalid_for_stmt_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'for' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20865,7 +21568,7 @@ invalid_for_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20874,16 +21577,19 @@ invalid_for_stmt_rule(Parser *p) static void * invalid_def_raw_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ASYNC? 'def' NAME '(' params? ')' ['->' expression] ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'def' NAME '(' params? ')' ['->' expression] ':' NEWLINE !INDENT")); @@ -20925,7 +21631,7 @@ invalid_def_raw_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after function definition on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20936,7 +21642,7 @@ invalid_def_raw_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20944,16 +21650,19 @@ invalid_def_raw_rule(Parser *p) static void * invalid_class_def_raw_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'class' NAME ['(' arguments? ')'] ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_class_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class' NAME ['(' arguments? ')'] ':' NEWLINE !INDENT")); @@ -20981,7 +21690,7 @@ invalid_class_def_raw_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after class definition on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20992,7 +21701,7 @@ invalid_class_def_raw_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21003,16 +21712,19 @@ invalid_class_def_raw_rule(Parser *p) static void * invalid_double_starred_kvpairs_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ','.double_starred_kvpair+ ',' invalid_kvpair if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_double_starred_kvpairs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ',' invalid_kvpair")); @@ -21037,7 +21749,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) } { // expression ':' '*' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_double_starred_kvpairs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ':' '*' bitwise_or")); @@ -21059,7 +21771,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( a , "cannot use a starred expression in a dictionary value" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -21070,7 +21782,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) } { // expression ':' &('}' | ',') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_double_starred_kvpairs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ':' &('}' | ',')")); @@ -21088,7 +21800,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "expression expected after dictionary key and ':'" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -21099,7 +21811,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21107,16 +21819,19 @@ invalid_double_starred_kvpairs_rule(Parser *p) static void * invalid_kvpair_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // expression !(':') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_kvpair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !(':')")); @@ -21131,7 +21846,7 @@ invalid_kvpair_rule(Parser *p) _res = RAISE_ERROR_KNOWN_LOCATION ( p , PyExc_SyntaxError , a -> lineno , a -> end_col_offset - 1 , a -> end_lineno , - 1 , "':' expected after dictionary key" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -21142,7 +21857,7 @@ invalid_kvpair_rule(Parser *p) } { // expression ':' '*' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_kvpair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ':' '*' bitwise_or")); @@ -21164,7 +21879,7 @@ invalid_kvpair_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( a , "cannot use a starred expression in a dictionary value" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -21175,7 +21890,7 @@ invalid_kvpair_rule(Parser *p) } { // expression ':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_kvpair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ':'")); @@ -21191,7 +21906,7 @@ invalid_kvpair_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "expression expected after dictionary key and ':'" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -21202,7 +21917,7 @@ invalid_kvpair_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21210,9 +21925,12 @@ invalid_kvpair_rule(Parser *p) static asdl_seq * _loop0_1_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -21222,14 +21940,14 @@ _loop0_1_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_1[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); @@ -21245,7 +21963,7 @@ _loop0_1_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -21262,13 +21980,13 @@ _loop0_1_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_1_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -21276,9 +21994,12 @@ _loop0_1_rule(Parser *p) static asdl_seq * _loop0_2_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -21288,14 +22009,14 @@ _loop0_2_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_2[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); @@ -21311,7 +22032,7 @@ _loop0_2_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -21328,13 +22049,13 @@ _loop0_2_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_2_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -21342,9 +22063,12 @@ _loop0_2_rule(Parser *p) static asdl_seq * _loop0_4_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -21354,14 +22078,14 @@ _loop0_4_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_4[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); @@ -21377,7 +22101,7 @@ _loop0_4_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -21386,7 +22110,7 @@ _loop0_4_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -21403,13 +22127,13 @@ _loop0_4_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_4_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -21417,16 +22141,19 @@ _loop0_4_rule(Parser *p) static asdl_seq * _gather_3_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // expression _loop0_4 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_3[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_4")); @@ -21448,7 +22175,7 @@ _gather_3_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21456,9 +22183,12 @@ _gather_3_rule(Parser *p) static asdl_seq * _loop0_6_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -21468,14 +22198,14 @@ _loop0_6_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_6[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); @@ -21491,7 +22221,7 @@ _loop0_6_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -21500,7 +22230,7 @@ _loop0_6_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -21517,13 +22247,13 @@ _loop0_6_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_6_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -21531,16 +22261,19 @@ _loop0_6_rule(Parser *p) static asdl_seq * _gather_5_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // expression _loop0_6 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_5[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_6")); @@ -21562,7 +22295,7 @@ _gather_5_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21570,9 +22303,12 @@ _gather_5_rule(Parser *p) static asdl_seq * _loop0_8_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -21582,14 +22318,14 @@ _loop0_8_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_8[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); @@ -21605,7 +22341,7 @@ _loop0_8_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -21614,7 +22350,7 @@ _loop0_8_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -21631,13 +22367,13 @@ _loop0_8_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_8_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -21645,16 +22381,19 @@ _loop0_8_rule(Parser *p) static asdl_seq * _gather_7_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // expression _loop0_8 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_7[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_8")); @@ -21676,7 +22415,7 @@ _gather_7_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21684,9 +22423,12 @@ _gather_7_rule(Parser *p) static asdl_seq * _loop0_10_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -21696,14 +22438,14 @@ _loop0_10_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_10[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); @@ -21719,7 +22461,7 @@ _loop0_10_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -21728,7 +22470,7 @@ _loop0_10_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -21745,13 +22487,13 @@ _loop0_10_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_10_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -21759,16 +22501,19 @@ _loop0_10_rule(Parser *p) static asdl_seq * _gather_9_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // expression _loop0_10 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_9[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_10")); @@ -21790,7 +22535,7 @@ _gather_9_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21798,9 +22543,12 @@ _gather_9_rule(Parser *p) static asdl_seq * _loop1_11_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -21810,14 +22558,14 @@ _loop1_11_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // statement if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_11[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "statement")); @@ -21833,7 +22581,7 @@ _loop1_11_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -21847,7 +22595,7 @@ _loop1_11_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -21855,13 +22603,13 @@ _loop1_11_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_11_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -21869,9 +22617,12 @@ _loop1_11_rule(Parser *p) static asdl_seq * _loop0_13_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -21881,14 +22632,14 @@ _loop0_13_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ';' simple_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_13[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "';' simple_stmt")); @@ -21904,7 +22655,7 @@ _loop0_13_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -21913,7 +22664,7 @@ _loop0_13_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -21930,13 +22681,13 @@ _loop0_13_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_13_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -21944,16 +22695,19 @@ _loop0_13_rule(Parser *p) static asdl_seq * _gather_12_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // simple_stmt _loop0_13 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_12[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "simple_stmt _loop0_13")); @@ -21975,7 +22729,7 @@ _gather_12_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21983,16 +22737,19 @@ _gather_12_rule(Parser *p) static void * _tmp_14_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'import' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_14[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'import'")); @@ -22011,7 +22768,7 @@ _tmp_14_rule(Parser *p) } { // 'from' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_14[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from'")); @@ -22030,7 +22787,7 @@ _tmp_14_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22038,16 +22795,19 @@ _tmp_14_rule(Parser *p) static void * _tmp_15_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'def' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_15[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'def'")); @@ -22066,7 +22826,7 @@ _tmp_15_rule(Parser *p) } { // '@' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_15[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@'")); @@ -22085,7 +22845,7 @@ _tmp_15_rule(Parser *p) } { // ASYNC if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_15[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC")); @@ -22104,7 +22864,7 @@ _tmp_15_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22112,16 +22872,19 @@ _tmp_15_rule(Parser *p) static void * _tmp_16_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'class' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_16[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class'")); @@ -22140,7 +22903,7 @@ _tmp_16_rule(Parser *p) } { // '@' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_16[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@'")); @@ -22159,7 +22922,7 @@ _tmp_16_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22167,16 +22930,19 @@ _tmp_16_rule(Parser *p) static void * _tmp_17_rule(Parser *p) { - D(p->level++); - if (p->error_indicator) { - D(p->level--); - return NULL; + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; + return NULL; } void * _res = NULL; int _mark = p->mark; { // 'with' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_17[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'with'")); @@ -22195,7 +22961,7 @@ _tmp_17_rule(Parser *p) } { // ASYNC if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_17[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC")); @@ -22214,7 +22980,7 @@ _tmp_17_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22222,16 +22988,19 @@ _tmp_17_rule(Parser *p) static void * _tmp_18_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'for' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_18[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'for'")); @@ -22250,7 +23019,7 @@ _tmp_18_rule(Parser *p) } { // ASYNC if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_18[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC")); @@ -22269,7 +23038,7 @@ _tmp_18_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22277,16 +23046,19 @@ _tmp_18_rule(Parser *p) static void * _tmp_19_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '=' annotated_rhs if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_19[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'=' annotated_rhs")); @@ -22302,7 +23074,7 @@ _tmp_19_rule(Parser *p) _res = d; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -22313,7 +23085,7 @@ _tmp_19_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22321,16 +23093,19 @@ _tmp_19_rule(Parser *p) static void * _tmp_20_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '(' single_target ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_20[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' single_target ')'")); @@ -22349,7 +23124,7 @@ _tmp_20_rule(Parser *p) _res = b; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -22360,7 +23135,7 @@ _tmp_20_rule(Parser *p) } { // single_subscript_attribute_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_20[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "single_subscript_attribute_target")); @@ -22379,7 +23154,7 @@ _tmp_20_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22387,16 +23162,19 @@ _tmp_20_rule(Parser *p) static void * _tmp_21_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '=' annotated_rhs if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_21[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'=' annotated_rhs")); @@ -22412,7 +23190,7 @@ _tmp_21_rule(Parser *p) _res = d; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -22423,7 +23201,7 @@ _tmp_21_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22431,9 +23209,12 @@ _tmp_21_rule(Parser *p) static asdl_seq * _loop1_22_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -22443,14 +23224,14 @@ _loop1_22_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // (star_targets '=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_22[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); @@ -22466,7 +23247,7 @@ _loop1_22_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -22480,7 +23261,7 @@ _loop1_22_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -22488,13 +23269,13 @@ _loop1_22_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_22_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -22502,16 +23283,19 @@ _loop1_22_rule(Parser *p) static void * _tmp_23_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // yield_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_23[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); @@ -22530,7 +23314,7 @@ _tmp_23_rule(Parser *p) } { // star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_23[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); @@ -22549,7 +23333,7 @@ _tmp_23_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22557,16 +23341,19 @@ _tmp_23_rule(Parser *p) static void * _tmp_24_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // yield_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_24[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); @@ -22585,7 +23372,7 @@ _tmp_24_rule(Parser *p) } { // star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_24[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); @@ -22604,7 +23391,7 @@ _tmp_24_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22612,9 +23399,12 @@ _tmp_24_rule(Parser *p) static asdl_seq * _loop0_26_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -22624,14 +23414,14 @@ _loop0_26_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_26[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' NAME")); @@ -22647,7 +23437,7 @@ _loop0_26_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -22656,7 +23446,7 @@ _loop0_26_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -22673,13 +23463,13 @@ _loop0_26_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_26_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -22687,16 +23477,19 @@ _loop0_26_rule(Parser *p) static asdl_seq * _gather_25_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // NAME _loop0_26 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_25[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME _loop0_26")); @@ -22718,7 +23511,7 @@ _gather_25_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22726,9 +23519,12 @@ _gather_25_rule(Parser *p) static asdl_seq * _loop0_28_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -22738,14 +23534,14 @@ _loop0_28_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_28[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' NAME")); @@ -22761,7 +23557,7 @@ _loop0_28_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -22770,7 +23566,7 @@ _loop0_28_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -22787,13 +23583,13 @@ _loop0_28_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_28_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -22801,16 +23597,19 @@ _loop0_28_rule(Parser *p) static asdl_seq * _gather_27_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // NAME _loop0_28 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_27[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME _loop0_28")); @@ -22832,7 +23631,7 @@ _gather_27_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22840,16 +23639,19 @@ _gather_27_rule(Parser *p) static void * _tmp_29_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_29[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); @@ -22865,7 +23667,7 @@ _tmp_29_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -22876,7 +23678,7 @@ _tmp_29_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22884,16 +23686,19 @@ _tmp_29_rule(Parser *p) static void * _tmp_30_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ';' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_30[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "';'")); @@ -22912,7 +23717,7 @@ _tmp_30_rule(Parser *p) } { // NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_30[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); @@ -22931,7 +23736,7 @@ _tmp_30_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22939,9 +23744,12 @@ _tmp_30_rule(Parser *p) static asdl_seq * _loop0_31_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -22951,14 +23759,14 @@ _loop0_31_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ('.' | '...') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_31[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); @@ -22974,7 +23782,7 @@ _loop0_31_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -22991,13 +23799,13 @@ _loop0_31_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_31_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23005,9 +23813,12 @@ _loop0_31_rule(Parser *p) static asdl_seq * _loop1_32_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23017,14 +23828,14 @@ _loop1_32_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ('.' | '...') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_32[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); @@ -23040,7 +23851,7 @@ _loop1_32_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23054,7 +23865,7 @@ _loop1_32_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -23062,13 +23873,13 @@ _loop1_32_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_32_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23076,9 +23887,12 @@ _loop1_32_rule(Parser *p) static asdl_seq * _loop0_34_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23088,14 +23902,14 @@ _loop0_34_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' import_from_as_name if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_34[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' import_from_as_name")); @@ -23111,7 +23925,7 @@ _loop0_34_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -23120,7 +23934,7 @@ _loop0_34_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23137,13 +23951,13 @@ _loop0_34_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_34_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23151,16 +23965,19 @@ _loop0_34_rule(Parser *p) static asdl_seq * _gather_33_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // import_from_as_name _loop0_34 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_33[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "import_from_as_name _loop0_34")); @@ -23182,7 +23999,7 @@ _gather_33_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23190,16 +24007,19 @@ _gather_33_rule(Parser *p) static void * _tmp_35_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_35[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); @@ -23215,7 +24035,7 @@ _tmp_35_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -23226,7 +24046,7 @@ _tmp_35_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23234,9 +24054,12 @@ _tmp_35_rule(Parser *p) static asdl_seq * _loop0_37_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23246,14 +24069,14 @@ _loop0_37_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' dotted_as_name if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_37[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' dotted_as_name")); @@ -23269,7 +24092,7 @@ _loop0_37_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -23278,7 +24101,7 @@ _loop0_37_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23295,13 +24118,13 @@ _loop0_37_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_37_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23309,16 +24132,19 @@ _loop0_37_rule(Parser *p) static asdl_seq * _gather_36_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // dotted_as_name _loop0_37 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_36[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dotted_as_name _loop0_37")); @@ -23340,7 +24166,7 @@ _gather_36_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23348,16 +24174,19 @@ _gather_36_rule(Parser *p) static void * _tmp_38_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_38[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); @@ -23373,7 +24202,7 @@ _tmp_38_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -23384,7 +24213,7 @@ _tmp_38_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23392,9 +24221,12 @@ _tmp_38_rule(Parser *p) static asdl_seq * _loop0_40_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23404,14 +24236,14 @@ _loop0_40_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' with_item if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_40[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); @@ -23427,7 +24259,7 @@ _loop0_40_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -23436,7 +24268,7 @@ _loop0_40_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23453,13 +24285,13 @@ _loop0_40_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_40_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23467,16 +24299,19 @@ _loop0_40_rule(Parser *p) static asdl_seq * _gather_39_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // with_item _loop0_40 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_39[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_40")); @@ -23498,7 +24333,7 @@ _gather_39_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23506,9 +24341,12 @@ _gather_39_rule(Parser *p) static asdl_seq * _loop0_42_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23518,14 +24356,14 @@ _loop0_42_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' with_item if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_42[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); @@ -23541,7 +24379,7 @@ _loop0_42_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -23550,7 +24388,7 @@ _loop0_42_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23567,13 +24405,13 @@ _loop0_42_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_42_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23581,16 +24419,19 @@ _loop0_42_rule(Parser *p) static asdl_seq * _gather_41_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // with_item _loop0_42 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_41[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_42")); @@ -23612,7 +24453,7 @@ _gather_41_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23620,9 +24461,12 @@ _gather_41_rule(Parser *p) static asdl_seq * _loop0_44_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23632,14 +24476,14 @@ _loop0_44_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' with_item if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_44[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); @@ -23655,7 +24499,7 @@ _loop0_44_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -23664,7 +24508,7 @@ _loop0_44_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23681,13 +24525,13 @@ _loop0_44_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_44_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23695,16 +24539,19 @@ _loop0_44_rule(Parser *p) static asdl_seq * _gather_43_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // with_item _loop0_44 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_43[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_44")); @@ -23726,7 +24573,7 @@ _gather_43_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23734,9 +24581,12 @@ _gather_43_rule(Parser *p) static asdl_seq * _loop0_46_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23746,14 +24596,14 @@ _loop0_46_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' with_item if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_46[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); @@ -23769,7 +24619,7 @@ _loop0_46_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -23778,7 +24628,7 @@ _loop0_46_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23795,13 +24645,13 @@ _loop0_46_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_46_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23809,16 +24659,19 @@ _loop0_46_rule(Parser *p) static asdl_seq * _gather_45_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // with_item _loop0_46 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_45[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_46")); @@ -23840,7 +24693,7 @@ _gather_45_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23848,16 +24701,19 @@ _gather_45_rule(Parser *p) static void * _tmp_47_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_47[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); @@ -23876,7 +24732,7 @@ _tmp_47_rule(Parser *p) } { // ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_47[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); @@ -23895,7 +24751,7 @@ _tmp_47_rule(Parser *p) } { // ':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_47[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); @@ -23914,7 +24770,7 @@ _tmp_47_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23922,9 +24778,12 @@ _tmp_47_rule(Parser *p) static asdl_seq * _loop1_48_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23934,14 +24793,14 @@ _loop1_48_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // except_block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_48[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_block")); @@ -23957,7 +24816,7 @@ _loop1_48_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23971,7 +24830,7 @@ _loop1_48_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -23979,13 +24838,13 @@ _loop1_48_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_48_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23993,16 +24852,19 @@ _loop1_48_rule(Parser *p) static void * _tmp_49_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_49[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); @@ -24018,7 +24880,7 @@ _tmp_49_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -24029,7 +24891,7 @@ _tmp_49_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24037,9 +24899,12 @@ _tmp_49_rule(Parser *p) static asdl_seq * _loop1_50_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -24049,14 +24914,14 @@ _loop1_50_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // case_block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_50[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "case_block")); @@ -24072,7 +24937,7 @@ _loop1_50_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -24086,7 +24951,7 @@ _loop1_50_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -24094,13 +24959,13 @@ _loop1_50_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_50_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -24108,9 +24973,12 @@ _loop1_50_rule(Parser *p) static asdl_seq * _loop0_52_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -24120,14 +24988,14 @@ _loop0_52_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // '|' closed_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_52[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'|' closed_pattern")); @@ -24143,7 +25011,7 @@ _loop0_52_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -24152,7 +25020,7 @@ _loop0_52_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -24169,13 +25037,13 @@ _loop0_52_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_52_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -24183,16 +25051,19 @@ _loop0_52_rule(Parser *p) static asdl_seq * _gather_51_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // closed_pattern _loop0_52 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_51[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "closed_pattern _loop0_52")); @@ -24214,7 +25085,7 @@ _gather_51_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24222,16 +25093,19 @@ _gather_51_rule(Parser *p) static void * _tmp_53_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '+' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_53[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); @@ -24250,7 +25124,7 @@ _tmp_53_rule(Parser *p) } { // '-' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_53[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); @@ -24269,7 +25143,7 @@ _tmp_53_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24277,16 +25151,19 @@ _tmp_53_rule(Parser *p) static void * _tmp_54_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '+' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_54[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); @@ -24305,7 +25182,7 @@ _tmp_54_rule(Parser *p) } { // '-' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_54[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); @@ -24324,7 +25201,7 @@ _tmp_54_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24332,16 +25209,19 @@ _tmp_54_rule(Parser *p) static void * _tmp_55_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '.' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_55[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); @@ -24360,7 +25240,7 @@ _tmp_55_rule(Parser *p) } { // '(' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_55[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); @@ -24379,7 +25259,7 @@ _tmp_55_rule(Parser *p) } { // '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_55[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); @@ -24398,7 +25278,7 @@ _tmp_55_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24406,16 +25286,19 @@ _tmp_55_rule(Parser *p) static void * _tmp_56_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '.' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_56[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); @@ -24434,7 +25317,7 @@ _tmp_56_rule(Parser *p) } { // '(' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_56[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); @@ -24453,7 +25336,7 @@ _tmp_56_rule(Parser *p) } { // '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_56[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); @@ -24472,7 +25355,7 @@ _tmp_56_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24480,9 +25363,12 @@ _tmp_56_rule(Parser *p) static asdl_seq * _loop0_58_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -24492,14 +25378,14 @@ _loop0_58_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' maybe_star_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_58[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' maybe_star_pattern")); @@ -24515,7 +25401,7 @@ _loop0_58_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -24524,7 +25410,7 @@ _loop0_58_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -24541,13 +25427,13 @@ _loop0_58_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_58_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -24555,16 +25441,19 @@ _loop0_58_rule(Parser *p) static asdl_seq * _gather_57_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // maybe_star_pattern _loop0_58 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_57[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "maybe_star_pattern _loop0_58")); @@ -24586,7 +25475,7 @@ _gather_57_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24594,9 +25483,12 @@ _gather_57_rule(Parser *p) static asdl_seq * _loop0_60_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -24606,14 +25498,14 @@ _loop0_60_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' key_value_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_60[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' key_value_pattern")); @@ -24629,7 +25521,7 @@ _loop0_60_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -24638,7 +25530,7 @@ _loop0_60_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -24655,13 +25547,13 @@ _loop0_60_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_60_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -24669,16 +25561,19 @@ _loop0_60_rule(Parser *p) static asdl_seq * _gather_59_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // key_value_pattern _loop0_60 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_59[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "key_value_pattern _loop0_60")); @@ -24700,7 +25595,7 @@ _gather_59_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24708,16 +25603,19 @@ _gather_59_rule(Parser *p) static void * _tmp_61_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // literal_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_61[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "literal_expr")); @@ -24736,7 +25634,7 @@ _tmp_61_rule(Parser *p) } { // attr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_61[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "attr")); @@ -24755,7 +25653,7 @@ _tmp_61_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24763,9 +25661,12 @@ _tmp_61_rule(Parser *p) static asdl_seq * _loop0_63_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -24775,14 +25676,14 @@ _loop0_63_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_63[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' pattern")); @@ -24798,7 +25699,7 @@ _loop0_63_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -24807,7 +25708,7 @@ _loop0_63_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -24824,13 +25725,13 @@ _loop0_63_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_63_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -24838,16 +25739,19 @@ _loop0_63_rule(Parser *p) static asdl_seq * _gather_62_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // pattern _loop0_63 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_62[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "pattern _loop0_63")); @@ -24869,7 +25773,7 @@ _gather_62_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24877,9 +25781,12 @@ _gather_62_rule(Parser *p) static asdl_seq * _loop0_65_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -24889,14 +25796,14 @@ _loop0_65_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' keyword_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_65[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' keyword_pattern")); @@ -24912,7 +25819,7 @@ _loop0_65_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -24921,7 +25828,7 @@ _loop0_65_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -24938,13 +25845,13 @@ _loop0_65_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_65_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -24952,16 +25859,19 @@ _loop0_65_rule(Parser *p) static asdl_seq * _gather_64_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // keyword_pattern _loop0_65 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_64[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "keyword_pattern _loop0_65")); @@ -24983,7 +25893,7 @@ _gather_64_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24991,16 +25901,19 @@ _gather_64_rule(Parser *p) static void * _tmp_66_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'from' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_66[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from' expression")); @@ -25016,7 +25929,7 @@ _tmp_66_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -25027,7 +25940,7 @@ _tmp_66_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -25035,16 +25948,19 @@ _tmp_66_rule(Parser *p) static void * _tmp_67_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '->' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_67[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); @@ -25060,7 +25976,7 @@ _tmp_67_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -25071,7 +25987,7 @@ _tmp_67_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -25079,16 +25995,19 @@ _tmp_67_rule(Parser *p) static void * _tmp_68_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '->' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_68[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); @@ -25104,7 +26023,7 @@ _tmp_68_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -25115,7 +26034,7 @@ _tmp_68_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -25123,16 +26042,19 @@ _tmp_68_rule(Parser *p) static void * _tmp_69_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // NEWLINE INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_69[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT")); @@ -25154,7 +26076,7 @@ _tmp_69_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -25162,9 +26084,12 @@ _tmp_69_rule(Parser *p) static asdl_seq * _loop0_70_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25174,14 +26099,14 @@ _loop0_70_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_70[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -25197,7 +26122,7 @@ _loop0_70_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25214,13 +26139,13 @@ _loop0_70_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_70_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25228,9 +26153,12 @@ _loop0_70_rule(Parser *p) static asdl_seq * _loop0_71_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25240,14 +26168,14 @@ _loop0_71_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_71[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); @@ -25263,7 +26191,7 @@ _loop0_71_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25280,13 +26208,13 @@ _loop0_71_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_71_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25294,9 +26222,12 @@ _loop0_71_rule(Parser *p) static asdl_seq * _loop0_72_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25306,14 +26237,14 @@ _loop0_72_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_72[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); @@ -25329,7 +26260,7 @@ _loop0_72_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25346,13 +26277,13 @@ _loop0_72_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_72_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25360,9 +26291,12 @@ _loop0_72_rule(Parser *p) static asdl_seq * _loop1_73_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25372,14 +26306,14 @@ _loop1_73_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_73[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -25395,7 +26329,7 @@ _loop1_73_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25409,7 +26343,7 @@ _loop1_73_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -25417,13 +26351,13 @@ _loop1_73_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_73_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25431,9 +26365,12 @@ _loop1_73_rule(Parser *p) static asdl_seq * _loop0_74_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25443,14 +26380,14 @@ _loop0_74_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_74[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); @@ -25466,7 +26403,7 @@ _loop0_74_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25483,13 +26420,13 @@ _loop0_74_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_74_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25497,9 +26434,12 @@ _loop0_74_rule(Parser *p) static asdl_seq * _loop1_75_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25509,14 +26449,14 @@ _loop1_75_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_75[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); @@ -25532,7 +26472,7 @@ _loop1_75_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25546,7 +26486,7 @@ _loop1_75_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -25554,13 +26494,13 @@ _loop1_75_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_75_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25568,9 +26508,12 @@ _loop1_75_rule(Parser *p) static asdl_seq * _loop1_76_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25580,14 +26523,14 @@ _loop1_76_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_76[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -25603,7 +26546,7 @@ _loop1_76_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25617,7 +26560,7 @@ _loop1_76_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -25625,13 +26568,13 @@ _loop1_76_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_76_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25639,9 +26582,12 @@ _loop1_76_rule(Parser *p) static asdl_seq * _loop1_77_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25651,14 +26597,14 @@ _loop1_77_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_77[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -25674,7 +26620,7 @@ _loop1_77_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25688,7 +26634,7 @@ _loop1_77_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -25696,13 +26642,13 @@ _loop1_77_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_77_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25710,9 +26656,12 @@ _loop1_77_rule(Parser *p) static asdl_seq * _loop0_78_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25722,14 +26671,14 @@ _loop0_78_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_78[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -25745,7 +26694,7 @@ _loop0_78_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25762,13 +26711,13 @@ _loop0_78_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_78_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25776,9 +26725,12 @@ _loop0_78_rule(Parser *p) static asdl_seq * _loop1_79_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25788,14 +26740,14 @@ _loop1_79_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_79[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); @@ -25811,7 +26763,7 @@ _loop1_79_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25825,7 +26777,7 @@ _loop1_79_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -25833,13 +26785,13 @@ _loop1_79_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_79_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25847,9 +26799,12 @@ _loop1_79_rule(Parser *p) static asdl_seq * _loop0_80_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25859,14 +26814,14 @@ _loop0_80_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_80[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -25882,7 +26837,7 @@ _loop0_80_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25899,13 +26854,13 @@ _loop0_80_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_80_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25913,9 +26868,12 @@ _loop0_80_rule(Parser *p) static asdl_seq * _loop1_81_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25925,14 +26883,14 @@ _loop1_81_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_81[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); @@ -25948,7 +26906,7 @@ _loop1_81_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25962,7 +26920,7 @@ _loop1_81_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -25970,13 +26928,13 @@ _loop1_81_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_81_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25984,9 +26942,12 @@ _loop1_81_rule(Parser *p) static asdl_seq * _loop0_82_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25996,14 +26957,14 @@ _loop0_82_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_maybe_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_82[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); @@ -26019,7 +26980,7 @@ _loop0_82_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26036,13 +26997,13 @@ _loop0_82_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_82_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26050,9 +27011,12 @@ _loop0_82_rule(Parser *p) static asdl_seq * _loop1_83_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26062,14 +27026,14 @@ _loop1_83_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_maybe_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_83[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); @@ -26085,7 +27049,7 @@ _loop1_83_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26099,7 +27063,7 @@ _loop1_83_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26107,13 +27071,13 @@ _loop1_83_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_83_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26121,9 +27085,12 @@ _loop1_83_rule(Parser *p) static asdl_seq * _loop1_84_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26133,14 +27100,14 @@ _loop1_84_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ('@' named_expression NEWLINE) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_84[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('@' named_expression NEWLINE)")); @@ -26156,7 +27123,7 @@ _loop1_84_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26170,7 +27137,7 @@ _loop1_84_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26178,13 +27145,13 @@ _loop1_84_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_84_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26192,16 +27159,19 @@ _loop1_84_rule(Parser *p) static void * _tmp_85_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '(' arguments? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_85[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); @@ -26220,7 +27190,7 @@ _tmp_85_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -26231,7 +27201,7 @@ _tmp_85_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -26239,9 +27209,12 @@ _tmp_85_rule(Parser *p) static asdl_seq * _loop1_86_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26251,14 +27224,14 @@ _loop1_86_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // (',' star_expression) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_86[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_expression)")); @@ -26274,7 +27247,7 @@ _loop1_86_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26288,7 +27261,7 @@ _loop1_86_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26296,13 +27269,13 @@ _loop1_86_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_86_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26310,9 +27283,12 @@ _loop1_86_rule(Parser *p) static asdl_seq * _loop0_88_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26322,14 +27298,14 @@ _loop0_88_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' star_named_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_88[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_named_expression")); @@ -26345,7 +27321,7 @@ _loop0_88_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -26354,7 +27330,7 @@ _loop0_88_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26371,13 +27347,13 @@ _loop0_88_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_88_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26385,16 +27361,19 @@ _loop0_88_rule(Parser *p) static asdl_seq * _gather_87_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // star_named_expression _loop0_88 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_87[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression _loop0_88")); @@ -26416,7 +27395,7 @@ _gather_87_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -26424,9 +27403,12 @@ _gather_87_rule(Parser *p) static asdl_seq * _loop1_89_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26436,14 +27418,14 @@ _loop1_89_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // (',' expression) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_89[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' expression)")); @@ -26459,7 +27441,7 @@ _loop1_89_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26473,7 +27455,7 @@ _loop1_89_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26481,13 +27463,13 @@ _loop1_89_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_89_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26495,9 +27477,12 @@ _loop1_89_rule(Parser *p) static asdl_seq * _loop0_90_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26507,14 +27492,14 @@ _loop0_90_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_90[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -26530,7 +27515,7 @@ _loop0_90_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26547,13 +27532,13 @@ _loop0_90_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_90_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26561,9 +27546,12 @@ _loop0_90_rule(Parser *p) static asdl_seq * _loop0_91_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26573,14 +27561,14 @@ _loop0_91_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_91[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); @@ -26596,7 +27584,7 @@ _loop0_91_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26613,13 +27601,13 @@ _loop0_91_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_91_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26627,9 +27615,12 @@ _loop0_91_rule(Parser *p) static asdl_seq * _loop0_92_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26639,14 +27630,14 @@ _loop0_92_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_92[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); @@ -26662,7 +27653,7 @@ _loop0_92_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26679,13 +27670,13 @@ _loop0_92_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_92_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26693,9 +27684,12 @@ _loop0_92_rule(Parser *p) static asdl_seq * _loop1_93_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26705,14 +27699,14 @@ _loop1_93_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_93[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -26728,7 +27722,7 @@ _loop1_93_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26742,7 +27736,7 @@ _loop1_93_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26750,13 +27744,13 @@ _loop1_93_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_93_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26764,9 +27758,12 @@ _loop1_93_rule(Parser *p) static asdl_seq * _loop0_94_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26776,14 +27773,14 @@ _loop0_94_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_94[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); @@ -26799,7 +27796,7 @@ _loop0_94_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26816,13 +27813,13 @@ _loop0_94_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_94_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26830,9 +27827,12 @@ _loop0_94_rule(Parser *p) static asdl_seq * _loop1_95_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26842,14 +27842,14 @@ _loop1_95_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_95[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); @@ -26865,7 +27865,7 @@ _loop1_95_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26879,7 +27879,7 @@ _loop1_95_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26887,13 +27887,13 @@ _loop1_95_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_95_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26901,9 +27901,12 @@ _loop1_95_rule(Parser *p) static asdl_seq * _loop1_96_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26913,14 +27916,14 @@ _loop1_96_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_96[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -26936,7 +27939,7 @@ _loop1_96_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26950,7 +27953,7 @@ _loop1_96_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26958,13 +27961,13 @@ _loop1_96_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_96_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26972,9 +27975,12 @@ _loop1_96_rule(Parser *p) static asdl_seq * _loop1_97_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26984,14 +27990,14 @@ _loop1_97_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -27007,7 +28013,7 @@ _loop1_97_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27021,7 +28027,7 @@ _loop1_97_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27029,13 +28035,13 @@ _loop1_97_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_97_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27043,9 +28049,12 @@ _loop1_97_rule(Parser *p) static asdl_seq * _loop0_98_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27055,14 +28064,14 @@ _loop0_98_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_98[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -27078,7 +28087,7 @@ _loop0_98_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27095,13 +28104,13 @@ _loop0_98_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_98_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27109,9 +28118,12 @@ _loop0_98_rule(Parser *p) static asdl_seq * _loop1_99_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27121,14 +28133,14 @@ _loop1_99_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_99[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); @@ -27144,7 +28156,7 @@ _loop1_99_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27158,7 +28170,7 @@ _loop1_99_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27166,13 +28178,13 @@ _loop1_99_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_99_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27180,9 +28192,12 @@ _loop1_99_rule(Parser *p) static asdl_seq * _loop0_100_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27192,14 +28207,14 @@ _loop0_100_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_100[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -27215,7 +28230,7 @@ _loop0_100_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27232,13 +28247,13 @@ _loop0_100_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_100_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27246,10 +28261,13 @@ _loop0_100_rule(Parser *p) static asdl_seq * _loop1_101_rule(Parser *p) { - D(p->level++); - if (p->error_indicator) { - D(p->level--); - return NULL; + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; + return NULL; } void *_res = NULL; int _mark = p->mark; @@ -27258,14 +28276,14 @@ _loop1_101_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_101[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); @@ -27281,7 +28299,7 @@ _loop1_101_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27295,7 +28313,7 @@ _loop1_101_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27303,13 +28321,13 @@ _loop1_101_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_101_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27317,9 +28335,12 @@ _loop1_101_rule(Parser *p) static asdl_seq * _loop0_102_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27329,14 +28350,14 @@ _loop0_102_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_maybe_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_102[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); @@ -27352,7 +28373,7 @@ _loop0_102_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27369,13 +28390,13 @@ _loop0_102_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_102_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27383,9 +28404,12 @@ _loop0_102_rule(Parser *p) static asdl_seq * _loop1_103_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27395,14 +28419,14 @@ _loop1_103_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_maybe_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_103[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); @@ -27418,7 +28442,7 @@ _loop1_103_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27432,7 +28456,7 @@ _loop1_103_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27440,13 +28464,13 @@ _loop1_103_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_103_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27454,9 +28478,12 @@ _loop1_103_rule(Parser *p) static asdl_seq * _loop1_104_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27466,14 +28493,14 @@ _loop1_104_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ('or' conjunction) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_104[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('or' conjunction)")); @@ -27489,7 +28516,7 @@ _loop1_104_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27503,7 +28530,7 @@ _loop1_104_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27511,13 +28538,13 @@ _loop1_104_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_104_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27525,9 +28552,12 @@ _loop1_104_rule(Parser *p) static asdl_seq * _loop1_105_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27537,14 +28567,14 @@ _loop1_105_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ('and' inversion) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_105[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('and' inversion)")); @@ -27560,7 +28590,7 @@ _loop1_105_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27574,7 +28604,7 @@ _loop1_105_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27582,13 +28612,13 @@ _loop1_105_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_105_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27596,9 +28626,12 @@ _loop1_105_rule(Parser *p) static asdl_seq * _loop1_106_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27608,14 +28641,14 @@ _loop1_106_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // compare_op_bitwise_or_pair if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_106[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "compare_op_bitwise_or_pair")); @@ -27631,7 +28664,7 @@ _loop1_106_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27645,7 +28678,7 @@ _loop1_106_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27653,13 +28686,13 @@ _loop1_106_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_106_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27667,16 +28700,19 @@ _loop1_106_rule(Parser *p) static void * _tmp_107_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '!=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_107[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!='")); @@ -27689,7 +28725,7 @@ _tmp_107_rule(Parser *p) _res = _PyPegen_check_barry_as_flufl ( p , tok ) ? NULL : tok; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -27700,7 +28736,7 @@ _tmp_107_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -27708,9 +28744,12 @@ _tmp_107_rule(Parser *p) static asdl_seq * _loop0_109_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27720,14 +28759,14 @@ _loop0_109_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' slice if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_109[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' slice")); @@ -27743,7 +28782,7 @@ _loop0_109_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -27752,7 +28791,7 @@ _loop0_109_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27769,13 +28808,13 @@ _loop0_109_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_109_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27783,16 +28822,19 @@ _loop0_109_rule(Parser *p) static asdl_seq * _gather_108_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // slice _loop0_109 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_108[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slice _loop0_109")); @@ -27814,7 +28856,7 @@ _gather_108_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -27822,16 +28864,19 @@ _gather_108_rule(Parser *p) static void * _tmp_110_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ':' expression? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_110[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':' expression?")); @@ -27847,7 +28892,7 @@ _tmp_110_rule(Parser *p) _res = d; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -27858,7 +28903,7 @@ _tmp_110_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -27866,16 +28911,19 @@ _tmp_110_rule(Parser *p) static void * _tmp_111_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // tuple if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_111[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); @@ -27894,7 +28942,7 @@ _tmp_111_rule(Parser *p) } { // group if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_111[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "group")); @@ -27913,7 +28961,7 @@ _tmp_111_rule(Parser *p) } { // genexp if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_111[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); @@ -27932,7 +28980,7 @@ _tmp_111_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -27940,16 +28988,19 @@ _tmp_111_rule(Parser *p) static void * _tmp_112_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // list if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); @@ -27968,7 +29019,7 @@ _tmp_112_rule(Parser *p) } { // listcomp if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "listcomp")); @@ -27987,7 +29038,7 @@ _tmp_112_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -27995,16 +29046,19 @@ _tmp_112_rule(Parser *p) static void * _tmp_113_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // dict if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dict")); @@ -28023,7 +29077,7 @@ _tmp_113_rule(Parser *p) } { // set if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "set")); @@ -28042,7 +29096,7 @@ _tmp_113_rule(Parser *p) } { // dictcomp if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dictcomp")); @@ -28061,7 +29115,7 @@ _tmp_113_rule(Parser *p) } { // setcomp if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "setcomp")); @@ -28080,7 +29134,7 @@ _tmp_113_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -28088,9 +29142,12 @@ _tmp_113_rule(Parser *p) static asdl_seq * _loop1_114_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -28100,14 +29157,14 @@ _loop1_114_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // STRING if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "STRING")); @@ -28123,7 +29180,7 @@ _loop1_114_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28137,7 +29194,7 @@ _loop1_114_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28145,13 +29202,13 @@ _loop1_114_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_114_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -28159,16 +29216,19 @@ _loop1_114_rule(Parser *p) static void * _tmp_115_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // star_named_expression ',' star_named_expressions? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_115[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?")); @@ -28187,7 +29247,7 @@ _tmp_115_rule(Parser *p) _res = _PyPegen_seq_insert_in_front ( p , y , z ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -28198,7 +29258,7 @@ _tmp_115_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -28206,16 +29266,19 @@ _tmp_115_rule(Parser *p) static void * _tmp_116_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // yield_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_116[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); @@ -28234,7 +29297,7 @@ _tmp_116_rule(Parser *p) } { // named_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_116[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression")); @@ -28253,7 +29316,7 @@ _tmp_116_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -28261,16 +29324,19 @@ _tmp_116_rule(Parser *p) static void * _tmp_117_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // assignment_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); @@ -28289,7 +29355,7 @@ _tmp_117_rule(Parser *p) } { // expression !':=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); @@ -28310,7 +29376,7 @@ _tmp_117_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -28318,9 +29384,12 @@ _tmp_117_rule(Parser *p) static asdl_seq * _loop0_119_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -28330,14 +29399,14 @@ _loop0_119_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' double_starred_kvpair if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_119[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); @@ -28353,7 +29422,7 @@ _loop0_119_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -28362,7 +29431,7 @@ _loop0_119_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28379,13 +29448,13 @@ _loop0_119_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_119_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -28393,16 +29462,19 @@ _loop0_119_rule(Parser *p) static asdl_seq * _gather_118_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // double_starred_kvpair _loop0_119 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_118[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_119")); @@ -28424,7 +29496,7 @@ _gather_118_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -28432,9 +29504,12 @@ _gather_118_rule(Parser *p) static asdl_seq * _loop1_120_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -28444,14 +29519,14 @@ _loop1_120_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // for_if_clause if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_120[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "for_if_clause")); @@ -28467,7 +29542,7 @@ _loop1_120_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28481,7 +29556,7 @@ _loop1_120_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28489,13 +29564,13 @@ _loop1_120_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_120_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -28503,9 +29578,12 @@ _loop1_120_rule(Parser *p) static asdl_seq * _loop0_121_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -28515,14 +29593,14 @@ _loop0_121_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ('if' disjunction) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_121[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); @@ -28538,7 +29616,7 @@ _loop0_121_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28555,13 +29633,13 @@ _loop0_121_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_121_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -28569,9 +29647,12 @@ _loop0_121_rule(Parser *p) static asdl_seq * _loop0_122_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -28581,14 +29662,14 @@ _loop0_122_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ('if' disjunction) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); @@ -28604,7 +29685,7 @@ _loop0_122_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28621,13 +29702,13 @@ _loop0_122_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_122_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -28635,9 +29716,12 @@ _loop0_122_rule(Parser *p) static asdl_seq * _loop0_124_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -28647,14 +29731,14 @@ _loop0_124_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' (starred_expression | (assignment_expression | expression !':=') !'=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); @@ -28670,7 +29754,7 @@ _loop0_124_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -28679,7 +29763,7 @@ _loop0_124_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28696,13 +29780,13 @@ _loop0_124_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_124_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -28711,16 +29795,19 @@ _loop0_124_rule(Parser *p) static asdl_seq * _gather_123_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_124 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_124")); @@ -28742,7 +29829,7 @@ _gather_123_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -28750,16 +29837,19 @@ _gather_123_rule(Parser *p) static void * _tmp_125_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' kwargs if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwargs")); @@ -28775,7 +29865,7 @@ _tmp_125_rule(Parser *p) _res = k; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -28786,7 +29876,7 @@ _tmp_125_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -28794,9 +29884,12 @@ _tmp_125_rule(Parser *p) static asdl_seq * _loop0_127_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -28806,14 +29899,14 @@ _loop0_127_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' kwarg_or_starred if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_127[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); @@ -28829,7 +29922,7 @@ _loop0_127_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -28838,7 +29931,7 @@ _loop0_127_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28855,13 +29948,13 @@ _loop0_127_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_127_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -28869,16 +29962,19 @@ _loop0_127_rule(Parser *p) static asdl_seq * _gather_126_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // kwarg_or_starred _loop0_127 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_126[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_127")); @@ -28900,7 +29996,7 @@ _gather_126_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -28908,9 +30004,12 @@ _gather_126_rule(Parser *p) static asdl_seq * _loop0_129_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -28920,14 +30019,14 @@ _loop0_129_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' kwarg_or_double_starred if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); @@ -28943,7 +30042,7 @@ _loop0_129_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -28952,7 +30051,7 @@ _loop0_129_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28969,13 +30068,13 @@ _loop0_129_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_129_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -28983,16 +30082,19 @@ _loop0_129_rule(Parser *p) static asdl_seq * _gather_128_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // kwarg_or_double_starred _loop0_129 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_129")); @@ -29014,7 +30116,7 @@ _gather_128_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -29022,9 +30124,12 @@ _gather_128_rule(Parser *p) static asdl_seq * _loop0_131_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -29034,14 +30139,14 @@ _loop0_131_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' kwarg_or_starred if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); @@ -29057,7 +30162,7 @@ _loop0_131_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -29066,7 +30171,7 @@ _loop0_131_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -29083,13 +30188,13 @@ _loop0_131_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_131_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -29097,16 +30202,19 @@ _loop0_131_rule(Parser *p) static asdl_seq * _gather_130_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // kwarg_or_starred _loop0_131 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_131")); @@ -29128,7 +30236,7 @@ _gather_130_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -29136,9 +30244,12 @@ _gather_130_rule(Parser *p) static asdl_seq * _loop0_133_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -29148,14 +30259,14 @@ _loop0_133_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' kwarg_or_double_starred if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_133[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); @@ -29171,7 +30282,7 @@ _loop0_133_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -29180,7 +30291,7 @@ _loop0_133_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -29197,13 +30308,13 @@ _loop0_133_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_133_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -29211,16 +30322,19 @@ _loop0_133_rule(Parser *p) static asdl_seq * _gather_132_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // kwarg_or_double_starred _loop0_133 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_133")); @@ -29242,7 +30356,7 @@ _gather_132_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -29250,9 +30364,12 @@ _gather_132_rule(Parser *p) static asdl_seq * _loop0_134_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -29262,14 +30379,14 @@ _loop0_134_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // (',' star_target) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); @@ -29285,7 +30402,7 @@ _loop0_134_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -29302,13 +30419,13 @@ _loop0_134_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_134_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -29316,9 +30433,12 @@ _loop0_134_rule(Parser *p) static asdl_seq * _loop0_136_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -29328,14 +30448,14 @@ _loop0_136_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); @@ -29351,7 +30471,7 @@ _loop0_136_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -29360,7 +30480,7 @@ _loop0_136_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -29377,13 +30497,13 @@ _loop0_136_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_136_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -29391,16 +30511,19 @@ _loop0_136_rule(Parser *p) static asdl_seq * _gather_135_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // star_target _loop0_136 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target _loop0_136")); @@ -29422,7 +30545,7 @@ _gather_135_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -29430,9 +30553,12 @@ _gather_135_rule(Parser *p) static asdl_seq * _loop1_137_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -29442,14 +30568,14 @@ _loop1_137_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // (',' star_target) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); @@ -29465,7 +30591,7 @@ _loop1_137_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -29479,7 +30605,7 @@ _loop1_137_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -29487,13 +30613,13 @@ _loop1_137_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_137_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -29501,16 +30627,19 @@ _loop1_137_rule(Parser *p) static void * _tmp_138_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // !'*' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); @@ -29531,7 +30660,7 @@ _tmp_138_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -29539,9 +30668,12 @@ _tmp_138_rule(Parser *p) static asdl_seq * _loop0_140_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -29551,14 +30683,14 @@ _loop0_140_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' del_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' del_target")); @@ -29574,7 +30706,7 @@ _loop0_140_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -29583,7 +30715,7 @@ _loop0_140_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -29600,13 +30732,13 @@ _loop0_140_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_140_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -29614,16 +30746,19 @@ _loop0_140_rule(Parser *p) static asdl_seq * _gather_139_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // del_target _loop0_140 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "del_target _loop0_140")); @@ -29645,7 +30780,7 @@ _gather_139_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -29653,16 +30788,19 @@ _gather_139_rule(Parser *p) static void * _tmp_141_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // args if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args")); @@ -29681,7 +30819,7 @@ _tmp_141_rule(Parser *p) } { // expression for_if_clauses if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); @@ -29703,7 +30841,7 @@ _tmp_141_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -29711,16 +30849,19 @@ _tmp_141_rule(Parser *p) static void * _tmp_142_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'True' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); @@ -29739,7 +30880,7 @@ _tmp_142_rule(Parser *p) } { // 'False' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); @@ -29758,7 +30899,7 @@ _tmp_142_rule(Parser *p) } { // 'None' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); @@ -29777,7 +30918,7 @@ _tmp_142_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -29785,16 +30926,19 @@ _tmp_142_rule(Parser *p) static void * _tmp_143_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // NAME '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '='")); @@ -29816,7 +30960,7 @@ _tmp_143_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -29824,16 +30968,19 @@ _tmp_143_rule(Parser *p) static void * _tmp_144_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // NAME STRING if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME STRING")); @@ -29855,7 +31002,7 @@ _tmp_144_rule(Parser *p) } { // SOFT_KEYWORD if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); @@ -29874,7 +31021,7 @@ _tmp_144_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -29882,16 +31029,19 @@ _tmp_144_rule(Parser *p) static void * _tmp_145_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'else' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else'")); @@ -29910,7 +31060,7 @@ _tmp_145_rule(Parser *p) } { // ':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); @@ -29929,7 +31079,7 @@ _tmp_145_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -29937,16 +31087,19 @@ _tmp_145_rule(Parser *p) static void * _tmp_146_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); @@ -29965,7 +31118,7 @@ _tmp_146_rule(Parser *p) } { // ':=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); @@ -29984,7 +31137,7 @@ _tmp_146_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -29992,16 +31145,19 @@ _tmp_146_rule(Parser *p) static void * _tmp_147_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // list if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); @@ -30020,7 +31176,7 @@ _tmp_147_rule(Parser *p) } { // tuple if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); @@ -30039,7 +31195,7 @@ _tmp_147_rule(Parser *p) } { // genexp if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); @@ -30058,7 +31214,7 @@ _tmp_147_rule(Parser *p) } { // 'True' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); @@ -30077,7 +31233,7 @@ _tmp_147_rule(Parser *p) } { // 'None' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); @@ -30096,7 +31252,7 @@ _tmp_147_rule(Parser *p) } { // 'False' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); @@ -30115,7 +31271,7 @@ _tmp_147_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -30123,16 +31279,19 @@ _tmp_147_rule(Parser *p) static void * _tmp_148_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); @@ -30151,7 +31310,7 @@ _tmp_148_rule(Parser *p) } { // ':=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); @@ -30170,7 +31329,7 @@ _tmp_148_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -30178,9 +31337,12 @@ _tmp_148_rule(Parser *p) static asdl_seq * _loop0_149_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -30190,14 +31352,14 @@ _loop0_149_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // star_named_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expressions")); @@ -30213,7 +31375,7 @@ _loop0_149_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -30230,13 +31392,13 @@ _loop0_149_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_149_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -30244,9 +31406,12 @@ _loop0_149_rule(Parser *p) static asdl_seq * _loop0_150_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -30256,14 +31421,14 @@ _loop0_150_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // (star_targets '=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); @@ -30279,7 +31444,7 @@ _loop0_150_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -30296,13 +31461,13 @@ _loop0_150_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_150_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -30310,9 +31475,12 @@ _loop0_150_rule(Parser *p) static asdl_seq * _loop0_151_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -30322,14 +31490,14 @@ _loop0_151_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // (star_targets '=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); @@ -30345,7 +31513,7 @@ _loop0_151_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -30362,13 +31530,13 @@ _loop0_151_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_151_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -30376,16 +31544,19 @@ _loop0_151_rule(Parser *p) static void * _tmp_152_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // yield_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); @@ -30404,7 +31575,7 @@ _tmp_152_rule(Parser *p) } { // star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); @@ -30423,7 +31594,7 @@ _tmp_152_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -30431,16 +31602,19 @@ _tmp_152_rule(Parser *p) static void * _tmp_153_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '[' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); @@ -30459,7 +31633,7 @@ _tmp_153_rule(Parser *p) } { // '(' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); @@ -30478,7 +31652,7 @@ _tmp_153_rule(Parser *p) } { // '{' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); @@ -30497,7 +31671,7 @@ _tmp_153_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -30505,16 +31679,19 @@ _tmp_153_rule(Parser *p) static void * _tmp_154_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '[' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); @@ -30533,7 +31710,7 @@ _tmp_154_rule(Parser *p) } { // '{' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); @@ -30552,7 +31729,7 @@ _tmp_154_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -30560,16 +31737,19 @@ _tmp_154_rule(Parser *p) static void * _tmp_155_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '[' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); @@ -30588,7 +31768,7 @@ _tmp_155_rule(Parser *p) } { // '{' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); @@ -30607,7 +31787,7 @@ _tmp_155_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -30615,9 +31795,12 @@ _tmp_155_rule(Parser *p) static asdl_seq * _loop0_156_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -30627,14 +31810,14 @@ _loop0_156_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -30650,7 +31833,7 @@ _loop0_156_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -30667,13 +31850,13 @@ _loop0_156_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_156_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -30681,9 +31864,12 @@ _loop0_156_rule(Parser *p) static asdl_seq * _loop1_157_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -30693,14 +31879,14 @@ _loop1_157_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); @@ -30716,7 +31902,7 @@ _loop1_157_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -30730,7 +31916,7 @@ _loop1_157_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30738,13 +31924,13 @@ _loop1_157_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_157_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -30752,9 +31938,12 @@ _loop1_157_rule(Parser *p) static asdl_seq * _loop0_158_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -30764,14 +31953,14 @@ _loop0_158_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_158[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -30787,7 +31976,7 @@ _loop0_158_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -30804,13 +31993,13 @@ _loop0_158_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_158_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -30818,9 +32007,12 @@ _loop0_158_rule(Parser *p) static asdl_seq * _loop1_159_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -30830,14 +32022,14 @@ _loop1_159_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); @@ -30853,7 +32045,7 @@ _loop1_159_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -30867,7 +32059,7 @@ _loop1_159_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30875,13 +32067,13 @@ _loop1_159_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_159_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -30889,16 +32081,19 @@ _loop1_159_rule(Parser *p) static void * _tmp_160_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); @@ -30917,7 +32112,7 @@ _tmp_160_rule(Parser *p) } { // ',' (')' | '**') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); @@ -30939,7 +32134,7 @@ _tmp_160_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -30947,16 +32142,19 @@ _tmp_160_rule(Parser *p) static void * _tmp_161_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); @@ -30975,7 +32173,7 @@ _tmp_161_rule(Parser *p) } { // ',' (':' | '**') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); @@ -30997,7 +32195,7 @@ _tmp_161_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -31005,16 +32203,19 @@ _tmp_161_rule(Parser *p) static void * _tmp_162_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); @@ -31033,7 +32234,7 @@ _tmp_162_rule(Parser *p) } { // ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); @@ -31052,7 +32253,7 @@ _tmp_162_rule(Parser *p) } { // ':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); @@ -31071,7 +32272,7 @@ _tmp_162_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -31079,9 +32280,12 @@ _tmp_162_rule(Parser *p) static asdl_seq * _loop0_164_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -31091,14 +32295,14 @@ _loop0_164_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' (expression ['as' star_target]) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_164[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); @@ -31114,7 +32318,7 @@ _loop0_164_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -31123,7 +32327,7 @@ _loop0_164_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -31140,13 +32344,13 @@ _loop0_164_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_164_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -31154,16 +32358,19 @@ _loop0_164_rule(Parser *p) static asdl_seq * _gather_163_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // (expression ['as' star_target]) _loop0_164 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_163[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_164")); @@ -31185,7 +32392,7 @@ _gather_163_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -31193,9 +32400,12 @@ _gather_163_rule(Parser *p) static asdl_seq * _loop0_166_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -31205,14 +32415,14 @@ _loop0_166_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' (expressions ['as' star_target]) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); @@ -31228,7 +32438,7 @@ _loop0_166_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -31237,7 +32447,7 @@ _loop0_166_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -31254,13 +32464,13 @@ _loop0_166_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_166_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -31268,16 +32478,19 @@ _loop0_166_rule(Parser *p) static asdl_seq * _gather_165_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // (expressions ['as' star_target]) _loop0_166 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_166")); @@ -31299,7 +32512,7 @@ _gather_165_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -31307,9 +32520,12 @@ _gather_165_rule(Parser *p) static asdl_seq * _loop0_168_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -31319,14 +32535,14 @@ _loop0_168_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' (expression ['as' star_target]) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); @@ -31342,7 +32558,7 @@ _loop0_168_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -31351,7 +32567,7 @@ _loop0_168_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -31368,13 +32584,13 @@ _loop0_168_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_168_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -31382,16 +32598,19 @@ _loop0_168_rule(Parser *p) static asdl_seq * _gather_167_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // (expression ['as' star_target]) _loop0_168 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_168")); @@ -31413,7 +32632,7 @@ _gather_167_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -31421,9 +32640,12 @@ _gather_167_rule(Parser *p) static asdl_seq * _loop0_170_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -31433,14 +32655,14 @@ _loop0_170_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' (expressions ['as' star_target]) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_170[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); @@ -31456,7 +32678,7 @@ _loop0_170_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -31465,7 +32687,7 @@ _loop0_170_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -31482,13 +32704,13 @@ _loop0_170_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_170_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -31496,16 +32718,19 @@ _loop0_170_rule(Parser *p) static asdl_seq * _gather_169_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // (expressions ['as' star_target]) _loop0_170 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_170")); @@ -31527,7 +32752,7 @@ _gather_169_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -31535,16 +32760,19 @@ _gather_169_rule(Parser *p) static void * _tmp_171_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'except' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_171[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except'")); @@ -31563,7 +32791,7 @@ _tmp_171_rule(Parser *p) } { // 'finally' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_171[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally'")); @@ -31582,7 +32810,7 @@ _tmp_171_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -31590,16 +32818,19 @@ _tmp_171_rule(Parser *p) static void * _tmp_172_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_172[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); @@ -31621,7 +32852,7 @@ _tmp_172_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -31629,16 +32860,19 @@ _tmp_172_rule(Parser *p) static void * _tmp_173_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_173[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); @@ -31660,7 +32894,7 @@ _tmp_173_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -31668,16 +32902,19 @@ _tmp_173_rule(Parser *p) static void * _tmp_174_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_174[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); @@ -31699,7 +32936,7 @@ _tmp_174_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -31707,16 +32944,19 @@ _tmp_174_rule(Parser *p) static void * _tmp_175_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // positional_patterns ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_175[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); @@ -31738,7 +32978,7 @@ _tmp_175_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -31746,16 +32986,19 @@ _tmp_175_rule(Parser *p) static void * _tmp_176_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '->' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_176[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); @@ -31777,7 +33020,7 @@ _tmp_176_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -31785,16 +33028,19 @@ _tmp_176_rule(Parser *p) static void * _tmp_177_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '(' arguments? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_177[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); @@ -31820,7 +33066,7 @@ _tmp_177_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -31828,9 +33074,12 @@ _tmp_177_rule(Parser *p) static asdl_seq * _loop0_179_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -31840,14 +33089,14 @@ _loop0_179_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' double_starred_kvpair if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); @@ -31863,7 +33112,7 @@ _loop0_179_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -31872,7 +33121,7 @@ _loop0_179_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -31889,13 +33138,13 @@ _loop0_179_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_179_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -31903,16 +33152,19 @@ _loop0_179_rule(Parser *p) static asdl_seq * _gather_178_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // double_starred_kvpair _loop0_179 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_178[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_179")); @@ -31934,7 +33186,7 @@ _gather_178_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -31942,16 +33194,19 @@ _gather_178_rule(Parser *p) static void * _tmp_180_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); @@ -31970,7 +33225,7 @@ _tmp_180_rule(Parser *p) } { // ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); @@ -31989,7 +33244,7 @@ _tmp_180_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -31997,16 +33252,19 @@ _tmp_180_rule(Parser *p) static void * _tmp_181_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // star_targets '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_181[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); @@ -32022,7 +33280,7 @@ _tmp_181_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -32033,7 +33291,7 @@ _tmp_181_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32041,16 +33299,19 @@ _tmp_181_rule(Parser *p) static void * _tmp_182_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '.' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); @@ -32069,7 +33330,7 @@ _tmp_182_rule(Parser *p) } { // '...' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); @@ -32088,7 +33349,7 @@ _tmp_182_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32096,16 +33357,19 @@ _tmp_182_rule(Parser *p) static void * _tmp_183_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '.' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); @@ -32124,7 +33388,7 @@ _tmp_183_rule(Parser *p) } { // '...' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); @@ -32143,7 +33407,7 @@ _tmp_183_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32151,16 +33415,19 @@ _tmp_183_rule(Parser *p) static void * _tmp_184_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '@' named_expression NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_184[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); @@ -32179,7 +33446,7 @@ _tmp_184_rule(Parser *p) _res = f; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -32190,7 +33457,7 @@ _tmp_184_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32198,16 +33465,19 @@ _tmp_184_rule(Parser *p) static void * _tmp_185_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' star_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_185[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression")); @@ -32223,7 +33493,7 @@ _tmp_185_rule(Parser *p) _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -32234,7 +33504,7 @@ _tmp_185_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32242,16 +33512,19 @@ _tmp_185_rule(Parser *p) static void * _tmp_186_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_186[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); @@ -32267,7 +33540,7 @@ _tmp_186_rule(Parser *p) _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -32278,7 +33551,7 @@ _tmp_186_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32286,16 +33559,19 @@ _tmp_186_rule(Parser *p) static void * _tmp_187_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'or' conjunction if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_187[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); @@ -32311,7 +33587,7 @@ _tmp_187_rule(Parser *p) _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -32322,7 +33598,7 @@ _tmp_187_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32330,16 +33606,19 @@ _tmp_187_rule(Parser *p) static void * _tmp_188_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'and' inversion if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_188[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion")); @@ -32355,7 +33634,7 @@ _tmp_188_rule(Parser *p) _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -32366,7 +33645,7 @@ _tmp_188_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32374,16 +33653,19 @@ _tmp_188_rule(Parser *p) static void * _tmp_189_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'if' disjunction if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_189[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); @@ -32399,7 +33681,7 @@ _tmp_189_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -32410,7 +33692,7 @@ _tmp_189_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32418,16 +33700,19 @@ _tmp_189_rule(Parser *p) static void * _tmp_190_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'if' disjunction if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_190[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); @@ -32443,7 +33728,7 @@ _tmp_190_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -32454,7 +33739,7 @@ _tmp_190_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32462,16 +33747,19 @@ _tmp_190_rule(Parser *p) static void * _tmp_191_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // starred_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_191[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); @@ -32490,7 +33778,7 @@ _tmp_191_rule(Parser *p) } { // (assignment_expression | expression !':=') !'=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_191[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); @@ -32511,7 +33799,7 @@ _tmp_191_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32519,16 +33807,19 @@ _tmp_191_rule(Parser *p) static void * _tmp_192_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_192[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); @@ -32544,7 +33835,7 @@ _tmp_192_rule(Parser *p) _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -32555,7 +33846,7 @@ _tmp_192_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32563,16 +33854,19 @@ _tmp_192_rule(Parser *p) static void * _tmp_193_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_193[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); @@ -32588,7 +33882,7 @@ _tmp_193_rule(Parser *p) _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -32599,7 +33893,7 @@ _tmp_193_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32607,16 +33901,19 @@ _tmp_193_rule(Parser *p) static void * _tmp_194_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // star_targets '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_194[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); @@ -32638,7 +33935,7 @@ _tmp_194_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32646,16 +33943,19 @@ _tmp_194_rule(Parser *p) static void * _tmp_195_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // star_targets '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_195[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); @@ -32677,7 +33977,7 @@ _tmp_195_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32685,16 +33985,19 @@ _tmp_195_rule(Parser *p) static void * _tmp_196_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); @@ -32713,7 +34016,7 @@ _tmp_196_rule(Parser *p) } { // '**' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); @@ -32732,7 +34035,7 @@ _tmp_196_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32740,16 +34043,19 @@ _tmp_196_rule(Parser *p) static void * _tmp_197_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); @@ -32768,7 +34074,7 @@ _tmp_197_rule(Parser *p) } { // '**' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); @@ -32787,7 +34093,7 @@ _tmp_197_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32795,16 +34101,19 @@ _tmp_197_rule(Parser *p) static void * _tmp_198_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // expression ['as' star_target] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_198[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); @@ -32827,7 +34136,7 @@ _tmp_198_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32835,16 +34144,19 @@ _tmp_198_rule(Parser *p) static void * _tmp_199_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // expressions ['as' star_target] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_199[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); @@ -32867,7 +34179,7 @@ _tmp_199_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32875,16 +34187,19 @@ _tmp_199_rule(Parser *p) static void * _tmp_200_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // expression ['as' star_target] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_200[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); @@ -32907,7 +34222,7 @@ _tmp_200_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32915,16 +34230,19 @@ _tmp_200_rule(Parser *p) static void * _tmp_201_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // expressions ['as' star_target] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); @@ -32947,7 +34265,7 @@ _tmp_201_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -32955,16 +34273,19 @@ _tmp_201_rule(Parser *p) static void * _tmp_202_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // assignment_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); @@ -32983,7 +34304,7 @@ _tmp_202_rule(Parser *p) } { // expression !':=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); @@ -33004,7 +34325,7 @@ _tmp_202_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -33012,16 +34333,19 @@ _tmp_202_rule(Parser *p) static void * _tmp_203_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_203[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); @@ -33043,7 +34367,7 @@ _tmp_203_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -33051,16 +34375,19 @@ _tmp_203_rule(Parser *p) static void * _tmp_204_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_204[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); @@ -33082,7 +34409,7 @@ _tmp_204_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -33090,16 +34417,19 @@ _tmp_204_rule(Parser *p) static void * _tmp_205_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_205[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); @@ -33121,7 +34451,7 @@ _tmp_205_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -33129,16 +34459,19 @@ _tmp_205_rule(Parser *p) static void * _tmp_206_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_206[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); @@ -33160,7 +34493,7 @@ _tmp_206_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } diff --git a/Parser/pegen.c b/Parser/pegen.c index e37aaf7975bdd..bae073cb5b347 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -1341,6 +1341,7 @@ void * _PyPegen_run_parser(Parser *p) { void *res = _PyPegen_parse(p); + assert(p->level == 0); if (res == NULL) { if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_SyntaxError)) { return NULL; diff --git a/Tools/peg_generator/pegen/c_generator.py b/Tools/peg_generator/pegen/c_generator.py index 3c3baef7286c7..49cfb720b1b24 100644 --- a/Tools/peg_generator/pegen/c_generator.py +++ b/Tools/peg_generator/pegen/c_generator.py @@ -37,6 +37,8 @@ # define D(x) #endif +# define MAXSTACK 6000 + """ @@ -357,10 +359,14 @@ def __init__( self.skip_actions = skip_actions def add_level(self) -> None: - self.print("D(p->level++);") + self.print("if (p->level++ == MAXSTACK) {") + with self.indent(): + self.print("p->error_indicator = 1;") + self.print("PyErr_NoMemory();") + self.print("}") def remove_level(self) -> None: - self.print("D(p->level--);") + self.print("p->level--;") def add_return(self, ret_val: str) -> None: self.remove_level() @@ -536,9 +542,10 @@ def _set_up_rule_memoization(self, node: Rule, result_type: str) -> None: self.print("p->in_raw_rule++;") self.print(f"void *_raw = {node.name}_raw(p);") self.print("p->in_raw_rule--;") - self.print("if (p->error_indicator)") + self.print("if (p->error_indicator) {") with self.indent(): - self.print("return NULL;") + self.add_return("NULL") + self.print("}") self.print("if (_raw == NULL || p->mark <= _resmark)") with self.indent(): self.print("break;") From webhook-mailer at python.org Mon Dec 20 12:18:23 2021 From: webhook-mailer at python.org (pablogsal) Date: Mon, 20 Dec 2021 17:18:23 -0000 Subject: [Python-checkins] [3.9] bpo-46110: Add a recursion check to avoid stack overflow in the PEG parser (GH-30177) (#30215) Message-ID: https://github.com/python/cpython/commit/e5cf31d3c2b30d12f238c6ab26d15855eefb2a8a commit: e5cf31d3c2b30d12f238c6ab26d15855eefb2a8a branch: 3.9 author: Pablo Galindo Salgado committer: pablogsal date: 2021-12-20T17:18:13Z summary: [3.9] bpo-46110: Add a recursion check to avoid stack overflow in the PEG parser (GH-30177) (#30215) Co-authored-by: Batuhan Taskaya . (cherry picked from commit e9898bf153d26059261ffef11f7643ae991e2a4c) Co-authored-by: Pablo Galindo Salgado files: A Misc/NEWS.d/next/Core and Builtins/2021-12-18-02-37-07.bpo-46110.B6hAfu.rst M Lib/test/test_syntax.py M Parser/pegen/parse.c M Tools/peg_generator/pegen/c_generator.py diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 46f27d0444364..2f151b44a418d 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -1004,6 +1004,14 @@ def test_syntax_error_on_deeply_nested_blocks(self): """ self._check_error(source, "too many statically nested blocks") + @support.cpython_only + def test_error_on_parser_stack_overflow(self): + source = "-" * 100000 + "4" + for mode in ["exec", "eval", "single"]: + with self.subTest(mode=mode): + with self.assertRaises(MemoryError): + compile(source, "", mode) + def test_main(): support.run_unittest(SyntaxTestCase) diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-18-02-37-07.bpo-46110.B6hAfu.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-18-02-37-07.bpo-46110.B6hAfu.rst new file mode 100644 index 0000000000000..593d2855972c4 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-18-02-37-07.bpo-46110.B6hAfu.rst @@ -0,0 +1,2 @@ +Add a maximum recursion check to the PEG parser to avoid stack overflow. +Patch by Pablo Galindo diff --git a/Parser/pegen/parse.c b/Parser/pegen/parse.c index b80e27f3c622a..105b0faa200e0 100644 --- a/Parser/pegen/parse.c +++ b/Parser/pegen/parse.c @@ -7,6 +7,8 @@ extern int Py_DebugFlag; #else #define D(x) #endif + +# define MAXSTACK 6000 static const int n_keyword_lists = 15; static KeywordToken *reserved_keywords[] = { (KeywordToken[]) {{NULL, -1}}, @@ -712,16 +714,19 @@ static void *_tmp_155_rule(Parser *p); static mod_ty file_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } mod_ty _res = NULL; int _mark = p->mark; { // statements? $ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> file[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "statements? $")); @@ -737,7 +742,7 @@ file_rule(Parser *p) _res = _PyPegen_make_module ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -748,7 +753,7 @@ file_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -756,16 +761,19 @@ file_rule(Parser *p) static mod_ty interactive_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } mod_ty _res = NULL; int _mark = p->mark; { // statement_newline if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> interactive[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "statement_newline")); @@ -778,7 +786,7 @@ interactive_rule(Parser *p) _res = Interactive ( a , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -789,7 +797,7 @@ interactive_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -797,16 +805,19 @@ interactive_rule(Parser *p) static mod_ty eval_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } mod_ty _res = NULL; int _mark = p->mark; { // expressions NEWLINE* $ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> eval[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions NEWLINE* $")); @@ -825,7 +836,7 @@ eval_rule(Parser *p) _res = Expression ( a , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -836,7 +847,7 @@ eval_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -844,16 +855,19 @@ eval_rule(Parser *p) static mod_ty func_type_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } mod_ty _res = NULL; int _mark = p->mark; { // '(' type_expressions? ')' '->' expression NEWLINE* $ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> func_type[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' type_expressions? ')' '->' expression NEWLINE* $")); @@ -884,7 +898,7 @@ func_type_rule(Parser *p) _res = FunctionType ( a , b , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -895,7 +909,7 @@ func_type_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -903,16 +917,19 @@ func_type_rule(Parser *p) static expr_ty fstring_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> fstring[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); @@ -931,7 +948,7 @@ fstring_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -946,16 +963,19 @@ fstring_rule(Parser *p) static asdl_seq* type_expressions_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // ','.expression+ ',' '*' expression ',' '**' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.expression+ ',' '*' expression ',' '**' expression")); @@ -986,7 +1006,7 @@ type_expressions_rule(Parser *p) _res = _PyPegen_seq_append_to_end ( p , CHECK ( _PyPegen_seq_append_to_end ( p , a , b ) ) , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -997,7 +1017,7 @@ type_expressions_rule(Parser *p) } { // ','.expression+ ',' '*' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.expression+ ',' '*' expression")); @@ -1019,7 +1039,7 @@ type_expressions_rule(Parser *p) _res = _PyPegen_seq_append_to_end ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1030,7 +1050,7 @@ type_expressions_rule(Parser *p) } { // ','.expression+ ',' '**' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.expression+ ',' '**' expression")); @@ -1052,7 +1072,7 @@ type_expressions_rule(Parser *p) _res = _PyPegen_seq_append_to_end ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1063,7 +1083,7 @@ type_expressions_rule(Parser *p) } { // '*' expression ',' '**' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' expression ',' '**' expression")); @@ -1088,7 +1108,7 @@ type_expressions_rule(Parser *p) _res = _PyPegen_seq_append_to_end ( p , CHECK ( _PyPegen_singleton_seq ( p , a ) ) , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1099,7 +1119,7 @@ type_expressions_rule(Parser *p) } { // '*' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' expression")); @@ -1115,7 +1135,7 @@ type_expressions_rule(Parser *p) _res = _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1126,7 +1146,7 @@ type_expressions_rule(Parser *p) } { // '**' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' expression")); @@ -1142,7 +1162,7 @@ type_expressions_rule(Parser *p) _res = _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1153,7 +1173,7 @@ type_expressions_rule(Parser *p) } { // ','.expression+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.expression+")); @@ -1172,7 +1192,7 @@ type_expressions_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1180,16 +1200,19 @@ type_expressions_rule(Parser *p) static asdl_seq* statements_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // statement+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statements[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "statement+")); @@ -1202,7 +1225,7 @@ statements_rule(Parser *p) _res = _PyPegen_seq_flatten ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1213,7 +1236,7 @@ statements_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1221,16 +1244,19 @@ statements_rule(Parser *p) static asdl_seq* statement_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // compound_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statement[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "compound_stmt")); @@ -1243,7 +1269,7 @@ statement_rule(Parser *p) _res = _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1254,7 +1280,7 @@ statement_rule(Parser *p) } { // simple_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statement[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "simple_stmt")); @@ -1273,7 +1299,7 @@ statement_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1281,16 +1307,19 @@ statement_rule(Parser *p) static asdl_seq* statement_newline_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -1299,7 +1328,7 @@ statement_newline_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // compound_stmt NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statement_newline[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "compound_stmt NEWLINE")); @@ -1315,7 +1344,7 @@ statement_newline_rule(Parser *p) _res = _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1326,7 +1355,7 @@ statement_newline_rule(Parser *p) } { // simple_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statement_newline[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "simple_stmt")); @@ -1345,7 +1374,7 @@ statement_newline_rule(Parser *p) } { // NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statement_newline[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); @@ -1357,7 +1386,7 @@ statement_newline_rule(Parser *p) D(fprintf(stderr, "%*c+ statement_newline[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -1367,7 +1396,7 @@ statement_newline_rule(Parser *p) _res = _PyPegen_singleton_seq ( p , CHECK ( _Py_Pass ( EXTRA ) ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1378,7 +1407,7 @@ statement_newline_rule(Parser *p) } { // $ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statement_newline[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "$")); @@ -1391,7 +1420,7 @@ statement_newline_rule(Parser *p) _res = _PyPegen_interactive_exit ( p ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1402,7 +1431,7 @@ statement_newline_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1410,16 +1439,19 @@ statement_newline_rule(Parser *p) static asdl_seq* simple_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // small_stmt !';' NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "small_stmt !';' NEWLINE")); @@ -1437,7 +1469,7 @@ simple_stmt_rule(Parser *p) _res = _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1448,7 +1480,7 @@ simple_stmt_rule(Parser *p) } { // ';'.small_stmt+ ';'? NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "';'.small_stmt+ ';'? NEWLINE")); @@ -1468,7 +1500,7 @@ simple_stmt_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1479,7 +1511,7 @@ simple_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1500,20 +1532,23 @@ simple_stmt_rule(Parser *p) static stmt_ty small_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; if (_PyPegen_is_memoized(p, small_stmt_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -1522,7 +1557,7 @@ small_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // assignment if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> small_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment")); @@ -1541,7 +1576,7 @@ small_stmt_rule(Parser *p) } { // star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> small_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); @@ -1553,7 +1588,7 @@ small_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ small_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -1563,7 +1598,7 @@ small_stmt_rule(Parser *p) _res = _Py_Expr ( e , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1574,7 +1609,7 @@ small_stmt_rule(Parser *p) } { // &'return' return_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> small_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'return' return_stmt")); @@ -1595,7 +1630,7 @@ small_stmt_rule(Parser *p) } { // &('import' | 'from') import_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> small_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('import' | 'from') import_stmt")); @@ -1616,7 +1651,7 @@ small_stmt_rule(Parser *p) } { // &'raise' raise_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> small_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'raise' raise_stmt")); @@ -1637,7 +1672,7 @@ small_stmt_rule(Parser *p) } { // 'pass' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> small_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'pass'")); @@ -1649,7 +1684,7 @@ small_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ small_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'pass'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -1659,7 +1694,7 @@ small_stmt_rule(Parser *p) _res = _Py_Pass ( EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1670,7 +1705,7 @@ small_stmt_rule(Parser *p) } { // &'del' del_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> small_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'del' del_stmt")); @@ -1691,7 +1726,7 @@ small_stmt_rule(Parser *p) } { // &'yield' yield_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> small_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'yield' yield_stmt")); @@ -1712,7 +1747,7 @@ small_stmt_rule(Parser *p) } { // &'assert' assert_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> small_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'assert' assert_stmt")); @@ -1733,7 +1768,7 @@ small_stmt_rule(Parser *p) } { // 'break' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> small_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'break'")); @@ -1745,7 +1780,7 @@ small_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ small_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'break'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -1755,7 +1790,7 @@ small_stmt_rule(Parser *p) _res = _Py_Break ( EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1766,7 +1801,7 @@ small_stmt_rule(Parser *p) } { // 'continue' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> small_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'continue'")); @@ -1778,7 +1813,7 @@ small_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ small_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'continue'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -1788,7 +1823,7 @@ small_stmt_rule(Parser *p) _res = _Py_Continue ( EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1799,7 +1834,7 @@ small_stmt_rule(Parser *p) } { // &'global' global_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> small_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'global' global_stmt")); @@ -1820,7 +1855,7 @@ small_stmt_rule(Parser *p) } { // &'nonlocal' nonlocal_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> small_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'nonlocal' nonlocal_stmt")); @@ -1842,7 +1877,7 @@ small_stmt_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, small_stmt_type, _res); - D(p->level--); + p->level--; return _res; } @@ -1857,16 +1892,19 @@ small_stmt_rule(Parser *p) static stmt_ty compound_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; { // &('def' | '@' | ASYNC) function_def if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('def' | '@' | ASYNC) function_def")); @@ -1887,7 +1925,7 @@ compound_stmt_rule(Parser *p) } { // &'if' if_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'if' if_stmt")); @@ -1908,7 +1946,7 @@ compound_stmt_rule(Parser *p) } { // &('class' | '@') class_def if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('class' | '@') class_def")); @@ -1929,7 +1967,7 @@ compound_stmt_rule(Parser *p) } { // &('with' | ASYNC) with_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('with' | ASYNC) with_stmt")); @@ -1950,7 +1988,7 @@ compound_stmt_rule(Parser *p) } { // &('for' | ASYNC) for_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('for' | ASYNC) for_stmt")); @@ -1971,7 +2009,7 @@ compound_stmt_rule(Parser *p) } { // &'try' try_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'try' try_stmt")); @@ -1992,7 +2030,7 @@ compound_stmt_rule(Parser *p) } { // &'while' while_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'while' while_stmt")); @@ -2013,7 +2051,7 @@ compound_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -2026,16 +2064,19 @@ compound_stmt_rule(Parser *p) static stmt_ty assignment_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -2044,7 +2085,7 @@ assignment_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME ':' expression ['=' annotated_rhs] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME ':' expression ['=' annotated_rhs]")); @@ -2065,7 +2106,7 @@ assignment_rule(Parser *p) D(fprintf(stderr, "%*c+ assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME ':' expression ['=' annotated_rhs]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2075,7 +2116,7 @@ assignment_rule(Parser *p) _res = CHECK_VERSION ( 6 , "Variable annotation syntax is" , _Py_AnnAssign ( CHECK ( _PyPegen_set_expr_context ( p , a , Store ) ) , b , c , 1 , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2086,7 +2127,7 @@ assignment_rule(Parser *p) } { // ('(' single_target ')' | single_subscript_attribute_target) ':' expression ['=' annotated_rhs] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('(' single_target ')' | single_subscript_attribute_target) ':' expression ['=' annotated_rhs]")); @@ -2107,7 +2148,7 @@ assignment_rule(Parser *p) D(fprintf(stderr, "%*c+ assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "('(' single_target ')' | single_subscript_attribute_target) ':' expression ['=' annotated_rhs]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2117,7 +2158,7 @@ assignment_rule(Parser *p) _res = CHECK_VERSION ( 6 , "Variable annotations syntax is" , _Py_AnnAssign ( a , b , c , 0 , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2128,7 +2169,7 @@ assignment_rule(Parser *p) } { // ((star_targets '='))+ (yield_expr | star_expressions) !'=' TYPE_COMMENT? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))+ (yield_expr | star_expressions) !'=' TYPE_COMMENT?")); @@ -2148,7 +2189,7 @@ assignment_rule(Parser *p) D(fprintf(stderr, "%*c+ assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "((star_targets '='))+ (yield_expr | star_expressions) !'=' TYPE_COMMENT?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2158,7 +2199,7 @@ assignment_rule(Parser *p) _res = _Py_Assign ( a , b , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2169,7 +2210,7 @@ assignment_rule(Parser *p) } { // single_target augassign ~ (yield_expr | star_expressions) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "single_target augassign ~ (yield_expr | star_expressions)")); @@ -2190,7 +2231,7 @@ assignment_rule(Parser *p) D(fprintf(stderr, "%*c+ assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "single_target augassign ~ (yield_expr | star_expressions)")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2200,7 +2241,7 @@ assignment_rule(Parser *p) _res = _Py_AugAssign ( a , b -> kind , c , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2209,13 +2250,13 @@ assignment_rule(Parser *p) D(fprintf(stderr, "%*c%s assignment[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "single_target augassign ~ (yield_expr | star_expressions)")); if (_cut_var) { - D(p->level--); + p->level--; return NULL; } } if (p->call_invalid_rules) { // invalid_assignment if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_assignment")); @@ -2234,7 +2275,7 @@ assignment_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -2255,16 +2296,19 @@ assignment_rule(Parser *p) static AugOperator* augassign_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } AugOperator* _res = NULL; int _mark = p->mark; { // '+=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+='")); @@ -2277,7 +2321,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , Add ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2288,7 +2332,7 @@ augassign_rule(Parser *p) } { // '-=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-='")); @@ -2301,7 +2345,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , Sub ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2312,7 +2356,7 @@ augassign_rule(Parser *p) } { // '*=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*='")); @@ -2325,7 +2369,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , Mult ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2336,7 +2380,7 @@ augassign_rule(Parser *p) } { // '@=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@='")); @@ -2349,7 +2393,7 @@ augassign_rule(Parser *p) _res = CHECK_VERSION ( 5 , "The '@' operator is" , _PyPegen_augoperator ( p , MatMult ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2360,7 +2404,7 @@ augassign_rule(Parser *p) } { // '/=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'/='")); @@ -2373,7 +2417,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , Div ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2384,7 +2428,7 @@ augassign_rule(Parser *p) } { // '%=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'%='")); @@ -2397,7 +2441,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , Mod ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2408,7 +2452,7 @@ augassign_rule(Parser *p) } { // '&=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'&='")); @@ -2421,7 +2465,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , BitAnd ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2432,7 +2476,7 @@ augassign_rule(Parser *p) } { // '|=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'|='")); @@ -2445,7 +2489,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , BitOr ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2456,7 +2500,7 @@ augassign_rule(Parser *p) } { // '^=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'^='")); @@ -2469,7 +2513,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , BitXor ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2480,7 +2524,7 @@ augassign_rule(Parser *p) } { // '<<=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'<<='")); @@ -2493,7 +2537,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , LShift ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2504,7 +2548,7 @@ augassign_rule(Parser *p) } { // '>>=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'>>='")); @@ -2517,7 +2561,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , RShift ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2528,7 +2572,7 @@ augassign_rule(Parser *p) } { // '**=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**='")); @@ -2541,7 +2585,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , Pow ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2552,7 +2596,7 @@ augassign_rule(Parser *p) } { // '//=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'//='")); @@ -2565,7 +2609,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , FloorDiv ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2576,7 +2620,7 @@ augassign_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -2584,16 +2628,19 @@ augassign_rule(Parser *p) static stmt_ty global_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -2602,7 +2649,7 @@ global_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'global' ','.NAME+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> global_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'global' ','.NAME+")); @@ -2617,7 +2664,7 @@ global_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ global_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'global' ','.NAME+")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2627,7 +2674,7 @@ global_stmt_rule(Parser *p) _res = _Py_Global ( CHECK ( _PyPegen_map_names_to_ids ( p , a ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2638,7 +2685,7 @@ global_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -2646,16 +2693,19 @@ global_stmt_rule(Parser *p) static stmt_ty nonlocal_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -2664,7 +2714,7 @@ nonlocal_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'nonlocal' ','.NAME+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> nonlocal_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'nonlocal' ','.NAME+")); @@ -2679,7 +2729,7 @@ nonlocal_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ nonlocal_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'nonlocal' ','.NAME+")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2689,7 +2739,7 @@ nonlocal_stmt_rule(Parser *p) _res = _Py_Nonlocal ( CHECK ( _PyPegen_map_names_to_ids ( p , a ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2700,7 +2750,7 @@ nonlocal_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -2708,16 +2758,19 @@ nonlocal_stmt_rule(Parser *p) static stmt_ty yield_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -2726,7 +2779,7 @@ yield_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // yield_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> yield_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); @@ -2738,7 +2791,7 @@ yield_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ yield_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2748,7 +2801,7 @@ yield_stmt_rule(Parser *p) _res = _Py_Expr ( y , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2759,7 +2812,7 @@ yield_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -2767,16 +2820,19 @@ yield_stmt_rule(Parser *p) static stmt_ty assert_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -2785,7 +2841,7 @@ assert_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'assert' expression [',' expression] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> assert_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'assert' expression [',' expression]")); @@ -2803,7 +2859,7 @@ assert_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ assert_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'assert' expression [',' expression]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2813,7 +2869,7 @@ assert_stmt_rule(Parser *p) _res = _Py_Assert ( a , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2824,7 +2880,7 @@ assert_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -2832,16 +2888,19 @@ assert_stmt_rule(Parser *p) static stmt_ty del_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -2850,7 +2909,7 @@ del_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'del' del_targets &(';' | NEWLINE) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'del' del_targets &(';' | NEWLINE)")); @@ -2867,7 +2926,7 @@ del_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ del_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'del' del_targets &(';' | NEWLINE)")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2877,7 +2936,7 @@ del_stmt_rule(Parser *p) _res = _Py_Delete ( a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2888,7 +2947,7 @@ del_stmt_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_del_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_del_stmt")); @@ -2907,7 +2966,7 @@ del_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -2915,16 +2974,19 @@ del_stmt_rule(Parser *p) static stmt_ty import_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; { // import_name if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "import_name")); @@ -2943,7 +3005,7 @@ import_stmt_rule(Parser *p) } { // import_from if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "import_from")); @@ -2962,7 +3024,7 @@ import_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -2970,16 +3032,19 @@ import_stmt_rule(Parser *p) static stmt_ty import_name_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -2988,7 +3053,7 @@ import_name_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'import' dotted_as_names if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_name[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'import' dotted_as_names")); @@ -3003,7 +3068,7 @@ import_name_rule(Parser *p) D(fprintf(stderr, "%*c+ import_name[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'import' dotted_as_names")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3013,7 +3078,7 @@ import_name_rule(Parser *p) _res = _Py_Import ( a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3024,7 +3089,7 @@ import_name_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3034,16 +3099,19 @@ import_name_rule(Parser *p) static stmt_ty import_from_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3052,7 +3120,7 @@ import_from_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'from' (('.' | '...'))* dotted_name 'import' import_from_targets if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from' (('.' | '...'))* dotted_name 'import' import_from_targets")); @@ -3076,7 +3144,7 @@ import_from_rule(Parser *p) D(fprintf(stderr, "%*c+ import_from[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'from' (('.' | '...'))* dotted_name 'import' import_from_targets")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3086,7 +3154,7 @@ import_from_rule(Parser *p) _res = _Py_ImportFrom ( b -> v . Name . id , c , _PyPegen_seq_count_dots ( a ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3097,7 +3165,7 @@ import_from_rule(Parser *p) } { // 'from' (('.' | '...'))+ 'import' import_from_targets if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from' (('.' | '...'))+ 'import' import_from_targets")); @@ -3118,7 +3186,7 @@ import_from_rule(Parser *p) D(fprintf(stderr, "%*c+ import_from[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'from' (('.' | '...'))+ 'import' import_from_targets")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3128,7 +3196,7 @@ import_from_rule(Parser *p) _res = _Py_ImportFrom ( NULL , b , _PyPegen_seq_count_dots ( a ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3139,7 +3207,7 @@ import_from_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3151,16 +3219,19 @@ import_from_rule(Parser *p) static asdl_seq* import_from_targets_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // '(' import_from_as_names ','? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' import_from_as_names ','? ')'")); @@ -3183,7 +3254,7 @@ import_from_targets_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3194,7 +3265,7 @@ import_from_targets_rule(Parser *p) } { // import_from_as_names !',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "import_from_as_names !','")); @@ -3215,7 +3286,7 @@ import_from_targets_rule(Parser *p) } { // '*' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*'")); @@ -3228,7 +3299,7 @@ import_from_targets_rule(Parser *p) _res = _PyPegen_singleton_seq ( p , CHECK ( _PyPegen_alias_for_star ( p ) ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3239,7 +3310,7 @@ import_from_targets_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_import_from_targets if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_import_from_targets")); @@ -3258,7 +3329,7 @@ import_from_targets_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3266,16 +3337,19 @@ import_from_targets_rule(Parser *p) static asdl_seq* import_from_as_names_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // ','.import_from_as_name+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from_as_names[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.import_from_as_name+")); @@ -3288,7 +3362,7 @@ import_from_as_names_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3299,7 +3373,7 @@ import_from_as_names_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3307,16 +3381,19 @@ import_from_as_names_rule(Parser *p) static alias_ty import_from_as_name_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } alias_ty _res = NULL; int _mark = p->mark; { // NAME ['as' NAME] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from_as_name[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME ['as' NAME]")); @@ -3332,7 +3409,7 @@ import_from_as_name_rule(Parser *p) _res = _Py_alias ( a -> v . Name . id , ( b ) ? ( ( expr_ty ) b ) -> v . Name . id : NULL , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3343,7 +3420,7 @@ import_from_as_name_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3351,16 +3428,19 @@ import_from_as_name_rule(Parser *p) static asdl_seq* dotted_as_names_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // ','.dotted_as_name+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dotted_as_names[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.dotted_as_name+")); @@ -3373,7 +3453,7 @@ dotted_as_names_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3384,7 +3464,7 @@ dotted_as_names_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3392,16 +3472,19 @@ dotted_as_names_rule(Parser *p) static alias_ty dotted_as_name_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } alias_ty _res = NULL; int _mark = p->mark; { // dotted_name ['as' NAME] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dotted_as_name[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dotted_name ['as' NAME]")); @@ -3417,7 +3500,7 @@ dotted_as_name_rule(Parser *p) _res = _Py_alias ( a -> v . Name . id , ( b ) ? ( ( expr_ty ) b ) -> v . Name . id : NULL , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3428,7 +3511,7 @@ dotted_as_name_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3438,10 +3521,13 @@ static expr_ty dotted_name_raw(Parser *); static expr_ty dotted_name_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, dotted_name_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -3449,35 +3535,40 @@ dotted_name_rule(Parser *p) while (1) { int tmpvar_0 = _PyPegen_update_memo(p, _mark, dotted_name_type, _res); if (tmpvar_0) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; void *_raw = dotted_name_raw(p); - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty dotted_name_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // dotted_name '.' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dotted_name[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dotted_name '.' NAME")); @@ -3496,7 +3587,7 @@ dotted_name_raw(Parser *p) _res = _PyPegen_join_names_with_dot ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3507,7 +3598,7 @@ dotted_name_raw(Parser *p) } { // NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dotted_name[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); @@ -3526,7 +3617,7 @@ dotted_name_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3536,16 +3627,19 @@ dotted_name_raw(Parser *p) static stmt_ty if_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3554,7 +3648,7 @@ if_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'if' named_expression ':' block elif_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> if_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' named_expression ':' block elif_stmt")); @@ -3578,7 +3672,7 @@ if_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ if_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' named_expression ':' block elif_stmt")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3588,7 +3682,7 @@ if_stmt_rule(Parser *p) _res = _Py_If ( a , b , CHECK ( _PyPegen_singleton_seq ( p , c ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3599,7 +3693,7 @@ if_stmt_rule(Parser *p) } { // 'if' named_expression ':' block else_block? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> if_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' named_expression ':' block else_block?")); @@ -3623,7 +3717,7 @@ if_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ if_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' named_expression ':' block else_block?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3633,7 +3727,7 @@ if_stmt_rule(Parser *p) _res = _Py_If ( a , b , c , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3644,7 +3738,7 @@ if_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3654,16 +3748,19 @@ if_stmt_rule(Parser *p) static stmt_ty elif_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3672,7 +3769,7 @@ elif_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'elif' named_expression ':' block elif_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> elif_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'elif' named_expression ':' block elif_stmt")); @@ -3696,7 +3793,7 @@ elif_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ elif_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'elif' named_expression ':' block elif_stmt")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3706,7 +3803,7 @@ elif_stmt_rule(Parser *p) _res = _Py_If ( a , b , CHECK ( _PyPegen_singleton_seq ( p , c ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3717,7 +3814,7 @@ elif_stmt_rule(Parser *p) } { // 'elif' named_expression ':' block else_block? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> elif_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'elif' named_expression ':' block else_block?")); @@ -3741,7 +3838,7 @@ elif_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ elif_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'elif' named_expression ':' block else_block?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3751,7 +3848,7 @@ elif_stmt_rule(Parser *p) _res = _Py_If ( a , b , c , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3762,7 +3859,7 @@ elif_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3770,16 +3867,19 @@ elif_stmt_rule(Parser *p) static asdl_seq* else_block_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // 'else' ':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> else_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else' ':' block")); @@ -3798,7 +3898,7 @@ else_block_rule(Parser *p) _res = b; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3809,7 +3909,7 @@ else_block_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3817,16 +3917,19 @@ else_block_rule(Parser *p) static stmt_ty while_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3835,7 +3938,7 @@ while_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'while' named_expression ':' block else_block? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> while_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'while' named_expression ':' block else_block?")); @@ -3859,7 +3962,7 @@ while_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ while_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'while' named_expression ':' block else_block?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3869,7 +3972,7 @@ while_stmt_rule(Parser *p) _res = _Py_While ( a , b , c , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3880,7 +3983,7 @@ while_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3891,16 +3994,19 @@ while_stmt_rule(Parser *p) static stmt_ty for_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3909,7 +4015,7 @@ for_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'for' star_targets 'in' ~ star_expressions ':' TYPE_COMMENT? block else_block? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'for' star_targets 'in' ~ star_expressions ':' TYPE_COMMENT? block else_block?")); @@ -3945,7 +4051,7 @@ for_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ for_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'for' star_targets 'in' ~ star_expressions ':' TYPE_COMMENT? block else_block?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3955,7 +4061,7 @@ for_stmt_rule(Parser *p) _res = _Py_For ( t , ex , b , el , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3964,13 +4070,13 @@ for_stmt_rule(Parser *p) D(fprintf(stderr, "%*c%s for_stmt[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'for' star_targets 'in' ~ star_expressions ':' TYPE_COMMENT? block else_block?")); if (_cut_var) { - D(p->level--); + p->level--; return NULL; } } { // ASYNC 'for' star_targets 'in' ~ star_expressions ':' TYPE_COMMENT? block else_block? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC 'for' star_targets 'in' ~ star_expressions ':' TYPE_COMMENT? block else_block?")); @@ -4009,7 +4115,7 @@ for_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ for_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC 'for' star_targets 'in' ~ star_expressions ':' TYPE_COMMENT? block else_block?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4019,7 +4125,7 @@ for_stmt_rule(Parser *p) _res = CHECK_VERSION ( 5 , "Async for loops are" , _Py_AsyncFor ( t , ex , b , el , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4028,13 +4134,13 @@ for_stmt_rule(Parser *p) D(fprintf(stderr, "%*c%s for_stmt[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "ASYNC 'for' star_targets 'in' ~ star_expressions ':' TYPE_COMMENT? block else_block?")); if (_cut_var) { - D(p->level--); + p->level--; return NULL; } } if (p->call_invalid_rules) { // invalid_for_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_for_target")); @@ -4053,7 +4159,7 @@ for_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4065,16 +4171,19 @@ for_stmt_rule(Parser *p) static stmt_ty with_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -4083,7 +4192,7 @@ with_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'with' '(' ','.with_item+ ','? ')' ':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'with' '(' ','.with_item+ ','? ')' ':' block")); @@ -4114,7 +4223,7 @@ with_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'with' '(' ','.with_item+ ','? ')' ':' block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4124,7 +4233,7 @@ with_stmt_rule(Parser *p) _res = _Py_With ( a , b , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4135,7 +4244,7 @@ with_stmt_rule(Parser *p) } { // 'with' ','.with_item+ ':' TYPE_COMMENT? block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'with' ','.with_item+ ':' TYPE_COMMENT? block")); @@ -4159,7 +4268,7 @@ with_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'with' ','.with_item+ ':' TYPE_COMMENT? block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4169,7 +4278,7 @@ with_stmt_rule(Parser *p) _res = _Py_With ( a , b , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4180,7 +4289,7 @@ with_stmt_rule(Parser *p) } { // ASYNC 'with' '(' ','.with_item+ ','? ')' ':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC 'with' '(' ','.with_item+ ','? ')' ':' block")); @@ -4214,7 +4323,7 @@ with_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC 'with' '(' ','.with_item+ ','? ')' ':' block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4224,7 +4333,7 @@ with_stmt_rule(Parser *p) _res = CHECK_VERSION ( 5 , "Async with statements are" , _Py_AsyncWith ( a , b , NULL , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4235,7 +4344,7 @@ with_stmt_rule(Parser *p) } { // ASYNC 'with' ','.with_item+ ':' TYPE_COMMENT? block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC 'with' ','.with_item+ ':' TYPE_COMMENT? block")); @@ -4262,7 +4371,7 @@ with_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC 'with' ','.with_item+ ':' TYPE_COMMENT? block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4272,7 +4381,7 @@ with_stmt_rule(Parser *p) _res = CHECK_VERSION ( 5 , "Async with statements are" , _Py_AsyncWith ( a , b , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4283,7 +4392,7 @@ with_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4294,16 +4403,19 @@ with_stmt_rule(Parser *p) static withitem_ty with_item_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } withitem_ty _res = NULL; int _mark = p->mark; { // expression 'as' star_target &(',' | ')' | ':') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_item[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression 'as' star_target &(',' | ')' | ':')")); @@ -4324,7 +4436,7 @@ with_item_rule(Parser *p) _res = _Py_withitem ( e , t , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4335,7 +4447,7 @@ with_item_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_with_item if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_item[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_with_item")); @@ -4354,7 +4466,7 @@ with_item_rule(Parser *p) } { // expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_item[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression")); @@ -4367,7 +4479,7 @@ with_item_rule(Parser *p) _res = _Py_withitem ( e , NULL , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4378,7 +4490,7 @@ with_item_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4388,16 +4500,19 @@ with_item_rule(Parser *p) static stmt_ty try_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -4406,7 +4521,7 @@ try_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'try' ':' block finally_block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> try_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'try' ':' block finally_block")); @@ -4427,7 +4542,7 @@ try_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' ':' block finally_block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4437,7 +4552,7 @@ try_stmt_rule(Parser *p) _res = _Py_Try ( b , NULL , NULL , f , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4448,7 +4563,7 @@ try_stmt_rule(Parser *p) } { // 'try' ':' block except_block+ else_block? finally_block? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> try_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'try' ':' block except_block+ else_block? finally_block?")); @@ -4475,7 +4590,7 @@ try_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' ':' block except_block+ else_block? finally_block?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4485,7 +4600,7 @@ try_stmt_rule(Parser *p) _res = _Py_Try ( b , ex , el , f , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4496,7 +4611,7 @@ try_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4504,16 +4619,19 @@ try_stmt_rule(Parser *p) static excepthandler_ty except_block_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } excepthandler_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -4522,7 +4640,7 @@ except_block_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'except' expression ['as' NAME] ':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> except_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' expression ['as' NAME] ':' block")); @@ -4546,7 +4664,7 @@ except_block_rule(Parser *p) D(fprintf(stderr, "%*c+ except_block[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' expression ['as' NAME] ':' block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4556,7 +4674,7 @@ except_block_rule(Parser *p) _res = _Py_ExceptHandler ( e , ( t ) ? ( ( expr_ty ) t ) -> v . Name . id : NULL , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4567,7 +4685,7 @@ except_block_rule(Parser *p) } { // 'except' ':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> except_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' ':' block")); @@ -4585,7 +4703,7 @@ except_block_rule(Parser *p) D(fprintf(stderr, "%*c+ except_block[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' ':' block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4595,7 +4713,7 @@ except_block_rule(Parser *p) _res = _Py_ExceptHandler ( NULL , NULL , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4606,7 +4724,7 @@ except_block_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4614,16 +4732,19 @@ except_block_rule(Parser *p) static asdl_seq* finally_block_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // 'finally' ':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> finally_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally' ':' block")); @@ -4642,7 +4763,7 @@ finally_block_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4653,7 +4774,7 @@ finally_block_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4661,16 +4782,19 @@ finally_block_rule(Parser *p) static stmt_ty return_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -4679,7 +4803,7 @@ return_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'return' star_expressions? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> return_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'return' star_expressions?")); @@ -4694,7 +4818,7 @@ return_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ return_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'return' star_expressions?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4704,7 +4828,7 @@ return_stmt_rule(Parser *p) _res = _Py_Return ( a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4715,7 +4839,7 @@ return_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4723,16 +4847,19 @@ return_stmt_rule(Parser *p) static stmt_ty raise_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -4741,7 +4868,7 @@ raise_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'raise' expression ['from' expression] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> raise_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'raise' expression ['from' expression]")); @@ -4759,7 +4886,7 @@ raise_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ raise_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'raise' expression ['from' expression]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4769,7 +4896,7 @@ raise_stmt_rule(Parser *p) _res = _Py_Raise ( a , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4780,7 +4907,7 @@ raise_stmt_rule(Parser *p) } { // 'raise' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> raise_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'raise'")); @@ -4792,7 +4919,7 @@ raise_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ raise_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'raise'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4802,7 +4929,7 @@ raise_stmt_rule(Parser *p) _res = _Py_Raise ( NULL , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4813,7 +4940,7 @@ raise_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4821,16 +4948,19 @@ raise_stmt_rule(Parser *p) static stmt_ty function_def_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; { // decorators function_def_raw if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> function_def[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "decorators function_def_raw")); @@ -4846,7 +4976,7 @@ function_def_rule(Parser *p) _res = _PyPegen_function_def_decorators ( p , d , f ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4857,7 +4987,7 @@ function_def_rule(Parser *p) } { // function_def_raw if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> function_def[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "function_def_raw")); @@ -4876,7 +5006,7 @@ function_def_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4886,16 +5016,19 @@ function_def_rule(Parser *p) static stmt_ty function_def_raw_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -4904,7 +5037,7 @@ function_def_raw_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'def' NAME '(' params? ')' ['->' expression] ':' func_type_comment? block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> function_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'def' NAME '(' params? ')' ['->' expression] ':' func_type_comment? block")); @@ -4940,7 +5073,7 @@ function_def_raw_rule(Parser *p) D(fprintf(stderr, "%*c+ function_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'def' NAME '(' params? ')' ['->' expression] ':' func_type_comment? block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4950,7 +5083,7 @@ function_def_raw_rule(Parser *p) _res = _Py_FunctionDef ( n -> v . Name . id , ( params ) ? params : CHECK ( _PyPegen_empty_arguments ( p ) ) , b , NULL , a , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4961,7 +5094,7 @@ function_def_raw_rule(Parser *p) } { // ASYNC 'def' NAME '(' params? ')' ['->' expression] ':' func_type_comment? block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> function_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC 'def' NAME '(' params? ')' ['->' expression] ':' func_type_comment? block")); @@ -5000,7 +5133,7 @@ function_def_raw_rule(Parser *p) D(fprintf(stderr, "%*c+ function_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC 'def' NAME '(' params? ')' ['->' expression] ':' func_type_comment? block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -5010,7 +5143,7 @@ function_def_raw_rule(Parser *p) _res = CHECK_VERSION ( 5 , "Async functions are" , _Py_AsyncFunctionDef ( n -> v . Name . id , ( params ) ? params : CHECK ( _PyPegen_empty_arguments ( p ) ) , b , NULL , a , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5021,7 +5154,7 @@ function_def_raw_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5032,16 +5165,19 @@ function_def_raw_rule(Parser *p) static Token* func_type_comment_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } Token* _res = NULL; int _mark = p->mark; { // NEWLINE TYPE_COMMENT &(NEWLINE INDENT) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> func_type_comment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE TYPE_COMMENT &(NEWLINE INDENT)")); @@ -5059,7 +5195,7 @@ func_type_comment_rule(Parser *p) _res = t; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5070,7 +5206,7 @@ func_type_comment_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_double_type_comments if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> func_type_comment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_double_type_comments")); @@ -5089,7 +5225,7 @@ func_type_comment_rule(Parser *p) } { // TYPE_COMMENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> func_type_comment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "TYPE_COMMENT")); @@ -5108,7 +5244,7 @@ func_type_comment_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5116,16 +5252,19 @@ func_type_comment_rule(Parser *p) static arguments_ty params_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arguments_ty _res = NULL; int _mark = p->mark; if (p->call_invalid_rules) { // invalid_parameters if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> params[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_parameters")); @@ -5144,7 +5283,7 @@ params_rule(Parser *p) } { // parameters if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> params[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "parameters")); @@ -5163,7 +5302,7 @@ params_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5176,16 +5315,19 @@ params_rule(Parser *p) static arguments_ty parameters_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arguments_ty _res = NULL; int _mark = p->mark; { // slash_no_default param_no_default* param_with_default* star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_no_default param_no_default* param_with_default* star_etc?")); @@ -5207,7 +5349,7 @@ parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , a , NULL , b , c , d ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5218,7 +5360,7 @@ parameters_rule(Parser *p) } { // slash_with_default param_with_default* star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default param_with_default* star_etc?")); @@ -5237,7 +5379,7 @@ parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , NULL , a , NULL , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5248,7 +5390,7 @@ parameters_rule(Parser *p) } { // param_no_default+ param_with_default* star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default+ param_with_default* star_etc?")); @@ -5267,7 +5409,7 @@ parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , NULL , NULL , a , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5278,7 +5420,7 @@ parameters_rule(Parser *p) } { // param_with_default+ star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default+ star_etc?")); @@ -5294,7 +5436,7 @@ parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , NULL , NULL , NULL , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5305,7 +5447,7 @@ parameters_rule(Parser *p) } { // star_etc if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_etc")); @@ -5318,7 +5460,7 @@ parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , NULL , NULL , NULL , NULL , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5329,7 +5471,7 @@ parameters_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5337,16 +5479,19 @@ parameters_rule(Parser *p) static asdl_seq* slash_no_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // param_no_default+ '/' ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slash_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default+ '/' ','")); @@ -5365,7 +5510,7 @@ slash_no_default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5376,7 +5521,7 @@ slash_no_default_rule(Parser *p) } { // param_no_default+ '/' &')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slash_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default+ '/' &')'")); @@ -5394,7 +5539,7 @@ slash_no_default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5405,7 +5550,7 @@ slash_no_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5415,16 +5560,19 @@ slash_no_default_rule(Parser *p) static SlashWithDefault* slash_with_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } SlashWithDefault* _res = NULL; int _mark = p->mark; { // param_no_default* param_with_default+ '/' ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slash_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default* param_with_default+ '/' ','")); @@ -5446,7 +5594,7 @@ slash_with_default_rule(Parser *p) _res = _PyPegen_slash_with_default ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5457,7 +5605,7 @@ slash_with_default_rule(Parser *p) } { // param_no_default* param_with_default+ '/' &')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slash_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default* param_with_default+ '/' &')'")); @@ -5478,7 +5626,7 @@ slash_with_default_rule(Parser *p) _res = _PyPegen_slash_with_default ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5489,7 +5637,7 @@ slash_with_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5501,16 +5649,19 @@ slash_with_default_rule(Parser *p) static StarEtc* star_etc_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } StarEtc* _res = NULL; int _mark = p->mark; { // '*' param_no_default param_maybe_default* kwds? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' param_no_default param_maybe_default* kwds?")); @@ -5532,7 +5683,7 @@ star_etc_rule(Parser *p) _res = _PyPegen_star_etc ( p , a , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5543,7 +5694,7 @@ star_etc_rule(Parser *p) } { // '*' ',' param_maybe_default+ kwds? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' ',' param_maybe_default+ kwds?")); @@ -5565,7 +5716,7 @@ star_etc_rule(Parser *p) _res = _PyPegen_star_etc ( p , NULL , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5576,7 +5727,7 @@ star_etc_rule(Parser *p) } { // kwds if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwds")); @@ -5589,7 +5740,7 @@ star_etc_rule(Parser *p) _res = _PyPegen_star_etc ( p , NULL , NULL , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5600,7 +5751,7 @@ star_etc_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_star_etc if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_star_etc")); @@ -5619,7 +5770,7 @@ star_etc_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5627,16 +5778,19 @@ star_etc_rule(Parser *p) static arg_ty kwds_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arg_ty _res = NULL; int _mark = p->mark; { // '**' param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwds[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' param_no_default")); @@ -5652,7 +5806,7 @@ kwds_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5663,7 +5817,7 @@ kwds_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5671,16 +5825,19 @@ kwds_rule(Parser *p) static arg_ty param_no_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arg_ty _res = NULL; int _mark = p->mark; { // param ',' TYPE_COMMENT? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param ',' TYPE_COMMENT?")); @@ -5699,7 +5856,7 @@ param_no_default_rule(Parser *p) _res = _PyPegen_add_type_comment_to_arg ( p , a , tc ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5710,7 +5867,7 @@ param_no_default_rule(Parser *p) } { // param TYPE_COMMENT? &')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param TYPE_COMMENT? &')'")); @@ -5728,7 +5885,7 @@ param_no_default_rule(Parser *p) _res = _PyPegen_add_type_comment_to_arg ( p , a , tc ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5739,7 +5896,7 @@ param_no_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5747,16 +5904,19 @@ param_no_default_rule(Parser *p) static NameDefaultPair* param_with_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } NameDefaultPair* _res = NULL; int _mark = p->mark; { // param default ',' TYPE_COMMENT? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param default ',' TYPE_COMMENT?")); @@ -5778,7 +5938,7 @@ param_with_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , tc ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5789,7 +5949,7 @@ param_with_default_rule(Parser *p) } { // param default TYPE_COMMENT? &')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param default TYPE_COMMENT? &')'")); @@ -5810,7 +5970,7 @@ param_with_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , tc ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5821,7 +5981,7 @@ param_with_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5831,16 +5991,19 @@ param_with_default_rule(Parser *p) static NameDefaultPair* param_maybe_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } NameDefaultPair* _res = NULL; int _mark = p->mark; { // param default? ',' TYPE_COMMENT? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param_maybe_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param default? ',' TYPE_COMMENT?")); @@ -5862,7 +6025,7 @@ param_maybe_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , tc ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5873,7 +6036,7 @@ param_maybe_default_rule(Parser *p) } { // param default? TYPE_COMMENT? &')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param_maybe_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param default? TYPE_COMMENT? &')'")); @@ -5894,7 +6057,7 @@ param_maybe_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , tc ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5905,7 +6068,7 @@ param_maybe_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5913,16 +6076,19 @@ param_maybe_default_rule(Parser *p) static arg_ty param_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arg_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -5931,7 +6097,7 @@ param_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME annotation? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME annotation?")); @@ -5946,7 +6112,7 @@ param_rule(Parser *p) D(fprintf(stderr, "%*c+ param[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME annotation?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -5956,7 +6122,7 @@ param_rule(Parser *p) _res = _Py_arg ( a -> v . Name . id , b , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5967,7 +6133,7 @@ param_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5975,16 +6141,19 @@ param_rule(Parser *p) static expr_ty annotation_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // ':' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> annotation[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':' expression")); @@ -6000,7 +6169,7 @@ annotation_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6011,7 +6180,7 @@ annotation_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6019,16 +6188,19 @@ annotation_rule(Parser *p) static expr_ty default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // '=' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'=' expression")); @@ -6044,7 +6216,7 @@ default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6055,7 +6227,7 @@ default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6063,16 +6235,19 @@ default_rule(Parser *p) static asdl_seq* decorators_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // (('@' named_expression NEWLINE))+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> decorators[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(('@' named_expression NEWLINE))+")); @@ -6085,7 +6260,7 @@ decorators_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6096,7 +6271,7 @@ decorators_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6104,16 +6279,19 @@ decorators_rule(Parser *p) static stmt_ty class_def_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; { // decorators class_def_raw if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_def[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "decorators class_def_raw")); @@ -6129,7 +6307,7 @@ class_def_rule(Parser *p) _res = _PyPegen_class_def_decorators ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6140,7 +6318,7 @@ class_def_rule(Parser *p) } { // class_def_raw if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_def[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "class_def_raw")); @@ -6159,7 +6337,7 @@ class_def_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6167,16 +6345,19 @@ class_def_rule(Parser *p) static stmt_ty class_def_raw_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6185,7 +6366,7 @@ class_def_raw_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'class' NAME ['(' arguments? ')'] ':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class' NAME ['(' arguments? ')'] ':' block")); @@ -6209,7 +6390,7 @@ class_def_raw_rule(Parser *p) D(fprintf(stderr, "%*c+ class_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'class' NAME ['(' arguments? ')'] ':' block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6219,7 +6400,7 @@ class_def_raw_rule(Parser *p) _res = _Py_ClassDef ( a -> v . Name . id , ( b ) ? ( ( expr_ty ) b ) -> v . Call . args : NULL , ( b ) ? ( ( expr_ty ) b ) -> v . Call . keywords : NULL , c , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6230,7 +6411,7 @@ class_def_raw_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6238,20 +6419,23 @@ class_def_raw_rule(Parser *p) static asdl_seq* block_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; if (_PyPegen_is_memoized(p, block_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; { // NEWLINE INDENT statements DEDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT statements DEDENT")); @@ -6273,7 +6457,7 @@ block_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6284,7 +6468,7 @@ block_rule(Parser *p) } { // simple_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "simple_stmt")); @@ -6303,7 +6487,7 @@ block_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_block")); @@ -6323,7 +6507,7 @@ block_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, block_type, _res); - D(p->level--); + p->level--; return _res; } @@ -6334,16 +6518,19 @@ block_rule(Parser *p) static expr_ty star_expressions_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6352,7 +6539,7 @@ star_expressions_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // star_expression ((',' star_expression))+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expression ((',' star_expression))+ ','?")); @@ -6371,7 +6558,7 @@ star_expressions_rule(Parser *p) D(fprintf(stderr, "%*c+ star_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expression ((',' star_expression))+ ','?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6381,7 +6568,7 @@ star_expressions_rule(Parser *p) _res = _Py_Tuple ( CHECK ( _PyPegen_seq_insert_in_front ( p , a , b ) ) , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6392,7 +6579,7 @@ star_expressions_rule(Parser *p) } { // star_expression ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expression ','")); @@ -6407,7 +6594,7 @@ star_expressions_rule(Parser *p) D(fprintf(stderr, "%*c+ star_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expression ','")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6417,7 +6604,7 @@ star_expressions_rule(Parser *p) _res = _Py_Tuple ( CHECK ( _PyPegen_singleton_seq ( p , a ) ) , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6428,7 +6615,7 @@ star_expressions_rule(Parser *p) } { // star_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expression")); @@ -6447,7 +6634,7 @@ star_expressions_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6455,20 +6642,23 @@ star_expressions_rule(Parser *p) static expr_ty star_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, star_expression_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6477,7 +6667,7 @@ star_expression_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '*' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' bitwise_or")); @@ -6492,7 +6682,7 @@ star_expression_rule(Parser *p) D(fprintf(stderr, "%*c+ star_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' bitwise_or")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6502,7 +6692,7 @@ star_expression_rule(Parser *p) _res = _Py_Starred ( a , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6513,7 +6703,7 @@ star_expression_rule(Parser *p) } { // expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression")); @@ -6533,7 +6723,7 @@ star_expression_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, star_expression_type, _res); - D(p->level--); + p->level--; return _res; } @@ -6541,16 +6731,19 @@ star_expression_rule(Parser *p) static asdl_seq* star_named_expressions_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // ','.star_named_expression+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_named_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.star_named_expression+ ','?")); @@ -6567,7 +6760,7 @@ star_named_expressions_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6578,7 +6771,7 @@ star_named_expressions_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6586,16 +6779,19 @@ star_named_expressions_rule(Parser *p) static expr_ty star_named_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6604,7 +6800,7 @@ star_named_expression_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '*' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' bitwise_or")); @@ -6619,7 +6815,7 @@ star_named_expression_rule(Parser *p) D(fprintf(stderr, "%*c+ star_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' bitwise_or")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6629,7 +6825,7 @@ star_named_expression_rule(Parser *p) _res = _Py_Starred ( a , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6640,7 +6836,7 @@ star_named_expression_rule(Parser *p) } { // named_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression")); @@ -6659,7 +6855,7 @@ star_named_expression_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6667,16 +6863,19 @@ star_named_expression_rule(Parser *p) static expr_ty named_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6685,7 +6884,7 @@ named_expression_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME ':=' ~ expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME ':=' ~ expression")); @@ -6706,7 +6905,7 @@ named_expression_rule(Parser *p) D(fprintf(stderr, "%*c+ named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME ':=' ~ expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6716,7 +6915,7 @@ named_expression_rule(Parser *p) _res = _Py_NamedExpr ( CHECK ( _PyPegen_set_expr_context ( p , a , Store ) ) , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6725,13 +6924,13 @@ named_expression_rule(Parser *p) D(fprintf(stderr, "%*c%s named_expression[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME ':=' ~ expression")); if (_cut_var) { - D(p->level--); + p->level--; return NULL; } } { // expression !':=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); @@ -6752,7 +6951,7 @@ named_expression_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_named_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_named_expression")); @@ -6771,7 +6970,7 @@ named_expression_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6779,16 +6978,19 @@ named_expression_rule(Parser *p) static expr_ty annotated_rhs_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // yield_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> annotated_rhs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); @@ -6807,7 +7009,7 @@ annotated_rhs_rule(Parser *p) } { // star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> annotated_rhs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); @@ -6826,7 +7028,7 @@ annotated_rhs_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6834,16 +7036,19 @@ annotated_rhs_rule(Parser *p) static expr_ty expressions_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6852,7 +7057,7 @@ expressions_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // expression ((',' expression))+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ((',' expression))+ ','?")); @@ -6871,7 +7076,7 @@ expressions_rule(Parser *p) D(fprintf(stderr, "%*c+ expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ((',' expression))+ ','?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6881,7 +7086,7 @@ expressions_rule(Parser *p) _res = _Py_Tuple ( CHECK ( _PyPegen_seq_insert_in_front ( p , a , b ) ) , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6892,7 +7097,7 @@ expressions_rule(Parser *p) } { // expression ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ','")); @@ -6907,7 +7112,7 @@ expressions_rule(Parser *p) D(fprintf(stderr, "%*c+ expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ','")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6917,7 +7122,7 @@ expressions_rule(Parser *p) _res = _Py_Tuple ( CHECK ( _PyPegen_singleton_seq ( p , a ) ) , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6928,7 +7133,7 @@ expressions_rule(Parser *p) } { // expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression")); @@ -6947,7 +7152,7 @@ expressions_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6955,20 +7160,23 @@ expressions_rule(Parser *p) static expr_ty expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, expression_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6977,7 +7185,7 @@ expression_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // disjunction 'if' disjunction 'else' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction 'else' expression")); @@ -7001,7 +7209,7 @@ expression_rule(Parser *p) D(fprintf(stderr, "%*c+ expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction 'else' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7011,7 +7219,7 @@ expression_rule(Parser *p) _res = _Py_IfExp ( b , a , c , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7022,7 +7230,7 @@ expression_rule(Parser *p) } { // disjunction if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "disjunction")); @@ -7041,7 +7249,7 @@ expression_rule(Parser *p) } { // lambdef if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambdef")); @@ -7061,7 +7269,7 @@ expression_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, expression_type, _res); - D(p->level--); + p->level--; return _res; } @@ -7069,16 +7277,19 @@ expression_rule(Parser *p) static expr_ty lambdef_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -7087,7 +7298,7 @@ lambdef_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'lambda' lambda_params? ':' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambdef[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'lambda' lambda_params? ':' expression")); @@ -7108,7 +7319,7 @@ lambdef_rule(Parser *p) D(fprintf(stderr, "%*c+ lambdef[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'lambda' lambda_params? ':' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7118,7 +7329,7 @@ lambdef_rule(Parser *p) _res = _Py_Lambda ( ( a ) ? a : CHECK ( _PyPegen_empty_arguments ( p ) ) , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7129,7 +7340,7 @@ lambdef_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7137,16 +7348,19 @@ lambdef_rule(Parser *p) static arguments_ty lambda_params_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arguments_ty _res = NULL; int _mark = p->mark; if (p->call_invalid_rules) { // invalid_lambda_parameters if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_params[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_lambda_parameters")); @@ -7165,7 +7379,7 @@ lambda_params_rule(Parser *p) } { // lambda_parameters if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_params[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_parameters")); @@ -7184,7 +7398,7 @@ lambda_params_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7197,16 +7411,19 @@ lambda_params_rule(Parser *p) static arguments_ty lambda_parameters_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arguments_ty _res = NULL; int _mark = p->mark; { // lambda_slash_no_default lambda_param_no_default* lambda_param_with_default* lambda_star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default lambda_param_no_default* lambda_param_with_default* lambda_star_etc?")); @@ -7228,7 +7445,7 @@ lambda_parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , a , NULL , b , c , d ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7239,7 +7456,7 @@ lambda_parameters_rule(Parser *p) } { // lambda_slash_with_default lambda_param_with_default* lambda_star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default lambda_param_with_default* lambda_star_etc?")); @@ -7258,7 +7475,7 @@ lambda_parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , NULL , a , NULL , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7269,7 +7486,7 @@ lambda_parameters_rule(Parser *p) } { // lambda_param_no_default+ lambda_param_with_default* lambda_star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default+ lambda_param_with_default* lambda_star_etc?")); @@ -7288,7 +7505,7 @@ lambda_parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , NULL , NULL , a , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7299,7 +7516,7 @@ lambda_parameters_rule(Parser *p) } { // lambda_param_with_default+ lambda_star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+ lambda_star_etc?")); @@ -7315,7 +7532,7 @@ lambda_parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , NULL , NULL , NULL , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7326,7 +7543,7 @@ lambda_parameters_rule(Parser *p) } { // lambda_star_etc if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_star_etc")); @@ -7339,7 +7556,7 @@ lambda_parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , NULL , NULL , NULL , NULL , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7350,7 +7567,7 @@ lambda_parameters_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7360,16 +7577,19 @@ lambda_parameters_rule(Parser *p) static asdl_seq* lambda_slash_no_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // lambda_param_no_default+ '/' ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_slash_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default+ '/' ','")); @@ -7388,7 +7608,7 @@ lambda_slash_no_default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7399,7 +7619,7 @@ lambda_slash_no_default_rule(Parser *p) } { // lambda_param_no_default+ '/' &':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_slash_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default+ '/' &':'")); @@ -7417,7 +7637,7 @@ lambda_slash_no_default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7428,7 +7648,7 @@ lambda_slash_no_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7438,16 +7658,19 @@ lambda_slash_no_default_rule(Parser *p) static SlashWithDefault* lambda_slash_with_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } SlashWithDefault* _res = NULL; int _mark = p->mark; { // lambda_param_no_default* lambda_param_with_default+ '/' ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_slash_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* lambda_param_with_default+ '/' ','")); @@ -7469,7 +7692,7 @@ lambda_slash_with_default_rule(Parser *p) _res = _PyPegen_slash_with_default ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7480,7 +7703,7 @@ lambda_slash_with_default_rule(Parser *p) } { // lambda_param_no_default* lambda_param_with_default+ '/' &':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_slash_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* lambda_param_with_default+ '/' &':'")); @@ -7501,7 +7724,7 @@ lambda_slash_with_default_rule(Parser *p) _res = _PyPegen_slash_with_default ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7512,7 +7735,7 @@ lambda_slash_with_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7524,16 +7747,19 @@ lambda_slash_with_default_rule(Parser *p) static StarEtc* lambda_star_etc_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } StarEtc* _res = NULL; int _mark = p->mark; { // '*' lambda_param_no_default lambda_param_maybe_default* lambda_kwds? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' lambda_param_no_default lambda_param_maybe_default* lambda_kwds?")); @@ -7555,7 +7781,7 @@ lambda_star_etc_rule(Parser *p) _res = _PyPegen_star_etc ( p , a , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7566,7 +7792,7 @@ lambda_star_etc_rule(Parser *p) } { // '*' ',' lambda_param_maybe_default+ lambda_kwds? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' ',' lambda_param_maybe_default+ lambda_kwds?")); @@ -7588,7 +7814,7 @@ lambda_star_etc_rule(Parser *p) _res = _PyPegen_star_etc ( p , NULL , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7599,7 +7825,7 @@ lambda_star_etc_rule(Parser *p) } { // lambda_kwds if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_kwds")); @@ -7612,7 +7838,7 @@ lambda_star_etc_rule(Parser *p) _res = _PyPegen_star_etc ( p , NULL , NULL , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7623,7 +7849,7 @@ lambda_star_etc_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_lambda_star_etc if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_lambda_star_etc")); @@ -7642,7 +7868,7 @@ lambda_star_etc_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7650,16 +7876,19 @@ lambda_star_etc_rule(Parser *p) static arg_ty lambda_kwds_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arg_ty _res = NULL; int _mark = p->mark; { // '**' lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_kwds[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' lambda_param_no_default")); @@ -7675,7 +7904,7 @@ lambda_kwds_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7686,7 +7915,7 @@ lambda_kwds_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7694,16 +7923,19 @@ lambda_kwds_rule(Parser *p) static arg_ty lambda_param_no_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arg_ty _res = NULL; int _mark = p->mark; { // lambda_param ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param ','")); @@ -7719,7 +7951,7 @@ lambda_param_no_default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7730,7 +7962,7 @@ lambda_param_no_default_rule(Parser *p) } { // lambda_param &':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param &':'")); @@ -7745,7 +7977,7 @@ lambda_param_no_default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7756,7 +7988,7 @@ lambda_param_no_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7764,16 +7996,19 @@ lambda_param_no_default_rule(Parser *p) static NameDefaultPair* lambda_param_with_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } NameDefaultPair* _res = NULL; int _mark = p->mark; { // lambda_param default ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param default ','")); @@ -7792,7 +8027,7 @@ lambda_param_with_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , NULL ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7803,7 +8038,7 @@ lambda_param_with_default_rule(Parser *p) } { // lambda_param default &':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param default &':'")); @@ -7821,7 +8056,7 @@ lambda_param_with_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , NULL ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7832,7 +8067,7 @@ lambda_param_with_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7840,16 +8075,19 @@ lambda_param_with_default_rule(Parser *p) static NameDefaultPair* lambda_param_maybe_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } NameDefaultPair* _res = NULL; int _mark = p->mark; { // lambda_param default? ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param_maybe_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param default? ','")); @@ -7868,7 +8106,7 @@ lambda_param_maybe_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , NULL ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7879,7 +8117,7 @@ lambda_param_maybe_default_rule(Parser *p) } { // lambda_param default? &':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param_maybe_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param default? &':'")); @@ -7897,7 +8135,7 @@ lambda_param_maybe_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , NULL ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7908,7 +8146,7 @@ lambda_param_maybe_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7916,16 +8154,19 @@ lambda_param_maybe_default_rule(Parser *p) static arg_ty lambda_param_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arg_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -7934,7 +8175,7 @@ lambda_param_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); @@ -7946,7 +8187,7 @@ lambda_param_rule(Parser *p) D(fprintf(stderr, "%*c+ lambda_param[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7956,7 +8197,7 @@ lambda_param_rule(Parser *p) _res = _Py_arg ( a -> v . Name . id , NULL , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7967,7 +8208,7 @@ lambda_param_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7975,20 +8216,23 @@ lambda_param_rule(Parser *p) static expr_ty disjunction_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, disjunction_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -7997,7 +8241,7 @@ disjunction_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // conjunction (('or' conjunction))+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> disjunction[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "conjunction (('or' conjunction))+")); @@ -8012,7 +8256,7 @@ disjunction_rule(Parser *p) D(fprintf(stderr, "%*c+ disjunction[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "conjunction (('or' conjunction))+")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -8022,7 +8266,7 @@ disjunction_rule(Parser *p) _res = _Py_BoolOp ( Or , CHECK ( _PyPegen_seq_insert_in_front ( p , a , b ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8033,7 +8277,7 @@ disjunction_rule(Parser *p) } { // conjunction if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> disjunction[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "conjunction")); @@ -8053,7 +8297,7 @@ disjunction_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, disjunction_type, _res); - D(p->level--); + p->level--; return _res; } @@ -8061,20 +8305,23 @@ disjunction_rule(Parser *p) static expr_ty conjunction_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, conjunction_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -8083,7 +8330,7 @@ conjunction_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // inversion (('and' inversion))+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> conjunction[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "inversion (('and' inversion))+")); @@ -8098,7 +8345,7 @@ conjunction_rule(Parser *p) D(fprintf(stderr, "%*c+ conjunction[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "inversion (('and' inversion))+")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -8108,7 +8355,7 @@ conjunction_rule(Parser *p) _res = _Py_BoolOp ( And , CHECK ( _PyPegen_seq_insert_in_front ( p , a , b ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8119,7 +8366,7 @@ conjunction_rule(Parser *p) } { // inversion if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> conjunction[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "inversion")); @@ -8139,7 +8386,7 @@ conjunction_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, conjunction_type, _res); - D(p->level--); + p->level--; return _res; } @@ -8147,20 +8394,23 @@ conjunction_rule(Parser *p) static expr_ty inversion_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, inversion_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -8169,7 +8419,7 @@ inversion_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'not' inversion if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> inversion[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'not' inversion")); @@ -8184,7 +8434,7 @@ inversion_rule(Parser *p) D(fprintf(stderr, "%*c+ inversion[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'not' inversion")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -8194,7 +8444,7 @@ inversion_rule(Parser *p) _res = _Py_UnaryOp ( Not , a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8205,7 +8455,7 @@ inversion_rule(Parser *p) } { // comparison if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> inversion[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "comparison")); @@ -8225,7 +8475,7 @@ inversion_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, inversion_type, _res); - D(p->level--); + p->level--; return _res; } @@ -8233,16 +8483,19 @@ inversion_rule(Parser *p) static expr_ty comparison_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -8251,7 +8504,7 @@ comparison_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // bitwise_or compare_op_bitwise_or_pair+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> comparison[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_or compare_op_bitwise_or_pair+")); @@ -8266,7 +8519,7 @@ comparison_rule(Parser *p) D(fprintf(stderr, "%*c+ comparison[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_or compare_op_bitwise_or_pair+")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -8276,7 +8529,7 @@ comparison_rule(Parser *p) _res = _Py_Compare ( a , CHECK ( _PyPegen_get_cmpops ( p , b ) ) , CHECK ( _PyPegen_get_exprs ( p , b ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8287,7 +8540,7 @@ comparison_rule(Parser *p) } { // bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> comparison[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_or")); @@ -8306,7 +8559,7 @@ comparison_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8324,16 +8577,19 @@ comparison_rule(Parser *p) static CmpopExprPair* compare_op_bitwise_or_pair_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // eq_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "eq_bitwise_or")); @@ -8352,7 +8608,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // noteq_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "noteq_bitwise_or")); @@ -8371,7 +8627,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // lte_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lte_bitwise_or")); @@ -8390,7 +8646,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // lt_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lt_bitwise_or")); @@ -8409,7 +8665,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // gte_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "gte_bitwise_or")); @@ -8428,7 +8684,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // gt_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "gt_bitwise_or")); @@ -8447,7 +8703,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // notin_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "notin_bitwise_or")); @@ -8466,7 +8722,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // in_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "in_bitwise_or")); @@ -8485,7 +8741,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // isnot_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "isnot_bitwise_or")); @@ -8504,7 +8760,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // is_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "is_bitwise_or")); @@ -8523,7 +8779,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8531,16 +8787,19 @@ compare_op_bitwise_or_pair_rule(Parser *p) static CmpopExprPair* eq_bitwise_or_rule(Parser *p) { - D(p->level++); - if (p->error_indicator) { - D(p->level--); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // '==' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> eq_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'==' bitwise_or")); @@ -8556,7 +8815,7 @@ eq_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , Eq , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8567,7 +8826,7 @@ eq_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8575,16 +8834,19 @@ eq_bitwise_or_rule(Parser *p) static CmpopExprPair* noteq_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // ('!=') bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> noteq_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('!=') bitwise_or")); @@ -8600,7 +8862,7 @@ noteq_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , NotEq , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8611,7 +8873,7 @@ noteq_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8619,16 +8881,19 @@ noteq_bitwise_or_rule(Parser *p) static CmpopExprPair* lte_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // '<=' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lte_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'<=' bitwise_or")); @@ -8644,7 +8909,7 @@ lte_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , LtE , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8655,7 +8920,7 @@ lte_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8663,16 +8928,19 @@ lte_bitwise_or_rule(Parser *p) static CmpopExprPair* lt_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // '<' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lt_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'<' bitwise_or")); @@ -8688,7 +8956,7 @@ lt_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , Lt , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8699,7 +8967,7 @@ lt_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8707,16 +8975,19 @@ lt_bitwise_or_rule(Parser *p) static CmpopExprPair* gte_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // '>=' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> gte_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'>=' bitwise_or")); @@ -8732,7 +9003,7 @@ gte_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , GtE , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8743,7 +9014,7 @@ gte_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8751,16 +9022,19 @@ gte_bitwise_or_rule(Parser *p) static CmpopExprPair* gt_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // '>' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> gt_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'>' bitwise_or")); @@ -8776,7 +9050,7 @@ gt_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , Gt , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8787,7 +9061,7 @@ gt_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8795,16 +9069,19 @@ gt_bitwise_or_rule(Parser *p) static CmpopExprPair* notin_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // 'not' 'in' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> notin_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'not' 'in' bitwise_or")); @@ -8823,7 +9100,7 @@ notin_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , NotIn , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8834,7 +9111,7 @@ notin_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8842,16 +9119,19 @@ notin_bitwise_or_rule(Parser *p) static CmpopExprPair* in_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // 'in' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> in_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'in' bitwise_or")); @@ -8867,7 +9147,7 @@ in_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , In , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8878,7 +9158,7 @@ in_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8886,16 +9166,19 @@ in_bitwise_or_rule(Parser *p) static CmpopExprPair* isnot_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // 'is' 'not' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> isnot_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'is' 'not' bitwise_or")); @@ -8914,7 +9197,7 @@ isnot_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , IsNot , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8925,7 +9208,7 @@ isnot_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8933,16 +9216,19 @@ isnot_bitwise_or_rule(Parser *p) static CmpopExprPair* is_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // 'is' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> is_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'is' bitwise_or")); @@ -8958,7 +9244,7 @@ is_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , Is , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8969,7 +9255,7 @@ is_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8979,10 +9265,13 @@ static expr_ty bitwise_or_raw(Parser *); static expr_ty bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, bitwise_or_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -8990,35 +9279,40 @@ bitwise_or_rule(Parser *p) while (1) { int tmpvar_1 = _PyPegen_update_memo(p, _mark, bitwise_or_type, _res); if (tmpvar_1) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; void *_raw = bitwise_or_raw(p); - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty bitwise_or_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -9027,7 +9321,7 @@ bitwise_or_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // bitwise_or '|' bitwise_xor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_or '|' bitwise_xor")); @@ -9045,7 +9339,7 @@ bitwise_or_raw(Parser *p) D(fprintf(stderr, "%*c+ bitwise_or[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_or '|' bitwise_xor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9055,7 +9349,7 @@ bitwise_or_raw(Parser *p) _res = _Py_BinOp ( a , BitOr , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9066,7 +9360,7 @@ bitwise_or_raw(Parser *p) } { // bitwise_xor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_xor")); @@ -9085,7 +9379,7 @@ bitwise_or_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9095,10 +9389,13 @@ static expr_ty bitwise_xor_raw(Parser *); static expr_ty bitwise_xor_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, bitwise_xor_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -9106,35 +9403,40 @@ bitwise_xor_rule(Parser *p) while (1) { int tmpvar_2 = _PyPegen_update_memo(p, _mark, bitwise_xor_type, _res); if (tmpvar_2) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; void *_raw = bitwise_xor_raw(p); - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty bitwise_xor_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -9143,7 +9445,7 @@ bitwise_xor_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // bitwise_xor '^' bitwise_and if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> bitwise_xor[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_xor '^' bitwise_and")); @@ -9161,7 +9463,7 @@ bitwise_xor_raw(Parser *p) D(fprintf(stderr, "%*c+ bitwise_xor[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_xor '^' bitwise_and")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9171,7 +9473,7 @@ bitwise_xor_raw(Parser *p) _res = _Py_BinOp ( a , BitXor , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9182,7 +9484,7 @@ bitwise_xor_raw(Parser *p) } { // bitwise_and if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> bitwise_xor[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_and")); @@ -9201,7 +9503,7 @@ bitwise_xor_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9211,10 +9513,13 @@ static expr_ty bitwise_and_raw(Parser *); static expr_ty bitwise_and_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, bitwise_and_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -9222,35 +9527,40 @@ bitwise_and_rule(Parser *p) while (1) { int tmpvar_3 = _PyPegen_update_memo(p, _mark, bitwise_and_type, _res); if (tmpvar_3) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; void *_raw = bitwise_and_raw(p); - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty bitwise_and_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -9259,7 +9569,7 @@ bitwise_and_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // bitwise_and '&' shift_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> bitwise_and[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_and '&' shift_expr")); @@ -9277,7 +9587,7 @@ bitwise_and_raw(Parser *p) D(fprintf(stderr, "%*c+ bitwise_and[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_and '&' shift_expr")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9287,7 +9597,7 @@ bitwise_and_raw(Parser *p) _res = _Py_BinOp ( a , BitAnd , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9298,7 +9608,7 @@ bitwise_and_raw(Parser *p) } { // shift_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> bitwise_and[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "shift_expr")); @@ -9317,7 +9627,7 @@ bitwise_and_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9327,10 +9637,13 @@ static expr_ty shift_expr_raw(Parser *); static expr_ty shift_expr_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, shift_expr_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -9338,35 +9651,40 @@ shift_expr_rule(Parser *p) while (1) { int tmpvar_4 = _PyPegen_update_memo(p, _mark, shift_expr_type, _res); if (tmpvar_4) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; void *_raw = shift_expr_raw(p); - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty shift_expr_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -9375,7 +9693,7 @@ shift_expr_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // shift_expr '<<' sum if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> shift_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "shift_expr '<<' sum")); @@ -9393,7 +9711,7 @@ shift_expr_raw(Parser *p) D(fprintf(stderr, "%*c+ shift_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "shift_expr '<<' sum")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9403,7 +9721,7 @@ shift_expr_raw(Parser *p) _res = _Py_BinOp ( a , LShift , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9414,7 +9732,7 @@ shift_expr_raw(Parser *p) } { // shift_expr '>>' sum if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> shift_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "shift_expr '>>' sum")); @@ -9432,7 +9750,7 @@ shift_expr_raw(Parser *p) D(fprintf(stderr, "%*c+ shift_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "shift_expr '>>' sum")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9442,7 +9760,7 @@ shift_expr_raw(Parser *p) _res = _Py_BinOp ( a , RShift , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9453,7 +9771,7 @@ shift_expr_raw(Parser *p) } { // sum if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> shift_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "sum")); @@ -9472,7 +9790,7 @@ shift_expr_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9482,10 +9800,13 @@ static expr_ty sum_raw(Parser *); static expr_ty sum_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, sum_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -9493,35 +9814,40 @@ sum_rule(Parser *p) while (1) { int tmpvar_5 = _PyPegen_update_memo(p, _mark, sum_type, _res); if (tmpvar_5) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; void *_raw = sum_raw(p); - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty sum_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -9530,7 +9856,7 @@ sum_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // sum '+' term if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> sum[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "sum '+' term")); @@ -9548,7 +9874,7 @@ sum_raw(Parser *p) D(fprintf(stderr, "%*c+ sum[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "sum '+' term")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9558,7 +9884,7 @@ sum_raw(Parser *p) _res = _Py_BinOp ( a , Add , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9569,7 +9895,7 @@ sum_raw(Parser *p) } { // sum '-' term if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> sum[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "sum '-' term")); @@ -9587,7 +9913,7 @@ sum_raw(Parser *p) D(fprintf(stderr, "%*c+ sum[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "sum '-' term")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9597,7 +9923,7 @@ sum_raw(Parser *p) _res = _Py_BinOp ( a , Sub , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9608,7 +9934,7 @@ sum_raw(Parser *p) } { // term if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> sum[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "term")); @@ -9627,7 +9953,7 @@ sum_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9643,10 +9969,13 @@ static expr_ty term_raw(Parser *); static expr_ty term_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, term_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -9654,35 +9983,40 @@ term_rule(Parser *p) while (1) { int tmpvar_6 = _PyPegen_update_memo(p, _mark, term_type, _res); if (tmpvar_6) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; void *_raw = term_raw(p); - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty term_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -9691,7 +10025,7 @@ term_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // term '*' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> term[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "term '*' factor")); @@ -9709,7 +10043,7 @@ term_raw(Parser *p) D(fprintf(stderr, "%*c+ term[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "term '*' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9719,7 +10053,7 @@ term_raw(Parser *p) _res = _Py_BinOp ( a , Mult , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9730,7 +10064,7 @@ term_raw(Parser *p) } { // term '/' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> term[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "term '/' factor")); @@ -9748,7 +10082,7 @@ term_raw(Parser *p) D(fprintf(stderr, "%*c+ term[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "term '/' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9758,7 +10092,7 @@ term_raw(Parser *p) _res = _Py_BinOp ( a , Div , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9769,7 +10103,7 @@ term_raw(Parser *p) } { // term '//' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> term[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "term '//' factor")); @@ -9787,7 +10121,7 @@ term_raw(Parser *p) D(fprintf(stderr, "%*c+ term[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "term '//' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9797,7 +10131,7 @@ term_raw(Parser *p) _res = _Py_BinOp ( a , FloorDiv , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9808,7 +10142,7 @@ term_raw(Parser *p) } { // term '%' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> term[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "term '%' factor")); @@ -9826,7 +10160,7 @@ term_raw(Parser *p) D(fprintf(stderr, "%*c+ term[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "term '%' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9836,7 +10170,7 @@ term_raw(Parser *p) _res = _Py_BinOp ( a , Mod , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9847,7 +10181,7 @@ term_raw(Parser *p) } { // term '@' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> term[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "term '@' factor")); @@ -9865,7 +10199,7 @@ term_raw(Parser *p) D(fprintf(stderr, "%*c+ term[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "term '@' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9875,7 +10209,7 @@ term_raw(Parser *p) _res = CHECK_VERSION ( 5 , "The '@' operator is" , _Py_BinOp ( a , MatMult , b , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9886,7 +10220,7 @@ term_raw(Parser *p) } { // factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> term[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "factor")); @@ -9905,7 +10239,7 @@ term_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9913,20 +10247,23 @@ term_raw(Parser *p) static expr_ty factor_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, factor_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -9935,7 +10272,7 @@ factor_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '+' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> factor[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+' factor")); @@ -9950,7 +10287,7 @@ factor_rule(Parser *p) D(fprintf(stderr, "%*c+ factor[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9960,7 +10297,7 @@ factor_rule(Parser *p) _res = _Py_UnaryOp ( UAdd , a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9971,7 +10308,7 @@ factor_rule(Parser *p) } { // '-' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> factor[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-' factor")); @@ -9986,7 +10323,7 @@ factor_rule(Parser *p) D(fprintf(stderr, "%*c+ factor[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9996,7 +10333,7 @@ factor_rule(Parser *p) _res = _Py_UnaryOp ( USub , a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10007,7 +10344,7 @@ factor_rule(Parser *p) } { // '~' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> factor[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'~' factor")); @@ -10022,7 +10359,7 @@ factor_rule(Parser *p) D(fprintf(stderr, "%*c+ factor[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'~' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10032,7 +10369,7 @@ factor_rule(Parser *p) _res = _Py_UnaryOp ( Invert , a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10043,7 +10380,7 @@ factor_rule(Parser *p) } { // power if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> factor[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "power")); @@ -10063,7 +10400,7 @@ factor_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, factor_type, _res); - D(p->level--); + p->level--; return _res; } @@ -10071,16 +10408,19 @@ factor_rule(Parser *p) static expr_ty power_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -10089,7 +10429,7 @@ power_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // await_primary '**' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> power[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "await_primary '**' factor")); @@ -10107,7 +10447,7 @@ power_rule(Parser *p) D(fprintf(stderr, "%*c+ power[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "await_primary '**' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10117,7 +10457,7 @@ power_rule(Parser *p) _res = _Py_BinOp ( a , Pow , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10128,7 +10468,7 @@ power_rule(Parser *p) } { // await_primary if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> power[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "await_primary")); @@ -10147,7 +10487,7 @@ power_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -10155,20 +10495,23 @@ power_rule(Parser *p) static expr_ty await_primary_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, await_primary_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -10177,7 +10520,7 @@ await_primary_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // AWAIT primary if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> await_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "AWAIT primary")); @@ -10192,7 +10535,7 @@ await_primary_rule(Parser *p) D(fprintf(stderr, "%*c+ await_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "AWAIT primary")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10202,7 +10545,7 @@ await_primary_rule(Parser *p) _res = CHECK_VERSION ( 5 , "Await expressions are" , _Py_Await ( a , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10213,7 +10556,7 @@ await_primary_rule(Parser *p) } { // primary if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> await_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "primary")); @@ -10233,7 +10576,7 @@ await_primary_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, await_primary_type, _res); - D(p->level--); + p->level--; return _res; } @@ -10249,10 +10592,13 @@ static expr_ty primary_raw(Parser *); static expr_ty primary_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, primary_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -10260,35 +10606,40 @@ primary_rule(Parser *p) while (1) { int tmpvar_7 = _PyPegen_update_memo(p, _mark, primary_type, _res); if (tmpvar_7) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; void *_raw = primary_raw(p); - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty primary_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -10297,7 +10648,7 @@ primary_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_primary if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_primary")); @@ -10316,7 +10667,7 @@ primary_raw(Parser *p) } { // primary '.' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "primary '.' NAME")); @@ -10334,7 +10685,7 @@ primary_raw(Parser *p) D(fprintf(stderr, "%*c+ primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "primary '.' NAME")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10344,7 +10695,7 @@ primary_raw(Parser *p) _res = _Py_Attribute ( a , b -> v . Name . id , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10355,7 +10706,7 @@ primary_raw(Parser *p) } { // primary genexp if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "primary genexp")); @@ -10370,7 +10721,7 @@ primary_raw(Parser *p) D(fprintf(stderr, "%*c+ primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "primary genexp")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10380,7 +10731,7 @@ primary_raw(Parser *p) _res = _Py_Call ( a , CHECK ( _PyPegen_singleton_seq ( p , b ) ) , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10391,7 +10742,7 @@ primary_raw(Parser *p) } { // primary '(' arguments? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "primary '(' arguments? ')'")); @@ -10412,7 +10763,7 @@ primary_raw(Parser *p) D(fprintf(stderr, "%*c+ primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "primary '(' arguments? ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10422,7 +10773,7 @@ primary_raw(Parser *p) _res = _Py_Call ( a , ( b ) ? ( ( expr_ty ) b ) -> v . Call . args : NULL , ( b ) ? ( ( expr_ty ) b ) -> v . Call . keywords : NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10433,7 +10784,7 @@ primary_raw(Parser *p) } { // primary '[' slices ']' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "primary '[' slices ']'")); @@ -10454,7 +10805,7 @@ primary_raw(Parser *p) D(fprintf(stderr, "%*c+ primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "primary '[' slices ']'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10464,7 +10815,7 @@ primary_raw(Parser *p) _res = _Py_Subscript ( a , b , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10475,7 +10826,7 @@ primary_raw(Parser *p) } { // atom if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "atom")); @@ -10494,7 +10845,7 @@ primary_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -10502,16 +10853,19 @@ primary_raw(Parser *p) static expr_ty slices_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -10520,7 +10874,7 @@ slices_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // slice !',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slices[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slice !','")); @@ -10535,7 +10889,7 @@ slices_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10546,7 +10900,7 @@ slices_rule(Parser *p) } { // ','.slice+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slices[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.slice+ ','?")); @@ -10562,7 +10916,7 @@ slices_rule(Parser *p) D(fprintf(stderr, "%*c+ slices[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.slice+ ','?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10572,7 +10926,7 @@ slices_rule(Parser *p) _res = _Py_Tuple ( a , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10583,7 +10937,7 @@ slices_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -10591,16 +10945,19 @@ slices_rule(Parser *p) static expr_ty slice_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -10609,7 +10966,7 @@ slice_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // expression? ':' expression? [':' expression?] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slice[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression? ':' expression? [':' expression?]")); @@ -10630,7 +10987,7 @@ slice_rule(Parser *p) D(fprintf(stderr, "%*c+ slice[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression? ':' expression? [':' expression?]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10640,7 +10997,7 @@ slice_rule(Parser *p) _res = _Py_Slice ( a , b , c , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10651,7 +11008,7 @@ slice_rule(Parser *p) } { // expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slice[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression")); @@ -10664,7 +11021,7 @@ slice_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10675,7 +11032,7 @@ slice_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -10694,16 +11051,19 @@ slice_rule(Parser *p) static expr_ty atom_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -10712,7 +11072,7 @@ atom_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); @@ -10731,7 +11091,7 @@ atom_rule(Parser *p) } { // 'True' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); @@ -10743,7 +11103,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10753,7 +11113,7 @@ atom_rule(Parser *p) _res = _Py_Constant ( Py_True , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10764,7 +11124,7 @@ atom_rule(Parser *p) } { // 'False' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); @@ -10776,7 +11136,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10786,7 +11146,7 @@ atom_rule(Parser *p) _res = _Py_Constant ( Py_False , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10797,7 +11157,7 @@ atom_rule(Parser *p) } { // 'None' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); @@ -10809,7 +11169,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10819,7 +11179,7 @@ atom_rule(Parser *p) _res = _Py_Constant ( Py_None , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10830,7 +11190,7 @@ atom_rule(Parser *p) } { // '__peg_parser__' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'__peg_parser__'")); @@ -10843,7 +11203,7 @@ atom_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "You found it!" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10854,7 +11214,7 @@ atom_rule(Parser *p) } { // &STRING strings if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&STRING strings")); @@ -10875,7 +11235,7 @@ atom_rule(Parser *p) } { // NUMBER if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NUMBER")); @@ -10894,7 +11254,7 @@ atom_rule(Parser *p) } { // &'(' (tuple | group | genexp) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'(' (tuple | group | genexp)")); @@ -10915,7 +11275,7 @@ atom_rule(Parser *p) } { // &'[' (list | listcomp) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'[' (list | listcomp)")); @@ -10936,7 +11296,7 @@ atom_rule(Parser *p) } { // &'{' (dict | set | dictcomp | setcomp) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'{' (dict | set | dictcomp | setcomp)")); @@ -10957,7 +11317,7 @@ atom_rule(Parser *p) } { // '...' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); @@ -10969,7 +11329,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10979,7 +11339,7 @@ atom_rule(Parser *p) _res = _Py_Constant ( Py_Ellipsis , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10990,7 +11350,7 @@ atom_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -10998,20 +11358,23 @@ atom_rule(Parser *p) static expr_ty strings_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, strings_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; { // STRING+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> strings[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "STRING+")); @@ -11024,7 +11387,7 @@ strings_rule(Parser *p) _res = _PyPegen_concatenate_strings ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11036,7 +11399,7 @@ strings_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, strings_type, _res); - D(p->level--); + p->level--; return _res; } @@ -11044,16 +11407,19 @@ strings_rule(Parser *p) static expr_ty list_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -11062,7 +11428,7 @@ list_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '[' star_named_expressions? ']' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> list[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'[' star_named_expressions? ']'")); @@ -11080,7 +11446,7 @@ list_rule(Parser *p) D(fprintf(stderr, "%*c+ list[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' star_named_expressions? ']'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -11090,7 +11456,7 @@ list_rule(Parser *p) _res = _Py_List ( a , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11101,7 +11467,7 @@ list_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11109,16 +11475,19 @@ list_rule(Parser *p) static expr_ty listcomp_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -11127,7 +11496,7 @@ listcomp_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '[' named_expression ~ for_if_clauses ']' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> listcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'[' named_expression ~ for_if_clauses ']'")); @@ -11151,7 +11520,7 @@ listcomp_rule(Parser *p) D(fprintf(stderr, "%*c+ listcomp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' named_expression ~ for_if_clauses ']'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -11161,7 +11530,7 @@ listcomp_rule(Parser *p) _res = _Py_ListComp ( a , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11170,13 +11539,13 @@ listcomp_rule(Parser *p) D(fprintf(stderr, "%*c%s listcomp[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'[' named_expression ~ for_if_clauses ']'")); if (_cut_var) { - D(p->level--); + p->level--; return NULL; } } if (p->call_invalid_rules) { // invalid_comprehension if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> listcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_comprehension")); @@ -11195,7 +11564,7 @@ listcomp_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11203,16 +11572,19 @@ listcomp_rule(Parser *p) static expr_ty tuple_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -11221,7 +11593,7 @@ tuple_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '(' [star_named_expression ',' star_named_expressions?] ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> tuple[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' [star_named_expression ',' star_named_expressions?] ')'")); @@ -11239,7 +11611,7 @@ tuple_rule(Parser *p) D(fprintf(stderr, "%*c+ tuple[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' [star_named_expression ',' star_named_expressions?] ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -11249,7 +11621,7 @@ tuple_rule(Parser *p) _res = _Py_Tuple ( a , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11260,7 +11632,7 @@ tuple_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11268,16 +11640,19 @@ tuple_rule(Parser *p) static expr_ty group_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // '(' (yield_expr | named_expression) ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> group[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' (yield_expr | named_expression) ')'")); @@ -11296,7 +11671,7 @@ group_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11307,7 +11682,7 @@ group_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_group if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> group[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_group")); @@ -11326,7 +11701,7 @@ group_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11334,16 +11709,19 @@ group_rule(Parser *p) static expr_ty genexp_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -11352,7 +11730,7 @@ genexp_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '(' named_expression ~ for_if_clauses ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> genexp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' named_expression ~ for_if_clauses ')'")); @@ -11376,7 +11754,7 @@ genexp_rule(Parser *p) D(fprintf(stderr, "%*c+ genexp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' named_expression ~ for_if_clauses ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -11386,7 +11764,7 @@ genexp_rule(Parser *p) _res = _Py_GeneratorExp ( a , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11395,13 +11773,13 @@ genexp_rule(Parser *p) D(fprintf(stderr, "%*c%s genexp[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' named_expression ~ for_if_clauses ')'")); if (_cut_var) { - D(p->level--); + p->level--; return NULL; } } if (p->call_invalid_rules) { // invalid_comprehension if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> genexp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_comprehension")); @@ -11420,7 +11798,7 @@ genexp_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11428,16 +11806,19 @@ genexp_rule(Parser *p) static expr_ty set_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -11446,7 +11827,7 @@ set_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '{' star_named_expressions '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> set[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' star_named_expressions '}'")); @@ -11464,7 +11845,7 @@ set_rule(Parser *p) D(fprintf(stderr, "%*c+ set[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' star_named_expressions '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -11474,7 +11855,7 @@ set_rule(Parser *p) _res = _Py_Set ( a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11485,7 +11866,7 @@ set_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11493,16 +11874,19 @@ set_rule(Parser *p) static expr_ty setcomp_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -11511,7 +11895,7 @@ setcomp_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '{' named_expression ~ for_if_clauses '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> setcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' named_expression ~ for_if_clauses '}'")); @@ -11535,7 +11919,7 @@ setcomp_rule(Parser *p) D(fprintf(stderr, "%*c+ setcomp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' named_expression ~ for_if_clauses '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -11545,7 +11929,7 @@ setcomp_rule(Parser *p) _res = _Py_SetComp ( a , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11554,13 +11938,13 @@ setcomp_rule(Parser *p) D(fprintf(stderr, "%*c%s setcomp[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{' named_expression ~ for_if_clauses '}'")); if (_cut_var) { - D(p->level--); + p->level--; return NULL; } } if (p->call_invalid_rules) { // invalid_comprehension if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> setcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_comprehension")); @@ -11579,7 +11963,7 @@ setcomp_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11587,16 +11971,19 @@ setcomp_rule(Parser *p) static expr_ty dict_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -11605,7 +11992,7 @@ dict_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '{' double_starred_kvpairs? '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dict[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' double_starred_kvpairs? '}'")); @@ -11623,7 +12010,7 @@ dict_rule(Parser *p) D(fprintf(stderr, "%*c+ dict[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' double_starred_kvpairs? '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -11633,7 +12020,7 @@ dict_rule(Parser *p) _res = _Py_Dict ( CHECK ( _PyPegen_get_keys ( p , a ) ) , CHECK ( _PyPegen_get_values ( p , a ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11644,7 +12031,7 @@ dict_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11652,16 +12039,19 @@ dict_rule(Parser *p) static expr_ty dictcomp_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -11670,7 +12060,7 @@ dictcomp_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '{' kvpair for_if_clauses '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dictcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' kvpair for_if_clauses '}'")); @@ -11691,7 +12081,7 @@ dictcomp_rule(Parser *p) D(fprintf(stderr, "%*c+ dictcomp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' kvpair for_if_clauses '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -11701,7 +12091,7 @@ dictcomp_rule(Parser *p) _res = _Py_DictComp ( a -> key , a -> value , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11712,7 +12102,7 @@ dictcomp_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_dict_comprehension if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dictcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_dict_comprehension")); @@ -11731,7 +12121,7 @@ dictcomp_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11739,16 +12129,19 @@ dictcomp_rule(Parser *p) static asdl_seq* double_starred_kvpairs_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // ','.double_starred_kvpair+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> double_starred_kvpairs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ','?")); @@ -11765,7 +12158,7 @@ double_starred_kvpairs_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11776,7 +12169,7 @@ double_starred_kvpairs_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11784,16 +12177,19 @@ double_starred_kvpairs_rule(Parser *p) static KeyValuePair* double_starred_kvpair_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } KeyValuePair* _res = NULL; int _mark = p->mark; { // '**' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> double_starred_kvpair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' bitwise_or")); @@ -11809,7 +12205,7 @@ double_starred_kvpair_rule(Parser *p) _res = _PyPegen_key_value_pair ( p , NULL , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11820,7 +12216,7 @@ double_starred_kvpair_rule(Parser *p) } { // kvpair if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> double_starred_kvpair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kvpair")); @@ -11839,7 +12235,7 @@ double_starred_kvpair_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11847,16 +12243,19 @@ double_starred_kvpair_rule(Parser *p) static KeyValuePair* kvpair_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } KeyValuePair* _res = NULL; int _mark = p->mark; { // expression ':' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kvpair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ':' expression")); @@ -11875,7 +12274,7 @@ kvpair_rule(Parser *p) _res = _PyPegen_key_value_pair ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11886,7 +12285,7 @@ kvpair_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11894,16 +12293,19 @@ kvpair_rule(Parser *p) static asdl_seq* for_if_clauses_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // for_if_clause+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_if_clauses[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "for_if_clause+")); @@ -11922,7 +12324,7 @@ for_if_clauses_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11933,16 +12335,19 @@ for_if_clauses_rule(Parser *p) static comprehension_ty for_if_clause_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } comprehension_ty _res = NULL; int _mark = p->mark; { // ASYNC 'for' star_targets 'in' ~ disjunction (('if' disjunction))* if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_if_clause[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC 'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); @@ -11973,7 +12378,7 @@ for_if_clause_rule(Parser *p) _res = CHECK_VERSION ( 6 , "Async comprehensions are" , _Py_comprehension ( a , b , c , 1 , p -> arena ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11982,13 +12387,13 @@ for_if_clause_rule(Parser *p) D(fprintf(stderr, "%*c%s for_if_clause[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "ASYNC 'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); if (_cut_var) { - D(p->level--); + p->level--; return NULL; } } { // 'for' star_targets 'in' ~ disjunction (('if' disjunction))* if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_if_clause[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); @@ -12016,7 +12421,7 @@ for_if_clause_rule(Parser *p) _res = _Py_comprehension ( a , b , c , 0 , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12025,13 +12430,13 @@ for_if_clause_rule(Parser *p) D(fprintf(stderr, "%*c%s for_if_clause[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); if (_cut_var) { - D(p->level--); + p->level--; return NULL; } } if (p->call_invalid_rules) { // invalid_for_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_if_clause[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_for_target")); @@ -12050,7 +12455,7 @@ for_if_clause_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12058,16 +12463,19 @@ for_if_clause_rule(Parser *p) static expr_ty yield_expr_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -12076,7 +12484,7 @@ yield_expr_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'yield' 'from' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> yield_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'yield' 'from' expression")); @@ -12094,7 +12502,7 @@ yield_expr_rule(Parser *p) D(fprintf(stderr, "%*c+ yield_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'yield' 'from' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12104,7 +12512,7 @@ yield_expr_rule(Parser *p) _res = _Py_YieldFrom ( a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12115,7 +12523,7 @@ yield_expr_rule(Parser *p) } { // 'yield' star_expressions? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> yield_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'yield' star_expressions?")); @@ -12130,7 +12538,7 @@ yield_expr_rule(Parser *p) D(fprintf(stderr, "%*c+ yield_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'yield' star_expressions?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12140,7 +12548,7 @@ yield_expr_rule(Parser *p) _res = _Py_Yield ( a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12151,7 +12559,7 @@ yield_expr_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12159,20 +12567,23 @@ yield_expr_rule(Parser *p) static expr_ty arguments_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, arguments_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; { // args ','? &')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ','? &')'")); @@ -12191,7 +12602,7 @@ arguments_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12202,7 +12613,7 @@ arguments_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_arguments if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_arguments")); @@ -12222,7 +12633,7 @@ arguments_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, arguments_type, _res); - D(p->level--); + p->level--; return _res; } @@ -12230,16 +12641,19 @@ arguments_rule(Parser *p) static expr_ty args_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -12248,7 +12662,7 @@ args_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // ','.(starred_expression | named_expression !'=')+ [',' kwargs] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> args[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | named_expression !'=')+ [',' kwargs]")); @@ -12263,7 +12677,7 @@ args_rule(Parser *p) D(fprintf(stderr, "%*c+ args[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | named_expression !'=')+ [',' kwargs]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12273,7 +12687,7 @@ args_rule(Parser *p) _res = _PyPegen_collect_call_seqs ( p , a , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12284,7 +12698,7 @@ args_rule(Parser *p) } { // kwargs if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> args[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwargs")); @@ -12296,7 +12710,7 @@ args_rule(Parser *p) D(fprintf(stderr, "%*c+ args[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwargs")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12306,7 +12720,7 @@ args_rule(Parser *p) _res = _Py_Call ( _PyPegen_dummy_name ( p ) , CHECK_NULL_ALLOWED ( _PyPegen_seq_extract_starred_exprs ( p , a ) ) , CHECK_NULL_ALLOWED ( _PyPegen_seq_delete_starred_exprs ( p , a ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12317,7 +12731,7 @@ args_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12328,16 +12742,19 @@ args_rule(Parser *p) static asdl_seq* kwargs_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // ','.kwarg_or_starred+ ',' ','.kwarg_or_double_starred+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwargs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+ ',' ','.kwarg_or_double_starred+")); @@ -12356,7 +12773,7 @@ kwargs_rule(Parser *p) _res = _PyPegen_join_sequences ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12367,7 +12784,7 @@ kwargs_rule(Parser *p) } { // ','.kwarg_or_starred+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwargs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+")); @@ -12386,7 +12803,7 @@ kwargs_rule(Parser *p) } { // ','.kwarg_or_double_starred+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwargs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_double_starred+")); @@ -12405,7 +12822,7 @@ kwargs_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12413,16 +12830,19 @@ kwargs_rule(Parser *p) static expr_ty starred_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -12431,7 +12851,7 @@ starred_expression_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '*' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> starred_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' expression")); @@ -12446,7 +12866,7 @@ starred_expression_rule(Parser *p) D(fprintf(stderr, "%*c+ starred_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12456,7 +12876,7 @@ starred_expression_rule(Parser *p) _res = _Py_Starred ( a , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12467,7 +12887,7 @@ starred_expression_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12475,16 +12895,19 @@ starred_expression_rule(Parser *p) static KeywordOrStarred* kwarg_or_starred_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } KeywordOrStarred* _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -12493,7 +12916,7 @@ kwarg_or_starred_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME '=' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwarg_or_starred[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '=' expression")); @@ -12511,7 +12934,7 @@ kwarg_or_starred_rule(Parser *p) D(fprintf(stderr, "%*c+ kwarg_or_starred[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12521,7 +12944,7 @@ kwarg_or_starred_rule(Parser *p) _res = _PyPegen_keyword_or_starred ( p , CHECK ( _Py_keyword ( a -> v . Name . id , b , EXTRA ) ) , 1 ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12532,7 +12955,7 @@ kwarg_or_starred_rule(Parser *p) } { // starred_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwarg_or_starred[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); @@ -12545,7 +12968,7 @@ kwarg_or_starred_rule(Parser *p) _res = _PyPegen_keyword_or_starred ( p , a , 0 ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12556,7 +12979,7 @@ kwarg_or_starred_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_kwarg if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwarg_or_starred[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_kwarg")); @@ -12575,7 +12998,7 @@ kwarg_or_starred_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12583,16 +13006,19 @@ kwarg_or_starred_rule(Parser *p) static KeywordOrStarred* kwarg_or_double_starred_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } KeywordOrStarred* _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -12601,7 +13027,7 @@ kwarg_or_double_starred_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME '=' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwarg_or_double_starred[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '=' expression")); @@ -12619,7 +13045,7 @@ kwarg_or_double_starred_rule(Parser *p) D(fprintf(stderr, "%*c+ kwarg_or_double_starred[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12629,7 +13055,7 @@ kwarg_or_double_starred_rule(Parser *p) _res = _PyPegen_keyword_or_starred ( p , CHECK ( _Py_keyword ( a -> v . Name . id , b , EXTRA ) ) , 1 ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12640,7 +13066,7 @@ kwarg_or_double_starred_rule(Parser *p) } { // '**' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwarg_or_double_starred[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' expression")); @@ -12655,7 +13081,7 @@ kwarg_or_double_starred_rule(Parser *p) D(fprintf(stderr, "%*c+ kwarg_or_double_starred[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12665,7 +13091,7 @@ kwarg_or_double_starred_rule(Parser *p) _res = _PyPegen_keyword_or_starred ( p , CHECK ( _Py_keyword ( NULL , a , EXTRA ) ) , 1 ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12676,7 +13102,7 @@ kwarg_or_double_starred_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_kwarg if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwarg_or_double_starred[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_kwarg")); @@ -12695,7 +13121,7 @@ kwarg_or_double_starred_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12703,16 +13129,19 @@ kwarg_or_double_starred_rule(Parser *p) static expr_ty star_targets_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -12721,7 +13150,7 @@ star_targets_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // star_target !',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target !','")); @@ -12736,7 +13165,7 @@ star_targets_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12747,7 +13176,7 @@ star_targets_rule(Parser *p) } { // star_target ((',' star_target))* ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target ((',' star_target))* ','?")); @@ -12766,7 +13195,7 @@ star_targets_rule(Parser *p) D(fprintf(stderr, "%*c+ star_targets[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target ((',' star_target))* ','?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12776,7 +13205,7 @@ star_targets_rule(Parser *p) _res = _Py_Tuple ( CHECK ( _PyPegen_seq_insert_in_front ( p , a , b ) ) , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12787,7 +13216,7 @@ star_targets_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12795,16 +13224,19 @@ star_targets_rule(Parser *p) static asdl_seq* star_targets_list_seq_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // ','.star_target+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_targets_list_seq[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.star_target+ ','?")); @@ -12821,7 +13253,7 @@ star_targets_list_seq_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12832,7 +13264,7 @@ star_targets_list_seq_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12840,16 +13272,19 @@ star_targets_list_seq_rule(Parser *p) static asdl_seq* star_targets_tuple_seq_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // star_target ((',' star_target))+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_targets_tuple_seq[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target ((',' star_target))+ ','?")); @@ -12869,7 +13304,7 @@ star_targets_tuple_seq_rule(Parser *p) _res = _PyPegen_seq_insert_in_front ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12880,7 +13315,7 @@ star_targets_tuple_seq_rule(Parser *p) } { // star_target ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_targets_tuple_seq[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target ','")); @@ -12896,7 +13331,7 @@ star_targets_tuple_seq_rule(Parser *p) _res = _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12907,7 +13342,7 @@ star_targets_tuple_seq_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12915,20 +13350,23 @@ star_targets_tuple_seq_rule(Parser *p) static expr_ty star_target_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, star_target_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -12937,7 +13375,7 @@ star_target_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '*' (!'*' star_target) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (!'*' star_target)")); @@ -12952,7 +13390,7 @@ star_target_rule(Parser *p) D(fprintf(stderr, "%*c+ star_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (!'*' star_target)")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12962,7 +13400,7 @@ star_target_rule(Parser *p) _res = _Py_Starred ( CHECK ( _PyPegen_set_expr_context ( p , a , Store ) ) , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12973,7 +13411,7 @@ star_target_rule(Parser *p) } { // target_with_star_atom if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "target_with_star_atom")); @@ -12993,7 +13431,7 @@ star_target_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, star_target_type, _res); - D(p->level--); + p->level--; return _res; } @@ -13004,20 +13442,23 @@ star_target_rule(Parser *p) static expr_ty target_with_star_atom_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, target_with_star_atom_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -13026,7 +13467,7 @@ target_with_star_atom_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // t_primary '.' NAME !t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> target_with_star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); @@ -13046,7 +13487,7 @@ target_with_star_atom_rule(Parser *p) D(fprintf(stderr, "%*c+ target_with_star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13056,7 +13497,7 @@ target_with_star_atom_rule(Parser *p) _res = _Py_Attribute ( a , b -> v . Name . id , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13067,7 +13508,7 @@ target_with_star_atom_rule(Parser *p) } { // t_primary '[' slices ']' !t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> target_with_star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); @@ -13090,7 +13531,7 @@ target_with_star_atom_rule(Parser *p) D(fprintf(stderr, "%*c+ target_with_star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13100,7 +13541,7 @@ target_with_star_atom_rule(Parser *p) _res = _Py_Subscript ( a , b , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13111,7 +13552,7 @@ target_with_star_atom_rule(Parser *p) } { // star_atom if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> target_with_star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_atom")); @@ -13131,7 +13572,7 @@ target_with_star_atom_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, target_with_star_atom_type, _res); - D(p->level--); + p->level--; return _res; } @@ -13143,16 +13584,19 @@ target_with_star_atom_rule(Parser *p) static expr_ty star_atom_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -13161,7 +13605,7 @@ star_atom_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); @@ -13174,7 +13618,7 @@ star_atom_rule(Parser *p) _res = _PyPegen_set_expr_context ( p , a , Store ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13185,7 +13629,7 @@ star_atom_rule(Parser *p) } { // '(' target_with_star_atom ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' target_with_star_atom ')'")); @@ -13204,7 +13648,7 @@ star_atom_rule(Parser *p) _res = _PyPegen_set_expr_context ( p , a , Store ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13215,7 +13659,7 @@ star_atom_rule(Parser *p) } { // '(' star_targets_tuple_seq? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' star_targets_tuple_seq? ')'")); @@ -13233,7 +13677,7 @@ star_atom_rule(Parser *p) D(fprintf(stderr, "%*c+ star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' star_targets_tuple_seq? ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13243,7 +13687,7 @@ star_atom_rule(Parser *p) _res = _Py_Tuple ( a , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13254,7 +13698,7 @@ star_atom_rule(Parser *p) } { // '[' star_targets_list_seq? ']' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'[' star_targets_list_seq? ']'")); @@ -13272,7 +13716,7 @@ star_atom_rule(Parser *p) D(fprintf(stderr, "%*c+ star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' star_targets_list_seq? ']'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13282,7 +13726,7 @@ star_atom_rule(Parser *p) _res = _Py_List ( a , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13293,7 +13737,7 @@ star_atom_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -13301,16 +13745,19 @@ star_atom_rule(Parser *p) static expr_ty single_target_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // single_subscript_attribute_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> single_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "single_subscript_attribute_target")); @@ -13329,7 +13776,7 @@ single_target_rule(Parser *p) } { // NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> single_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); @@ -13342,7 +13789,7 @@ single_target_rule(Parser *p) _res = _PyPegen_set_expr_context ( p , a , Store ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13353,7 +13800,7 @@ single_target_rule(Parser *p) } { // '(' single_target ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> single_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' single_target ')'")); @@ -13372,7 +13819,7 @@ single_target_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13383,7 +13830,7 @@ single_target_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -13393,16 +13840,19 @@ single_target_rule(Parser *p) static expr_ty single_subscript_attribute_target_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -13411,7 +13861,7 @@ single_subscript_attribute_target_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // t_primary '.' NAME !t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> single_subscript_attribute_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); @@ -13431,7 +13881,7 @@ single_subscript_attribute_target_rule(Parser *p) D(fprintf(stderr, "%*c+ single_subscript_attribute_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13441,7 +13891,7 @@ single_subscript_attribute_target_rule(Parser *p) _res = _Py_Attribute ( a , b -> v . Name . id , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13452,7 +13902,7 @@ single_subscript_attribute_target_rule(Parser *p) } { // t_primary '[' slices ']' !t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> single_subscript_attribute_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); @@ -13475,7 +13925,7 @@ single_subscript_attribute_target_rule(Parser *p) D(fprintf(stderr, "%*c+ single_subscript_attribute_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13485,7 +13935,7 @@ single_subscript_attribute_target_rule(Parser *p) _res = _Py_Subscript ( a , b , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13496,7 +13946,7 @@ single_subscript_attribute_target_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -13504,16 +13954,19 @@ single_subscript_attribute_target_rule(Parser *p) static asdl_seq* del_targets_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // ','.del_target+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.del_target+ ','?")); @@ -13530,7 +13983,7 @@ del_targets_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13541,7 +13994,7 @@ del_targets_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -13552,20 +14005,23 @@ del_targets_rule(Parser *p) static expr_ty del_target_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, del_target_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -13574,7 +14030,7 @@ del_target_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // t_primary '.' NAME !t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); @@ -13594,7 +14050,7 @@ del_target_rule(Parser *p) D(fprintf(stderr, "%*c+ del_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13604,7 +14060,7 @@ del_target_rule(Parser *p) _res = _Py_Attribute ( a , b -> v . Name . id , Del , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13615,7 +14071,7 @@ del_target_rule(Parser *p) } { // t_primary '[' slices ']' !t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); @@ -13638,7 +14094,7 @@ del_target_rule(Parser *p) D(fprintf(stderr, "%*c+ del_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13648,7 +14104,7 @@ del_target_rule(Parser *p) _res = _Py_Subscript ( a , b , Del , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13659,7 +14115,7 @@ del_target_rule(Parser *p) } { // del_t_atom if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "del_t_atom")); @@ -13679,7 +14135,7 @@ del_target_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, del_target_type, _res); - D(p->level--); + p->level--; return _res; } @@ -13687,16 +14143,19 @@ del_target_rule(Parser *p) static expr_ty del_t_atom_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -13705,7 +14164,7 @@ del_t_atom_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_t_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); @@ -13718,7 +14177,7 @@ del_t_atom_rule(Parser *p) _res = _PyPegen_set_expr_context ( p , a , Del ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13729,7 +14188,7 @@ del_t_atom_rule(Parser *p) } { // '(' del_target ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_t_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' del_target ')'")); @@ -13748,7 +14207,7 @@ del_t_atom_rule(Parser *p) _res = _PyPegen_set_expr_context ( p , a , Del ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13759,7 +14218,7 @@ del_t_atom_rule(Parser *p) } { // '(' del_targets? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_t_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' del_targets? ')'")); @@ -13777,7 +14236,7 @@ del_t_atom_rule(Parser *p) D(fprintf(stderr, "%*c+ del_t_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' del_targets? ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13787,7 +14246,7 @@ del_t_atom_rule(Parser *p) _res = _Py_Tuple ( a , Del , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13798,7 +14257,7 @@ del_t_atom_rule(Parser *p) } { // '[' del_targets? ']' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_t_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'[' del_targets? ']'")); @@ -13816,7 +14275,7 @@ del_t_atom_rule(Parser *p) D(fprintf(stderr, "%*c+ del_t_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' del_targets? ']'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13826,7 +14285,7 @@ del_t_atom_rule(Parser *p) _res = _Py_List ( a , Del , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13837,7 +14296,7 @@ del_t_atom_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -13852,10 +14311,13 @@ static expr_ty t_primary_raw(Parser *); static expr_ty t_primary_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, t_primary_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -13863,35 +14325,40 @@ t_primary_rule(Parser *p) while (1) { int tmpvar_8 = _PyPegen_update_memo(p, _mark, t_primary_type, _res); if (tmpvar_8) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; void *_raw = t_primary_raw(p); - if (p->error_indicator) + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty t_primary_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -13900,7 +14367,7 @@ t_primary_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // t_primary '.' NAME &t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME &t_lookahead")); @@ -13920,7 +14387,7 @@ t_primary_raw(Parser *p) D(fprintf(stderr, "%*c+ t_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME &t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13930,7 +14397,7 @@ t_primary_raw(Parser *p) _res = _Py_Attribute ( a , b -> v . Name . id , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13941,7 +14408,7 @@ t_primary_raw(Parser *p) } { // t_primary '[' slices ']' &t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' &t_lookahead")); @@ -13964,7 +14431,7 @@ t_primary_raw(Parser *p) D(fprintf(stderr, "%*c+ t_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' &t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13974,7 +14441,7 @@ t_primary_raw(Parser *p) _res = _Py_Subscript ( a , b , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13985,7 +14452,7 @@ t_primary_raw(Parser *p) } { // t_primary genexp &t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary genexp &t_lookahead")); @@ -14002,7 +14469,7 @@ t_primary_raw(Parser *p) D(fprintf(stderr, "%*c+ t_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary genexp &t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14012,7 +14479,7 @@ t_primary_raw(Parser *p) _res = _Py_Call ( a , CHECK ( _PyPegen_singleton_seq ( p , b ) ) , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14023,7 +14490,7 @@ t_primary_raw(Parser *p) } { // t_primary '(' arguments? ')' &t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '(' arguments? ')' &t_lookahead")); @@ -14046,7 +14513,7 @@ t_primary_raw(Parser *p) D(fprintf(stderr, "%*c+ t_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '(' arguments? ')' &t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14056,7 +14523,7 @@ t_primary_raw(Parser *p) _res = _Py_Call ( a , ( b ) ? ( ( expr_ty ) b ) -> v . Call . args : NULL , ( b ) ? ( ( expr_ty ) b ) -> v . Call . keywords : NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14067,7 +14534,7 @@ t_primary_raw(Parser *p) } { // atom &t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "atom &t_lookahead")); @@ -14082,7 +14549,7 @@ t_primary_raw(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14093,7 +14560,7 @@ t_primary_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14101,16 +14568,19 @@ t_primary_raw(Parser *p) static void * t_lookahead_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '(' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_lookahead[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); @@ -14129,7 +14599,7 @@ t_lookahead_rule(Parser *p) } { // '[' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_lookahead[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); @@ -14148,7 +14618,7 @@ t_lookahead_rule(Parser *p) } { // '.' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_lookahead[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); @@ -14167,7 +14637,7 @@ t_lookahead_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14180,16 +14650,19 @@ t_lookahead_rule(Parser *p) static void * invalid_arguments_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // args ',' '*' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ',' '*'")); @@ -14208,7 +14681,7 @@ invalid_arguments_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "iterable argument unpacking follows keyword argument unpacking" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14219,7 +14692,7 @@ invalid_arguments_rule(Parser *p) } { // expression for_if_clauses ',' [args | expression for_if_clauses] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses ',' [args | expression for_if_clauses]")); @@ -14242,7 +14715,7 @@ invalid_arguments_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "Generator expression must be parenthesized" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14253,7 +14726,7 @@ invalid_arguments_rule(Parser *p) } { // args for_if_clauses if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args for_if_clauses")); @@ -14269,7 +14742,7 @@ invalid_arguments_rule(Parser *p) _res = _PyPegen_nonparen_genexp_in_call ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14280,7 +14753,7 @@ invalid_arguments_rule(Parser *p) } { // args ',' expression for_if_clauses if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ',' expression for_if_clauses")); @@ -14302,7 +14775,7 @@ invalid_arguments_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "Generator expression must be parenthesized" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14313,7 +14786,7 @@ invalid_arguments_rule(Parser *p) } { // args ',' args if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ',' args")); @@ -14332,7 +14805,7 @@ invalid_arguments_rule(Parser *p) _res = _PyPegen_arguments_parsing_error ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14343,7 +14816,7 @@ invalid_arguments_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14351,16 +14824,19 @@ invalid_arguments_rule(Parser *p) static void * invalid_kwarg_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // !(NAME '=') expression '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_kwarg[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!(NAME '=') expression '='")); @@ -14378,7 +14854,7 @@ invalid_kwarg_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "expression cannot contain assignment, perhaps you meant \"==\"?" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14389,7 +14865,7 @@ invalid_kwarg_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14397,16 +14873,19 @@ invalid_kwarg_rule(Parser *p) static void * invalid_named_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // expression ':=' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ':=' expression")); @@ -14425,7 +14904,7 @@ invalid_named_expression_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use assignment expressions with %s" , _PyPegen_get_expr_name ( a ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14436,7 +14915,7 @@ invalid_named_expression_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14450,16 +14929,19 @@ invalid_named_expression_rule(Parser *p) static void * invalid_assignment_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // invalid_ann_assign_target ':' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_ann_assign_target ':' expression")); @@ -14478,7 +14960,7 @@ invalid_assignment_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "only single target (not %s) can be annotated" , _PyPegen_get_expr_name ( a ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14489,7 +14971,7 @@ invalid_assignment_rule(Parser *p) } { // star_named_expression ',' star_named_expressions* ':' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions* ':' expression")); @@ -14514,7 +14996,7 @@ invalid_assignment_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "only single target (not tuple) can be annotated" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14525,7 +15007,7 @@ invalid_assignment_rule(Parser *p) } { // expression ':' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ':' expression")); @@ -14544,7 +15026,7 @@ invalid_assignment_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "illegal target for annotation" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14555,7 +15037,7 @@ invalid_assignment_rule(Parser *p) } { // ((star_targets '='))* star_expressions '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* star_expressions '='")); @@ -14574,7 +15056,7 @@ invalid_assignment_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( STAR_TARGETS , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14585,7 +15067,7 @@ invalid_assignment_rule(Parser *p) } { // ((star_targets '='))* yield_expr '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* yield_expr '='")); @@ -14604,7 +15086,7 @@ invalid_assignment_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "assignment to yield expression not possible" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14615,7 +15097,7 @@ invalid_assignment_rule(Parser *p) } { // star_expressions augassign (yield_expr | star_expressions) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions augassign (yield_expr | star_expressions)")); @@ -14634,7 +15116,7 @@ invalid_assignment_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "'%s' is an illegal expression for augmented assignment" , _PyPegen_get_expr_name ( a ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14645,7 +15127,7 @@ invalid_assignment_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14653,16 +15135,19 @@ invalid_assignment_rule(Parser *p) static expr_ty invalid_ann_assign_target_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // list if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_ann_assign_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); @@ -14681,7 +15166,7 @@ invalid_ann_assign_target_rule(Parser *p) } { // tuple if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_ann_assign_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); @@ -14700,7 +15185,7 @@ invalid_ann_assign_target_rule(Parser *p) } { // '(' invalid_ann_assign_target ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_ann_assign_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' invalid_ann_assign_target ')'")); @@ -14719,7 +15204,7 @@ invalid_ann_assign_target_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14730,7 +15215,7 @@ invalid_ann_assign_target_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14738,16 +15223,19 @@ invalid_ann_assign_target_rule(Parser *p) static void * invalid_del_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'del' star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_del_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'del' star_expressions")); @@ -14763,7 +15251,7 @@ invalid_del_stmt_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( DEL_TARGETS , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14774,7 +15262,7 @@ invalid_del_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14782,16 +15270,19 @@ invalid_del_stmt_rule(Parser *p) static void * invalid_block_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE !INDENT")); @@ -14806,7 +15297,7 @@ invalid_block_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14817,7 +15308,7 @@ invalid_block_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14826,16 +15317,19 @@ invalid_block_rule(Parser *p) static void * invalid_primary_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // primary '{' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "primary '{'")); @@ -14851,7 +15345,7 @@ invalid_primary_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "invalid syntax" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14862,7 +15356,7 @@ invalid_primary_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14870,16 +15364,19 @@ invalid_primary_rule(Parser *p) static void * invalid_comprehension_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ('[' | '(' | '{') starred_expression for_if_clauses if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '(' | '{') starred_expression for_if_clauses")); @@ -14898,7 +15395,7 @@ invalid_comprehension_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "iterable unpacking cannot be used in comprehension" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14909,7 +15406,7 @@ invalid_comprehension_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14917,16 +15414,19 @@ invalid_comprehension_rule(Parser *p) static void * invalid_dict_comprehension_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '{' '**' bitwise_or for_if_clauses '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_dict_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' '**' bitwise_or for_if_clauses '}'")); @@ -14951,7 +15451,7 @@ invalid_dict_comprehension_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "dict unpacking cannot be used in dict comprehension" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14962,7 +15462,7 @@ invalid_dict_comprehension_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14971,16 +15471,19 @@ invalid_dict_comprehension_rule(Parser *p) static void * invalid_parameters_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // param_no_default* (slash_with_default | param_with_default+) param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default* (slash_with_default | param_with_default+) param_no_default")); @@ -14999,7 +15502,7 @@ invalid_parameters_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "non-default argument follows default argument" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15010,7 +15513,7 @@ invalid_parameters_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15019,16 +15522,19 @@ invalid_parameters_rule(Parser *p) static void * invalid_lambda_parameters_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // lambda_param_no_default* (lambda_slash_with_default | lambda_param_with_default+) lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* (lambda_slash_with_default | lambda_param_with_default+) lambda_param_no_default")); @@ -15047,7 +15553,7 @@ invalid_lambda_parameters_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "non-default argument follows default argument" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15058,7 +15564,7 @@ invalid_lambda_parameters_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15066,16 +15572,19 @@ invalid_lambda_parameters_rule(Parser *p) static void * invalid_star_etc_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '*' (')' | ',' (')' | '**')) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))")); @@ -15091,7 +15600,7 @@ invalid_star_etc_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "named arguments must follow bare *" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15102,7 +15611,7 @@ invalid_star_etc_rule(Parser *p) } { // '*' ',' TYPE_COMMENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' ',' TYPE_COMMENT")); @@ -15121,7 +15630,7 @@ invalid_star_etc_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "bare * has associated type comment" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15132,7 +15641,7 @@ invalid_star_etc_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15140,16 +15649,19 @@ invalid_star_etc_rule(Parser *p) static void * invalid_lambda_star_etc_rule(Parser *p) { - D(p->level++); - if (p->error_indicator) { - D(p->level--); - return NULL; + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; + return NULL; } void * _res = NULL; int _mark = p->mark; { // '*' (':' | ',' (':' | '**')) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))")); @@ -15165,7 +15677,7 @@ invalid_lambda_star_etc_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "named arguments must follow bare *" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15176,7 +15688,7 @@ invalid_lambda_star_etc_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15184,16 +15696,19 @@ invalid_lambda_star_etc_rule(Parser *p) static void * invalid_double_type_comments_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // TYPE_COMMENT NEWLINE TYPE_COMMENT NEWLINE INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_double_type_comments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "TYPE_COMMENT NEWLINE TYPE_COMMENT NEWLINE INDENT")); @@ -15218,7 +15733,7 @@ invalid_double_type_comments_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "Cannot have two type comments on def" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15229,7 +15744,7 @@ invalid_double_type_comments_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15237,16 +15752,19 @@ invalid_double_type_comments_rule(Parser *p) static void * invalid_with_item_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // expression 'as' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_with_item[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression 'as' expression")); @@ -15265,7 +15783,7 @@ invalid_with_item_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( STAR_TARGETS , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15276,7 +15794,7 @@ invalid_with_item_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15284,16 +15802,19 @@ invalid_with_item_rule(Parser *p) static void * invalid_for_target_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ASYNC? 'for' star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_for_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'for' star_expressions")); @@ -15313,7 +15834,7 @@ invalid_for_target_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( FOR_TARGETS , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15324,7 +15845,7 @@ invalid_for_target_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15332,16 +15853,19 @@ invalid_for_target_rule(Parser *p) static void * invalid_group_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '(' starred_expression ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_group[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' starred_expression ')'")); @@ -15360,7 +15884,7 @@ invalid_group_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "can't use starred expression here" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15371,7 +15895,7 @@ invalid_group_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15379,16 +15903,19 @@ invalid_group_rule(Parser *p) static void * invalid_import_from_targets_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // import_from_as_names ',' NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_import_from_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "import_from_as_names ',' NEWLINE")); @@ -15407,7 +15934,7 @@ invalid_import_from_targets_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "trailing comma not allowed without surrounding parentheses" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15418,7 +15945,7 @@ invalid_import_from_targets_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15426,9 +15953,12 @@ invalid_import_from_targets_rule(Parser *p) static asdl_seq * _loop0_1_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -15438,14 +15968,14 @@ _loop0_1_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_1[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); @@ -15461,7 +15991,7 @@ _loop0_1_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -15478,13 +16008,13 @@ _loop0_1_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_1_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -15492,9 +16022,12 @@ _loop0_1_rule(Parser *p) static asdl_seq * _loop0_2_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -15504,14 +16037,14 @@ _loop0_2_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_2[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); @@ -15527,7 +16060,7 @@ _loop0_2_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -15544,13 +16077,13 @@ _loop0_2_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_2_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -15558,9 +16091,12 @@ _loop0_2_rule(Parser *p) static asdl_seq * _loop0_4_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -15570,14 +16106,14 @@ _loop0_4_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ',' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_4[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); @@ -15593,7 +16129,7 @@ _loop0_4_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -15602,7 +16138,7 @@ _loop0_4_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -15619,13 +16155,13 @@ _loop0_4_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_4_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -15633,16 +16169,19 @@ _loop0_4_rule(Parser *p) static asdl_seq * _gather_3_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // expression _loop0_4 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_3[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_4")); @@ -15664,7 +16203,7 @@ _gather_3_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15672,9 +16211,12 @@ _gather_3_rule(Parser *p) static asdl_seq * _loop0_6_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -15684,14 +16226,14 @@ _loop0_6_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ',' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_6[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); @@ -15707,7 +16249,7 @@ _loop0_6_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -15716,7 +16258,7 @@ _loop0_6_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -15733,13 +16275,13 @@ _loop0_6_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_6_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -15747,16 +16289,19 @@ _loop0_6_rule(Parser *p) static asdl_seq * _gather_5_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // expression _loop0_6 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_5[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_6")); @@ -15778,7 +16323,7 @@ _gather_5_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15786,9 +16331,12 @@ _gather_5_rule(Parser *p) static asdl_seq * _loop0_8_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -15798,14 +16346,14 @@ _loop0_8_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ',' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_8[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); @@ -15821,7 +16369,7 @@ _loop0_8_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -15830,7 +16378,7 @@ _loop0_8_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -15847,13 +16395,13 @@ _loop0_8_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_8_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -15861,16 +16409,19 @@ _loop0_8_rule(Parser *p) static asdl_seq * _gather_7_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // expression _loop0_8 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_7[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_8")); @@ -15892,7 +16443,7 @@ _gather_7_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15900,9 +16451,12 @@ _gather_7_rule(Parser *p) static asdl_seq * _loop0_10_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -15912,14 +16466,14 @@ _loop0_10_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ',' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_10[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); @@ -15935,7 +16489,7 @@ _loop0_10_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -15944,7 +16498,7 @@ _loop0_10_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -15961,13 +16515,13 @@ _loop0_10_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_10_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -15975,16 +16529,19 @@ _loop0_10_rule(Parser *p) static asdl_seq * _gather_9_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // expression _loop0_10 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_9[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_10")); @@ -16006,7 +16563,7 @@ _gather_9_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16014,9 +16571,12 @@ _gather_9_rule(Parser *p) static asdl_seq * _loop1_11_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -16026,14 +16586,14 @@ _loop1_11_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // statement if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_11[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "statement")); @@ -16049,7 +16609,7 @@ _loop1_11_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -16063,7 +16623,7 @@ _loop1_11_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -16071,13 +16631,13 @@ _loop1_11_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_11_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -16085,9 +16645,12 @@ _loop1_11_rule(Parser *p) static asdl_seq * _loop0_13_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -16097,14 +16660,14 @@ _loop0_13_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ';' small_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_13[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "';' small_stmt")); @@ -16120,7 +16683,7 @@ _loop0_13_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -16129,7 +16692,7 @@ _loop0_13_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -16146,13 +16709,13 @@ _loop0_13_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_13_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -16160,16 +16723,19 @@ _loop0_13_rule(Parser *p) static asdl_seq * _gather_12_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // small_stmt _loop0_13 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_12[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "small_stmt _loop0_13")); @@ -16191,7 +16757,7 @@ _gather_12_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16199,16 +16765,19 @@ _gather_12_rule(Parser *p) static void * _tmp_14_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'import' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_14[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'import'")); @@ -16227,7 +16796,7 @@ _tmp_14_rule(Parser *p) } { // 'from' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_14[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from'")); @@ -16246,7 +16815,7 @@ _tmp_14_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16254,16 +16823,19 @@ _tmp_14_rule(Parser *p) static void * _tmp_15_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'def' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_15[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'def'")); @@ -16282,7 +16854,7 @@ _tmp_15_rule(Parser *p) } { // '@' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_15[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@'")); @@ -16301,7 +16873,7 @@ _tmp_15_rule(Parser *p) } { // ASYNC if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_15[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC")); @@ -16320,7 +16892,7 @@ _tmp_15_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16328,16 +16900,19 @@ _tmp_15_rule(Parser *p) static void * _tmp_16_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'class' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_16[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class'")); @@ -16356,7 +16931,7 @@ _tmp_16_rule(Parser *p) } { // '@' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_16[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@'")); @@ -16375,7 +16950,7 @@ _tmp_16_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16383,16 +16958,19 @@ _tmp_16_rule(Parser *p) static void * _tmp_17_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'with' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_17[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'with'")); @@ -16411,7 +16989,7 @@ _tmp_17_rule(Parser *p) } { // ASYNC if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_17[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC")); @@ -16430,7 +17008,7 @@ _tmp_17_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16438,16 +17016,19 @@ _tmp_17_rule(Parser *p) static void * _tmp_18_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'for' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_18[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'for'")); @@ -16466,7 +17047,7 @@ _tmp_18_rule(Parser *p) } { // ASYNC if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_18[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC")); @@ -16485,7 +17066,7 @@ _tmp_18_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16493,16 +17074,19 @@ _tmp_18_rule(Parser *p) static void * _tmp_19_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '=' annotated_rhs if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_19[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'=' annotated_rhs")); @@ -16518,7 +17102,7 @@ _tmp_19_rule(Parser *p) _res = d; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16529,7 +17113,7 @@ _tmp_19_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16537,16 +17121,19 @@ _tmp_19_rule(Parser *p) static void * _tmp_20_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '(' single_target ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_20[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' single_target ')'")); @@ -16565,7 +17152,7 @@ _tmp_20_rule(Parser *p) _res = b; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16576,7 +17163,7 @@ _tmp_20_rule(Parser *p) } { // single_subscript_attribute_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_20[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "single_subscript_attribute_target")); @@ -16595,7 +17182,7 @@ _tmp_20_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16603,16 +17190,19 @@ _tmp_20_rule(Parser *p) static void * _tmp_21_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '=' annotated_rhs if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_21[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'=' annotated_rhs")); @@ -16628,7 +17218,7 @@ _tmp_21_rule(Parser *p) _res = d; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16639,7 +17229,7 @@ _tmp_21_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16647,9 +17237,12 @@ _tmp_21_rule(Parser *p) static asdl_seq * _loop1_22_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -16659,14 +17252,14 @@ _loop1_22_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // (star_targets '=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_22[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); @@ -16682,7 +17275,7 @@ _loop1_22_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -16696,7 +17289,7 @@ _loop1_22_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -16704,13 +17297,13 @@ _loop1_22_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_22_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -16718,16 +17311,19 @@ _loop1_22_rule(Parser *p) static void * _tmp_23_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // yield_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_23[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); @@ -16746,7 +17342,7 @@ _tmp_23_rule(Parser *p) } { // star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_23[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); @@ -16765,7 +17361,7 @@ _tmp_23_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16773,16 +17369,19 @@ _tmp_23_rule(Parser *p) static void * _tmp_24_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // yield_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_24[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); @@ -16801,7 +17400,7 @@ _tmp_24_rule(Parser *p) } { // star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_24[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); @@ -16820,7 +17419,7 @@ _tmp_24_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16828,9 +17427,12 @@ _tmp_24_rule(Parser *p) static asdl_seq * _loop0_26_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -16840,14 +17442,14 @@ _loop0_26_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ',' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_26[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' NAME")); @@ -16863,7 +17465,7 @@ _loop0_26_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -16872,7 +17474,7 @@ _loop0_26_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -16889,13 +17491,13 @@ _loop0_26_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_26_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -16903,16 +17505,19 @@ _loop0_26_rule(Parser *p) static asdl_seq * _gather_25_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // NAME _loop0_26 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_25[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME _loop0_26")); @@ -16934,7 +17539,7 @@ _gather_25_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16942,9 +17547,12 @@ _gather_25_rule(Parser *p) static asdl_seq * _loop0_28_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -16954,14 +17562,14 @@ _loop0_28_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ',' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_28[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' NAME")); @@ -16977,7 +17585,7 @@ _loop0_28_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -16986,7 +17594,7 @@ _loop0_28_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -17003,13 +17611,13 @@ _loop0_28_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_28_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -17017,16 +17625,19 @@ _loop0_28_rule(Parser *p) static asdl_seq * _gather_27_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // NAME _loop0_28 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_27[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME _loop0_28")); @@ -17048,7 +17659,7 @@ _gather_27_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -17056,16 +17667,19 @@ _gather_27_rule(Parser *p) static void * _tmp_29_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_29[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); @@ -17081,7 +17695,7 @@ _tmp_29_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17092,7 +17706,7 @@ _tmp_29_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -17100,16 +17714,19 @@ _tmp_29_rule(Parser *p) static void * _tmp_30_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ';' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_30[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "';'")); @@ -17128,7 +17745,7 @@ _tmp_30_rule(Parser *p) } { // NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_30[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); @@ -17147,7 +17764,7 @@ _tmp_30_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -17155,9 +17772,12 @@ _tmp_30_rule(Parser *p) static asdl_seq * _loop0_31_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -17167,14 +17787,14 @@ _loop0_31_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ('.' | '...') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_31[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); @@ -17190,7 +17810,7 @@ _loop0_31_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -17207,13 +17827,13 @@ _loop0_31_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_31_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -17221,9 +17841,12 @@ _loop0_31_rule(Parser *p) static asdl_seq * _loop1_32_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -17233,14 +17856,14 @@ _loop1_32_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ('.' | '...') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_32[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); @@ -17256,7 +17879,7 @@ _loop1_32_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -17270,7 +17893,7 @@ _loop1_32_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -17278,13 +17901,13 @@ _loop1_32_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_32_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -17292,9 +17915,12 @@ _loop1_32_rule(Parser *p) static asdl_seq * _loop0_34_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -17304,14 +17930,14 @@ _loop0_34_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ',' import_from_as_name if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_34[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' import_from_as_name")); @@ -17327,7 +17953,7 @@ _loop0_34_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -17336,7 +17962,7 @@ _loop0_34_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -17353,13 +17979,13 @@ _loop0_34_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_34_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -17367,16 +17993,19 @@ _loop0_34_rule(Parser *p) static asdl_seq * _gather_33_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // import_from_as_name _loop0_34 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_33[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "import_from_as_name _loop0_34")); @@ -17398,7 +18027,7 @@ _gather_33_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -17406,16 +18035,19 @@ _gather_33_rule(Parser *p) static void * _tmp_35_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_35[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); @@ -17431,7 +18063,7 @@ _tmp_35_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17442,7 +18074,7 @@ _tmp_35_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -17450,9 +18082,12 @@ _tmp_35_rule(Parser *p) static asdl_seq * _loop0_37_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -17462,14 +18097,14 @@ _loop0_37_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ',' dotted_as_name if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_37[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' dotted_as_name")); @@ -17485,7 +18120,7 @@ _loop0_37_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -17494,7 +18129,7 @@ _loop0_37_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -17511,13 +18146,13 @@ _loop0_37_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_37_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -17525,16 +18160,19 @@ _loop0_37_rule(Parser *p) static asdl_seq * _gather_36_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // dotted_as_name _loop0_37 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_36[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dotted_as_name _loop0_37")); @@ -17556,7 +18194,7 @@ _gather_36_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -17564,16 +18202,19 @@ _gather_36_rule(Parser *p) static void * _tmp_38_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_38[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); @@ -17589,7 +18230,7 @@ _tmp_38_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17600,7 +18241,7 @@ _tmp_38_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -17608,9 +18249,12 @@ _tmp_38_rule(Parser *p) static asdl_seq * _loop0_40_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -17620,14 +18264,14 @@ _loop0_40_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ',' with_item if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_40[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); @@ -17643,7 +18287,7 @@ _loop0_40_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -17652,7 +18296,7 @@ _loop0_40_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -17669,13 +18313,13 @@ _loop0_40_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_40_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -17683,16 +18327,19 @@ _loop0_40_rule(Parser *p) static asdl_seq * _gather_39_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // with_item _loop0_40 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_39[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_40")); @@ -17714,7 +18361,7 @@ _gather_39_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -17722,9 +18369,12 @@ _gather_39_rule(Parser *p) static asdl_seq * _loop0_42_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -17734,14 +18384,14 @@ _loop0_42_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ',' with_item if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_42[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); @@ -17757,7 +18407,7 @@ _loop0_42_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -17766,7 +18416,7 @@ _loop0_42_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -17783,13 +18433,13 @@ _loop0_42_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_42_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -17797,16 +18447,19 @@ _loop0_42_rule(Parser *p) static asdl_seq * _gather_41_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // with_item _loop0_42 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_41[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_42")); @@ -17828,7 +18481,7 @@ _gather_41_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -17836,9 +18489,12 @@ _gather_41_rule(Parser *p) static asdl_seq * _loop0_44_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -17848,14 +18504,14 @@ _loop0_44_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ',' with_item if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_44[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); @@ -17871,7 +18527,7 @@ _loop0_44_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -17880,7 +18536,7 @@ _loop0_44_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -17897,13 +18553,13 @@ _loop0_44_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_44_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -17911,16 +18567,19 @@ _loop0_44_rule(Parser *p) static asdl_seq * _gather_43_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // with_item _loop0_44 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_43[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_44")); @@ -17942,7 +18601,7 @@ _gather_43_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -17950,9 +18609,12 @@ _gather_43_rule(Parser *p) static asdl_seq * _loop0_46_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -17962,14 +18624,14 @@ _loop0_46_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ',' with_item if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_46[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); @@ -17985,7 +18647,7 @@ _loop0_46_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -17994,7 +18656,7 @@ _loop0_46_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -18011,13 +18673,13 @@ _loop0_46_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_46_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -18025,16 +18687,19 @@ _loop0_46_rule(Parser *p) static asdl_seq * _gather_45_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // with_item _loop0_46 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_45[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_46")); @@ -18056,7 +18721,7 @@ _gather_45_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18064,16 +18729,19 @@ _gather_45_rule(Parser *p) static void * _tmp_47_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_47[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); @@ -18092,7 +18760,7 @@ _tmp_47_rule(Parser *p) } { // ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_47[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); @@ -18111,7 +18779,7 @@ _tmp_47_rule(Parser *p) } { // ':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_47[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); @@ -18130,7 +18798,7 @@ _tmp_47_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18138,9 +18806,12 @@ _tmp_47_rule(Parser *p) static asdl_seq * _loop1_48_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -18150,14 +18821,14 @@ _loop1_48_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // except_block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_48[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_block")); @@ -18173,7 +18844,7 @@ _loop1_48_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -18187,7 +18858,7 @@ _loop1_48_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -18195,13 +18866,13 @@ _loop1_48_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_48_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -18209,16 +18880,19 @@ _loop1_48_rule(Parser *p) static void * _tmp_49_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_49[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); @@ -18234,7 +18908,7 @@ _tmp_49_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18245,7 +18919,7 @@ _tmp_49_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18253,16 +18927,19 @@ _tmp_49_rule(Parser *p) static void * _tmp_50_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'from' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_50[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from' expression")); @@ -18278,7 +18955,7 @@ _tmp_50_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18289,7 +18966,7 @@ _tmp_50_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18297,16 +18974,19 @@ _tmp_50_rule(Parser *p) static void * _tmp_51_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '->' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_51[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); @@ -18322,7 +19002,7 @@ _tmp_51_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18333,7 +19013,7 @@ _tmp_51_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18341,16 +19021,19 @@ _tmp_51_rule(Parser *p) static void * _tmp_52_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '->' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_52[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); @@ -18366,7 +19049,7 @@ _tmp_52_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18377,7 +19060,7 @@ _tmp_52_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18385,16 +19068,19 @@ _tmp_52_rule(Parser *p) static void * _tmp_53_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // NEWLINE INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_53[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT")); @@ -18416,7 +19102,7 @@ _tmp_53_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18424,9 +19110,12 @@ _tmp_53_rule(Parser *p) static asdl_seq * _loop0_54_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -18436,14 +19125,14 @@ _loop0_54_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_54[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -18459,7 +19148,7 @@ _loop0_54_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -18476,13 +19165,13 @@ _loop0_54_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_54_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -18490,9 +19179,12 @@ _loop0_54_rule(Parser *p) static asdl_seq * _loop0_55_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -18502,14 +19194,14 @@ _loop0_55_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_55[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); @@ -18525,7 +19217,7 @@ _loop0_55_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -18542,13 +19234,13 @@ _loop0_55_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_55_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -18556,9 +19248,12 @@ _loop0_55_rule(Parser *p) static asdl_seq * _loop0_56_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -18568,14 +19263,14 @@ _loop0_56_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_56[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); @@ -18591,7 +19286,7 @@ _loop0_56_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -18608,13 +19303,13 @@ _loop0_56_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_56_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -18622,9 +19317,12 @@ _loop0_56_rule(Parser *p) static asdl_seq * _loop1_57_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -18634,14 +19332,14 @@ _loop1_57_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_57[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -18657,7 +19355,7 @@ _loop1_57_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -18671,7 +19369,7 @@ _loop1_57_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -18679,13 +19377,13 @@ _loop1_57_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_57_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -18693,9 +19391,12 @@ _loop1_57_rule(Parser *p) static asdl_seq * _loop0_58_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -18705,14 +19406,14 @@ _loop0_58_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_58[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); @@ -18728,7 +19429,7 @@ _loop0_58_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -18745,13 +19446,13 @@ _loop0_58_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_58_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -18759,9 +19460,12 @@ _loop0_58_rule(Parser *p) static asdl_seq * _loop1_59_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -18771,14 +19475,14 @@ _loop1_59_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_59[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); @@ -18794,7 +19498,7 @@ _loop1_59_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -18808,7 +19512,7 @@ _loop1_59_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -18816,13 +19520,13 @@ _loop1_59_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_59_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -18830,9 +19534,12 @@ _loop1_59_rule(Parser *p) static asdl_seq * _loop1_60_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -18842,14 +19549,14 @@ _loop1_60_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_60[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -18865,7 +19572,7 @@ _loop1_60_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -18879,7 +19586,7 @@ _loop1_60_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -18887,13 +19594,13 @@ _loop1_60_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_60_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -18901,9 +19608,12 @@ _loop1_60_rule(Parser *p) static asdl_seq * _loop1_61_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -18913,14 +19623,14 @@ _loop1_61_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_61[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -18936,7 +19646,7 @@ _loop1_61_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -18950,7 +19660,7 @@ _loop1_61_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -18958,13 +19668,13 @@ _loop1_61_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_61_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -18972,9 +19682,12 @@ _loop1_61_rule(Parser *p) static asdl_seq * _loop0_62_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -18984,14 +19697,14 @@ _loop0_62_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_62[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -19007,7 +19720,7 @@ _loop0_62_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -19024,13 +19737,13 @@ _loop0_62_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_62_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -19038,9 +19751,12 @@ _loop0_62_rule(Parser *p) static asdl_seq * _loop1_63_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -19050,14 +19766,14 @@ _loop1_63_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_63[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); @@ -19073,7 +19789,7 @@ _loop1_63_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -19087,7 +19803,7 @@ _loop1_63_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -19095,13 +19811,13 @@ _loop1_63_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_63_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -19109,9 +19825,12 @@ _loop1_63_rule(Parser *p) static asdl_seq * _loop0_64_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -19121,14 +19840,14 @@ _loop0_64_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_64[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -19144,7 +19863,7 @@ _loop0_64_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -19161,13 +19880,13 @@ _loop0_64_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_64_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -19175,9 +19894,12 @@ _loop0_64_rule(Parser *p) static asdl_seq * _loop1_65_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -19187,14 +19909,14 @@ _loop1_65_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_65[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); @@ -19210,7 +19932,7 @@ _loop1_65_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -19224,7 +19946,7 @@ _loop1_65_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -19232,13 +19954,13 @@ _loop1_65_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_65_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -19246,9 +19968,12 @@ _loop1_65_rule(Parser *p) static asdl_seq * _loop0_66_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -19258,14 +19983,14 @@ _loop0_66_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // param_maybe_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_66[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); @@ -19281,7 +20006,7 @@ _loop0_66_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -19298,13 +20023,13 @@ _loop0_66_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_66_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -19312,9 +20037,12 @@ _loop0_66_rule(Parser *p) static asdl_seq * _loop1_67_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -19324,14 +20052,14 @@ _loop1_67_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // param_maybe_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_67[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); @@ -19347,7 +20075,7 @@ _loop1_67_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -19361,7 +20089,7 @@ _loop1_67_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -19369,13 +20097,13 @@ _loop1_67_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_67_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -19383,9 +20111,12 @@ _loop1_67_rule(Parser *p) static asdl_seq * _loop1_68_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -19395,14 +20126,14 @@ _loop1_68_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ('@' named_expression NEWLINE) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_68[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('@' named_expression NEWLINE)")); @@ -19418,7 +20149,7 @@ _loop1_68_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -19432,7 +20163,7 @@ _loop1_68_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -19440,13 +20171,13 @@ _loop1_68_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_68_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -19454,16 +20185,19 @@ _loop1_68_rule(Parser *p) static void * _tmp_69_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '(' arguments? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_69[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); @@ -19482,7 +20216,7 @@ _tmp_69_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19493,7 +20227,7 @@ _tmp_69_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19501,9 +20235,12 @@ _tmp_69_rule(Parser *p) static asdl_seq * _loop1_70_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -19513,14 +20250,14 @@ _loop1_70_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // (',' star_expression) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_70[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_expression)")); @@ -19536,7 +20273,7 @@ _loop1_70_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -19550,7 +20287,7 @@ _loop1_70_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -19558,13 +20295,13 @@ _loop1_70_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_70_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -19572,9 +20309,12 @@ _loop1_70_rule(Parser *p) static asdl_seq * _loop0_72_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -19584,14 +20324,14 @@ _loop0_72_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ',' star_named_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_72[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_named_expression")); @@ -19607,7 +20347,7 @@ _loop0_72_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -19616,7 +20356,7 @@ _loop0_72_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -19633,13 +20373,13 @@ _loop0_72_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_72_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -19647,16 +20387,19 @@ _loop0_72_rule(Parser *p) static asdl_seq * _gather_71_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // star_named_expression _loop0_72 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_71[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression _loop0_72")); @@ -19678,7 +20421,7 @@ _gather_71_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19686,9 +20429,12 @@ _gather_71_rule(Parser *p) static asdl_seq * _loop1_73_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -19698,14 +20444,14 @@ _loop1_73_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // (',' expression) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_73[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' expression)")); @@ -19721,7 +20467,7 @@ _loop1_73_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -19735,7 +20481,7 @@ _loop1_73_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -19743,13 +20489,13 @@ _loop1_73_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_73_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -19757,9 +20503,12 @@ _loop1_73_rule(Parser *p) static asdl_seq * _loop0_74_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -19769,14 +20518,14 @@ _loop0_74_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_74[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -19792,7 +20541,7 @@ _loop0_74_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -19809,13 +20558,13 @@ _loop0_74_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_74_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -19823,9 +20572,12 @@ _loop0_74_rule(Parser *p) static asdl_seq * _loop0_75_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -19835,14 +20587,14 @@ _loop0_75_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_75[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); @@ -19858,7 +20610,7 @@ _loop0_75_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -19875,13 +20627,13 @@ _loop0_75_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_75_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -19889,9 +20641,12 @@ _loop0_75_rule(Parser *p) static asdl_seq * _loop0_76_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -19901,14 +20656,14 @@ _loop0_76_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_76[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); @@ -19924,7 +20679,7 @@ _loop0_76_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -19941,13 +20696,13 @@ _loop0_76_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_76_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -19955,9 +20710,12 @@ _loop0_76_rule(Parser *p) static asdl_seq * _loop1_77_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -19967,14 +20725,14 @@ _loop1_77_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_77[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -19990,7 +20748,7 @@ _loop1_77_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -20004,7 +20762,7 @@ _loop1_77_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -20012,13 +20770,13 @@ _loop1_77_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_77_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -20026,9 +20784,12 @@ _loop1_77_rule(Parser *p) static asdl_seq * _loop0_78_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -20038,14 +20799,14 @@ _loop0_78_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_78[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); @@ -20061,7 +20822,7 @@ _loop0_78_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -20078,13 +20839,13 @@ _loop0_78_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_78_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -20092,9 +20853,12 @@ _loop0_78_rule(Parser *p) static asdl_seq * _loop1_79_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -20104,14 +20868,14 @@ _loop1_79_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_79[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); @@ -20127,7 +20891,7 @@ _loop1_79_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -20141,7 +20905,7 @@ _loop1_79_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -20149,13 +20913,13 @@ _loop1_79_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_79_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -20163,9 +20927,12 @@ _loop1_79_rule(Parser *p) static asdl_seq * _loop1_80_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -20175,14 +20942,14 @@ _loop1_80_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_80[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -20198,7 +20965,7 @@ _loop1_80_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -20212,7 +20979,7 @@ _loop1_80_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -20220,13 +20987,13 @@ _loop1_80_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_80_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -20234,9 +21001,12 @@ _loop1_80_rule(Parser *p) static asdl_seq * _loop1_81_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -20246,14 +21016,14 @@ _loop1_81_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_81[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -20269,7 +21039,7 @@ _loop1_81_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -20283,7 +21053,7 @@ _loop1_81_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -20291,13 +21061,13 @@ _loop1_81_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_81_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -20305,9 +21075,12 @@ _loop1_81_rule(Parser *p) static asdl_seq * _loop0_82_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -20317,14 +21090,14 @@ _loop0_82_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_82[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -20340,7 +21113,7 @@ _loop0_82_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -20357,13 +21130,13 @@ _loop0_82_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_82_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -20371,9 +21144,12 @@ _loop0_82_rule(Parser *p) static asdl_seq * _loop1_83_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -20383,14 +21159,14 @@ _loop1_83_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_83[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); @@ -20406,7 +21182,7 @@ _loop1_83_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -20420,7 +21196,7 @@ _loop1_83_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -20428,13 +21204,13 @@ _loop1_83_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_83_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -20442,9 +21218,12 @@ _loop1_83_rule(Parser *p) static asdl_seq * _loop0_84_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -20454,14 +21233,14 @@ _loop0_84_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_84[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -20477,7 +21256,7 @@ _loop0_84_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -20494,13 +21273,13 @@ _loop0_84_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_84_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -20508,9 +21287,12 @@ _loop0_84_rule(Parser *p) static asdl_seq * _loop1_85_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -20520,14 +21302,14 @@ _loop1_85_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_85[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); @@ -20543,7 +21325,7 @@ _loop1_85_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -20557,7 +21339,7 @@ _loop1_85_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -20565,13 +21347,13 @@ _loop1_85_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_85_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -20579,9 +21361,12 @@ _loop1_85_rule(Parser *p) static asdl_seq * _loop0_86_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -20591,14 +21376,14 @@ _loop0_86_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // lambda_param_maybe_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_86[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); @@ -20614,7 +21399,7 @@ _loop0_86_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -20631,13 +21416,13 @@ _loop0_86_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_86_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -20645,9 +21430,12 @@ _loop0_86_rule(Parser *p) static asdl_seq * _loop1_87_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -20657,14 +21445,14 @@ _loop1_87_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // lambda_param_maybe_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_87[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); @@ -20680,7 +21468,7 @@ _loop1_87_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -20694,7 +21482,7 @@ _loop1_87_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -20702,13 +21490,13 @@ _loop1_87_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_87_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -20716,9 +21504,12 @@ _loop1_87_rule(Parser *p) static asdl_seq * _loop1_88_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -20728,14 +21519,14 @@ _loop1_88_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ('or' conjunction) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_88[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('or' conjunction)")); @@ -20751,7 +21542,7 @@ _loop1_88_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -20765,7 +21556,7 @@ _loop1_88_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -20773,13 +21564,13 @@ _loop1_88_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_88_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -20787,9 +21578,12 @@ _loop1_88_rule(Parser *p) static asdl_seq * _loop1_89_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -20799,14 +21593,14 @@ _loop1_89_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ('and' inversion) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_89[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('and' inversion)")); @@ -20822,7 +21616,7 @@ _loop1_89_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -20836,7 +21630,7 @@ _loop1_89_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -20844,13 +21638,13 @@ _loop1_89_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_89_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -20858,9 +21652,12 @@ _loop1_89_rule(Parser *p) static asdl_seq * _loop1_90_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -20870,14 +21667,14 @@ _loop1_90_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // compare_op_bitwise_or_pair if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_90[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "compare_op_bitwise_or_pair")); @@ -20893,7 +21690,7 @@ _loop1_90_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -20907,7 +21704,7 @@ _loop1_90_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -20915,13 +21712,13 @@ _loop1_90_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_90_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -20929,16 +21726,19 @@ _loop1_90_rule(Parser *p) static void * _tmp_91_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '!=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_91[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!='")); @@ -20951,7 +21751,7 @@ _tmp_91_rule(Parser *p) _res = _PyPegen_check_barry_as_flufl ( p , tok ) ? NULL : tok; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20962,7 +21762,7 @@ _tmp_91_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20970,9 +21770,12 @@ _tmp_91_rule(Parser *p) static asdl_seq * _loop0_93_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -20982,14 +21785,14 @@ _loop0_93_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ',' slice if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_93[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' slice")); @@ -21005,7 +21808,7 @@ _loop0_93_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -21014,7 +21817,7 @@ _loop0_93_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -21031,13 +21834,13 @@ _loop0_93_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_93_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -21045,16 +21848,19 @@ _loop0_93_rule(Parser *p) static asdl_seq * _gather_92_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // slice _loop0_93 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_92[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slice _loop0_93")); @@ -21076,7 +21882,7 @@ _gather_92_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21084,16 +21890,19 @@ _gather_92_rule(Parser *p) static void * _tmp_94_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ':' expression? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_94[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':' expression?")); @@ -21109,7 +21918,7 @@ _tmp_94_rule(Parser *p) _res = d; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -21120,7 +21929,7 @@ _tmp_94_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21128,16 +21937,19 @@ _tmp_94_rule(Parser *p) static void * _tmp_95_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // tuple if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_95[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); @@ -21156,7 +21968,7 @@ _tmp_95_rule(Parser *p) } { // group if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_95[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "group")); @@ -21175,7 +21987,7 @@ _tmp_95_rule(Parser *p) } { // genexp if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_95[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); @@ -21194,7 +22006,7 @@ _tmp_95_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21202,16 +22014,19 @@ _tmp_95_rule(Parser *p) static void * _tmp_96_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // list if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_96[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); @@ -21230,7 +22045,7 @@ _tmp_96_rule(Parser *p) } { // listcomp if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_96[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "listcomp")); @@ -21249,7 +22064,7 @@ _tmp_96_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21257,16 +22072,19 @@ _tmp_96_rule(Parser *p) static void * _tmp_97_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // dict if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dict")); @@ -21285,7 +22103,7 @@ _tmp_97_rule(Parser *p) } { // set if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "set")); @@ -21304,7 +22122,7 @@ _tmp_97_rule(Parser *p) } { // dictcomp if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dictcomp")); @@ -21323,7 +22141,7 @@ _tmp_97_rule(Parser *p) } { // setcomp if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "setcomp")); @@ -21342,7 +22160,7 @@ _tmp_97_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21350,9 +22168,12 @@ _tmp_97_rule(Parser *p) static asdl_seq * _loop1_98_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -21362,14 +22183,14 @@ _loop1_98_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // STRING if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_98[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "STRING")); @@ -21385,7 +22206,7 @@ _loop1_98_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -21399,7 +22220,7 @@ _loop1_98_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -21407,13 +22228,13 @@ _loop1_98_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_98_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -21421,16 +22242,19 @@ _loop1_98_rule(Parser *p) static void * _tmp_99_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // star_named_expression ',' star_named_expressions? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_99[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?")); @@ -21449,7 +22273,7 @@ _tmp_99_rule(Parser *p) _res = _PyPegen_seq_insert_in_front ( p , y , z ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -21460,7 +22284,7 @@ _tmp_99_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21468,16 +22292,19 @@ _tmp_99_rule(Parser *p) static void * _tmp_100_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // yield_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_100[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); @@ -21496,7 +22323,7 @@ _tmp_100_rule(Parser *p) } { // named_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_100[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression")); @@ -21515,7 +22342,7 @@ _tmp_100_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21523,9 +22350,12 @@ _tmp_100_rule(Parser *p) static asdl_seq * _loop0_102_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -21535,14 +22365,14 @@ _loop0_102_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ',' double_starred_kvpair if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_102[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); @@ -21558,7 +22388,7 @@ _loop0_102_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -21567,7 +22397,7 @@ _loop0_102_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -21584,13 +22414,13 @@ _loop0_102_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_102_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -21598,16 +22428,19 @@ _loop0_102_rule(Parser *p) static asdl_seq * _gather_101_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // double_starred_kvpair _loop0_102 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_101[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_102")); @@ -21629,7 +22462,7 @@ _gather_101_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21637,9 +22470,12 @@ _gather_101_rule(Parser *p) static asdl_seq * _loop1_103_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -21649,14 +22485,14 @@ _loop1_103_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // for_if_clause if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_103[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "for_if_clause")); @@ -21672,7 +22508,7 @@ _loop1_103_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -21686,7 +22522,7 @@ _loop1_103_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -21694,13 +22530,13 @@ _loop1_103_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_103_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -21708,9 +22544,12 @@ _loop1_103_rule(Parser *p) static asdl_seq * _loop0_104_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -21720,14 +22559,14 @@ _loop0_104_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ('if' disjunction) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_104[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); @@ -21743,7 +22582,7 @@ _loop0_104_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -21760,13 +22599,13 @@ _loop0_104_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_104_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -21774,9 +22613,12 @@ _loop0_104_rule(Parser *p) static asdl_seq * _loop0_105_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -21786,14 +22628,14 @@ _loop0_105_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ('if' disjunction) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_105[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); @@ -21809,7 +22651,7 @@ _loop0_105_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -21826,13 +22668,13 @@ _loop0_105_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_105_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -21840,9 +22682,12 @@ _loop0_105_rule(Parser *p) static asdl_seq * _loop0_107_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -21852,14 +22697,14 @@ _loop0_107_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ',' (starred_expression | named_expression !'=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_107[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression | named_expression !'=')")); @@ -21875,7 +22720,7 @@ _loop0_107_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -21884,7 +22729,7 @@ _loop0_107_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -21901,13 +22746,13 @@ _loop0_107_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_107_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -21915,16 +22760,19 @@ _loop0_107_rule(Parser *p) static asdl_seq * _gather_106_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // (starred_expression | named_expression !'=') _loop0_107 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_106[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression | named_expression !'=') _loop0_107")); @@ -21946,7 +22794,7 @@ _gather_106_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21954,16 +22802,19 @@ _gather_106_rule(Parser *p) static void * _tmp_108_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' kwargs if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_108[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwargs")); @@ -21979,7 +22830,7 @@ _tmp_108_rule(Parser *p) _res = k; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -21990,7 +22841,7 @@ _tmp_108_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21998,9 +22849,12 @@ _tmp_108_rule(Parser *p) static asdl_seq * _loop0_110_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -22010,14 +22864,14 @@ _loop0_110_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ',' kwarg_or_starred if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_110[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); @@ -22033,7 +22887,7 @@ _loop0_110_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -22042,7 +22896,7 @@ _loop0_110_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -22059,13 +22913,13 @@ _loop0_110_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_110_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -22073,16 +22927,19 @@ _loop0_110_rule(Parser *p) static asdl_seq * _gather_109_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // kwarg_or_starred _loop0_110 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_109[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_110")); @@ -22104,7 +22961,7 @@ _gather_109_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22112,9 +22969,12 @@ _gather_109_rule(Parser *p) static asdl_seq * _loop0_112_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -22124,14 +22984,14 @@ _loop0_112_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ',' kwarg_or_double_starred if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); @@ -22147,7 +23007,7 @@ _loop0_112_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -22156,7 +23016,7 @@ _loop0_112_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -22173,13 +23033,13 @@ _loop0_112_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_112_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -22187,16 +23047,19 @@ _loop0_112_rule(Parser *p) static asdl_seq * _gather_111_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // kwarg_or_double_starred _loop0_112 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_111[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_112")); @@ -22218,7 +23081,7 @@ _gather_111_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22226,9 +23089,12 @@ _gather_111_rule(Parser *p) static asdl_seq * _loop0_114_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -22238,14 +23104,14 @@ _loop0_114_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ',' kwarg_or_starred if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); @@ -22261,7 +23127,7 @@ _loop0_114_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -22270,7 +23136,7 @@ _loop0_114_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -22287,13 +23153,13 @@ _loop0_114_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_114_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -22301,16 +23167,19 @@ _loop0_114_rule(Parser *p) static asdl_seq * _gather_113_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // kwarg_or_starred _loop0_114 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_114")); @@ -22332,7 +23201,7 @@ _gather_113_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22340,9 +23209,12 @@ _gather_113_rule(Parser *p) static asdl_seq * _loop0_116_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -22352,14 +23224,14 @@ _loop0_116_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ',' kwarg_or_double_starred if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_116[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); @@ -22375,7 +23247,7 @@ _loop0_116_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -22384,7 +23256,7 @@ _loop0_116_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -22401,13 +23273,13 @@ _loop0_116_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_116_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -22415,16 +23287,19 @@ _loop0_116_rule(Parser *p) static asdl_seq * _gather_115_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // kwarg_or_double_starred _loop0_116 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_115[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_116")); @@ -22446,7 +23321,7 @@ _gather_115_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22454,9 +23329,12 @@ _gather_115_rule(Parser *p) static asdl_seq * _loop0_117_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -22466,14 +23344,14 @@ _loop0_117_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // (',' star_target) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); @@ -22489,7 +23367,7 @@ _loop0_117_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -22506,13 +23384,13 @@ _loop0_117_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_117_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -22520,9 +23398,12 @@ _loop0_117_rule(Parser *p) static asdl_seq * _loop0_119_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -22532,14 +23413,14 @@ _loop0_119_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ',' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_119[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); @@ -22555,7 +23436,7 @@ _loop0_119_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -22564,7 +23445,7 @@ _loop0_119_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -22581,13 +23462,13 @@ _loop0_119_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_119_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -22595,16 +23476,19 @@ _loop0_119_rule(Parser *p) static asdl_seq * _gather_118_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // star_target _loop0_119 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_118[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target _loop0_119")); @@ -22626,7 +23510,7 @@ _gather_118_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22634,9 +23518,12 @@ _gather_118_rule(Parser *p) static asdl_seq * _loop1_120_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -22646,14 +23533,14 @@ _loop1_120_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // (',' star_target) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_120[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); @@ -22669,7 +23556,7 @@ _loop1_120_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -22683,7 +23570,7 @@ _loop1_120_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -22691,13 +23578,13 @@ _loop1_120_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_120_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -22705,16 +23592,19 @@ _loop1_120_rule(Parser *p) static void * _tmp_121_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // !'*' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_121[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); @@ -22735,7 +23625,7 @@ _tmp_121_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22743,9 +23633,12 @@ _tmp_121_rule(Parser *p) static asdl_seq * _loop0_123_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -22755,14 +23648,14 @@ _loop0_123_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // ',' del_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' del_target")); @@ -22778,7 +23671,7 @@ _loop0_123_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -22787,7 +23680,7 @@ _loop0_123_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -22804,13 +23697,13 @@ _loop0_123_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_123_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -22818,16 +23711,19 @@ _loop0_123_rule(Parser *p) static asdl_seq * _gather_122_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // del_target _loop0_123 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "del_target _loop0_123")); @@ -22849,7 +23745,7 @@ _gather_122_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22857,16 +23753,19 @@ _gather_122_rule(Parser *p) static void * _tmp_124_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // args if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args")); @@ -22885,7 +23784,7 @@ _tmp_124_rule(Parser *p) } { // expression for_if_clauses if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); @@ -22907,7 +23806,7 @@ _tmp_124_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22915,16 +23814,19 @@ _tmp_124_rule(Parser *p) static void * _tmp_125_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // NAME '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '='")); @@ -22946,7 +23848,7 @@ _tmp_125_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22954,9 +23856,12 @@ _tmp_125_rule(Parser *p) static asdl_seq * _loop0_126_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -22966,14 +23871,14 @@ _loop0_126_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // star_named_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_126[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expressions")); @@ -22989,7 +23894,7 @@ _loop0_126_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23006,13 +23911,13 @@ _loop0_126_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_126_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23020,9 +23925,12 @@ _loop0_126_rule(Parser *p) static asdl_seq * _loop0_127_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23032,14 +23940,14 @@ _loop0_127_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // (star_targets '=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_127[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); @@ -23055,7 +23963,7 @@ _loop0_127_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23072,13 +23980,13 @@ _loop0_127_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_127_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23086,9 +23994,12 @@ _loop0_127_rule(Parser *p) static asdl_seq * _loop0_128_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23098,14 +24009,14 @@ _loop0_128_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // (star_targets '=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); @@ -23121,7 +24032,7 @@ _loop0_128_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23138,13 +24049,13 @@ _loop0_128_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_128_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23152,16 +24063,19 @@ _loop0_128_rule(Parser *p) static void * _tmp_129_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // yield_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); @@ -23180,7 +24094,7 @@ _tmp_129_rule(Parser *p) } { // star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); @@ -23199,7 +24113,7 @@ _tmp_129_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23207,16 +24121,19 @@ _tmp_129_rule(Parser *p) static void * _tmp_130_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '[' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); @@ -23235,7 +24152,7 @@ _tmp_130_rule(Parser *p) } { // '(' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); @@ -23254,7 +24171,7 @@ _tmp_130_rule(Parser *p) } { // '{' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); @@ -23273,7 +24190,7 @@ _tmp_130_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23281,9 +24198,12 @@ _tmp_130_rule(Parser *p) static asdl_seq * _loop0_131_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23293,14 +24213,14 @@ _loop0_131_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -23316,7 +24236,7 @@ _loop0_131_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23333,13 +24253,13 @@ _loop0_131_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_131_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23347,16 +24267,19 @@ _loop0_131_rule(Parser *p) static void * _tmp_132_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // slash_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default")); @@ -23375,7 +24298,7 @@ _tmp_132_rule(Parser *p) } { // param_with_default+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default+")); @@ -23394,7 +24317,7 @@ _tmp_132_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23402,9 +24325,12 @@ _tmp_132_rule(Parser *p) static asdl_seq * _loop0_133_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23414,14 +24340,14 @@ _loop0_133_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_133[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -23437,7 +24363,7 @@ _loop0_133_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23454,13 +24380,13 @@ _loop0_133_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_133_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23468,16 +24394,19 @@ _loop0_133_rule(Parser *p) static void * _tmp_134_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // lambda_slash_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); @@ -23496,7 +24425,7 @@ _tmp_134_rule(Parser *p) } { // lambda_param_with_default+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+")); @@ -23515,7 +24444,7 @@ _tmp_134_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23523,16 +24452,19 @@ _tmp_134_rule(Parser *p) static void * _tmp_135_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); @@ -23551,7 +24483,7 @@ _tmp_135_rule(Parser *p) } { // ',' (')' | '**') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); @@ -23573,7 +24505,7 @@ _tmp_135_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23581,16 +24513,19 @@ _tmp_135_rule(Parser *p) static void * _tmp_136_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); @@ -23609,7 +24544,7 @@ _tmp_136_rule(Parser *p) } { // ',' (':' | '**') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); @@ -23631,7 +24566,7 @@ _tmp_136_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23639,16 +24574,19 @@ _tmp_136_rule(Parser *p) static void * _tmp_137_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // star_targets '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); @@ -23664,7 +24602,7 @@ _tmp_137_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -23675,7 +24613,7 @@ _tmp_137_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23683,16 +24621,19 @@ _tmp_137_rule(Parser *p) static void * _tmp_138_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '.' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); @@ -23711,7 +24652,7 @@ _tmp_138_rule(Parser *p) } { // '...' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); @@ -23730,7 +24671,7 @@ _tmp_138_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23738,16 +24679,19 @@ _tmp_138_rule(Parser *p) static void * _tmp_139_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '.' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); @@ -23766,7 +24710,7 @@ _tmp_139_rule(Parser *p) } { // '...' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); @@ -23785,7 +24729,7 @@ _tmp_139_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23793,16 +24737,19 @@ _tmp_139_rule(Parser *p) static void * _tmp_140_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '@' named_expression NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); @@ -23821,7 +24768,7 @@ _tmp_140_rule(Parser *p) _res = f; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -23832,7 +24779,7 @@ _tmp_140_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23840,16 +24787,19 @@ _tmp_140_rule(Parser *p) static void * _tmp_141_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' star_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression")); @@ -23865,7 +24815,7 @@ _tmp_141_rule(Parser *p) _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -23876,7 +24826,7 @@ _tmp_141_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23884,16 +24834,19 @@ _tmp_141_rule(Parser *p) static void * _tmp_142_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); @@ -23909,7 +24862,7 @@ _tmp_142_rule(Parser *p) _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -23920,7 +24873,7 @@ _tmp_142_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23928,16 +24881,19 @@ _tmp_142_rule(Parser *p) static void * _tmp_143_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'or' conjunction if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); @@ -23953,7 +24909,7 @@ _tmp_143_rule(Parser *p) _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -23964,7 +24920,7 @@ _tmp_143_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23972,16 +24928,19 @@ _tmp_143_rule(Parser *p) static void * _tmp_144_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'and' inversion if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion")); @@ -23997,7 +24956,7 @@ _tmp_144_rule(Parser *p) _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -24008,7 +24967,7 @@ _tmp_144_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24016,16 +24975,19 @@ _tmp_144_rule(Parser *p) static void * _tmp_145_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'if' disjunction if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); @@ -24041,7 +25003,7 @@ _tmp_145_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -24052,7 +25014,7 @@ _tmp_145_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24060,16 +25022,19 @@ _tmp_145_rule(Parser *p) static void * _tmp_146_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'if' disjunction if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); @@ -24085,7 +25050,7 @@ _tmp_146_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -24096,7 +25061,7 @@ _tmp_146_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24104,16 +25069,19 @@ _tmp_146_rule(Parser *p) static void * _tmp_147_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // starred_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); @@ -24132,7 +25100,7 @@ _tmp_147_rule(Parser *p) } { // named_expression !'=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression !'='")); @@ -24153,7 +25121,7 @@ _tmp_147_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24161,16 +25129,19 @@ _tmp_147_rule(Parser *p) static void * _tmp_148_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); @@ -24186,7 +25157,7 @@ _tmp_148_rule(Parser *p) _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -24197,7 +25168,7 @@ _tmp_148_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24205,16 +25176,19 @@ _tmp_148_rule(Parser *p) static void * _tmp_149_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); @@ -24230,7 +25204,7 @@ _tmp_149_rule(Parser *p) _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -24241,7 +25215,7 @@ _tmp_149_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24249,16 +25223,19 @@ _tmp_149_rule(Parser *p) static void * _tmp_150_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // star_targets '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); @@ -24280,7 +25257,7 @@ _tmp_150_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24288,16 +25265,19 @@ _tmp_150_rule(Parser *p) static void * _tmp_151_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // star_targets '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); @@ -24319,7 +25299,7 @@ _tmp_151_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24327,9 +25307,12 @@ _tmp_151_rule(Parser *p) static asdl_seq * _loop1_152_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -24339,14 +25322,14 @@ _loop1_152_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); @@ -24362,7 +25345,7 @@ _loop1_152_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -24376,7 +25359,7 @@ _loop1_152_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -24384,13 +25367,13 @@ _loop1_152_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_152_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -24398,9 +25381,12 @@ _loop1_152_rule(Parser *p) static asdl_seq * _loop1_153_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -24410,14 +25396,14 @@ _loop1_153_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } ssize_t _children_capacity = 1; ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); @@ -24433,7 +25419,7 @@ _loop1_153_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -24447,7 +25433,7 @@ _loop1_153_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -24455,13 +25441,13 @@ _loop1_153_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_153_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -24469,16 +25455,19 @@ _loop1_153_rule(Parser *p) static void * _tmp_154_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); @@ -24497,7 +25486,7 @@ _tmp_154_rule(Parser *p) } { // '**' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); @@ -24516,7 +25505,7 @@ _tmp_154_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24524,16 +25513,19 @@ _tmp_154_rule(Parser *p) static void * _tmp_155_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); @@ -24552,7 +25544,7 @@ _tmp_155_rule(Parser *p) } { // '**' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); @@ -24571,7 +25563,7 @@ _tmp_155_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } diff --git a/Tools/peg_generator/pegen/c_generator.py b/Tools/peg_generator/pegen/c_generator.py index fe79717b79c01..99090c0604254 100644 --- a/Tools/peg_generator/pegen/c_generator.py +++ b/Tools/peg_generator/pegen/c_generator.py @@ -37,6 +37,8 @@ #define D(x) #endif +# define MAXSTACK 6000 + """ @@ -331,10 +333,14 @@ def __init__( self.skip_actions = skip_actions def add_level(self) -> None: - self.print("D(p->level++);") + self.print("if (p->level++ == MAXSTACK) {") + with self.indent(): + self.print("p->error_indicator = 1;") + self.print("PyErr_NoMemory();") + self.print("}") def remove_level(self) -> None: - self.print("D(p->level--);") + self.print("p->level--;") def add_return(self, ret_val: str) -> None: self.remove_level() @@ -498,9 +504,10 @@ def _set_up_rule_memoization(self, node: Rule, result_type: str) -> None: ) self.print("p->mark = _mark;") self.print(f"void *_raw = {node.name}_raw(p);") - self.print("if (p->error_indicator)") + self.print("if (p->error_indicator) {") with self.indent(): - self.print("return NULL;") + self.add_return("NULL") + self.print("}") self.print("if (_raw == NULL || p->mark <= _resmark)") with self.indent(): self.print("break;") From webhook-mailer at python.org Tue Dec 21 04:01:09 2021 From: webhook-mailer at python.org (mdickinson) Date: Tue, 21 Dec 2021 09:01:09 -0000 Subject: [Python-checkins] Update potentially confusing note for mean. (GH-30174) Message-ID: https://github.com/python/cpython/commit/e9a01e231aae19fd1249368e477a60bc033b2646 commit: e9a01e231aae19fd1249368e477a60bc033b2646 branch: main author: Mark Dickinson committer: mdickinson date: 2021-12-21T09:00:53Z summary: Update potentially confusing note for mean. (GH-30174) files: M Doc/library/statistics.rst diff --git a/Doc/library/statistics.rst b/Doc/library/statistics.rst index 8638abfb697b8..4cd983bb25468 100644 --- a/Doc/library/statistics.rst +++ b/Doc/library/statistics.rst @@ -116,10 +116,11 @@ However, for reading convenience, most of the examples show sorted sequences. .. note:: - The mean is strongly affected by outliers and is not a robust estimator - for central location: the mean is not necessarily a typical example of - the data points. For more robust measures of central location, see - :func:`median` and :func:`mode`. + The mean is strongly affected by `outliers + `_ and is not necessarily a + typical example of the data points. For a more robust, although less + efficient, measure of `central tendency + `_, see :func:`median`. The sample mean gives an unbiased estimate of the true population mean, so that when taken on average over all the possible samples, From webhook-mailer at python.org Tue Dec 21 05:12:34 2021 From: webhook-mailer at python.org (iritkatriel) Date: Tue, 21 Dec 2021 10:12:34 -0000 Subject: [Python-checkins] bpo-46107: ExceptionGroup.subgroup()/split() should copy __note__ to the parts (GH-30159) Message-ID: https://github.com/python/cpython/commit/c66fc0fb53b5316dc325fde3bc738890515d38a4 commit: c66fc0fb53b5316dc325fde3bc738890515d38a4 branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-12-21T10:12:26Z summary: bpo-46107: ExceptionGroup.subgroup()/split() should copy __note__ to the parts (GH-30159) files: A Misc/NEWS.d/next/Core and Builtins/2021-12-16-23-27-05.bpo-46107.7q5an0.rst M Lib/test/test_exception_group.py M Objects/exceptions.c diff --git a/Lib/test/test_exception_group.py b/Lib/test/test_exception_group.py index c793c45e7241a..f0ae37741ab60 100644 --- a/Lib/test/test_exception_group.py +++ b/Lib/test/test_exception_group.py @@ -495,13 +495,14 @@ def leaves(exc): match and e in match_leaves, rest and e in rest_leaves) - # message, cause and context equal to eg + # message, cause and context, traceback and note equal to eg for part in [match, rest, sg]: if part is not None: self.assertEqual(eg.message, part.message) self.assertIs(eg.__cause__, part.__cause__) self.assertIs(eg.__context__, part.__context__) self.assertIs(eg.__traceback__, part.__traceback__) + self.assertIs(eg.__note__, part.__note__) def tbs_for_leaf(leaf, eg): for e, tbs in leaf_generator(eg): @@ -566,6 +567,7 @@ def level3(i): try: nested_group() except ExceptionGroup as e: + e.__note__ = f"the note: {id(e)}" eg = e eg_template = [ diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-16-23-27-05.bpo-46107.7q5an0.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-16-23-27-05.bpo-46107.7q5an0.rst new file mode 100644 index 0000000000000..3257805f2ab5a --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-16-23-27-05.bpo-46107.7q5an0.rst @@ -0,0 +1 @@ +Fix bug where :meth:`ExceptionGroup.split` and :meth:`ExceptionGroup.subgroup` did not copy the exception group's ``__note__`` field to the parts. diff --git a/Objects/exceptions.c b/Objects/exceptions.c index 1db49d949b5c0..d82340b8e78ab 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -901,6 +901,11 @@ exceptiongroup_subset( } PyException_SetContext(eg, PyException_GetContext(orig)); PyException_SetCause(eg, PyException_GetCause(orig)); + + PyObject *note = _PyBaseExceptionObject_cast(orig)->note; + Py_XINCREF(note); + _PyBaseExceptionObject_cast(eg)->note = note; + *result = eg; return 0; error: From webhook-mailer at python.org Tue Dec 21 07:44:54 2021 From: webhook-mailer at python.org (mdickinson) Date: Tue, 21 Dec 2021 12:44:54 -0000 Subject: [Python-checkins] Update potentially confusing note for mean. (GH-30174) (GH-30221) Message-ID: https://github.com/python/cpython/commit/a2295a4029707ebaf2cd1bb8b3223b73f6dbfee6 commit: a2295a4029707ebaf2cd1bb8b3223b73f6dbfee6 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: mdickinson date: 2021-12-21T12:44:13Z summary: Update potentially confusing note for mean. (GH-30174) (GH-30221) files: M Doc/library/statistics.rst diff --git a/Doc/library/statistics.rst b/Doc/library/statistics.rst index 38a499ab37e89..a6cbdd7695a64 100644 --- a/Doc/library/statistics.rst +++ b/Doc/library/statistics.rst @@ -105,10 +105,11 @@ However, for reading convenience, most of the examples show sorted sequences. .. note:: - The mean is strongly affected by outliers and is not a robust estimator - for central location: the mean is not necessarily a typical example of - the data points. For more robust measures of central location, see - :func:`median` and :func:`mode`. + The mean is strongly affected by `outliers + `_ and is not necessarily a + typical example of the data points. For a more robust, although less + efficient, measure of `central tendency + `_, see :func:`median`. The sample mean gives an unbiased estimate of the true population mean, so that when taken on average over all the possible samples, From webhook-mailer at python.org Tue Dec 21 09:15:44 2021 From: webhook-mailer at python.org (mdickinson) Date: Tue, 21 Dec 2021 14:15:44 -0000 Subject: [Python-checkins] Update potentially confusing note for mean. (GH-30174) (GH-30220) Message-ID: https://github.com/python/cpython/commit/989d2371c8ff1c41e1b190a7df0a0d0231c2ae65 commit: 989d2371c8ff1c41e1b190a7df0a0d0231c2ae65 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: mdickinson date: 2021-12-21T14:15:39Z summary: Update potentially confusing note for mean. (GH-30174) (GH-30220) (cherry picked from commit e9a01e231aae19fd1249368e477a60bc033b2646) files: M Doc/library/statistics.rst diff --git a/Doc/library/statistics.rst b/Doc/library/statistics.rst index 3c3f9d2df5858..fd486191c0190 100644 --- a/Doc/library/statistics.rst +++ b/Doc/library/statistics.rst @@ -116,10 +116,11 @@ However, for reading convenience, most of the examples show sorted sequences. .. note:: - The mean is strongly affected by outliers and is not a robust estimator - for central location: the mean is not necessarily a typical example of - the data points. For more robust measures of central location, see - :func:`median` and :func:`mode`. + The mean is strongly affected by `outliers + `_ and is not necessarily a + typical example of the data points. For a more robust, although less + efficient, measure of `central tendency + `_, see :func:`median`. The sample mean gives an unbiased estimate of the true population mean, so that when taken on average over all the possible samples, From webhook-mailer at python.org Tue Dec 21 21:20:30 2021 From: webhook-mailer at python.org (ned-deily) Date: Wed, 22 Dec 2021 02:20:30 -0000 Subject: [Python-checkins] bpo-46106: Update OpenSSL to 1.1.1m (GH-30211) Message-ID: https://github.com/python/cpython/commit/fc54e722a2e66971f1a8e16cff24c844bf9c5ac4 commit: fc54e722a2e66971f1a8e16cff24c844bf9c5ac4 branch: main author: Kumar Aditya <59607654+kumaraditya303 at users.noreply.github.com> committer: ned-deily date: 2021-12-21T21:20:16-05:00 summary: bpo-46106: Update OpenSSL to 1.1.1m (GH-30211) Co-authored-by: Ned Deily files: A Misc/NEWS.d/next/Build/2021-12-20-07-10-41.bpo-46106.5qcv3L.rst D Mac/BuildScript/0001-Darwin-platform-allows-to-build-on-releases-before-Y.patch M .azure-pipelines/ci.yml M .azure-pipelines/pr.yml M .github/workflows/build.yml M Mac/BuildScript/build-installer.py M PCbuild/get_externals.bat M PCbuild/python.props M Tools/ssl/multissltests.py diff --git a/.azure-pipelines/ci.yml b/.azure-pipelines/ci.yml index 2284a5fb36b19..25cc726504b37 100644 --- a/.azure-pipelines/ci.yml +++ b/.azure-pipelines/ci.yml @@ -57,7 +57,7 @@ jobs: variables: testRunTitle: '$(build.sourceBranchName)-linux' testRunPlatform: linux - openssl_version: 1.1.1l + openssl_version: 1.1.1m steps: - template: ./posix-steps.yml @@ -83,7 +83,7 @@ jobs: variables: testRunTitle: '$(Build.SourceBranchName)-linux-coverage' testRunPlatform: linux-coverage - openssl_version: 1.1.1l + openssl_version: 1.1.1m steps: - template: ./posix-steps.yml diff --git a/.azure-pipelines/pr.yml b/.azure-pipelines/pr.yml index 1a3bf75ed4c1e..e2aae324f211b 100644 --- a/.azure-pipelines/pr.yml +++ b/.azure-pipelines/pr.yml @@ -57,7 +57,7 @@ jobs: variables: testRunTitle: '$(system.pullRequest.TargetBranch)-linux' testRunPlatform: linux - openssl_version: 1.1.1l + openssl_version: 1.1.1m steps: - template: ./posix-steps.yml @@ -83,7 +83,7 @@ jobs: variables: testRunTitle: '$(Build.SourceBranchName)-linux-coverage' testRunPlatform: linux-coverage - openssl_version: 1.1.1l + openssl_version: 1.1.1m steps: - template: ./posix-steps.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e02e9ade1ae13..f220aaa1d72a2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -163,7 +163,7 @@ jobs: needs: check_source if: needs.check_source.outputs.run_tests == 'true' env: - OPENSSL_VER: 1.1.1l + OPENSSL_VER: 1.1.1m PYTHONSTRICTEXTENSIONBUILD: 1 steps: - uses: actions/checkout at v2 @@ -222,7 +222,7 @@ jobs: strategy: fail-fast: false matrix: - openssl_ver: [1.1.1l, 3.0.1] + openssl_ver: [1.1.1m, 3.0.1] env: OPENSSL_VER: ${{ matrix.openssl_ver }} MULTISSL_DIR: ${{ github.workspace }}/multissl @@ -269,7 +269,7 @@ jobs: needs: check_source if: needs.check_source.outputs.run_tests == 'true' env: - OPENSSL_VER: 1.1.1l + OPENSSL_VER: 1.1.1m PYTHONSTRICTEXTENSIONBUILD: 1 ASAN_OPTIONS: detect_leaks=0:allocator_may_return_null=1:handle_segv=0 steps: diff --git a/Mac/BuildScript/0001-Darwin-platform-allows-to-build-on-releases-before-Y.patch b/Mac/BuildScript/0001-Darwin-platform-allows-to-build-on-releases-before-Y.patch deleted file mode 100644 index 51ccdc2267ee8..0000000000000 --- a/Mac/BuildScript/0001-Darwin-platform-allows-to-build-on-releases-before-Y.patch +++ /dev/null @@ -1,59 +0,0 @@ -From cef404f1e7a598166cbc2fd2e0048f7e2d752ad5 Mon Sep 17 00:00:00 2001 -From: David Carlier -Date: Tue, 24 Aug 2021 22:40:14 +0100 -Subject: [PATCH] Darwin platform allows to build on releases before - Yosemite/ios 8. - -issue #16407 #16408 ---- - crypto/rand/rand_unix.c | 5 +---- - include/crypto/rand.h | 10 ++++++++++ - 2 files changed, 11 insertions(+), 4 deletions(-) - -diff --git a/crypto/rand/rand_unix.c b/crypto/rand/rand_unix.c -index 43f1069d15..0f4525106a 100644 ---- a/crypto/rand/rand_unix.c -+++ b/crypto/rand/rand_unix.c -@@ -34,9 +34,6 @@ - #if defined(__OpenBSD__) - # include - #endif --#if defined(__APPLE__) --# include --#endif - - #if defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__) - # include -@@ -381,7 +378,7 @@ static ssize_t syscall_random(void *buf, size_t buflen) - if (errno != ENOSYS) - return -1; - } --# elif defined(__APPLE__) -+# elif defined(OPENSSL_APPLE_CRYPTO_RANDOM) - if (CCRandomGenerateBytes(buf, buflen) == kCCSuccess) - return (ssize_t)buflen; - -diff --git a/include/crypto/rand.h b/include/crypto/rand.h -index 5350d3a931..674f840fd1 100644 ---- a/include/crypto/rand.h -+++ b/include/crypto/rand.h -@@ -20,6 +20,16 @@ - - # include - -+# if defined(__APPLE__) && !defined(OPENSSL_NO_APPLE_CRYPTO_RANDOM) -+# include -+# if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000) || \ -+ (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) -+# define OPENSSL_APPLE_CRYPTO_RANDOM 1 -+# include -+# include -+# endif -+# endif -+ - /* forward declaration */ - typedef struct rand_pool_st RAND_POOL; - --- -2.33.0 - diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 5365f62bf3d0e..0f8924bb72740 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -246,10 +246,9 @@ def library_recipes(): result.extend([ dict( - name="OpenSSL 1.1.1l", - url="https://www.openssl.org/source/openssl-1.1.1l.tar.gz", - checksum='ac0d4387f3ba0ad741b0580dd45f6ff3', - patches=['0001-Darwin-platform-allows-to-build-on-releases-before-Y.patch'], + name="OpenSSL 1.1.1m", + url="https://www.openssl.org/source/openssl-1.1.1m.tar.gz", + checksum='8ec70f665c145c3103f6e330f538a9db', buildrecipe=build_universal_openssl, configure=None, install=None, diff --git a/Misc/NEWS.d/next/Build/2021-12-20-07-10-41.bpo-46106.5qcv3L.rst b/Misc/NEWS.d/next/Build/2021-12-20-07-10-41.bpo-46106.5qcv3L.rst new file mode 100644 index 0000000000000..d3e25f77c7336 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-12-20-07-10-41.bpo-46106.5qcv3L.rst @@ -0,0 +1,2 @@ +Updated OpenSSL to 1.1.1m in Windows builds, macOS installer builds, and CI. +Patch by Kumar Aditya. \ No newline at end of file diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index 207f91baba537..7126d8afd000b 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -53,7 +53,7 @@ echo.Fetching external libraries... set libraries= set libraries=%libraries% bzip2-1.0.6 if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi-3.4.2 -if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1l +if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1m set libraries=%libraries% sqlite-3.36.0.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.12.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.12.0 @@ -77,7 +77,7 @@ echo.Fetching external binaries... set binaries= if NOT "%IncludeLibffi%"=="false" set binaries=%binaries% libffi-3.4.2 -if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-1.1.1l +if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-1.1.1m if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.12.0 if NOT "%IncludeSSLSrc%"=="false" set binaries=%binaries% nasm-2.11.06 diff --git a/PCbuild/python.props b/PCbuild/python.props index ce860764e445f..70827883f4838 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -67,8 +67,8 @@ $(ExternalsDir)libffi-3.4.2\ $(ExternalsDir)libffi-3.4.2\$(ArchName)\ $(libffiOutDir)include - $(ExternalsDir)openssl-1.1.1l\ - $(ExternalsDir)openssl-bin-1.1.1l\$(ArchName)\ + $(ExternalsDir)openssl-1.1.1m\ + $(ExternalsDir)openssl-bin-1.1.1m\$(ArchName)\ $(opensslOutDir)include $(ExternalsDir)\nasm-2.11.06\ $(ExternalsDir)\zlib-1.2.11\ diff --git a/Tools/ssl/multissltests.py b/Tools/ssl/multissltests.py index 8fe5b5d0c2629..a41cabff534b0 100755 --- a/Tools/ssl/multissltests.py +++ b/Tools/ssl/multissltests.py @@ -47,7 +47,7 @@ ] OPENSSL_RECENT_VERSIONS = [ - "1.1.1l", + "1.1.1m", "3.0.1" ] From webhook-mailer at python.org Tue Dec 21 23:24:11 2021 From: webhook-mailer at python.org (ned-deily) Date: Wed, 22 Dec 2021 04:24:11 -0000 Subject: [Python-checkins] bpo-46106: Update OpenSSL to 1.1.1m (GH-30211) (GH-30224) Message-ID: https://github.com/python/cpython/commit/cf96c279ac960f2a5025e2ac887f9b932a4f1474 commit: cf96c279ac960f2a5025e2ac887f9b932a4f1474 branch: 3.10 author: Ned Deily committer: ned-deily date: 2021-12-21T23:24:03-05:00 summary: bpo-46106: Update OpenSSL to 1.1.1m (GH-30211) (GH-30224) Co-authored-by: Ned Deily Co-authored-by: Kumar Aditya <59607654+kumaraditya303 at users.noreply.github.com> files: A Misc/NEWS.d/next/Build/2021-12-20-07-10-41.bpo-46106.5qcv3L.rst D Mac/BuildScript/0001-Darwin-platform-allows-to-build-on-releases-before-Y.patch M .azure-pipelines/ci.yml M .azure-pipelines/pr.yml M .github/workflows/build.yml M Mac/BuildScript/build-installer.py M PCbuild/get_externals.bat M PCbuild/python.props M Tools/ssl/multissltests.py diff --git a/.azure-pipelines/ci.yml b/.azure-pipelines/ci.yml index 2284a5fb36b19..25cc726504b37 100644 --- a/.azure-pipelines/ci.yml +++ b/.azure-pipelines/ci.yml @@ -57,7 +57,7 @@ jobs: variables: testRunTitle: '$(build.sourceBranchName)-linux' testRunPlatform: linux - openssl_version: 1.1.1l + openssl_version: 1.1.1m steps: - template: ./posix-steps.yml @@ -83,7 +83,7 @@ jobs: variables: testRunTitle: '$(Build.SourceBranchName)-linux-coverage' testRunPlatform: linux-coverage - openssl_version: 1.1.1l + openssl_version: 1.1.1m steps: - template: ./posix-steps.yml diff --git a/.azure-pipelines/pr.yml b/.azure-pipelines/pr.yml index 1a3bf75ed4c1e..e2aae324f211b 100644 --- a/.azure-pipelines/pr.yml +++ b/.azure-pipelines/pr.yml @@ -57,7 +57,7 @@ jobs: variables: testRunTitle: '$(system.pullRequest.TargetBranch)-linux' testRunPlatform: linux - openssl_version: 1.1.1l + openssl_version: 1.1.1m steps: - template: ./posix-steps.yml @@ -83,7 +83,7 @@ jobs: variables: testRunTitle: '$(Build.SourceBranchName)-linux-coverage' testRunPlatform: linux-coverage - openssl_version: 1.1.1l + openssl_version: 1.1.1m steps: - template: ./posix-steps.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b85cf17df33d8..1102449a1af06 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -181,7 +181,7 @@ jobs: needs: check_source if: needs.check_source.outputs.run_tests == 'true' env: - OPENSSL_VER: 1.1.1l + OPENSSL_VER: 1.1.1m PYTHONSTRICTEXTENSIONBUILD: 1 steps: - uses: actions/checkout at v2 @@ -225,7 +225,7 @@ jobs: strategy: fail-fast: false matrix: - openssl_ver: [1.1.1l, 3.0.1] + openssl_ver: [1.1.1m, 3.0.1] env: OPENSSL_VER: ${{ matrix.openssl_ver }} MULTISSL_DIR: ${{ github.workspace }}/multissl diff --git a/Mac/BuildScript/0001-Darwin-platform-allows-to-build-on-releases-before-Y.patch b/Mac/BuildScript/0001-Darwin-platform-allows-to-build-on-releases-before-Y.patch deleted file mode 100644 index 51ccdc2267ee8..0000000000000 --- a/Mac/BuildScript/0001-Darwin-platform-allows-to-build-on-releases-before-Y.patch +++ /dev/null @@ -1,59 +0,0 @@ -From cef404f1e7a598166cbc2fd2e0048f7e2d752ad5 Mon Sep 17 00:00:00 2001 -From: David Carlier -Date: Tue, 24 Aug 2021 22:40:14 +0100 -Subject: [PATCH] Darwin platform allows to build on releases before - Yosemite/ios 8. - -issue #16407 #16408 ---- - crypto/rand/rand_unix.c | 5 +---- - include/crypto/rand.h | 10 ++++++++++ - 2 files changed, 11 insertions(+), 4 deletions(-) - -diff --git a/crypto/rand/rand_unix.c b/crypto/rand/rand_unix.c -index 43f1069d15..0f4525106a 100644 ---- a/crypto/rand/rand_unix.c -+++ b/crypto/rand/rand_unix.c -@@ -34,9 +34,6 @@ - #if defined(__OpenBSD__) - # include - #endif --#if defined(__APPLE__) --# include --#endif - - #if defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__) - # include -@@ -381,7 +378,7 @@ static ssize_t syscall_random(void *buf, size_t buflen) - if (errno != ENOSYS) - return -1; - } --# elif defined(__APPLE__) -+# elif defined(OPENSSL_APPLE_CRYPTO_RANDOM) - if (CCRandomGenerateBytes(buf, buflen) == kCCSuccess) - return (ssize_t)buflen; - -diff --git a/include/crypto/rand.h b/include/crypto/rand.h -index 5350d3a931..674f840fd1 100644 ---- a/include/crypto/rand.h -+++ b/include/crypto/rand.h -@@ -20,6 +20,16 @@ - - # include - -+# if defined(__APPLE__) && !defined(OPENSSL_NO_APPLE_CRYPTO_RANDOM) -+# include -+# if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000) || \ -+ (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) -+# define OPENSSL_APPLE_CRYPTO_RANDOM 1 -+# include -+# include -+# endif -+# endif -+ - /* forward declaration */ - typedef struct rand_pool_st RAND_POOL; - --- -2.33.0 - diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 9fefe67753666..1eef40fc940f4 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -246,10 +246,9 @@ def library_recipes(): result.extend([ dict( - name="OpenSSL 1.1.1l", - url="https://www.openssl.org/source/openssl-1.1.1l.tar.gz", - checksum='ac0d4387f3ba0ad741b0580dd45f6ff3', - patches=['0001-Darwin-platform-allows-to-build-on-releases-before-Y.patch'], + name="OpenSSL 1.1.1m", + url="https://www.openssl.org/source/openssl-1.1.1m.tar.gz", + checksum='8ec70f665c145c3103f6e330f538a9db', buildrecipe=build_universal_openssl, configure=None, install=None, diff --git a/Misc/NEWS.d/next/Build/2021-12-20-07-10-41.bpo-46106.5qcv3L.rst b/Misc/NEWS.d/next/Build/2021-12-20-07-10-41.bpo-46106.5qcv3L.rst new file mode 100644 index 0000000000000..d3e25f77c7336 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-12-20-07-10-41.bpo-46106.5qcv3L.rst @@ -0,0 +1,2 @@ +Updated OpenSSL to 1.1.1m in Windows builds, macOS installer builds, and CI. +Patch by Kumar Aditya. \ No newline at end of file diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index cc01909ed48ec..2d12abcda7139 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -53,7 +53,7 @@ echo.Fetching external libraries... set libraries= set libraries=%libraries% bzip2-1.0.6 if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi-3.3.0 -if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1l +if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1m set libraries=%libraries% sqlite-3.35.5.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.12.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.12.0 @@ -77,7 +77,7 @@ echo.Fetching external binaries... set binaries= if NOT "%IncludeLibffi%"=="false" set binaries=%binaries% libffi-3.3.0 -if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-1.1.1l +if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-1.1.1m if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.12.0 if NOT "%IncludeSSLSrc%"=="false" set binaries=%binaries% nasm-2.11.06 diff --git a/PCbuild/python.props b/PCbuild/python.props index 2ef290cca286a..5bf1f61e08c5f 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -63,8 +63,8 @@ $(ExternalsDir)libffi-3.3.0\ $(ExternalsDir)libffi-3.3.0\$(ArchName)\ $(libffiOutDir)include - $(ExternalsDir)openssl-1.1.1l\ - $(ExternalsDir)openssl-bin-1.1.1l\$(ArchName)\ + $(ExternalsDir)openssl-1.1.1m\ + $(ExternalsDir)openssl-bin-1.1.1m\$(ArchName)\ $(opensslOutDir)include $(ExternalsDir)\nasm-2.11.06\ $(ExternalsDir)\zlib-1.2.11\ diff --git a/Tools/ssl/multissltests.py b/Tools/ssl/multissltests.py index 8fe5b5d0c2629..a41cabff534b0 100755 --- a/Tools/ssl/multissltests.py +++ b/Tools/ssl/multissltests.py @@ -47,7 +47,7 @@ ] OPENSSL_RECENT_VERSIONS = [ - "1.1.1l", + "1.1.1m", "3.0.1" ] From webhook-mailer at python.org Tue Dec 21 23:25:13 2021 From: webhook-mailer at python.org (ned-deily) Date: Wed, 22 Dec 2021 04:25:13 -0000 Subject: [Python-checkins] bpo-46106: Update OpenSSL to 1.1.1m (GH-30211) (GH-30225) Message-ID: https://github.com/python/cpython/commit/5c4d11fe755a7adeaee6b838bc8faceadc29ed7d commit: 5c4d11fe755a7adeaee6b838bc8faceadc29ed7d branch: 3.9 author: Ned Deily committer: ned-deily date: 2021-12-21T23:25:09-05:00 summary: bpo-46106: Update OpenSSL to 1.1.1m (GH-30211) (GH-30225) Co-authored-by: Ned Deily Co-authored-by: Kumar Aditya <59607654+kumaraditya303 at users.noreply.github.com> files: A Misc/NEWS.d/next/Build/2021-12-20-07-10-41.bpo-46106.5qcv3L.rst D Mac/BuildScript/0001-Darwin-platform-allows-to-build-on-releases-before-Y.patch M .azure-pipelines/ci.yml M .azure-pipelines/pr.yml M .github/workflows/build.yml M Mac/BuildScript/build-installer.py M PCbuild/get_externals.bat M PCbuild/python.props M Tools/ssl/multissltests.py diff --git a/.azure-pipelines/ci.yml b/.azure-pipelines/ci.yml index 2284a5fb36b19..25cc726504b37 100644 --- a/.azure-pipelines/ci.yml +++ b/.azure-pipelines/ci.yml @@ -57,7 +57,7 @@ jobs: variables: testRunTitle: '$(build.sourceBranchName)-linux' testRunPlatform: linux - openssl_version: 1.1.1l + openssl_version: 1.1.1m steps: - template: ./posix-steps.yml @@ -83,7 +83,7 @@ jobs: variables: testRunTitle: '$(Build.SourceBranchName)-linux-coverage' testRunPlatform: linux-coverage - openssl_version: 1.1.1l + openssl_version: 1.1.1m steps: - template: ./posix-steps.yml diff --git a/.azure-pipelines/pr.yml b/.azure-pipelines/pr.yml index 1a3bf75ed4c1e..e2aae324f211b 100644 --- a/.azure-pipelines/pr.yml +++ b/.azure-pipelines/pr.yml @@ -57,7 +57,7 @@ jobs: variables: testRunTitle: '$(system.pullRequest.TargetBranch)-linux' testRunPlatform: linux - openssl_version: 1.1.1l + openssl_version: 1.1.1m steps: - template: ./posix-steps.yml @@ -83,7 +83,7 @@ jobs: variables: testRunTitle: '$(Build.SourceBranchName)-linux-coverage' testRunPlatform: linux-coverage - openssl_version: 1.1.1l + openssl_version: 1.1.1m steps: - template: ./posix-steps.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e7f37f57e9a95..6f1b16537f506 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -165,7 +165,7 @@ jobs: needs: check_source if: needs.check_source.outputs.run_tests == 'true' env: - OPENSSL_VER: 1.1.1l + OPENSSL_VER: 1.1.1m PYTHONSTRICTEXTENSIONBUILD: 1 steps: - uses: actions/checkout at v2 @@ -207,7 +207,7 @@ jobs: strategy: fail-fast: false matrix: - openssl_ver: [1.0.2u, 1.1.0l, 1.1.1l, 3.0.1] + openssl_ver: [1.0.2u, 1.1.0l, 1.1.1m, 3.0.1] env: OPENSSL_VER: ${{ matrix.openssl_ver }} MULTISSL_DIR: ${{ github.workspace }}/multissl diff --git a/Mac/BuildScript/0001-Darwin-platform-allows-to-build-on-releases-before-Y.patch b/Mac/BuildScript/0001-Darwin-platform-allows-to-build-on-releases-before-Y.patch deleted file mode 100644 index 51ccdc2267ee8..0000000000000 --- a/Mac/BuildScript/0001-Darwin-platform-allows-to-build-on-releases-before-Y.patch +++ /dev/null @@ -1,59 +0,0 @@ -From cef404f1e7a598166cbc2fd2e0048f7e2d752ad5 Mon Sep 17 00:00:00 2001 -From: David Carlier -Date: Tue, 24 Aug 2021 22:40:14 +0100 -Subject: [PATCH] Darwin platform allows to build on releases before - Yosemite/ios 8. - -issue #16407 #16408 ---- - crypto/rand/rand_unix.c | 5 +---- - include/crypto/rand.h | 10 ++++++++++ - 2 files changed, 11 insertions(+), 4 deletions(-) - -diff --git a/crypto/rand/rand_unix.c b/crypto/rand/rand_unix.c -index 43f1069d15..0f4525106a 100644 ---- a/crypto/rand/rand_unix.c -+++ b/crypto/rand/rand_unix.c -@@ -34,9 +34,6 @@ - #if defined(__OpenBSD__) - # include - #endif --#if defined(__APPLE__) --# include --#endif - - #if defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__) - # include -@@ -381,7 +378,7 @@ static ssize_t syscall_random(void *buf, size_t buflen) - if (errno != ENOSYS) - return -1; - } --# elif defined(__APPLE__) -+# elif defined(OPENSSL_APPLE_CRYPTO_RANDOM) - if (CCRandomGenerateBytes(buf, buflen) == kCCSuccess) - return (ssize_t)buflen; - -diff --git a/include/crypto/rand.h b/include/crypto/rand.h -index 5350d3a931..674f840fd1 100644 ---- a/include/crypto/rand.h -+++ b/include/crypto/rand.h -@@ -20,6 +20,16 @@ - - # include - -+# if defined(__APPLE__) && !defined(OPENSSL_NO_APPLE_CRYPTO_RANDOM) -+# include -+# if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000) || \ -+ (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) -+# define OPENSSL_APPLE_CRYPTO_RANDOM 1 -+# include -+# include -+# endif -+# endif -+ - /* forward declaration */ - typedef struct rand_pool_st RAND_POOL; - --- -2.33.0 - diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index cc24d54753924..3f5acfdf56648 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -244,10 +244,9 @@ def library_recipes(): result.extend([ dict( - name="OpenSSL 1.1.1l", - url="https://www.openssl.org/source/openssl-1.1.1l.tar.gz", - checksum='ac0d4387f3ba0ad741b0580dd45f6ff3', - patches=['0001-Darwin-platform-allows-to-build-on-releases-before-Y.patch'], + name="OpenSSL 1.1.1m", + url="https://www.openssl.org/source/openssl-1.1.1m.tar.gz", + checksum='8ec70f665c145c3103f6e330f538a9db', buildrecipe=build_universal_openssl, configure=None, install=None, diff --git a/Misc/NEWS.d/next/Build/2021-12-20-07-10-41.bpo-46106.5qcv3L.rst b/Misc/NEWS.d/next/Build/2021-12-20-07-10-41.bpo-46106.5qcv3L.rst new file mode 100644 index 0000000000000..d3e25f77c7336 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-12-20-07-10-41.bpo-46106.5qcv3L.rst @@ -0,0 +1,2 @@ +Updated OpenSSL to 1.1.1m in Windows builds, macOS installer builds, and CI. +Patch by Kumar Aditya. \ No newline at end of file diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index cc01909ed48ec..2d12abcda7139 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -53,7 +53,7 @@ echo.Fetching external libraries... set libraries= set libraries=%libraries% bzip2-1.0.6 if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi-3.3.0 -if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1l +if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1m set libraries=%libraries% sqlite-3.35.5.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.12.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.12.0 @@ -77,7 +77,7 @@ echo.Fetching external binaries... set binaries= if NOT "%IncludeLibffi%"=="false" set binaries=%binaries% libffi-3.3.0 -if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-1.1.1l +if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-1.1.1m if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.12.0 if NOT "%IncludeSSLSrc%"=="false" set binaries=%binaries% nasm-2.11.06 diff --git a/PCbuild/python.props b/PCbuild/python.props index 2ef290cca286a..5bf1f61e08c5f 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -63,8 +63,8 @@ $(ExternalsDir)libffi-3.3.0\ $(ExternalsDir)libffi-3.3.0\$(ArchName)\ $(libffiOutDir)include - $(ExternalsDir)openssl-1.1.1l\ - $(ExternalsDir)openssl-bin-1.1.1l\$(ArchName)\ + $(ExternalsDir)openssl-1.1.1m\ + $(ExternalsDir)openssl-bin-1.1.1m\$(ArchName)\ $(opensslOutDir)include $(ExternalsDir)\nasm-2.11.06\ $(ExternalsDir)\zlib-1.2.11\ diff --git a/Tools/ssl/multissltests.py b/Tools/ssl/multissltests.py index 8732d01e51be0..437efb22914b8 100755 --- a/Tools/ssl/multissltests.py +++ b/Tools/ssl/multissltests.py @@ -49,7 +49,7 @@ ] OPENSSL_RECENT_VERSIONS = [ - "1.1.1l", + "1.1.1m", "3.0.1" ] From webhook-mailer at python.org Wed Dec 22 08:08:03 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Wed, 22 Dec 2021 13:08:03 -0000 Subject: [Python-checkins] bpo-46140: take more Py_buffer arguments as const * (GH-30217) Message-ID: https://github.com/python/cpython/commit/31ff96712e8f89ac1056c2da880b44650002219f commit: 31ff96712e8f89ac1056c2da880b44650002219f branch: main author: David Hewitt <1939362+davidhewitt at users.noreply.github.com> committer: serhiy-storchaka date: 2021-12-22T15:07:46+02:00 summary: bpo-46140: take more Py_buffer arguments as const * (GH-30217) files: A Misc/NEWS.d/next/C API/2021-12-21-22-56-36.bpo-46140.dvXkYK.rst M Doc/c-api/buffer.rst M Doc/c-api/memoryview.rst M Include/cpython/abstract.h M Include/memoryobject.h M Objects/abstract.c M Objects/memoryobject.c diff --git a/Doc/c-api/buffer.rst b/Doc/c-api/buffer.rst index e32719373cc71..820a3a6f990ef 100644 --- a/Doc/c-api/buffer.rst +++ b/Doc/c-api/buffer.rst @@ -470,27 +470,27 @@ Buffer-related functions .. versionadded:: 3.9 -.. c:function:: int PyBuffer_IsContiguous(Py_buffer *view, char order) +.. c:function:: int PyBuffer_IsContiguous(const Py_buffer *view, char order) Return ``1`` if the memory defined by the *view* is C-style (*order* is ``'C'``) or Fortran-style (*order* is ``'F'``) :term:`contiguous` or either one (*order* is ``'A'``). Return ``0`` otherwise. This function always succeeds. -.. c:function:: void* PyBuffer_GetPointer(Py_buffer *view, Py_ssize_t *indices) +.. c:function:: void* PyBuffer_GetPointer(const Py_buffer *view, const Py_ssize_t *indices) Get the memory area pointed to by the *indices* inside the given *view*. *indices* must point to an array of ``view->ndim`` indices. -.. c:function:: int PyBuffer_FromContiguous(Py_buffer *view, void *buf, Py_ssize_t len, char fort) +.. c:function:: int PyBuffer_FromContiguous(const Py_buffer *view, const void *buf, Py_ssize_t len, char fort) Copy contiguous *len* bytes from *buf* to *view*. *fort* can be ``'C'`` or ``'F'`` (for C-style or Fortran-style ordering). ``0`` is returned on success, ``-1`` on error. -.. c:function:: int PyBuffer_ToContiguous(void *buf, Py_buffer *src, Py_ssize_t len, char order) +.. c:function:: int PyBuffer_ToContiguous(void *buf, const Py_buffer *src, Py_ssize_t len, char order) Copy *len* bytes from *src* to its contiguous representation in *buf*. *order* can be ``'C'`` or ``'F'`` or ``'A'`` (for C-style or Fortran-style diff --git a/Doc/c-api/memoryview.rst b/Doc/c-api/memoryview.rst index 24f8c935302e8..4d94b3f545f32 100644 --- a/Doc/c-api/memoryview.rst +++ b/Doc/c-api/memoryview.rst @@ -27,7 +27,7 @@ any other object. .. versionadded:: 3.3 -.. c:function:: PyObject *PyMemoryView_FromBuffer(Py_buffer *view) +.. c:function:: PyObject *PyMemoryView_FromBuffer(const Py_buffer *view) Create a memoryview object wrapping the given buffer structure *view*. For simple byte buffers, :c:func:`PyMemoryView_FromMemory` is the preferred @@ -61,4 +61,3 @@ any other object. on or ``NULL`` if the memoryview has been created by one of the functions :c:func:`PyMemoryView_FromMemory` or :c:func:`PyMemoryView_FromBuffer`. *mview* **must** be a memoryview instance. - diff --git a/Include/cpython/abstract.h b/Include/cpython/abstract.h index 55a742c31fada..2876a7bb84f52 100644 --- a/Include/cpython/abstract.h +++ b/Include/cpython/abstract.h @@ -183,17 +183,17 @@ PyAPI_FUNC(int) PyObject_GetBuffer(PyObject *obj, Py_buffer *view, /* Get the memory area pointed to by the indices for the buffer given. Note that view->ndim is the assumed size of indices. */ -PyAPI_FUNC(void *) PyBuffer_GetPointer(Py_buffer *view, Py_ssize_t *indices); +PyAPI_FUNC(void *) PyBuffer_GetPointer(const Py_buffer *view, const Py_ssize_t *indices); /* Return the implied itemsize of the data-format area from a struct-style description. */ PyAPI_FUNC(Py_ssize_t) PyBuffer_SizeFromFormat(const char *format); /* Implementation in memoryobject.c */ -PyAPI_FUNC(int) PyBuffer_ToContiguous(void *buf, Py_buffer *view, +PyAPI_FUNC(int) PyBuffer_ToContiguous(void *buf, const Py_buffer *view, Py_ssize_t len, char order); -PyAPI_FUNC(int) PyBuffer_FromContiguous(Py_buffer *view, void *buf, +PyAPI_FUNC(int) PyBuffer_FromContiguous(const Py_buffer *view, const void *buf, Py_ssize_t len, char order); /* Copy len bytes of data from the contiguous chunk of memory diff --git a/Include/memoryobject.h b/Include/memoryobject.h index 306028f4b225d..0298cc9373068 100644 --- a/Include/memoryobject.h +++ b/Include/memoryobject.h @@ -26,7 +26,7 @@ PyAPI_FUNC(PyObject *) PyMemoryView_FromMemory(char *mem, Py_ssize_t size, int flags); #endif #ifndef Py_LIMITED_API -PyAPI_FUNC(PyObject *) PyMemoryView_FromBuffer(Py_buffer *info); +PyAPI_FUNC(PyObject *) PyMemoryView_FromBuffer(const Py_buffer *info); #endif PyAPI_FUNC(PyObject *) PyMemoryView_GetContiguous(PyObject *base, int buffertype, diff --git a/Misc/NEWS.d/next/C API/2021-12-21-22-56-36.bpo-46140.dvXkYK.rst b/Misc/NEWS.d/next/C API/2021-12-21-22-56-36.bpo-46140.dvXkYK.rst new file mode 100644 index 0000000000000..26b985924b54d --- /dev/null +++ b/Misc/NEWS.d/next/C API/2021-12-21-22-56-36.bpo-46140.dvXkYK.rst @@ -0,0 +1 @@ +:c:func:`PyBuffer_GetPointer`, :c:func:`PyBuffer_FromContiguous`, :c:func:`PyBuffer_ToContiguous` and :c:func:`PyMemoryView_FromBuffer` now take buffer info by ``const Py_buffer *`` instead of ``Py_buffer *``, as they do not need mutability. :c:func:`PyBuffer_FromContiguous` also now takes the source buffer as ``const void *``, and similarly :c:func:`PyBuffer_GetPointer` takes the strides as ``const Py_ssize_t *``. \ No newline at end of file diff --git a/Objects/abstract.c b/Objects/abstract.c index 5c533bf03292d..6a2d5eda14079 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -474,7 +474,7 @@ PyBuffer_IsContiguous(const Py_buffer *view, char order) void* -PyBuffer_GetPointer(Py_buffer *view, Py_ssize_t *indices) +PyBuffer_GetPointer(const Py_buffer *view, const Py_ssize_t *indices) { char* pointer; int i; @@ -564,12 +564,13 @@ PyBuffer_SizeFromFormat(const char *format) } int -PyBuffer_FromContiguous(Py_buffer *view, void *buf, Py_ssize_t len, char fort) +PyBuffer_FromContiguous(const Py_buffer *view, const void *buf, Py_ssize_t len, char fort) { int k; void (*addone)(int, Py_ssize_t *, const Py_ssize_t *); Py_ssize_t *indices, elements; - char *src, *ptr; + char *ptr; + const char *src; if (len > view->len) { len = view->len; diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c index 6257455d34715..dfcb31e5b3307 100644 --- a/Objects/memoryobject.c +++ b/Objects/memoryobject.c @@ -389,7 +389,7 @@ copy_rec(const Py_ssize_t *shape, Py_ssize_t ndim, Py_ssize_t itemsize, /* Faster copying of one-dimensional arrays. */ static int -copy_single(Py_buffer *dest, Py_buffer *src) +copy_single(const Py_buffer *dest, const Py_buffer *src) { char *mem = NULL; @@ -421,7 +421,7 @@ copy_single(Py_buffer *dest, Py_buffer *src) structure. Copying is atomic, the function never fails with a partial copy. */ static int -copy_buffer(Py_buffer *dest, Py_buffer *src) +copy_buffer(const Py_buffer *dest, const Py_buffer *src) { char *mem = NULL; @@ -479,7 +479,7 @@ init_fortran_strides_from_shape(Py_buffer *view) or 'A' (Any). Assumptions: src has PyBUF_FULL information, src->ndim >= 1, len(mem) == src->len. */ static int -buffer_to_contiguous(char *mem, Py_buffer *src, char order) +buffer_to_contiguous(char *mem, const Py_buffer *src, char order) { Py_buffer dest; Py_ssize_t *strides; @@ -755,7 +755,7 @@ PyMemoryView_FromMemory(char *mem, Py_ssize_t size, int flags) without full information. Because of this fact init_shape_strides() must be able to reconstruct missing values. */ PyObject * -PyMemoryView_FromBuffer(Py_buffer *info) +PyMemoryView_FromBuffer(const Py_buffer *info) { _PyManagedBufferObject *mbuf; PyObject *mv; @@ -840,7 +840,7 @@ mbuf_copy_format(_PyManagedBufferObject *mbuf, const char *fmt) passes the altered format pointer to PyBuffer_Release(). */ static PyObject * -memory_from_contiguous_copy(Py_buffer *src, char order) +memory_from_contiguous_copy(const Py_buffer *src, char order) { _PyManagedBufferObject *mbuf; PyMemoryViewObject *mv; @@ -982,7 +982,7 @@ typedef struct { } Py_buffer_full; int -PyBuffer_ToContiguous(void *buf, Py_buffer *src, Py_ssize_t len, char order) +PyBuffer_ToContiguous(void *buf, const Py_buffer *src, Py_ssize_t len, char order) { Py_buffer_full *fb = NULL; int ret; @@ -2271,7 +2271,7 @@ memory_repr(PyMemoryViewObject *self) /**************************************************************************/ static char * -lookup_dimension(Py_buffer *view, char *ptr, int dim, Py_ssize_t index) +lookup_dimension(const Py_buffer *view, char *ptr, int dim, Py_ssize_t index) { Py_ssize_t nitems; /* items in the given dimension */ @@ -2297,7 +2297,7 @@ lookup_dimension(Py_buffer *view, char *ptr, int dim, Py_ssize_t index) /* Get the pointer to the item at index. */ static char * -ptr_from_index(Py_buffer *view, Py_ssize_t index) +ptr_from_index(const Py_buffer *view, Py_ssize_t index) { char *ptr = (char *)view->buf; return lookup_dimension(view, ptr, 0, index); @@ -2305,7 +2305,7 @@ ptr_from_index(Py_buffer *view, Py_ssize_t index) /* Get the pointer to the item at tuple. */ static char * -ptr_from_tuple(Py_buffer *view, PyObject *tup) +ptr_from_tuple(const Py_buffer *view, PyObject *tup) { char *ptr = (char *)view->buf; Py_ssize_t dim, nindices = PyTuple_GET_SIZE(tup); From webhook-mailer at python.org Thu Dec 23 04:17:48 2021 From: webhook-mailer at python.org (asvetlov) Date: Thu, 23 Dec 2021 09:17:48 -0000 Subject: [Python-checkins] bpo-46157: fix typo in docs (GH-30237) Message-ID: https://github.com/python/cpython/commit/71ef0b4c2b77195bb1adc42602549284f7ee9566 commit: 71ef0b4c2b77195bb1adc42602549284f7ee9566 branch: main author: Kumar Aditya <59607654+kumaraditya303 at users.noreply.github.com> committer: asvetlov date: 2021-12-23T11:17:31+02:00 summary: bpo-46157: fix typo in docs (GH-30237) files: M Doc/library/asyncio-eventloop.rst M Doc/library/enum.rst M Doc/library/json.rst M Doc/library/os.rst M Doc/library/poplib.rst M Doc/library/tarfile.rst diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index a3609d3925833..c25b3e80982ac 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -322,7 +322,7 @@ Creating Futures and Tasks .. method:: loop.create_future() - Create an :class:`asyncio.Future` object attached to the event loop. + Create a :class:`asyncio.Future` object attached to the event loop. This is the preferred way to create Futures in asyncio. This lets third-party event loops provide alternative implementations of @@ -649,7 +649,7 @@ Creating network servers * *backlog* is the maximum number of queued connections passed to :meth:`~socket.socket.listen` (defaults to 100). - * *ssl* can be set to an :class:`~ssl.SSLContext` instance to enable + * *ssl* can be set to a :class:`~ssl.SSLContext` instance to enable TLS over the accepted connections. * *reuse_address* tells the kernel to reuse a local socket in @@ -737,7 +737,7 @@ Creating network servers * *sock* is a preexisting socket object returned from :meth:`socket.accept `. - * *ssl* can be set to an :class:`~ssl.SSLContext` to enable SSL over + * *ssl* can be set to a :class:`~ssl.SSLContext` to enable SSL over the accepted connections. * *ssl_handshake_timeout* is (for an SSL connection) the time in seconds to @@ -897,7 +897,7 @@ convenient. .. versionchanged:: 3.7 Even though the method was always documented as a coroutine - method, before Python 3.7 it returned an :class:`Future`. + method, before Python 3.7 it returned a :class:`Future`. Since Python 3.7, this is an ``async def`` method. .. coroutinemethod:: loop.sock_connect(sock, address) diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst index 572048a255bf0..8bb19dcdf2b61 100644 --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -177,7 +177,7 @@ Data Types .. method:: EnumType.__getitem__(cls, name) - Returns the Enum member in *cls* matching *name*, or raises an :exc:`KeyError`:: + Returns the Enum member in *cls* matching *name*, or raises a :exc:`KeyError`:: >>> Color['BLUE'] Color.BLUE diff --git a/Doc/library/json.rst b/Doc/library/json.rst index 1810e04cc8349..510b0459bbb5a 100644 --- a/Doc/library/json.rst +++ b/Doc/library/json.rst @@ -159,7 +159,7 @@ Basic Usage If *check_circular* is false (default: ``True``), then the circular reference check for container types will be skipped and a circular reference - will result in an :exc:`RecursionError` (or worse). + will result in a :exc:`RecursionError` (or worse). If *allow_nan* is false (default: ``True``), then it will be a :exc:`ValueError` to serialize out of range :class:`float` values (``nan``, @@ -432,7 +432,7 @@ Encoders and Decoders If *check_circular* is true (the default), then lists, dicts, and custom encoded objects will be checked for circular references during encoding to - prevent an infinite recursion (which would cause an :exc:`RecursionError`). + prevent an infinite recursion (which would cause a :exc:`RecursionError`). Otherwise, no such check takes place. If *allow_nan* is true (the default), then ``NaN``, ``Infinity``, and diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 8092397be650f..8e11c693c7c2e 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -2081,7 +2081,7 @@ features: directories you can set the umask before invoking :func:`makedirs`. The file permission bits of existing parent directories are not changed. - If *exist_ok* is ``False`` (the default), an :exc:`FileExistsError` is + If *exist_ok* is ``False`` (the default), a :exc:`FileExistsError` is raised if the target directory already exists. .. note:: @@ -2357,7 +2357,7 @@ features: .. function:: rmdir(path, *, dir_fd=None) Remove (delete) the directory *path*. If the directory does not exist or is - not empty, an :exc:`FileNotFoundError` or an :exc:`OSError` is raised + not empty, a :exc:`FileNotFoundError` or an :exc:`OSError` is raised respectively. In order to remove whole directory trees, :func:`shutil.rmtree` can be used. diff --git a/Doc/library/poplib.rst b/Doc/library/poplib.rst index 27202a168e7c1..2f993f990de01 100644 --- a/Doc/library/poplib.rst +++ b/Doc/library/poplib.rst @@ -121,7 +121,7 @@ POP3 Objects All POP3 commands are represented by methods of the same name, in lowercase; most return the response text sent by the server. -An :class:`POP3` instance has the following methods: +A :class:`POP3` instance has the following methods: .. method:: POP3.set_debuglevel(level) diff --git a/Doc/library/tarfile.rst b/Doc/library/tarfile.rst index 6afb8397b7866..f5c49b0ac4f73 100644 --- a/Doc/library/tarfile.rst +++ b/Doc/library/tarfile.rst @@ -63,19 +63,19 @@ Some facts and figures: +------------------+---------------------------------------------+ | ``'x'`` or | Create a tarfile exclusively without | | ``'x:'`` | compression. | - | | Raise an :exc:`FileExistsError` exception | + | | Raise a :exc:`FileExistsError` exception | | | if it already exists. | +------------------+---------------------------------------------+ | ``'x:gz'`` | Create a tarfile with gzip compression. | - | | Raise an :exc:`FileExistsError` exception | + | | Raise a :exc:`FileExistsError` exception | | | if it already exists. | +------------------+---------------------------------------------+ | ``'x:bz2'`` | Create a tarfile with bzip2 compression. | - | | Raise an :exc:`FileExistsError` exception | + | | Raise a :exc:`FileExistsError` exception | | | if it already exists. | +------------------+---------------------------------------------+ | ``'x:xz'`` | Create a tarfile with lzma compression. | - | | Raise an :exc:`FileExistsError` exception | + | | Raise a :exc:`FileExistsError` exception | | | if it already exists. | +------------------+---------------------------------------------+ | ``'a' or 'a:'`` | Open for appending with no compression. The | From webhook-mailer at python.org Thu Dec 23 05:25:43 2021 From: webhook-mailer at python.org (asvetlov) Date: Thu, 23 Dec 2021 10:25:43 -0000 Subject: [Python-checkins] typos (#30239) Message-ID: https://github.com/python/cpython/commit/cf15419a99962b3503ff7123e148d71f7f01bc15 commit: cf15419a99962b3503ff7123e148d71f7f01bc15 branch: main author: Kumar Aditya <59607654+kumaraditya303 at users.noreply.github.com> committer: asvetlov date: 2021-12-23T12:25:12+02:00 summary: typos (#30239) files: M Doc/library/asyncio-eventloop.rst diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index c25b3e80982ac..5b48945599f76 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -322,7 +322,7 @@ Creating Futures and Tasks .. method:: loop.create_future() - Create a :class:`asyncio.Future` object attached to the event loop. + Create an :class:`asyncio.Future` object attached to the event loop. This is the preferred way to create Futures in asyncio. This lets third-party event loops provide alternative implementations of @@ -649,7 +649,7 @@ Creating network servers * *backlog* is the maximum number of queued connections passed to :meth:`~socket.socket.listen` (defaults to 100). - * *ssl* can be set to a :class:`~ssl.SSLContext` instance to enable + * *ssl* can be set to an :class:`~ssl.SSLContext` instance to enable TLS over the accepted connections. * *reuse_address* tells the kernel to reuse a local socket in @@ -737,7 +737,7 @@ Creating network servers * *sock* is a preexisting socket object returned from :meth:`socket.accept `. - * *ssl* can be set to a :class:`~ssl.SSLContext` to enable SSL over + * *ssl* can be set to an :class:`~ssl.SSLContext` to enable SSL over the accepted connections. * *ssl_handshake_timeout* is (for an SSL connection) the time in seconds to From webhook-mailer at python.org Thu Dec 23 22:17:55 2021 From: webhook-mailer at python.org (gpshead) Date: Fri, 24 Dec 2021 03:17:55 -0000 Subject: [Python-checkins] Allow test_pathlib to pass on systems where fakeuser exists. (GH-30244) Message-ID: https://github.com/python/cpython/commit/d8880677a79ba4e70bbe7583eecf573bfceb7e98 commit: d8880677a79ba4e70bbe7583eecf573bfceb7e98 branch: main author: Gregory P. Smith committer: gpshead date: 2021-12-23T19:17:40-08:00 summary: Allow test_pathlib to pass on systems where fakeuser exists. (GH-30244) files: M Lib/test/test_pathlib.py diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 5f6d9f47d13d7..2268d36b0639f 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -2564,7 +2564,7 @@ def test_expanduser(self): p4 = P('../~' + username + '/Documents') p5 = P('/~' + username + '/Documents') p6 = P('') - p7 = P('~fakeuser/Documents') + p7 = P('~fake800813user/Documents') with os_helper.EnvironmentVarGuard() as env: env.pop('HOME', None) From webhook-mailer at python.org Fri Dec 24 03:07:32 2021 From: webhook-mailer at python.org (miss-islington) Date: Fri, 24 Dec 2021 08:07:32 -0000 Subject: [Python-checkins] Allow test_pathlib to pass on systems where fakeuser exists. (GH-30244) Message-ID: https://github.com/python/cpython/commit/1c77aa9fc3c105053167d519607565068a2688b5 commit: 1c77aa9fc3c105053167d519607565068a2688b5 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-24T00:07:24-08:00 summary: Allow test_pathlib to pass on systems where fakeuser exists. (GH-30244) (cherry picked from commit d8880677a79ba4e70bbe7583eecf573bfceb7e98) Co-authored-by: Gregory P. Smith files: M Lib/test/test_pathlib.py diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 5f6d9f47d13d7..2268d36b0639f 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -2564,7 +2564,7 @@ def test_expanduser(self): p4 = P('../~' + username + '/Documents') p5 = P('/~' + username + '/Documents') p6 = P('') - p7 = P('~fakeuser/Documents') + p7 = P('~fake800813user/Documents') with os_helper.EnvironmentVarGuard() as env: env.pop('HOME', None) From webhook-mailer at python.org Fri Dec 24 03:07:45 2021 From: webhook-mailer at python.org (miss-islington) Date: Fri, 24 Dec 2021 08:07:45 -0000 Subject: [Python-checkins] Allow test_pathlib to pass on systems where fakeuser exists. (GH-30244) Message-ID: https://github.com/python/cpython/commit/97a015b7b0e8b7ac8775ba5e33a9359a149253bc commit: 97a015b7b0e8b7ac8775ba5e33a9359a149253bc branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-24T00:07:41-08:00 summary: Allow test_pathlib to pass on systems where fakeuser exists. (GH-30244) (cherry picked from commit d8880677a79ba4e70bbe7583eecf573bfceb7e98) Co-authored-by: Gregory P. Smith files: M Lib/test/test_pathlib.py diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 183c157afdcd0..548951a67a6f2 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -2449,7 +2449,7 @@ def test_expanduser(self): p4 = P('../~' + username + '/Documents') p5 = P('/~' + username + '/Documents') p6 = P('') - p7 = P('~fakeuser/Documents') + p7 = P('~fake800813user/Documents') with support.EnvironmentVarGuard() as env: env.pop('HOME', None) From webhook-mailer at python.org Fri Dec 24 03:07:54 2021 From: webhook-mailer at python.org (gpshead) Date: Fri, 24 Dec 2021 08:07:54 -0000 Subject: [Python-checkins] bpo-46150: ensure `fakeuser` does not exist in `PosixPathTest.test_expanduser` (GH-30240) Message-ID: https://github.com/python/cpython/commit/b8de8b7039cee47465b2af9950b0b9ed2d3f2903 commit: b8de8b7039cee47465b2af9950b0b9ed2d3f2903 branch: main author: Nikita Sobolev committer: gpshead date: 2021-12-24T00:07:50-08:00 summary: bpo-46150: ensure `fakeuser` does not exist in `PosixPathTest.test_expanduser` (GH-30240) Ensure `fakeuser` does not exist in `PosixPathTest.test_expanduser` files: A Misc/NEWS.d/next/Tests/2021-12-23-13-42-15.bpo-46150.RhtADs.rst M Lib/test/test_pathlib.py diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 2268d36b0639f..555c7ee795bd1 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -2558,13 +2558,21 @@ def test_expanduser(self): othername = username otherhome = userhome + fakename = 'fakeuser' + # This user can theoretically exist on a test runner. Create unique name: + try: + while pwd.getpwnam(fakename): + fakename += '1' + except KeyError: + pass # Non-existent name found + p1 = P('~/Documents') - p2 = P('~' + username + '/Documents') - p3 = P('~' + othername + '/Documents') - p4 = P('../~' + username + '/Documents') - p5 = P('/~' + username + '/Documents') + p2 = P(f'~{username}/Documents') + p3 = P(f'~{othername}/Documents') + p4 = P(f'../~{username}/Documents') + p5 = P(f'/~{username}/Documents') p6 = P('') - p7 = P('~fake800813user/Documents') + p7 = P(f'~{fakename}/Documents') with os_helper.EnvironmentVarGuard() as env: env.pop('HOME', None) diff --git a/Misc/NEWS.d/next/Tests/2021-12-23-13-42-15.bpo-46150.RhtADs.rst b/Misc/NEWS.d/next/Tests/2021-12-23-13-42-15.bpo-46150.RhtADs.rst new file mode 100644 index 0000000000000..8ef9cd9b4a594 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-12-23-13-42-15.bpo-46150.RhtADs.rst @@ -0,0 +1,2 @@ +Now ``fakename`` in ``test_pathlib.PosixPathTest.test_expanduser`` is checked +to be non-existent. From webhook-mailer at python.org Fri Dec 24 03:31:26 2021 From: webhook-mailer at python.org (miss-islington) Date: Fri, 24 Dec 2021 08:31:26 -0000 Subject: [Python-checkins] bpo-46150: ensure `fakeuser` does not exist in `PosixPathTest.test_expanduser` (GH-30240) Message-ID: https://github.com/python/cpython/commit/8005e22c9c71708ead0e5b16e55e005844c5131f commit: 8005e22c9c71708ead0e5b16e55e005844c5131f branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-24T00:31:13-08:00 summary: bpo-46150: ensure `fakeuser` does not exist in `PosixPathTest.test_expanduser` (GH-30240) Ensure `fakeuser` does not exist in `PosixPathTest.test_expanduser` (cherry picked from commit b8de8b7039cee47465b2af9950b0b9ed2d3f2903) Co-authored-by: Nikita Sobolev files: A Misc/NEWS.d/next/Tests/2021-12-23-13-42-15.bpo-46150.RhtADs.rst M Lib/test/test_pathlib.py diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 2268d36b0639f..555c7ee795bd1 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -2558,13 +2558,21 @@ def test_expanduser(self): othername = username otherhome = userhome + fakename = 'fakeuser' + # This user can theoretically exist on a test runner. Create unique name: + try: + while pwd.getpwnam(fakename): + fakename += '1' + except KeyError: + pass # Non-existent name found + p1 = P('~/Documents') - p2 = P('~' + username + '/Documents') - p3 = P('~' + othername + '/Documents') - p4 = P('../~' + username + '/Documents') - p5 = P('/~' + username + '/Documents') + p2 = P(f'~{username}/Documents') + p3 = P(f'~{othername}/Documents') + p4 = P(f'../~{username}/Documents') + p5 = P(f'/~{username}/Documents') p6 = P('') - p7 = P('~fake800813user/Documents') + p7 = P(f'~{fakename}/Documents') with os_helper.EnvironmentVarGuard() as env: env.pop('HOME', None) diff --git a/Misc/NEWS.d/next/Tests/2021-12-23-13-42-15.bpo-46150.RhtADs.rst b/Misc/NEWS.d/next/Tests/2021-12-23-13-42-15.bpo-46150.RhtADs.rst new file mode 100644 index 0000000000000..8ef9cd9b4a594 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-12-23-13-42-15.bpo-46150.RhtADs.rst @@ -0,0 +1,2 @@ +Now ``fakename`` in ``test_pathlib.PosixPathTest.test_expanduser`` is checked +to be non-existent. From webhook-mailer at python.org Fri Dec 24 03:32:31 2021 From: webhook-mailer at python.org (miss-islington) Date: Fri, 24 Dec 2021 08:32:31 -0000 Subject: [Python-checkins] bpo-46150: ensure `fakeuser` does not exist in `PosixPathTest.test_expanduser` (GH-30240) Message-ID: https://github.com/python/cpython/commit/d718764f389acd1bf4a5a65661bb58862f14fb98 commit: d718764f389acd1bf4a5a65661bb58862f14fb98 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-24T00:32:27-08:00 summary: bpo-46150: ensure `fakeuser` does not exist in `PosixPathTest.test_expanduser` (GH-30240) Ensure `fakeuser` does not exist in `PosixPathTest.test_expanduser` (cherry picked from commit b8de8b7039cee47465b2af9950b0b9ed2d3f2903) Co-authored-by: Nikita Sobolev files: A Misc/NEWS.d/next/Tests/2021-12-23-13-42-15.bpo-46150.RhtADs.rst M Lib/test/test_pathlib.py diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 548951a67a6f2..1406ed3b12c4a 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -2443,13 +2443,21 @@ def test_expanduser(self): othername = username otherhome = userhome + fakename = 'fakeuser' + # This user can theoretically exist on a test runner. Create unique name: + try: + while pwd.getpwnam(fakename): + fakename += '1' + except KeyError: + pass # Non-existent name found + p1 = P('~/Documents') - p2 = P('~' + username + '/Documents') - p3 = P('~' + othername + '/Documents') - p4 = P('../~' + username + '/Documents') - p5 = P('/~' + username + '/Documents') + p2 = P(f'~{username}/Documents') + p3 = P(f'~{othername}/Documents') + p4 = P(f'../~{username}/Documents') + p5 = P(f'/~{username}/Documents') p6 = P('') - p7 = P('~fake800813user/Documents') + p7 = P(f'~{fakename}/Documents') with support.EnvironmentVarGuard() as env: env.pop('HOME', None) diff --git a/Misc/NEWS.d/next/Tests/2021-12-23-13-42-15.bpo-46150.RhtADs.rst b/Misc/NEWS.d/next/Tests/2021-12-23-13-42-15.bpo-46150.RhtADs.rst new file mode 100644 index 0000000000000..8ef9cd9b4a594 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-12-23-13-42-15.bpo-46150.RhtADs.rst @@ -0,0 +1,2 @@ +Now ``fakename`` in ``test_pathlib.PosixPathTest.test_expanduser`` is checked +to be non-existent. From webhook-mailer at python.org Fri Dec 24 04:27:35 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Fri, 24 Dec 2021 09:27:35 -0000 Subject: [Python-checkins] bpo-45878: convert `try/except` to `self.assertRaises` in `Lib/ctypes/test/test_functions.py` (GH-29721) (GH-29723) Message-ID: https://github.com/python/cpython/commit/393ff040281db818f2d6e0240919316f58f989a6 commit: 393ff040281db818f2d6e0240919316f58f989a6 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: serhiy-storchaka date: 2021-12-24T11:27:17+02:00 summary: bpo-45878: convert `try/except` to `self.assertRaises` in `Lib/ctypes/test/test_functions.py` (GH-29721) (GH-29723) (cherry picked from commit b48ac6fe38b2fca9963b097c04cdecfc6083104e) Co-authored-by: Nikita Sobolev files: A Misc/NEWS.d/next/Tests/2021-11-23-12-36-21.bpo-45878.eOs_Mp.rst M Lib/ctypes/test/test_functions.py diff --git a/Lib/ctypes/test/test_functions.py b/Lib/ctypes/test/test_functions.py index d3c6536f2766a..bdb044e594a2c 100644 --- a/Lib/ctypes/test/test_functions.py +++ b/Lib/ctypes/test/test_functions.py @@ -35,34 +35,24 @@ def test_mro(self): # wasn't checked, and it even crashed Python. # Found by Greg Chapman. - try: + with self.assertRaises(TypeError): class X(object, Array): _length_ = 5 _type_ = "i" - except TypeError: - pass - from _ctypes import _Pointer - try: + with self.assertRaises(TypeError): class X(object, _Pointer): pass - except TypeError: - pass from _ctypes import _SimpleCData - try: + with self.assertRaises(TypeError): class X(object, _SimpleCData): _type_ = "i" - except TypeError: - pass - try: + with self.assertRaises(TypeError): class X(object, Structure): _fields_ = [] - except TypeError: - pass - @need_symbol('c_wchar') def test_wchar_parm(self): diff --git a/Misc/NEWS.d/next/Tests/2021-11-23-12-36-21.bpo-45878.eOs_Mp.rst b/Misc/NEWS.d/next/Tests/2021-11-23-12-36-21.bpo-45878.eOs_Mp.rst new file mode 100644 index 0000000000000..fca90ef46981b --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-11-23-12-36-21.bpo-45878.eOs_Mp.rst @@ -0,0 +1,2 @@ +Test ``Lib/ctypes/test/test_functions.py::test_mro`` now uses +``self.assertRaises`` instead of ``try/except``. From webhook-mailer at python.org Fri Dec 24 04:29:08 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Fri, 24 Dec 2021 09:29:08 -0000 Subject: [Python-checkins] bpo-45878: convert `try/except` to `self.assertRaises` in `Lib/ctypes/test/test_functions.py` (GH-29721) (GH-29748) Message-ID: https://github.com/python/cpython/commit/a9e0b2b49374df91c40fe409508cfcdc6332450e commit: a9e0b2b49374df91c40fe409508cfcdc6332450e branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: serhiy-storchaka date: 2021-12-24T11:28:57+02:00 summary: bpo-45878: convert `try/except` to `self.assertRaises` in `Lib/ctypes/test/test_functions.py` (GH-29721) (GH-29748) (cherry picked from commit b48ac6fe38b2fca9963b097c04cdecfc6083104e) Co-authored-by: Nikita Sobolev files: A Misc/NEWS.d/next/Tests/2021-11-23-12-36-21.bpo-45878.eOs_Mp.rst M Lib/ctypes/test/test_functions.py diff --git a/Lib/ctypes/test/test_functions.py b/Lib/ctypes/test/test_functions.py index d3c6536f2766a..bdb044e594a2c 100644 --- a/Lib/ctypes/test/test_functions.py +++ b/Lib/ctypes/test/test_functions.py @@ -35,34 +35,24 @@ def test_mro(self): # wasn't checked, and it even crashed Python. # Found by Greg Chapman. - try: + with self.assertRaises(TypeError): class X(object, Array): _length_ = 5 _type_ = "i" - except TypeError: - pass - from _ctypes import _Pointer - try: + with self.assertRaises(TypeError): class X(object, _Pointer): pass - except TypeError: - pass from _ctypes import _SimpleCData - try: + with self.assertRaises(TypeError): class X(object, _SimpleCData): _type_ = "i" - except TypeError: - pass - try: + with self.assertRaises(TypeError): class X(object, Structure): _fields_ = [] - except TypeError: - pass - @need_symbol('c_wchar') def test_wchar_parm(self): diff --git a/Misc/NEWS.d/next/Tests/2021-11-23-12-36-21.bpo-45878.eOs_Mp.rst b/Misc/NEWS.d/next/Tests/2021-11-23-12-36-21.bpo-45878.eOs_Mp.rst new file mode 100644 index 0000000000000..fca90ef46981b --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-11-23-12-36-21.bpo-45878.eOs_Mp.rst @@ -0,0 +1,2 @@ +Test ``Lib/ctypes/test/test_functions.py::test_mro`` now uses +``self.assertRaises`` instead of ``try/except``. From webhook-mailer at python.org Fri Dec 24 16:36:39 2021 From: webhook-mailer at python.org (gpshead) Date: Fri, 24 Dec 2021 21:36:39 -0000 Subject: [Python-checkins] bpo-46120: State that `|` is preferred over `Union` (GH-30222) Message-ID: https://github.com/python/cpython/commit/1b30660c3b40da557050948ac8635f2dc50c4ee2 commit: 1b30660c3b40da557050948ac8635f2dc50c4ee2 branch: main author: Nikita Sobolev committer: gpshead date: 2021-12-24T13:36:09-08:00 summary: bpo-46120: State that `|` is preferred over `Union` (GH-30222) Co-authored-by: ?ric Co-authored-by: Guido van Rossum files: A Misc/NEWS.d/next/Documentation/2021-12-21-12-45-57.bpo-46120.PE0DmJ.rst M Doc/library/typing.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 727941b57b547..08b59d84246f8 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -625,7 +625,7 @@ These can be used as types in annotations using ``[]``, each having a unique syn Union type; ``Union[X, Y]`` is equivalent to ``X | Y`` and means either X or Y. - To define a union, use e.g. ``Union[int, str]`` or the shorthand ``int | str``. Details: + To define a union, use e.g. ``Union[int, str]`` or the shorthand ``int | str``. Using that shorthand is recommended. Details: * The arguments must be types and there must be at least one. diff --git a/Misc/NEWS.d/next/Documentation/2021-12-21-12-45-57.bpo-46120.PE0DmJ.rst b/Misc/NEWS.d/next/Documentation/2021-12-21-12-45-57.bpo-46120.PE0DmJ.rst new file mode 100644 index 0000000000000..17f67472e2ab0 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-12-21-12-45-57.bpo-46120.PE0DmJ.rst @@ -0,0 +1 @@ +State that ``|`` is preferred for readability over ``Union`` in the :mod:`typing` docs. From webhook-mailer at python.org Sat Dec 25 07:16:18 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Sat, 25 Dec 2021 12:16:18 -0000 Subject: [Python-checkins] bpo-46032: Check types in singledispatch's register() at declaration time (GH-30050) Message-ID: https://github.com/python/cpython/commit/078abb676cf759b1e960f78390b6e80f256f0255 commit: 078abb676cf759b1e960f78390b6e80f256f0255 branch: main author: Serhiy Storchaka committer: serhiy-storchaka date: 2021-12-25T14:16:14+02:00 summary: bpo-46032: Check types in singledispatch's register() at declaration time (GH-30050) The registry() method of functools.singledispatch() functions checks now the first argument or the first parameter annotation and raises a TypeError if it is not supported. Previously unsupported "types" were ignored (e.g. typing.List[int]) or caused an error at calling time (e.g. list[int]). files: A Misc/NEWS.d/next/Library/2021-12-11-15-45-07.bpo-46032.HmciLT.rst M Lib/functools.py M Lib/test/test_functools.py diff --git a/Lib/functools.py b/Lib/functools.py index ccac6f89996b6..91b678c226966 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -740,6 +740,7 @@ def _compose_mro(cls, types): # Remove entries which are already present in the __mro__ or unrelated. def is_related(typ): return (typ not in bases and hasattr(typ, '__mro__') + and not isinstance(typ, GenericAlias) and issubclass(cls, typ)) types = [n for n in types if is_related(n)] # Remove entries which are strict bases of other entries (they will end up @@ -841,9 +842,13 @@ def _is_union_type(cls): from typing import get_origin, Union return get_origin(cls) in {Union, types.UnionType} - def _is_valid_union_type(cls): + def _is_valid_dispatch_type(cls): + if isinstance(cls, type) and not isinstance(cls, GenericAlias): + return True from typing import get_args - return _is_union_type(cls) and all(isinstance(arg, type) for arg in get_args(cls)) + return (_is_union_type(cls) and + all(isinstance(arg, type) and not isinstance(arg, GenericAlias) + for arg in get_args(cls))) def register(cls, func=None): """generic_func.register(cls, func) -> func @@ -852,9 +857,15 @@ def register(cls, func=None): """ nonlocal cache_token - if func is None: - if isinstance(cls, type) or _is_valid_union_type(cls): + if _is_valid_dispatch_type(cls): + if func is None: return lambda f: register(cls, f) + else: + if func is not None: + raise TypeError( + f"Invalid first argument to `register()`. " + f"{cls!r} is not a class or union type." + ) ann = getattr(cls, '__annotations__', {}) if not ann: raise TypeError( @@ -867,7 +878,7 @@ def register(cls, func=None): # only import typing if annotation parsing is necessary from typing import get_type_hints argname, cls = next(iter(get_type_hints(func).items())) - if not isinstance(cls, type) and not _is_valid_union_type(cls): + if not _is_valid_dispatch_type(cls): if _is_union_type(cls): raise TypeError( f"Invalid annotation for {argname!r}. " diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 755ac038792b7..70ae8e06bb475 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -2722,6 +2722,74 @@ def _(arg: int | float): self.assertEqual(f(1), "types.UnionType") self.assertEqual(f(1.0), "types.UnionType") + def test_register_genericalias(self): + @functools.singledispatch + def f(arg): + return "default" + + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(list[int], lambda arg: "types.GenericAlias") + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(typing.List[int], lambda arg: "typing.GenericAlias") + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(list[int] | str, lambda arg: "types.UnionTypes(types.GenericAlias)") + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(typing.List[float] | bytes, lambda arg: "typing.Union[typing.GenericAlias]") + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(typing.Any, lambda arg: "typing.Any") + + self.assertEqual(f([1]), "default") + self.assertEqual(f([1.0]), "default") + self.assertEqual(f(""), "default") + self.assertEqual(f(b""), "default") + + def test_register_genericalias_decorator(self): + @functools.singledispatch + def f(arg): + return "default" + + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(list[int]) + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(typing.List[int]) + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(list[int] | str) + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(typing.List[int] | str) + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(typing.Any) + + def test_register_genericalias_annotation(self): + @functools.singledispatch + def f(arg): + return "default" + + with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"): + @f.register + def _(arg: list[int]): + return "types.GenericAlias" + with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"): + @f.register + def _(arg: typing.List[float]): + return "typing.GenericAlias" + with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"): + @f.register + def _(arg: list[int] | str): + return "types.UnionType(types.GenericAlias)" + with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"): + @f.register + def _(arg: typing.List[float] | bytes): + return "typing.Union[typing.GenericAlias]" + with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"): + @f.register + def _(arg: typing.Any): + return "typing.Any" + + self.assertEqual(f([1]), "default") + self.assertEqual(f([1.0]), "default") + self.assertEqual(f(""), "default") + self.assertEqual(f(b""), "default") + class CachedCostItem: _cost = 1 diff --git a/Misc/NEWS.d/next/Library/2021-12-11-15-45-07.bpo-46032.HmciLT.rst b/Misc/NEWS.d/next/Library/2021-12-11-15-45-07.bpo-46032.HmciLT.rst new file mode 100644 index 0000000000000..97a553d7ba29f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-11-15-45-07.bpo-46032.HmciLT.rst @@ -0,0 +1,5 @@ +The ``registry()`` method of :func:`functools.singledispatch` functions +checks now the first argument or the first parameter annotation and raises a +TypeError if it is not supported. Previously unsupported "types" were +ignored (e.g. ``typing.List[int]``) or caused an error at calling time (e.g. +``list[int]``). From webhook-mailer at python.org Sat Dec 25 09:12:57 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Sat, 25 Dec 2021 14:12:57 -0000 Subject: [Python-checkins] [3.10] bpo-46032: Check types in singledispatch's register() at declaration time (GH-30050) (GH-30254) Message-ID: https://github.com/python/cpython/commit/03c7449fbc7c57f5e0365f234a0b65c1dde763f2 commit: 03c7449fbc7c57f5e0365f234a0b65c1dde763f2 branch: 3.10 author: Serhiy Storchaka committer: serhiy-storchaka date: 2021-12-25T16:12:32+02:00 summary: [3.10] bpo-46032: Check types in singledispatch's register() at declaration time (GH-30050) (GH-30254) The registry() method of functools.singledispatch() functions checks now the first argument or the first parameter annotation and raises a TypeError if it is not supported. Previously unsupported "types" were ignored (e.g. typing.List[int]) or caused an error at calling time (e.g. list[int]). (cherry picked from commit 078abb676cf759b1e960f78390b6e80f256f0255) files: A Misc/NEWS.d/next/Library/2021-12-11-15-45-07.bpo-46032.HmciLT.rst M Lib/functools.py M Lib/test/test_functools.py diff --git a/Lib/functools.py b/Lib/functools.py index 77ec852805c10..305ceb450a71c 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -740,6 +740,7 @@ def _compose_mro(cls, types): # Remove entries which are already present in the __mro__ or unrelated. def is_related(typ): return (typ not in bases and hasattr(typ, '__mro__') + and not isinstance(typ, GenericAlias) and issubclass(cls, typ)) types = [n for n in types if is_related(n)] # Remove entries which are strict bases of other entries (they will end up @@ -837,6 +838,9 @@ def dispatch(cls): dispatch_cache[cls] = impl return impl + def _is_valid_dispatch_type(cls): + return isinstance(cls, type) and not isinstance(cls, GenericAlias) + def register(cls, func=None): """generic_func.register(cls, func) -> func @@ -844,9 +848,15 @@ def register(cls, func=None): """ nonlocal cache_token - if func is None: - if isinstance(cls, type): + if _is_valid_dispatch_type(cls): + if func is None: return lambda f: register(cls, f) + else: + if func is not None: + raise TypeError( + f"Invalid first argument to `register()`. " + f"{cls!r} is not a class." + ) ann = getattr(cls, '__annotations__', {}) if not ann: raise TypeError( @@ -859,11 +869,12 @@ def register(cls, func=None): # only import typing if annotation parsing is necessary from typing import get_type_hints argname, cls = next(iter(get_type_hints(func).items())) - if not isinstance(cls, type): + if not _is_valid_dispatch_type(cls): raise TypeError( f"Invalid annotation for {argname!r}. " f"{cls!r} is not a class." ) + registry[cls] = func if cache_token is None and hasattr(cls, '__abstractmethods__'): cache_token = get_cache_token() diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 7bc355ff7213e..9343d4e9fa316 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -2665,6 +2665,74 @@ def f(*args): with self.assertRaisesRegex(TypeError, msg): f() + def test_register_genericalias(self): + @functools.singledispatch + def f(arg): + return "default" + + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(list[int], lambda arg: "types.GenericAlias") + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(typing.List[int], lambda arg: "typing.GenericAlias") + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(list[int] | str, lambda arg: "types.UnionTypes(types.GenericAlias)") + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(typing.List[float] | bytes, lambda arg: "typing.Union[typing.GenericAlias]") + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(typing.Any, lambda arg: "typing.Any") + + self.assertEqual(f([1]), "default") + self.assertEqual(f([1.0]), "default") + self.assertEqual(f(""), "default") + self.assertEqual(f(b""), "default") + + def test_register_genericalias_decorator(self): + @functools.singledispatch + def f(arg): + return "default" + + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(list[int]) + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(typing.List[int]) + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(list[int] | str) + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(typing.List[int] | str) + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(typing.Any) + + def test_register_genericalias_annotation(self): + @functools.singledispatch + def f(arg): + return "default" + + with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"): + @f.register + def _(arg: list[int]): + return "types.GenericAlias" + with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"): + @f.register + def _(arg: typing.List[float]): + return "typing.GenericAlias" + with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"): + @f.register + def _(arg: list[int] | str): + return "types.UnionType(types.GenericAlias)" + with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"): + @f.register + def _(arg: typing.List[float] | bytes): + return "typing.Union[typing.GenericAlias]" + with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"): + @f.register + def _(arg: typing.Any): + return "typing.Any" + + self.assertEqual(f([1]), "default") + self.assertEqual(f([1.0]), "default") + self.assertEqual(f(""), "default") + self.assertEqual(f(b""), "default") + class CachedCostItem: _cost = 1 diff --git a/Misc/NEWS.d/next/Library/2021-12-11-15-45-07.bpo-46032.HmciLT.rst b/Misc/NEWS.d/next/Library/2021-12-11-15-45-07.bpo-46032.HmciLT.rst new file mode 100644 index 0000000000000..97a553d7ba29f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-11-15-45-07.bpo-46032.HmciLT.rst @@ -0,0 +1,5 @@ +The ``registry()`` method of :func:`functools.singledispatch` functions +checks now the first argument or the first parameter annotation and raises a +TypeError if it is not supported. Previously unsupported "types" were +ignored (e.g. ``typing.List[int]``) or caused an error at calling time (e.g. +``list[int]``). From webhook-mailer at python.org Sun Dec 26 05:37:48 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Sun, 26 Dec 2021 10:37:48 -0000 Subject: [Python-checkins] [3.10] Remove a NEWS entry for bpo-45878 (GH-30258) Message-ID: https://github.com/python/cpython/commit/11909c12c75a7f377460561abc97707a4006fc07 commit: 11909c12c75a7f377460561abc97707a4006fc07 branch: 3.10 author: Serhiy Storchaka committer: serhiy-storchaka date: 2021-12-26T12:37:39+02:00 summary: [3.10] Remove a NEWS entry for bpo-45878 (GH-30258) The docs linter complains about it, and in general news entries for such changes are not required. files: D Misc/NEWS.d/next/Tests/2021-11-23-12-36-21.bpo-45878.eOs_Mp.rst diff --git a/Misc/NEWS.d/next/Tests/2021-11-23-12-36-21.bpo-45878.eOs_Mp.rst b/Misc/NEWS.d/next/Tests/2021-11-23-12-36-21.bpo-45878.eOs_Mp.rst deleted file mode 100644 index fca90ef46981b..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-11-23-12-36-21.bpo-45878.eOs_Mp.rst +++ /dev/null @@ -1,2 +0,0 @@ -Test ``Lib/ctypes/test/test_functions.py::test_mro`` now uses -``self.assertRaises`` instead of ``try/except``. From webhook-mailer at python.org Sun Dec 26 05:38:23 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Sun, 26 Dec 2021 10:38:23 -0000 Subject: [Python-checkins] Remove a NEWS entry for bpo-45878 (GH-30259) Message-ID: https://github.com/python/cpython/commit/1fb7c61ca76c6fbff4d90b272e34e92bc2c7d729 commit: 1fb7c61ca76c6fbff4d90b272e34e92bc2c7d729 branch: main author: Serhiy Storchaka committer: serhiy-storchaka date: 2021-12-26T12:38:19+02:00 summary: Remove a NEWS entry for bpo-45878 (GH-30259) The docs linter complains about it, and in general news entries for such changes are not required. files: M Misc/NEWS.d/3.11.0a3.rst diff --git a/Misc/NEWS.d/3.11.0a3.rst b/Misc/NEWS.d/3.11.0a3.rst index b5bcd5ae5a70e..426531904993a 100644 --- a/Misc/NEWS.d/3.11.0a3.rst +++ b/Misc/NEWS.d/3.11.0a3.rst @@ -813,16 +813,6 @@ Add new Test for ``Lib/email/mime/nonmultipart.py::MIMENonMultipart``. .. -.. bpo: 45878 -.. date: 2021-11-23-12-36-21 -.. nonce: eOs_Mp -.. section: Tests - -Test ``Lib/ctypes/test/test_functions.py::test_mro`` now uses -``self.assertRaises`` instead of ``try/except``. - -.. - .. bpo: 45835 .. date: 2021-11-17-14-28-08 .. nonce: Mgyhjx From webhook-mailer at python.org Sun Dec 26 05:43:12 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Sun, 26 Dec 2021 10:43:12 -0000 Subject: [Python-checkins] docs: Fix typos and use anchor for internal link (GH-30236) Message-ID: https://github.com/python/cpython/commit/c1d7a6bed9f2bb8cb7612d196fc0caba016fa98c commit: c1d7a6bed9f2bb8cb7612d196fc0caba016fa98c branch: main author: Rafael Fontenelle committer: serhiy-storchaka date: 2021-12-26T12:43:06+02:00 summary: docs: Fix typos and use anchor for internal link (GH-30236) files: M Doc/whatsnew/3.10.rst diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index b56663f5eae8b..85bb1f8838e9b 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -1437,7 +1437,7 @@ and to match the behavior of static type checkers specified in the PEP. 1. ``Literal`` now de-duplicates parameters. 2. Equality comparisons between ``Literal`` objects are now order independent. -3. ``Literal`` comparisons now respects types. For example, +3. ``Literal`` comparisons now respect types. For example, ``Literal[0] == Literal[False]`` previously evaluated to ``True``. It is now ``False``. To support this change, the internally used type cache now supports differentiating types. @@ -1647,13 +1647,12 @@ Deprecated :meth:`importlib.machinery.FrozenImporter.find_module`, :meth:`importlib.machinery.WindowsRegistryFinder.find_module`, :meth:`importlib.machinery.PathFinder.find_module`, - :meth:`importlib.abc.MetaPathFinder.find_module`), + :meth:`importlib.abc.MetaPathFinder.find_module` ), :meth:`importlib.abc.PathEntryFinder.find_module` ( - :meth:`importlib.machinery.FileFinder.find_module`, - ), and + :meth:`importlib.machinery.FileFinder.find_module` ), and :meth:`importlib.abc.PathEntryFinder.find_loader` ( - :meth:`importlib.machinery.FileFinder.find_loader` - ) now raise :exc:`DeprecationWarning` and are slated for removal in + :meth:`importlib.machinery.FileFinder.find_loader` ) + now raise :exc:`DeprecationWarning` and are slated for removal in Python 3.12 (previously they were documented as deprecated in Python 3.4). (Contributed by Brett Cannon in :issue:`42135`.) @@ -1694,7 +1693,7 @@ Deprecated * :func:`asyncio.get_event_loop` now emits a deprecation warning if there is no running event loop. In the future it will be an alias of :func:`~asyncio.get_running_loop`. - :mod:`asyncio` functions which implicitly create a :class:`~asyncio.Future` + :mod:`asyncio` functions which implicitly create :class:`~asyncio.Future` or :class:`~asyncio.Task` objects now emit a deprecation warning if there is no running event loop and no explicit *loop* argument is passed: :func:`~asyncio.ensure_future`, @@ -1834,7 +1833,7 @@ Removed running in different threads. Note that the low-level API will still accept ``loop``. - See `Changes in the Python API`_ for examples of how to replace existing code. + See :ref:`changes-python-api` for examples of how to replace existing code. (Contributed by Yurii Karabas, Andrew Svetlov, Yury Selivanov and Kyle Stanley in :issue:`42392`.) @@ -1858,6 +1857,7 @@ Changes in the Python syntax following keyword. (Contributed by Serhiy Storchaka in :issue:`43833`). +.. _changes-python-api: Changes in the Python API ------------------------- @@ -1979,7 +1979,7 @@ Build Changes (Contributed by Victor Stinner in :issue:`36020`.) * :mod:`sqlite3` requires SQLite 3.7.15 or higher. (Contributed by Sergey Fedoseev - and Erlend E. Aasland :issue:`40744` and :issue:`40810`.) + and Erlend E. Aasland in :issue:`40744` and :issue:`40810`.) * The :mod:`atexit` module must now always be built as a built-in module. (Contributed by Victor Stinner in :issue:`42639`.) From webhook-mailer at python.org Sun Dec 26 06:09:24 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Sun, 26 Dec 2021 11:09:24 -0000 Subject: [Python-checkins] doc: fix a typo in unittest.mock.rst (GH-30227) Message-ID: https://github.com/python/cpython/commit/10bf0a9ac3c9bbde2fa8989d9435462f0e7da545 commit: 10bf0a9ac3c9bbde2fa8989d9435462f0e7da545 branch: main author: Joe committer: serhiy-storchaka date: 2021-12-26T13:09:17+02:00 summary: doc: fix a typo in unittest.mock.rst (GH-30227) files: M Doc/library/unittest.mock.rst diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst index 0856c3fbded08..69f1035703ba5 100644 --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -1516,7 +1516,7 @@ attribute in a class) that does not exist will fail with :exc:`AttributeError`:: >>> test() Traceback (most recent call last): ... - AttributeError: does not have the attribute 'non_existing' + AttributeError: does not have the attribute 'non_existing_attribute' but adding ``create=True`` in the call to :func:`patch` will make the previous example work as expected:: From webhook-mailer at python.org Sun Dec 26 06:11:12 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Sun, 26 Dec 2021 11:11:12 -0000 Subject: [Python-checkins] Fix typo in io.rst (GH-30218) Message-ID: https://github.com/python/cpython/commit/f9a4352056175d96195d4cb54c97c1334ea5150c commit: f9a4352056175d96195d4cb54c97c1334ea5150c branch: main author: David Gilbertson committer: serhiy-storchaka date: 2021-12-26T13:11:08+02:00 summary: Fix typo in io.rst (GH-30218) files: M Doc/library/io.rst diff --git a/Doc/library/io.rst b/Doc/library/io.rst index 0881015c7fad6..de88c572f3662 100644 --- a/Doc/library/io.rst +++ b/Doc/library/io.rst @@ -131,7 +131,7 @@ explicitly when opening text files. If you want to use UTF-8, pass ``encoding="utf-8"``. To use the current locale encoding, ``encoding="locale"`` is supported in Python 3.10. -When you need to run existing code on Windows that attempts to opens +When you need to run existing code on Windows that attempts to open UTF-8 files using the default locale encoding, you can enable the UTF-8 mode. See :ref:`UTF-8 mode on Windows `. From webhook-mailer at python.org Sun Dec 26 06:13:18 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Sun, 26 Dec 2021 11:13:18 -0000 Subject: [Python-checkins] bpo-23819: Fix asyncio tests on python optimized mode (GH-30195) Message-ID: https://github.com/python/cpython/commit/a23ab7b6d8b3ae3a47747c0c4bceb2370cc48dcc commit: a23ab7b6d8b3ae3a47747c0c4bceb2370cc48dcc branch: main author: Kumar Aditya <59607654+kumaraditya303 at users.noreply.github.com> committer: serhiy-storchaka date: 2021-12-26T13:13:14+02:00 summary: bpo-23819: Fix asyncio tests on python optimized mode (GH-30195) files: A Misc/NEWS.d/next/Tests/2021-12-19-08-44-32.bpo-23819.9ueiII.rst M Lib/asyncio/base_events.py M Lib/test/test_asyncio/test_base_events.py M Lib/test/test_asyncio/test_proactor_events.py M Lib/test/test_asyncio/test_selector_events.py diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index cbf6d5db0a002..56ea7ba44e2ea 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -1285,8 +1285,8 @@ async def create_datagram_endpoint(self, protocol_factory, addr_infos = {} # Using order preserving dict for idx, addr in ((0, local_addr), (1, remote_addr)): if addr is not None: - assert isinstance(addr, tuple) and len(addr) == 2, ( - '2-tuple is expected') + if not (isinstance(addr, tuple) and len(addr) == 2): + raise TypeError('2-tuple is expected') infos = await self._ensure_resolved( addr, family=family, type=socket.SOCK_DGRAM, diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index 4c0d09e6f702e..3f4c2d85e0380 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -1603,11 +1603,11 @@ def test_create_datagram_endpoint_addr_error(self): coro = self.loop.create_datagram_endpoint( MyDatagramProto, local_addr='localhost') self.assertRaises( - AssertionError, self.loop.run_until_complete, coro) + TypeError, self.loop.run_until_complete, coro) coro = self.loop.create_datagram_endpoint( MyDatagramProto, local_addr=('localhost', 1, 2, 3)) self.assertRaises( - AssertionError, self.loop.run_until_complete, coro) + TypeError, self.loop.run_until_complete, coro) def test_create_datagram_endpoint_connect_err(self): self.loop.sock_connect = mock.Mock() diff --git a/Lib/test/test_asyncio/test_proactor_events.py b/Lib/test/test_asyncio/test_proactor_events.py index 4c8906d531ce5..45af8101a0093 100644 --- a/Lib/test/test_asyncio/test_proactor_events.py +++ b/Lib/test/test_asyncio/test_proactor_events.py @@ -77,6 +77,7 @@ def test_loop_reading_data(self): self.loop._proactor.recv_into.assert_called_with(self.sock, called_buf) self.protocol.data_received.assert_called_with(bytearray(buf)) + @unittest.skipIf(sys.flags.optimize, "Assertions are disabled in optimized mode") def test_loop_reading_no_data(self): res = self.loop.create_future() res.set_result(0) @@ -869,6 +870,7 @@ def test_datagram_loop_reading_data(self): self.protocol.datagram_received.assert_called_with(b'data', ('127.0.0.1', 12068)) close_transport(tr) + @unittest.skipIf(sys.flags.optimize, "Assertions are disabled in optimized mode") def test_datagram_loop_reading_no_data(self): res = self.loop.create_future() res.set_result((b'', ('127.0.0.1', 12068))) diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py index 1613c753c26ee..b684fab2771f2 100644 --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -1,5 +1,6 @@ """Tests for selector_events.py""" +import sys import selectors import socket import unittest @@ -804,6 +805,7 @@ def test_write_ready_closing(self): self.sock.close.assert_called_with() self.protocol.connection_lost.assert_called_with(None) + @unittest.skipIf(sys.flags.optimize, "Assertions are disabled in optimized mode") def test_write_ready_no_data(self): transport = self.socket_transport() # This is an internal error. diff --git a/Misc/NEWS.d/next/Tests/2021-12-19-08-44-32.bpo-23819.9ueiII.rst b/Misc/NEWS.d/next/Tests/2021-12-19-08-44-32.bpo-23819.9ueiII.rst new file mode 100644 index 0000000000000..4ef0fe6f6d5fa --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-12-19-08-44-32.bpo-23819.9ueiII.rst @@ -0,0 +1 @@ +Fixed :mod:`asyncio` tests in python optimized mode. Patch by Kumar Aditya. \ No newline at end of file From webhook-mailer at python.org Sun Dec 26 06:15:18 2021 From: webhook-mailer at python.org (miss-islington) Date: Sun, 26 Dec 2021 11:15:18 -0000 Subject: [Python-checkins] Doc: Fix link in multiprocessing.starmap pointing to builtin map. (GH-26560) Message-ID: https://github.com/python/cpython/commit/2cb9ed2a6a082972bfc496eccb320c3ae3df72df commit: 2cb9ed2a6a082972bfc496eccb320c3ae3df72df branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-26T03:15:14-08:00 summary: Doc: Fix link in multiprocessing.starmap pointing to builtin map. (GH-26560) (cherry picked from commit 32096df0e00e692ee6dc688e62213bff0dffd573) Co-authored-by: Julien Palard files: M Doc/library/multiprocessing.rst diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst index 4562128394f88..e81dd7e648f7f 100644 --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -2250,8 +2250,9 @@ with the :class:`Pool` class. .. method:: starmap(func, iterable[, chunksize]) - Like :meth:`map` except that the elements of the *iterable* are expected - to be iterables that are unpacked as arguments. + Like :meth:`~multiprocessing.pool.Pool.map` except that the + elements of the *iterable* are expected to be iterables that are + unpacked as arguments. Hence an *iterable* of ``[(1,2), (3, 4)]`` results in ``[func(1,2), func(3,4)]``. From webhook-mailer at python.org Sun Dec 26 06:15:41 2021 From: webhook-mailer at python.org (miss-islington) Date: Sun, 26 Dec 2021 11:15:41 -0000 Subject: [Python-checkins] Doc: Fix link in multiprocessing.starmap pointing to builtin map. (GH-26560) Message-ID: https://github.com/python/cpython/commit/3c1100fc59aca4bb8d0b9cdfbd439d4d2dc9651c commit: 3c1100fc59aca4bb8d0b9cdfbd439d4d2dc9651c branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-26T03:15:38-08:00 summary: Doc: Fix link in multiprocessing.starmap pointing to builtin map. (GH-26560) (cherry picked from commit 32096df0e00e692ee6dc688e62213bff0dffd573) Co-authored-by: Julien Palard files: M Doc/library/multiprocessing.rst diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst index 2c7d7d8c0e8b1..96bc6c153284a 100644 --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -2250,8 +2250,9 @@ with the :class:`Pool` class. .. method:: starmap(func, iterable[, chunksize]) - Like :meth:`map` except that the elements of the *iterable* are expected - to be iterables that are unpacked as arguments. + Like :meth:`~multiprocessing.pool.Pool.map` except that the + elements of the *iterable* are expected to be iterables that are + unpacked as arguments. Hence an *iterable* of ``[(1,2), (3, 4)]`` results in ``[func(1,2), func(3,4)]``. From webhook-mailer at python.org Sun Dec 26 06:22:48 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Sun, 26 Dec 2021 11:22:48 -0000 Subject: [Python-checkins] bpo-22815: Print unexpected successes in summary in TextTestResult (GH-30138) Message-ID: https://github.com/python/cpython/commit/1944434b44e0118e812bf63f47b268ff6dd0c8f1 commit: 1944434b44e0118e812bf63f47b268ff6dd0c8f1 branch: main author: Serhiy Storchaka committer: serhiy-storchaka date: 2021-12-26T13:22:44+02:00 summary: bpo-22815: Print unexpected successes in summary in TextTestResult (GH-30138) files: A Misc/NEWS.d/next/Library/2021-12-16-12-54-21.bpo-22815.0NRH8s.rst M Lib/unittest/runner.py M Lib/unittest/test/test_program.py diff --git a/Lib/unittest/runner.py b/Lib/unittest/runner.py index 120ee6aba3570..6678adb6a7d81 100644 --- a/Lib/unittest/runner.py +++ b/Lib/unittest/runner.py @@ -142,6 +142,12 @@ def printErrors(self): self.stream.flush() self.printErrorList('ERROR', self.errors) self.printErrorList('FAIL', self.failures) + unexpectedSuccesses = getattr(self, 'unexpectedSuccesses', ()) + if unexpectedSuccesses: + self.stream.writeln(self.separator1) + for test in unexpectedSuccesses: + self.stream.writeln(f"UNEXPECTED SUCCESS: {self.getDescription(test)}") + self.stream.flush() def printErrorList(self, flavour, errors): for test, err in errors: diff --git a/Lib/unittest/test/test_program.py b/Lib/unittest/test/test_program.py index 2bf7dd72ed21c..f7049fbb24e7b 100644 --- a/Lib/unittest/test/test_program.py +++ b/Lib/unittest/test/test_program.py @@ -61,6 +61,17 @@ def testPass(self): pass def testFail(self): raise AssertionError + def testError(self): + 1/0 + @unittest.skip('skipping') + def testSkipped(self): + raise AssertionError + @unittest.expectedFailure + def testExpectedFailure(self): + raise AssertionError + @unittest.expectedFailure + def testUnexpectedSuccess(self): + pass class FooBarLoader(unittest.TestLoader): """Test loader that returns a suite containing FooBar.""" @@ -111,9 +122,13 @@ def test_NonExit(self): testRunner=unittest.TextTestRunner(stream=stream), testLoader=self.FooBarLoader()) self.assertTrue(hasattr(program, 'result')) - self.assertIn('\nFAIL: testFail ', stream.getvalue()) - self.assertTrue(stream.getvalue().endswith('\n\nFAILED (failures=1)\n')) - + out = stream.getvalue() + self.assertIn('\nFAIL: testFail ', out) + self.assertIn('\nERROR: testError ', out) + self.assertIn('\nUNEXPECTED SUCCESS: testUnexpectedSuccess ', out) + expected = ('\n\nFAILED (failures=1, errors=1, skipped=1, ' + 'expected failures=1, unexpected successes=1)\n') + self.assertTrue(out.endswith(expected)) def test_Exit(self): stream = BufferedWriter() @@ -124,9 +139,13 @@ def test_Exit(self): testRunner=unittest.TextTestRunner(stream=stream), exit=True, testLoader=self.FooBarLoader()) - self.assertIn('\nFAIL: testFail ', stream.getvalue()) - self.assertTrue(stream.getvalue().endswith('\n\nFAILED (failures=1)\n')) - + out = stream.getvalue() + self.assertIn('\nFAIL: testFail ', out) + self.assertIn('\nERROR: testError ', out) + self.assertIn('\nUNEXPECTED SUCCESS: testUnexpectedSuccess ', out) + expected = ('\n\nFAILED (failures=1, errors=1, skipped=1, ' + 'expected failures=1, unexpected successes=1)\n') + self.assertTrue(out.endswith(expected)) def test_ExitAsDefault(self): stream = BufferedWriter() @@ -136,8 +155,13 @@ def test_ExitAsDefault(self): argv=["foobar"], testRunner=unittest.TextTestRunner(stream=stream), testLoader=self.FooBarLoader()) - self.assertIn('\nFAIL: testFail ', stream.getvalue()) - self.assertTrue(stream.getvalue().endswith('\n\nFAILED (failures=1)\n')) + out = stream.getvalue() + self.assertIn('\nFAIL: testFail ', out) + self.assertIn('\nERROR: testError ', out) + self.assertIn('\nUNEXPECTED SUCCESS: testUnexpectedSuccess ', out) + expected = ('\n\nFAILED (failures=1, errors=1, skipped=1, ' + 'expected failures=1, unexpected successes=1)\n') + self.assertTrue(out.endswith(expected)) class InitialisableProgram(unittest.TestProgram): diff --git a/Misc/NEWS.d/next/Library/2021-12-16-12-54-21.bpo-22815.0NRH8s.rst b/Misc/NEWS.d/next/Library/2021-12-16-12-54-21.bpo-22815.0NRH8s.rst new file mode 100644 index 0000000000000..5c4600f316ac3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-16-12-54-21.bpo-22815.0NRH8s.rst @@ -0,0 +1,2 @@ +Print unexpected successes together with failures and errors in summary in +:class:`unittest.TextTestResult`. From webhook-mailer at python.org Sun Dec 26 06:26:02 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Sun, 26 Dec 2021 11:26:02 -0000 Subject: [Python-checkins] [3.9] Remove a NEWS entry for bpo-45878 (GH-30258) (GH-30260) Message-ID: https://github.com/python/cpython/commit/bee660e46ae2a051400177dcd758d95b5b4a6fcc commit: bee660e46ae2a051400177dcd758d95b5b4a6fcc branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: serhiy-storchaka date: 2021-12-26T13:25:49+02:00 summary: [3.9] Remove a NEWS entry for bpo-45878 (GH-30258) (GH-30260) The docs linter complains about it, and in general news entries for such changes are not required. (cherry picked from commit 11909c12c75a7f377460561abc97707a4006fc07) Co-authored-by: Serhiy Storchaka files: D Misc/NEWS.d/next/Tests/2021-11-23-12-36-21.bpo-45878.eOs_Mp.rst diff --git a/Misc/NEWS.d/next/Tests/2021-11-23-12-36-21.bpo-45878.eOs_Mp.rst b/Misc/NEWS.d/next/Tests/2021-11-23-12-36-21.bpo-45878.eOs_Mp.rst deleted file mode 100644 index fca90ef46981b..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-11-23-12-36-21.bpo-45878.eOs_Mp.rst +++ /dev/null @@ -1,2 +0,0 @@ -Test ``Lib/ctypes/test/test_functions.py::test_mro`` now uses -``self.assertRaises`` instead of ``try/except``. From webhook-mailer at python.org Sun Dec 26 06:27:07 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Sun, 26 Dec 2021 11:27:07 -0000 Subject: [Python-checkins] bpo-43413: Revert changes in set.__init__ (GH-28403) Message-ID: https://github.com/python/cpython/commit/ad4857884b4821fc2c9bd23b63d03f9570eb03d1 commit: ad4857884b4821fc2c9bd23b63d03f9570eb03d1 branch: main author: Serhiy Storchaka committer: serhiy-storchaka date: 2021-12-26T13:27:01+02:00 summary: bpo-43413: Revert changes in set.__init__ (GH-28403) Co-authored-by: Jason R. Coombs files: A Misc/NEWS.d/next/Core and Builtins/2021-05-30-16-37-47.bpo-43413.vYFPPC1.rst M Lib/test/test_set.py M Misc/NEWS.d/3.11.0a1.rst M Objects/setobject.c diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py index 65fda9e469bcc..77f3da40c063a 100644 --- a/Lib/test/test_set.py +++ b/Lib/test/test_set.py @@ -667,10 +667,13 @@ def __new__(cls, arg, newarg=None): self = super().__new__(cls, arg) self.newarg = newarg return self - u = subclass_with_new([1, 2], newarg=3) + u = subclass_with_new([1, 2]) self.assertIs(type(u), subclass_with_new) self.assertEqual(set(u), {1, 2}) - self.assertEqual(u.newarg, 3) + self.assertIsNone(u.newarg) + # disallow kwargs in __new__ only (https://bugs.python.org/issue43413#msg402000) + with self.assertRaises(TypeError): + subclass_with_new([1, 2], newarg=3) class TestFrozenSet(TestJointOps, unittest.TestCase): diff --git a/Misc/NEWS.d/3.11.0a1.rst b/Misc/NEWS.d/3.11.0a1.rst index 28b81b75266fc..fa30c693c34c1 100644 --- a/Misc/NEWS.d/3.11.0a1.rst +++ b/Misc/NEWS.d/3.11.0a1.rst @@ -1140,7 +1140,7 @@ blocks. Patch by Pablo Galindo. Constructors of subclasses of some builtin classes (e.g. :class:`tuple`, :class:`list`, :class:`frozenset`) no longer accept arbitrary keyword -arguments. Subclass of :class:`set` can now define a ``__new__()`` method +arguments. [reverted in 3.11a4] Subclass of :class:`set` can now define a ``__new__()`` method with additional keyword parameters without overriding also ``__init__()``. .. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-05-30-16-37-47.bpo-43413.vYFPPC1.rst b/Misc/NEWS.d/next/Core and Builtins/2021-05-30-16-37-47.bpo-43413.vYFPPC1.rst new file mode 100644 index 0000000000000..cf879eceeb721 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-05-30-16-37-47.bpo-43413.vYFPPC1.rst @@ -0,0 +1 @@ +Revert changes in ``set.__init__``. Subclass of :class:`set` needs to define a ``__init__()`` method if it defines a ``__new__()`` method with additional keyword parameters. diff --git a/Objects/setobject.c b/Objects/setobject.c index 0be067857d694..6e110ef196c82 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -1946,9 +1946,7 @@ set_init(PySetObject *self, PyObject *args, PyObject *kwds) { PyObject *iterable = NULL; - if ((Py_IS_TYPE(self, &PySet_Type) || - Py_TYPE(self)->tp_new == PySet_Type.tp_new) && - !_PyArg_NoKeywords("set", kwds)) + if (!_PyArg_NoKeywords("set", kwds)) return -1; if (!PyArg_UnpackTuple(args, Py_TYPE(self)->tp_name, 0, 1, &iterable)) return -1; From webhook-mailer at python.org Sun Dec 26 06:28:28 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Sun, 26 Dec 2021 11:28:28 -0000 Subject: [Python-checkins] bpo-45496: Allow flexibility in winfo_rgb tests (GH-30185) Message-ID: https://github.com/python/cpython/commit/2e3e0d23adca8d83722d939d6abd1e467d7578f7 commit: 2e3e0d23adca8d83722d939d6abd1e467d7578f7 branch: main author: E-Paine <63801254+E-Paine at users.noreply.github.com> committer: serhiy-storchaka date: 2021-12-26T13:28:24+02:00 summary: bpo-45496: Allow flexibility in winfo_rgb tests (GH-30185) files: M Lib/tkinter/test/test_tkinter/test_misc.py diff --git a/Lib/tkinter/test/test_tkinter/test_misc.py b/Lib/tkinter/test/test_tkinter/test_misc.py index 2c78eaca2c85b..044eb10d68835 100644 --- a/Lib/tkinter/test/test_tkinter/test_misc.py +++ b/Lib/tkinter/test/test_tkinter/test_misc.py @@ -201,6 +201,13 @@ def test_clipboard_astral(self): root.clipboard_get() def test_winfo_rgb(self): + + def assertApprox(col1, col2): + # A small amount of flexibility is required (bpo-45496) + # 33 is ~0.05% of 65535, which is a reasonable margin + for col1_channel, col2_channel in zip(col1, col2): + self.assertAlmostEqual(col1_channel, col2_channel, delta=33) + root = self.root rgb = root.winfo_rgb @@ -210,9 +217,9 @@ def test_winfo_rgb(self): # #RGB - extends each 4-bit hex value to be 16-bit. self.assertEqual(rgb('#F0F'), (0xFFFF, 0x0000, 0xFFFF)) # #RRGGBB - extends each 8-bit hex value to be 16-bit. - self.assertEqual(rgb('#4a3c8c'), (0x4a4a, 0x3c3c, 0x8c8c)) + assertApprox(rgb('#4a3c8c'), (0x4a4a, 0x3c3c, 0x8c8c)) # #RRRRGGGGBBBB - self.assertEqual(rgb('#dede14143939'), (0xdede, 0x1414, 0x3939)) + assertApprox(rgb('#dede14143939'), (0xdede, 0x1414, 0x3939)) # Invalid string. with self.assertRaises(tkinter.TclError): rgb('#123456789a') From webhook-mailer at python.org Sun Dec 26 06:30:03 2021 From: webhook-mailer at python.org (miss-islington) Date: Sun, 26 Dec 2021 11:30:03 -0000 Subject: [Python-checkins] docs: Fix typos and use anchor for internal link (GH-30236) Message-ID: https://github.com/python/cpython/commit/d968e422efa2050ff2c88467e7cea61ba5c55576 commit: d968e422efa2050ff2c88467e7cea61ba5c55576 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-26T03:29:58-08:00 summary: docs: Fix typos and use anchor for internal link (GH-30236) (cherry picked from commit c1d7a6bed9f2bb8cb7612d196fc0caba016fa98c) Co-authored-by: Rafael Fontenelle files: M Doc/whatsnew/3.10.rst diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index 978651f33b206..c07523c49163b 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -1426,7 +1426,7 @@ and to match the behavior of static type checkers specified in the PEP. 1. ``Literal`` now de-duplicates parameters. 2. Equality comparisons between ``Literal`` objects are now order independent. -3. ``Literal`` comparisons now respects types. For example, +3. ``Literal`` comparisons now respect types. For example, ``Literal[0] == Literal[False]`` previously evaluated to ``True``. It is now ``False``. To support this change, the internally used type cache now supports differentiating types. @@ -1643,13 +1643,12 @@ Deprecated :meth:`importlib.machinery.FrozenImporter.find_module`, :meth:`importlib.machinery.WindowsRegistryFinder.find_module`, :meth:`importlib.machinery.PathFinder.find_module`, - :meth:`importlib.abc.MetaPathFinder.find_module`), + :meth:`importlib.abc.MetaPathFinder.find_module` ), :meth:`importlib.abc.PathEntryFinder.find_module` ( - :meth:`importlib.machinery.FileFinder.find_module`, - ), and + :meth:`importlib.machinery.FileFinder.find_module` ), and :meth:`importlib.abc.PathEntryFinder.find_loader` ( - :meth:`importlib.machinery.FileFinder.find_loader` - ) now raise :exc:`DeprecationWarning` and are slated for removal in + :meth:`importlib.machinery.FileFinder.find_loader` ) + now raise :exc:`DeprecationWarning` and are slated for removal in Python 3.12 (previously they were documented as deprecated in Python 3.4). (Contributed by Brett Cannon in :issue:`42135`.) @@ -1690,7 +1689,7 @@ Deprecated * :func:`asyncio.get_event_loop` now emits a deprecation warning if there is no running event loop. In the future it will be an alias of :func:`~asyncio.get_running_loop`. - :mod:`asyncio` functions which implicitly create a :class:`~asyncio.Future` + :mod:`asyncio` functions which implicitly create :class:`~asyncio.Future` or :class:`~asyncio.Task` objects now emit a deprecation warning if there is no running event loop and no explicit *loop* argument is passed: :func:`~asyncio.ensure_future`, @@ -1830,7 +1829,7 @@ Removed running in different threads. Note that the low-level API will still accept ``loop``. - See `Changes in the Python API`_ for examples of how to replace existing code. + See :ref:`changes-python-api` for examples of how to replace existing code. (Contributed by Yurii Karabas, Andrew Svetlov, Yury Selivanov and Kyle Stanley in :issue:`42392`.) @@ -1854,6 +1853,7 @@ Changes in the Python syntax following keyword. (Contributed by Serhiy Storchaka in :issue:`43833`). +.. _changes-python-api: Changes in the Python API ------------------------- @@ -1975,7 +1975,7 @@ Build Changes (Contributed by Victor Stinner in :issue:`36020`.) * :mod:`sqlite3` requires SQLite 3.7.15 or higher. (Contributed by Sergey Fedoseev - and Erlend E. Aasland :issue:`40744` and :issue:`40810`.) + and Erlend E. Aasland in :issue:`40744` and :issue:`40810`.) * The :mod:`atexit` module must now always be built as a built-in module. (Contributed by Victor Stinner in :issue:`42639`.) From webhook-mailer at python.org Sun Dec 26 06:51:55 2021 From: webhook-mailer at python.org (miss-islington) Date: Sun, 26 Dec 2021 11:51:55 -0000 Subject: [Python-checkins] doc: fix a typo in unittest.mock.rst (GH-30227) Message-ID: https://github.com/python/cpython/commit/cfdb2302f48b4da5cf4ee78c092edf1f447ae494 commit: cfdb2302f48b4da5cf4ee78c092edf1f447ae494 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-26T03:51:42-08:00 summary: doc: fix a typo in unittest.mock.rst (GH-30227) (cherry picked from commit 10bf0a9ac3c9bbde2fa8989d9435462f0e7da545) Co-authored-by: Joe files: M Doc/library/unittest.mock.rst diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst index d0640b42ef40a..4d74f9cee84ee 100644 --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -1516,7 +1516,7 @@ attribute in a class) that does not exist will fail with :exc:`AttributeError`:: >>> test() Traceback (most recent call last): ... - AttributeError: does not have the attribute 'non_existing' + AttributeError: does not have the attribute 'non_existing_attribute' but adding ``create=True`` in the call to :func:`patch` will make the previous example work as expected:: From webhook-mailer at python.org Sun Dec 26 06:52:01 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Sun, 26 Dec 2021 11:52:01 -0000 Subject: [Python-checkins] doc: fix a typo in unittest.mock.rst (GH-30227) (GH-30263) Message-ID: https://github.com/python/cpython/commit/f1f54c8fb94de6176767f2163a4ed80a9660494a commit: f1f54c8fb94de6176767f2163a4ed80a9660494a branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: serhiy-storchaka date: 2021-12-26T13:51:57+02:00 summary: doc: fix a typo in unittest.mock.rst (GH-30227) (GH-30263) (cherry picked from commit 10bf0a9ac3c9bbde2fa8989d9435462f0e7da545) Co-authored-by: Joe files: M Doc/library/unittest.mock.rst diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst index 3c74b61779d47..3fbb1b6b83a76 100644 --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -1515,7 +1515,7 @@ attribute in a class) that does not exist will fail with :exc:`AttributeError`:: >>> test() Traceback (most recent call last): ... - AttributeError: does not have the attribute 'non_existing' + AttributeError: does not have the attribute 'non_existing_attribute' but adding ``create=True`` in the call to :func:`patch` will make the previous example work as expected:: From webhook-mailer at python.org Sun Dec 26 06:52:50 2021 From: webhook-mailer at python.org (miss-islington) Date: Sun, 26 Dec 2021 11:52:50 -0000 Subject: [Python-checkins] Fix typo in io.rst (GH-30218) Message-ID: https://github.com/python/cpython/commit/a55082085cbc59733ecc932cc2e7d544be8c6a7d commit: a55082085cbc59733ecc932cc2e7d544be8c6a7d branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-26T03:52:46-08:00 summary: Fix typo in io.rst (GH-30218) (cherry picked from commit f9a4352056175d96195d4cb54c97c1334ea5150c) Co-authored-by: David Gilbertson files: M Doc/library/io.rst diff --git a/Doc/library/io.rst b/Doc/library/io.rst index 0881015c7fad6..de88c572f3662 100644 --- a/Doc/library/io.rst +++ b/Doc/library/io.rst @@ -131,7 +131,7 @@ explicitly when opening text files. If you want to use UTF-8, pass ``encoding="utf-8"``. To use the current locale encoding, ``encoding="locale"`` is supported in Python 3.10. -When you need to run existing code on Windows that attempts to opens +When you need to run existing code on Windows that attempts to open UTF-8 files using the default locale encoding, you can enable the UTF-8 mode. See :ref:`UTF-8 mode on Windows `. From webhook-mailer at python.org Sun Dec 26 06:54:22 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Sun, 26 Dec 2021 11:54:22 -0000 Subject: [Python-checkins] [3.9] bpo-23819: Fix asyncio tests on python optimized mode (GH-30195) (GH-30265) Message-ID: https://github.com/python/cpython/commit/07229054a129a72b4ffdf29252eb73c6154c0ccf commit: 07229054a129a72b4ffdf29252eb73c6154c0ccf branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: serhiy-storchaka date: 2021-12-26T13:54:18+02:00 summary: [3.9] bpo-23819: Fix asyncio tests on python optimized mode (GH-30195) (GH-30265) (cherry picked from commit a23ab7b6d8b3ae3a47747c0c4bceb2370cc48dcc) Co-authored-by: Kumar Aditya <59607654+kumaraditya303 at users.noreply.github.com> files: A Misc/NEWS.d/next/Tests/2021-12-19-08-44-32.bpo-23819.9ueiII.rst M Lib/asyncio/base_events.py M Lib/test/test_asyncio/test_base_events.py M Lib/test/test_asyncio/test_proactor_events.py M Lib/test/test_asyncio/test_selector_events.py diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index bb2f99150b115..8c1fb49694875 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -1290,8 +1290,8 @@ async def create_datagram_endpoint(self, protocol_factory, addr_infos = {} # Using order preserving dict for idx, addr in ((0, local_addr), (1, remote_addr)): if addr is not None: - assert isinstance(addr, tuple) and len(addr) == 2, ( - '2-tuple is expected') + if not (isinstance(addr, tuple) and len(addr) == 2): + raise TypeError('2-tuple is expected') infos = await self._ensure_resolved( addr, family=family, type=socket.SOCK_DGRAM, diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index 533d5cc7f5038..4886da28bdf14 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -1592,11 +1592,11 @@ def test_create_datagram_endpoint_addr_error(self): coro = self.loop.create_datagram_endpoint( MyDatagramProto, local_addr='localhost') self.assertRaises( - AssertionError, self.loop.run_until_complete, coro) + TypeError, self.loop.run_until_complete, coro) coro = self.loop.create_datagram_endpoint( MyDatagramProto, local_addr=('localhost', 1, 2, 3)) self.assertRaises( - AssertionError, self.loop.run_until_complete, coro) + TypeError, self.loop.run_until_complete, coro) def test_create_datagram_endpoint_connect_err(self): self.loop.sock_connect = mock.Mock() diff --git a/Lib/test/test_asyncio/test_proactor_events.py b/Lib/test/test_asyncio/test_proactor_events.py index 451f86ae0274f..59d5e5b6ccb63 100644 --- a/Lib/test/test_asyncio/test_proactor_events.py +++ b/Lib/test/test_asyncio/test_proactor_events.py @@ -72,6 +72,7 @@ def test_loop_reading_data(self): self.loop._proactor.recv.assert_called_with(self.sock, 32768) self.protocol.data_received.assert_called_with(b'data') + @unittest.skipIf(sys.flags.optimize, "Assertions are disabled in optimized mode") def test_loop_reading_no_data(self): res = self.loop.create_future() res.set_result(b'') @@ -853,6 +854,7 @@ def test_datagram_loop_reading_data(self): self.protocol.datagram_received.assert_called_with(b'data', ('127.0.0.1', 12068)) close_transport(tr) + @unittest.skipIf(sys.flags.optimize, "Assertions are disabled in optimized mode") def test_datagram_loop_reading_no_data(self): res = self.loop.create_future() res.set_result((b'', ('127.0.0.1', 12068))) diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py index 1613c753c26ee..b684fab2771f2 100644 --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -1,5 +1,6 @@ """Tests for selector_events.py""" +import sys import selectors import socket import unittest @@ -804,6 +805,7 @@ def test_write_ready_closing(self): self.sock.close.assert_called_with() self.protocol.connection_lost.assert_called_with(None) + @unittest.skipIf(sys.flags.optimize, "Assertions are disabled in optimized mode") def test_write_ready_no_data(self): transport = self.socket_transport() # This is an internal error. diff --git a/Misc/NEWS.d/next/Tests/2021-12-19-08-44-32.bpo-23819.9ueiII.rst b/Misc/NEWS.d/next/Tests/2021-12-19-08-44-32.bpo-23819.9ueiII.rst new file mode 100644 index 0000000000000..4ef0fe6f6d5fa --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-12-19-08-44-32.bpo-23819.9ueiII.rst @@ -0,0 +1 @@ +Fixed :mod:`asyncio` tests in python optimized mode. Patch by Kumar Aditya. \ No newline at end of file From webhook-mailer at python.org Sun Dec 26 07:04:31 2021 From: webhook-mailer at python.org (miss-islington) Date: Sun, 26 Dec 2021 12:04:31 -0000 Subject: [Python-checkins] bpo-45496: Allow flexibility in winfo_rgb tests (GH-30185) Message-ID: https://github.com/python/cpython/commit/bb0b5c12419b8fa657c96185d62212aea975f500 commit: bb0b5c12419b8fa657c96185d62212aea975f500 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-26T04:04:26-08:00 summary: bpo-45496: Allow flexibility in winfo_rgb tests (GH-30185) (cherry picked from commit 2e3e0d23adca8d83722d939d6abd1e467d7578f7) Co-authored-by: E-Paine <63801254+E-Paine at users.noreply.github.com> files: M Lib/tkinter/test/test_tkinter/test_misc.py diff --git a/Lib/tkinter/test/test_tkinter/test_misc.py b/Lib/tkinter/test/test_tkinter/test_misc.py index b9201f1070940..8898a74c46f13 100644 --- a/Lib/tkinter/test/test_tkinter/test_misc.py +++ b/Lib/tkinter/test/test_tkinter/test_misc.py @@ -200,6 +200,13 @@ def test_clipboard_astral(self): root.clipboard_get() def test_winfo_rgb(self): + + def assertApprox(col1, col2): + # A small amount of flexibility is required (bpo-45496) + # 33 is ~0.05% of 65535, which is a reasonable margin + for col1_channel, col2_channel in zip(col1, col2): + self.assertAlmostEqual(col1_channel, col2_channel, delta=33) + root = self.root rgb = root.winfo_rgb @@ -209,9 +216,9 @@ def test_winfo_rgb(self): # #RGB - extends each 4-bit hex value to be 16-bit. self.assertEqual(rgb('#F0F'), (0xFFFF, 0x0000, 0xFFFF)) # #RRGGBB - extends each 8-bit hex value to be 16-bit. - self.assertEqual(rgb('#4a3c8c'), (0x4a4a, 0x3c3c, 0x8c8c)) + assertApprox(rgb('#4a3c8c'), (0x4a4a, 0x3c3c, 0x8c8c)) # #RRRRGGGGBBBB - self.assertEqual(rgb('#dede14143939'), (0xdede, 0x1414, 0x3939)) + assertApprox(rgb('#dede14143939'), (0xdede, 0x1414, 0x3939)) # Invalid string. with self.assertRaises(tkinter.TclError): rgb('#123456789a') From webhook-mailer at python.org Sun Dec 26 07:23:32 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Sun, 26 Dec 2021 12:23:32 -0000 Subject: [Python-checkins] [3.9] bpo-46032: Check types in singledispatch's register() at declaration time (GH-30050) (GH-30254) (GH-30255) Message-ID: https://github.com/python/cpython/commit/25a12aac4de819745dfc64664ba183a5784b5a81 commit: 25a12aac4de819745dfc64664ba183a5784b5a81 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: serhiy-storchaka date: 2021-12-26T14:23:23+02:00 summary: [3.9] bpo-46032: Check types in singledispatch's register() at declaration time (GH-30050) (GH-30254) (GH-30255) The registry() method of functools.singledispatch() functions checks now the first argument or the first parameter annotation and raises a TypeError if it is not supported. Previously unsupported "types" were ignored (e.g. typing.List[int]) or caused an error at calling time (e.g. list[int]). (cherry picked from commit 078abb676cf759b1e960f78390b6e80f256f0255) (cherry picked from commit 03c7449fbc7c57f5e0365f234a0b65c1dde763f2) Co-authored-by: Serhiy Storchaka files: A Misc/NEWS.d/next/Library/2021-12-11-15-45-07.bpo-46032.HmciLT.rst M Lib/functools.py M Lib/test/test_functools.py diff --git a/Lib/functools.py b/Lib/functools.py index 1a290e1c02461..77e5035ebcc9d 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -739,6 +739,7 @@ def _compose_mro(cls, types): # Remove entries which are already present in the __mro__ or unrelated. def is_related(typ): return (typ not in bases and hasattr(typ, '__mro__') + and not isinstance(typ, GenericAlias) and issubclass(cls, typ)) types = [n for n in types if is_related(n)] # Remove entries which are strict bases of other entries (they will end up @@ -836,6 +837,9 @@ def dispatch(cls): dispatch_cache[cls] = impl return impl + def _is_valid_dispatch_type(cls): + return isinstance(cls, type) and not isinstance(cls, GenericAlias) + def register(cls, func=None): """generic_func.register(cls, func) -> func @@ -843,9 +847,15 @@ def register(cls, func=None): """ nonlocal cache_token - if func is None: - if isinstance(cls, type): + if _is_valid_dispatch_type(cls): + if func is None: return lambda f: register(cls, f) + else: + if func is not None: + raise TypeError( + f"Invalid first argument to `register()`. " + f"{cls!r} is not a class." + ) ann = getattr(cls, '__annotations__', {}) if not ann: raise TypeError( @@ -858,11 +868,12 @@ def register(cls, func=None): # only import typing if annotation parsing is necessary from typing import get_type_hints argname, cls = next(iter(get_type_hints(func).items())) - if not isinstance(cls, type): + if not _is_valid_dispatch_type(cls): raise TypeError( f"Invalid annotation for {argname!r}. " f"{cls!r} is not a class." ) + registry[cls] = func if cache_token is None and hasattr(cls, '__abstractmethods__'): cache_token = get_cache_token() diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index b2a7e5a88b422..d7dec3f3d2756 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -2560,7 +2560,7 @@ def decorated_classmethod(cls, arg: int) -> str: self.assertEqual(without_single_dispatch_foo, single_dispatch_foo) self.assertEqual(single_dispatch_foo, '5') - + self.assertEqual( WithoutSingleDispatch.decorated_classmethod(5), WithSingleDispatch.decorated_classmethod(5) @@ -2655,6 +2655,74 @@ def f(*args): with self.assertRaisesRegex(TypeError, msg): f() + def test_register_genericalias(self): + @functools.singledispatch + def f(arg): + return "default" + + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(list[int], lambda arg: "types.GenericAlias") + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(typing.List[int], lambda arg: "typing.GenericAlias") + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(typing.Union[list[int], str], lambda arg: "typing.Union[types.GenericAlias]") + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(typing.Union[typing.List[float], bytes], lambda arg: "typing.Union[typing.GenericAlias]") + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(typing.Any, lambda arg: "typing.Any") + + self.assertEqual(f([1]), "default") + self.assertEqual(f([1.0]), "default") + self.assertEqual(f(""), "default") + self.assertEqual(f(b""), "default") + + def test_register_genericalias_decorator(self): + @functools.singledispatch + def f(arg): + return "default" + + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(list[int]) + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(typing.List[int]) + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(typing.Union[list[int], str]) + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(typing.Union[typing.List[int], str]) + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(typing.Any) + + def test_register_genericalias_annotation(self): + @functools.singledispatch + def f(arg): + return "default" + + with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"): + @f.register + def _(arg: list[int]): + return "types.GenericAlias" + with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"): + @f.register + def _(arg: typing.List[float]): + return "typing.GenericAlias" + with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"): + @f.register + def _(arg: typing.Union[list[int], str]): + return "types.UnionType(types.GenericAlias)" + with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"): + @f.register + def _(arg: typing.Union[typing.List[float], bytes]): + return "typing.Union[typing.GenericAlias]" + with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"): + @f.register + def _(arg: typing.Any): + return "typing.Any" + + self.assertEqual(f([1]), "default") + self.assertEqual(f([1.0]), "default") + self.assertEqual(f(""), "default") + self.assertEqual(f(b""), "default") + class CachedCostItem: _cost = 1 diff --git a/Misc/NEWS.d/next/Library/2021-12-11-15-45-07.bpo-46032.HmciLT.rst b/Misc/NEWS.d/next/Library/2021-12-11-15-45-07.bpo-46032.HmciLT.rst new file mode 100644 index 0000000000000..97a553d7ba29f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-11-15-45-07.bpo-46032.HmciLT.rst @@ -0,0 +1,5 @@ +The ``registry()`` method of :func:`functools.singledispatch` functions +checks now the first argument or the first parameter annotation and raises a +TypeError if it is not supported. Previously unsupported "types" were +ignored (e.g. ``typing.List[int]``) or caused an error at calling time (e.g. +``list[int]``). From webhook-mailer at python.org Sun Dec 26 07:27:37 2021 From: webhook-mailer at python.org (miss-islington) Date: Sun, 26 Dec 2021 12:27:37 -0000 Subject: [Python-checkins] bpo-45496: Allow flexibility in winfo_rgb tests (GH-30185) Message-ID: https://github.com/python/cpython/commit/aa056ed472e9d0a79ea21784f6f5171d12a13f85 commit: aa056ed472e9d0a79ea21784f6f5171d12a13f85 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-26T04:27:29-08:00 summary: bpo-45496: Allow flexibility in winfo_rgb tests (GH-30185) (cherry picked from commit 2e3e0d23adca8d83722d939d6abd1e467d7578f7) Co-authored-by: E-Paine <63801254+E-Paine at users.noreply.github.com> files: M Lib/tkinter/test/test_tkinter/test_misc.py diff --git a/Lib/tkinter/test/test_tkinter/test_misc.py b/Lib/tkinter/test/test_tkinter/test_misc.py index 554ae74d6b415..43ffd46bf0ba0 100644 --- a/Lib/tkinter/test/test_tkinter/test_misc.py +++ b/Lib/tkinter/test/test_tkinter/test_misc.py @@ -193,6 +193,13 @@ def test_clipboard_astral(self): root.clipboard_get() def test_winfo_rgb(self): + + def assertApprox(col1, col2): + # A small amount of flexibility is required (bpo-45496) + # 33 is ~0.05% of 65535, which is a reasonable margin + for col1_channel, col2_channel in zip(col1, col2): + self.assertAlmostEqual(col1_channel, col2_channel, delta=33) + root = self.root rgb = root.winfo_rgb @@ -202,9 +209,9 @@ def test_winfo_rgb(self): # #RGB - extends each 4-bit hex value to be 16-bit. self.assertEqual(rgb('#F0F'), (0xFFFF, 0x0000, 0xFFFF)) # #RRGGBB - extends each 8-bit hex value to be 16-bit. - self.assertEqual(rgb('#4a3c8c'), (0x4a4a, 0x3c3c, 0x8c8c)) + assertApprox(rgb('#4a3c8c'), (0x4a4a, 0x3c3c, 0x8c8c)) # #RRRRGGGGBBBB - self.assertEqual(rgb('#dede14143939'), (0xdede, 0x1414, 0x3939)) + assertApprox(rgb('#dede14143939'), (0xdede, 0x1414, 0x3939)) # Invalid string. with self.assertRaises(tkinter.TclError): rgb('#123456789a') From webhook-mailer at python.org Mon Dec 27 11:16:00 2021 From: webhook-mailer at python.org (ambv) Date: Mon, 27 Dec 2021 16:16:00 -0000 Subject: [Python-checkins] bpo-42918: Improve built-in function compile() in mode 'single' (GH-29934) (GH-30040) Message-ID: https://github.com/python/cpython/commit/576e38f9db61ca09ca6dc57ad13b02a7bf9d370a commit: 576e38f9db61ca09ca6dc57ad13b02a7bf9d370a branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-12-27T17:15:44+01:00 summary: bpo-42918: Improve built-in function compile() in mode 'single' (GH-29934) (GH-30040) Co-authored-by: Alex Waygood (cherry picked from commit 28179aac796ed1debdce336c4b8ca18e8475d40d) Co-authored-by: Weipeng Hong files: A Misc/NEWS.d/next/Core and Builtins/2021-12-06-15-32-12.bpo-42918.Czpgtg.rst M Lib/test/test_compile.py M Parser/pegen.c diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index 4de54488d84b6..5f80a583450ea 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -502,6 +502,7 @@ def test_single_statement(self): self.compile_single("if x:\n f(x)") self.compile_single("if x:\n f(x)\nelse:\n g(x)") self.compile_single("class T:\n pass") + self.compile_single("c = '''\na=1\nb=2\nc=3\n'''") def test_bad_single_statement(self): self.assertInvalidSingle('1\n2') @@ -512,6 +513,7 @@ def test_bad_single_statement(self): self.assertInvalidSingle('f()\n# blah\nblah()') self.assertInvalidSingle('f()\nxy # blah\nblah()') self.assertInvalidSingle('x = 5 # comment\nx = 6\n') + self.assertInvalidSingle("c = '''\nd=1\n'''\na = 1\n\nb = 2\n") def test_particularly_evil_undecodable(self): # Issue 24022 diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-06-15-32-12.bpo-42918.Czpgtg.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-06-15-32-12.bpo-42918.Czpgtg.rst new file mode 100644 index 0000000000000..f03dadebcf3b3 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-06-15-32-12.bpo-42918.Czpgtg.rst @@ -0,0 +1,3 @@ +Fix bug where the built-in :func:`compile` function did not always raise a +:exc:`SyntaxError` when passed multiple statements in 'single' mode. Patch by +Weipeng Hong. diff --git a/Parser/pegen.c b/Parser/pegen.c index bae073cb5b347..0504906c947d0 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -1131,31 +1131,13 @@ _PyPegen_number_token(Parser *p) t->end_col_offset, p->arena); } -static int // bool -newline_in_string(Parser *p, const char *cur) -{ - for (const char *c = cur; c >= p->tok->buf; c--) { - if (*c == '\'' || *c == '"') { - return 1; - } - } - return 0; -} - /* Check that the source for a single input statement really is a single statement by looking at what is left in the buffer after parsing. Trailing whitespace and comments are OK. */ static int // bool bad_single_statement(Parser *p) { - const char *cur = strchr(p->tok->buf, '\n'); - - /* Newlines are allowed if preceded by a line continuation character - or if they appear inside a string. */ - if (!cur || (cur != p->tok->buf && *(cur - 1) == '\\') - || newline_in_string(p, cur)) { - return 0; - } + char *cur = p->tok->cur; char c = *cur; for (;;) { From webhook-mailer at python.org Mon Dec 27 13:04:57 2021 From: webhook-mailer at python.org (mdickinson) Date: Mon, 27 Dec 2021 18:04:57 -0000 Subject: [Python-checkins] bpo-46055: Streamline inner loop for right shifts (#30243) Message-ID: https://github.com/python/cpython/commit/360fedc2d2ce6ccb0dab554ef45fe83f7aea1862 commit: 360fedc2d2ce6ccb0dab554ef45fe83f7aea1862 branch: main author: Mark Dickinson committer: mdickinson date: 2021-12-27T18:04:36Z summary: bpo-46055: Streamline inner loop for right shifts (#30243) files: M Objects/longobject.c diff --git a/Objects/longobject.c b/Objects/longobject.c index 77434e67642f5..ddb3def402cdd 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -4491,7 +4491,7 @@ long_rshift1(PyLongObject *a, Py_ssize_t wordshift, digit remshift) { PyLongObject *z = NULL; Py_ssize_t newsize, hishift, i, j; - digit lomask, himask; + twodigits accum; if (Py_SIZE(a) < 0) { /* Right shifting negative numbers is harder */ @@ -4511,16 +4511,17 @@ long_rshift1(PyLongObject *a, Py_ssize_t wordshift, digit remshift) if (newsize <= 0) return PyLong_FromLong(0); hishift = PyLong_SHIFT - remshift; - lomask = ((digit)1 << hishift) - 1; - himask = PyLong_MASK ^ lomask; z = _PyLong_New(newsize); if (z == NULL) return NULL; - for (i = 0, j = wordshift; i < newsize; i++, j++) { - z->ob_digit[i] = (a->ob_digit[j] >> remshift) & lomask; - if (i+1 < newsize) - z->ob_digit[i] |= (a->ob_digit[j+1] << hishift) & himask; + j = wordshift; + accum = a->ob_digit[j++] >> remshift; + for (i = 0; j < Py_SIZE(a); i++, j++) { + accum |= (twodigits)a->ob_digit[j] << hishift; + z->ob_digit[i] = (digit)(accum & PyLong_MASK); + accum >>= PyLong_SHIFT; } + z->ob_digit[i] = (digit)accum; z = maybe_small_long(long_normalize(z)); } return (PyObject *)z; From webhook-mailer at python.org Mon Dec 27 13:37:01 2021 From: webhook-mailer at python.org (mdickinson) Date: Mon, 27 Dec 2021 18:37:01 -0000 Subject: [Python-checkins] bpo-46055: Speed up binary shifting operators (GH-30044) Message-ID: https://github.com/python/cpython/commit/3581c7abbe15bad6ae08fc38887e5948f8f39e08 commit: 3581c7abbe15bad6ae08fc38887e5948f8f39e08 branch: main author: Xinhang Xu committer: mdickinson date: 2021-12-27T18:36:55Z summary: bpo-46055: Speed up binary shifting operators (GH-30044) Co-authored-by: Mark Dickinson files: A Misc/NEWS.d/next/Core and Builtins/2021-12-24-20-21-45.bpo-46055.R0QMVQ.rst M Lib/test/test_long.py M Misc/ACKS M Objects/longobject.c diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py index e5c4d7fc4220f..3c8e9e22e17a1 100644 --- a/Lib/test/test_long.py +++ b/Lib/test/test_long.py @@ -946,8 +946,13 @@ def test_huge_lshift(self, size): self.assertEqual(1 << (sys.maxsize + 1000), 1 << 1000 << sys.maxsize) def test_huge_rshift(self): - self.assertEqual(42 >> (1 << 1000), 0) - self.assertEqual((-42) >> (1 << 1000), -1) + huge_shift = 1 << 1000 + self.assertEqual(42 >> huge_shift, 0) + self.assertEqual((-42) >> huge_shift, -1) + self.assertEqual(1123 >> huge_shift, 0) + self.assertEqual((-1123) >> huge_shift, -1) + self.assertEqual(2**128 >> huge_shift, 0) + self.assertEqual(-2**128 >> huge_shift, -1) @support.cpython_only @support.bigmemtest(sys.maxsize + 500, memuse=2/15, dry_run=False) @@ -956,6 +961,60 @@ def test_huge_rshift_of_huge(self, size): self.assertEqual(huge >> (sys.maxsize + 1), (1 << 499) + 5) self.assertEqual(huge >> (sys.maxsize + 1000), 0) + def test_small_rshift(self): + self.assertEqual(42 >> 1, 21) + self.assertEqual((-42) >> 1, -21) + self.assertEqual(43 >> 1, 21) + self.assertEqual((-43) >> 1, -22) + + self.assertEqual(1122 >> 1, 561) + self.assertEqual((-1122) >> 1, -561) + self.assertEqual(1123 >> 1, 561) + self.assertEqual((-1123) >> 1, -562) + + self.assertEqual(2**128 >> 1, 2**127) + self.assertEqual(-2**128 >> 1, -2**127) + self.assertEqual((2**128 + 1) >> 1, 2**127) + self.assertEqual(-(2**128 + 1) >> 1, -2**127 - 1) + + def test_medium_rshift(self): + self.assertEqual(42 >> 9, 0) + self.assertEqual((-42) >> 9, -1) + self.assertEqual(1122 >> 9, 2) + self.assertEqual((-1122) >> 9, -3) + self.assertEqual(2**128 >> 9, 2**119) + self.assertEqual(-2**128 >> 9, -2**119) + + def test_big_rshift(self): + self.assertEqual(42 >> 32, 0) + self.assertEqual((-42) >> 32, -1) + self.assertEqual(1122 >> 32, 0) + self.assertEqual((-1122) >> 32, -1) + self.assertEqual(2**128 >> 32, 2**96) + self.assertEqual(-2**128 >> 32, -2**96) + + def test_small_lshift(self): + self.assertEqual(42 << 1, 84) + self.assertEqual((-42) << 1, -84) + self.assertEqual(561 << 1, 1122) + self.assertEqual((-561) << 1, -1122) + self.assertEqual(2**127 << 1, 2**128) + self.assertEqual(-2**127 << 1, -2**128) + + def test_medium_lshift(self): + self.assertEqual(42 << 9, 21504) + self.assertEqual((-42) << 9, -21504) + self.assertEqual(1122 << 9, 574464) + self.assertEqual((-1122) << 9, -574464) + + def test_big_lshift(self): + self.assertEqual(42 << 32, 42 * 2**32) + self.assertEqual((-42) << 32, -42 * 2**32) + self.assertEqual(1122 << 32, 1122 * 2**32) + self.assertEqual((-1122) << 32, -1122 * 2**32) + self.assertEqual(2**128 << 32, 2**160) + self.assertEqual(-2**128 << 32, -2**160) + @support.cpython_only def test_small_ints_in_huge_calculation(self): a = 2 ** 100 diff --git a/Misc/ACKS b/Misc/ACKS index 94a82a0750622..8baaf7304b603 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1964,6 +1964,7 @@ Doug Wyatt Xiang Zhang Robert Xiao Florent Xicluna +Xinhang Xu Arnon Yaari Alakshendra Yadav Hirokazu Yamamoto diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-24-20-21-45.bpo-46055.R0QMVQ.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-24-20-21-45.bpo-46055.R0QMVQ.rst new file mode 100644 index 0000000000000..124138806f17d --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-24-20-21-45.bpo-46055.R0QMVQ.rst @@ -0,0 +1,2 @@ +Speed up shifting operation involving integers less than +:c:macro:`PyLong_BASE`. Patch by Xinhang Xu. diff --git a/Objects/longobject.c b/Objects/longobject.c index ddb3def402cdd..09ae9455c5b26 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -4493,6 +4493,15 @@ long_rshift1(PyLongObject *a, Py_ssize_t wordshift, digit remshift) Py_ssize_t newsize, hishift, i, j; twodigits accum; + if (IS_MEDIUM_VALUE(a)) { + stwodigits m, x; + digit shift; + m = medium_value(a); + shift = wordshift == 0 ? remshift : PyLong_SHIFT; + x = m < 0 ? ~(~m >> shift) : m >> shift; + return _PyLong_FromSTwoDigits(x); + } + if (Py_SIZE(a) < 0) { /* Right shifting negative numbers is harder */ PyLongObject *a1, *a2; @@ -4566,11 +4575,17 @@ _PyLong_Rshift(PyObject *a, size_t shiftby) static PyObject * long_lshift1(PyLongObject *a, Py_ssize_t wordshift, digit remshift) { - /* This version due to Tim Peters */ PyLongObject *z = NULL; Py_ssize_t oldsize, newsize, i, j; twodigits accum; + if (wordshift == 0 && IS_MEDIUM_VALUE(a)) { + stwodigits m = medium_value(a); + // bypass undefined shift operator behavior + stwodigits x = m < 0 ? -(-m << remshift) : m << remshift; + return _PyLong_FromSTwoDigits(x); + } + oldsize = Py_ABS(Py_SIZE(a)); newsize = oldsize + wordshift; if (remshift) From webhook-mailer at python.org Mon Dec 27 21:06:02 2021 From: webhook-mailer at python.org (corona10) Date: Tue, 28 Dec 2021 02:06:02 -0000 Subject: [Python-checkins] bpo-45189: Drop the "list_frozen" command from _test_embed. (GH-30273) Message-ID: https://github.com/python/cpython/commit/196b53eb1e62871ca80dee180e4891b4dd5c52ac commit: 196b53eb1e62871ca80dee180e4891b4dd5c52ac branch: main author: Dong-hee Na committer: corona10 date: 2021-12-28T11:05:50+09:00 summary: bpo-45189: Drop the "list_frozen" command from _test_embed. (GH-30273) files: M Programs/_testembed.c M Tools/scripts/generate_stdlib_module_names.py diff --git a/Programs/_testembed.c b/Programs/_testembed.c index fc5f44d5eb626..b31781938eb39 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -1827,26 +1827,6 @@ static int test_frozenmain(void) } #endif // !MS_WINDOWS - -// List frozen modules. -// Command used by Tools/scripts/generate_stdlib_module_names.py script. -static int list_frozen(void) -{ - const struct _frozen *p; - for (p = _PyImport_FrozenBootstrap; ; p++) { - if (p->name == NULL) - break; - printf("%s\n", p->name); - } - for (p = _PyImport_FrozenStdlib; ; p++) { - if (p->name == NULL) - break; - printf("%s\n", p->name); - } - return 0; -} - - static int test_repeated_init_and_inittab(void) { // bpo-44441: Py_RunMain() must reset PyImport_Inittab at exit. @@ -1960,8 +1940,6 @@ static struct TestCase TestCases[] = { {"test_frozenmain", test_frozenmain}, #endif - // Command - {"list_frozen", list_frozen}, {NULL, NULL} }; diff --git a/Tools/scripts/generate_stdlib_module_names.py b/Tools/scripts/generate_stdlib_module_names.py index 3e896ba737543..fe1e429ebce17 100644 --- a/Tools/scripts/generate_stdlib_module_names.py +++ b/Tools/scripts/generate_stdlib_module_names.py @@ -1,5 +1,6 @@ # This script lists the names of standard library modules # to update Python/stdlib_mod_names.h +import _imp import os.path import re import subprocess @@ -11,7 +12,6 @@ STDLIB_PATH = os.path.join(SRC_DIR, 'Lib') MODULES_SETUP = os.path.join(SRC_DIR, 'Modules', 'Setup') SETUP_PY = os.path.join(SRC_DIR, 'setup.py') -TEST_EMBED = os.path.join(SRC_DIR, 'Programs', '_testembed') IGNORE = { '__init__', @@ -117,16 +117,11 @@ def list_modules_setup_extensions(names): # List frozen modules of the PyImport_FrozenModules list (Python/frozen.c). # Use the "./Programs/_testembed list_frozen" command. def list_frozen(names): - args = [TEST_EMBED, 'list_frozen'] - proc = subprocess.run(args, stdout=subprocess.PIPE, text=True) - exitcode = proc.returncode - if exitcode: - cmd = ' '.join(args) - print(f"{cmd} failed with exitcode {exitcode}") - sys.exit(exitcode) submodules = set() - for line in proc.stdout.splitlines(): - name = line.strip() + for name in _imp._frozen_module_names(): + # To skip __hello__, __hello_alias__ and etc. + if name.startswith('__'): + continue if '.' in name: submodules.add(name) else: From webhook-mailer at python.org Tue Dec 28 02:10:51 2021 From: webhook-mailer at python.org (ned-deily) Date: Tue, 28 Dec 2021 07:10:51 -0000 Subject: [Python-checkins] Update REAME and Docs sidebar for EOL Message-ID: https://github.com/python/cpython/commit/8d999cbf4adea053be6dbb612b9844635c4dfb8e commit: 8d999cbf4adea053be6dbb612b9844635c4dfb8e branch: 3.6 author: Ned Deily committer: ned-deily date: 2021-12-28T02:10:16-05:00 summary: Update REAME and Docs sidebar for EOL files: M Doc/tools/static/switchers.js M Doc/tools/templates/indexsidebar.html M README.rst diff --git a/Doc/tools/static/switchers.js b/Doc/tools/static/switchers.js index 30801917ed9eb..3008e1631e793 100644 --- a/Doc/tools/static/switchers.js +++ b/Doc/tools/static/switchers.js @@ -10,8 +10,9 @@ '(?:release/\\d.\\d[\\x\\d\\.]*)']; var all_versions = { - '3.10': 'dev (3.10)', - '3.9': 'pre (3.9)', + '3.11': 'dev (3.11)', + '3.10': '3.10', + '3.9': '3.9', '3.8': '3.8', '3.7': '3.7', '3.6': '3.6', diff --git a/Doc/tools/templates/indexsidebar.html b/Doc/tools/templates/indexsidebar.html index 2ef90f094ddaa..f7bf6d8e49117 100644 --- a/Doc/tools/templates/indexsidebar.html +++ b/Doc/tools/templates/indexsidebar.html @@ -2,12 +2,8 @@

{% trans %}Download{% endtrans %}

{% trans %}Download these documents{% endtrans %}

{% trans %}Docs by version{% endtrans %}

@@ -18,4 +14,5 @@

{% trans %}Other resources{% endtrans %}

  • {% trans %}Beginner's Guide{% endtrans %}
  • {% trans %}Book List{% endtrans %}
  • {% trans %}Audio/Visual Talks{% endtrans %}
  • +
  • {% trans %}Python Developer?s Guide{% endtrans %}
  • diff --git a/README.rst b/README.rst index 3e72bad19a34d..570b6f1669db9 100644 --- a/README.rst +++ b/README.rst @@ -236,6 +236,7 @@ All current PEPs, as well as guidelines for submitting a new PEP, are listed at Release Schedule ---------------- +As of 2021-12-23, Python 3.6 has reached ``end-of-life`` status. See :pep:`494` for Python 3.6 release details. From webhook-mailer at python.org Tue Dec 28 07:26:45 2021 From: webhook-mailer at python.org (mdickinson) Date: Tue, 28 Dec 2021 12:26:45 -0000 Subject: [Python-checkins] bpo-37295: Speed up math.comb(n, k) for 0 <= k <= n <= 67 (GH-30275) Message-ID: https://github.com/python/cpython/commit/02b5417f1107415abaf81acab7522f9aa84269ea commit: 02b5417f1107415abaf81acab7522f9aa84269ea branch: main author: Mark Dickinson committer: mdickinson date: 2021-12-28T12:26:40Z summary: bpo-37295: Speed up math.comb(n, k) for 0 <= k <= n <= 67 (GH-30275) files: A Misc/NEWS.d/next/Library/2021-12-27-15-52-28.bpo-37295.s3LPo0.rst M Modules/mathmodule.c diff --git a/Misc/NEWS.d/next/Library/2021-12-27-15-52-28.bpo-37295.s3LPo0.rst b/Misc/NEWS.d/next/Library/2021-12-27-15-52-28.bpo-37295.s3LPo0.rst new file mode 100644 index 0000000000000..a624f10637002 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-27-15-52-28.bpo-37295.s3LPo0.rst @@ -0,0 +1 @@ +Add fast path for ``0 <= k <= n <= 67`` for :func:`math.comb`. diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 011ce0afd3aec..c4a23b6514f6b 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -3450,6 +3450,71 @@ math_perm_impl(PyObject *module, PyObject *n, PyObject *k) return NULL; } +/* least significant 64 bits of the odd part of factorial(n), for n in range(68). + +Python code to generate the values: + + import math + + for n in range(68): + fac = math.factorial(n) + fac_odd_part = fac // (fac & -fac) + reduced_fac_odd_part = fac_odd_part % (2**64) + print(f"{reduced_fac_odd_part:#018x}u") +*/ +static uint64_t reduced_factorial_odd_part[] = { + 0x0000000000000001u, 0x0000000000000001u, 0x0000000000000001u, 0x0000000000000003u, + 0x0000000000000003u, 0x000000000000000fu, 0x000000000000002du, 0x000000000000013bu, + 0x000000000000013bu, 0x0000000000000b13u, 0x000000000000375fu, 0x0000000000026115u, + 0x000000000007233fu, 0x00000000005cca33u, 0x0000000002898765u, 0x00000000260eeeebu, + 0x00000000260eeeebu, 0x0000000286fddd9bu, 0x00000016beecca73u, 0x000001b02b930689u, + 0x00000870d9df20adu, 0x0000b141df4dae31u, 0x00079dd498567c1bu, 0x00af2e19afc5266du, + 0x020d8a4d0f4f7347u, 0x335281867ec241efu, 0x9b3093d46fdd5923u, 0x5e1f9767cc5866b1u, + 0x92dd23d6966aced7u, 0xa30d0f4f0a196e5bu, 0x8dc3e5a1977d7755u, 0x2ab8ce915831734bu, + 0x2ab8ce915831734bu, 0x81d2a0bc5e5fdcabu, 0x9efcac82445da75bu, 0xbc8b95cf58cde171u, + 0xa0e8444a1f3cecf9u, 0x4191deb683ce3ffdu, 0xddd3878bc84ebfc7u, 0xcb39a64b83ff3751u, + 0xf8203f7993fc1495u, 0xbd2a2a78b35f4bddu, 0x84757be6b6d13921u, 0x3fbbcfc0b524988bu, + 0xbd11ed47c8928df9u, 0x3c26b59e41c2f4c5u, 0x677a5137e883fdb3u, 0xff74e943b03b93ddu, + 0xfe5ebbcb10b2bb97u, 0xb021f1de3235e7e7u, 0x33509eb2e743a58fu, 0x390f9da41279fb7du, + 0xe5cb0154f031c559u, 0x93074695ba4ddb6du, 0x81c471caa636247fu, 0xe1347289b5a1d749u, + 0x286f21c3f76ce2ffu, 0x00be84a2173e8ac7u, 0x1595065ca215b88bu, 0xf95877595b018809u, + 0x9c2efe3c5516f887u, 0x373294604679382bu, 0xaf1ff7a888adcd35u, 0x18ddf279a2c5800bu, + 0x18ddf279a2c5800bu, 0x505a90e2542582cbu, 0x5bacad2cd8d5dc2bu, 0xfe3152bcbff89f41u, +}; + +/* inverses of reduced_factorial_odd_part values modulo 2**64. + +Python code to generate the values: + + import math + + for n in range(68): + fac = math.factorial(n) + fac_odd_part = fac // (fac & -fac) + inverted_fac_odd_part = pow(fac_odd_part, -1, 2**64) + print(f"{inverted_fac_odd_part:#018x}u") +*/ +static uint64_t inverted_factorial_odd_part[] = { + 0x0000000000000001u, 0x0000000000000001u, 0x0000000000000001u, 0xaaaaaaaaaaaaaaabu, + 0xaaaaaaaaaaaaaaabu, 0xeeeeeeeeeeeeeeefu, 0x4fa4fa4fa4fa4fa5u, 0x2ff2ff2ff2ff2ff3u, + 0x2ff2ff2ff2ff2ff3u, 0x938cc70553e3771bu, 0xb71c27cddd93e49fu, 0xb38e3229fcdee63du, + 0xe684bb63544a4cbfu, 0xc2f684917ca340fbu, 0xf747c9cba417526du, 0xbb26eb51d7bd49c3u, + 0xbb26eb51d7bd49c3u, 0xb0a7efb985294093u, 0xbe4b8c69f259eabbu, 0x6854d17ed6dc4fb9u, + 0xe1aa904c915f4325u, 0x3b8206df131cead1u, 0x79c6009fea76fe13u, 0xd8c5d381633cd365u, + 0x4841f12b21144677u, 0x4a91ff68200b0d0fu, 0x8f9513a58c4f9e8bu, 0x2b3e690621a42251u, + 0x4f520f00e03c04e7u, 0x2edf84ee600211d3u, 0xadcaa2764aaacdfdu, 0x161f4f9033f4fe63u, + 0x161f4f9033f4fe63u, 0xbada2932ea4d3e03u, 0xcec189f3efaa30d3u, 0xf7475bb68330bf91u, + 0x37eb7bf7d5b01549u, 0x46b35660a4e91555u, 0xa567c12d81f151f7u, 0x4c724007bb2071b1u, + 0x0f4a0cce58a016bdu, 0xfa21068e66106475u, 0x244ab72b5a318ae1u, 0x366ce67e080d0f23u, + 0xd666fdae5dd2a449u, 0xd740ddd0acc06a0du, 0xb050bbbb28e6f97bu, 0x70b003fe890a5c75u, + 0xd03aabff83037427u, 0x13ec4ca72c783bd7u, 0x90282c06afdbd96fu, 0x4414ddb9db4a95d5u, + 0xa2c68735ae6832e9u, 0xbf72d71455676665u, 0xa8469fab6b759b7fu, 0xc1e55b56e606caf9u, + 0x40455630fc4a1cffu, 0x0120a7b0046d16f7u, 0xa7c3553b08faef23u, 0x9f0bfd1b08d48639u, + 0xa433ffce9a304d37u, 0xa22ad1d53915c683u, 0xcb6cbc723ba5dd1du, 0x547fb1b8ab9d0ba3u, + 0x547fb1b8ab9d0ba3u, 0x8f15a826498852e3u, 0x32e1a03f38880283u, 0x3de4cce63283f0c1u, +}; + + /*[clinic input] math.comb @@ -3512,6 +3577,30 @@ math_comb_impl(PyObject *module, PyObject *n, PyObject *k) goto done; } assert(ki >= 0); + + if (ni <= 67) { + /* + For 0 <= k <= n <= 67, comb(n, k) always fits into a uint64_t. + We compute it as + + comb_odd_part << shift + + where 2**shift is the largest power of two dividing comb(n, k) + and comb_odd_part is comb(n, k) >> shift. comb_odd_part can be + calculated efficiently via arithmetic modulo 2**64, using three + lookups and two uint64_t multiplications, while the necessary + shift can be computed via Kummer's theorem: it's the number of + carries when adding k to n - k in binary, which in turn is the + number of set bits of n ^ k ^ (n - k). + */ + uint64_t comb_odd_part = reduced_factorial_odd_part[ni] + * inverted_factorial_odd_part[ki] + * inverted_factorial_odd_part[ni - ki]; + int shift = _Py_popcount32((uint32_t)(ni ^ ki ^ (ni - ki))); + result = PyLong_FromUnsignedLongLong(comb_odd_part << shift); + goto done; + } + ki = Py_MIN(ki, ni - ki); if (ki > 1) { result = perm_comb_small((unsigned long long)ni, From webhook-mailer at python.org Tue Dec 28 12:49:52 2021 From: webhook-mailer at python.org (brandtbucher) Date: Tue, 28 Dec 2021 17:49:52 -0000 Subject: [Python-checkins] bpo-46090: Allow PyThreadState.datastack_* members to be NULL (GH-30234) Message-ID: https://github.com/python/cpython/commit/77195cd44b2506cda88a3cfc98918526068b1d46 commit: 77195cd44b2506cda88a3cfc98918526068b1d46 branch: main author: Brandt Bucher committer: brandtbucher date: 2021-12-28T09:49:48-08:00 summary: bpo-46090: Allow PyThreadState.datastack_* members to be NULL (GH-30234) files: M Include/internal/pycore_frame.h M Python/pystate.c diff --git a/Include/internal/pycore_frame.h b/Include/internal/pycore_frame.h index 883bef199ba59..8eca39d1ab250 100644 --- a/Include/internal/pycore_frame.h +++ b/Include/internal/pycore_frame.h @@ -174,10 +174,13 @@ static inline InterpreterFrame * _PyThreadState_BumpFramePointer(PyThreadState *tstate, size_t size) { PyObject **base = tstate->datastack_top; - PyObject **top = base + size; - if (top < tstate->datastack_limit) { - tstate->datastack_top = top; - return (InterpreterFrame *)base; + if (base) { + PyObject **top = base + size; + assert(tstate->datastack_limit); + if (top < tstate->datastack_limit) { + tstate->datastack_top = top; + return (InterpreterFrame *)base; + } } return _PyThreadState_BumpFramePointerSlow(tstate, size); } diff --git a/Python/pystate.c b/Python/pystate.c index 0301ce676950b..68fae8d283091 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -749,8 +749,7 @@ free_threadstate(PyThreadState *tstate) static void init_threadstate(PyThreadState *tstate, PyInterpreterState *interp, uint64_t id, - PyThreadState *next, - _PyStackChunk *datastack_chunk) + PyThreadState *next) { if (tstate->_initialized) { Py_FatalError("thread state already initialized"); @@ -784,11 +783,9 @@ init_threadstate(PyThreadState *tstate, tstate->exc_info = &tstate->exc_state; tstate->cframe = &tstate->root_cframe; - assert(datastack_chunk != NULL); - tstate->datastack_chunk = datastack_chunk; - /* If top points to entry 0, then _PyThreadState_PopFrame will try to pop this chunk */ - tstate->datastack_top = &tstate->datastack_chunk->data[1]; - tstate->datastack_limit = (PyObject **)(((char *)tstate->datastack_chunk) + DATA_STACK_CHUNK_SIZE); + tstate->datastack_chunk = NULL; + tstate->datastack_top = NULL; + tstate->datastack_limit = NULL; tstate->_initialized = 1; } @@ -799,11 +796,6 @@ new_threadstate(PyInterpreterState *interp) PyThreadState *tstate; _PyRuntimeState *runtime = interp->runtime; - _PyStackChunk *datastack_chunk = allocate_chunk(DATA_STACK_CHUNK_SIZE, NULL); - if (datastack_chunk == NULL) { - return NULL; - } - /* We serialize concurrent creation to protect global state. */ HEAD_LOCK(runtime); @@ -833,14 +825,13 @@ new_threadstate(PyInterpreterState *interp) } interp->threads.head = tstate; - init_threadstate(tstate, interp, id, old_head, datastack_chunk); + init_threadstate(tstate, interp, id, old_head); HEAD_UNLOCK(runtime); return tstate; error: HEAD_UNLOCK(runtime); - _PyObject_VirtualFree(datastack_chunk, datastack_chunk->size); return NULL; } @@ -2186,8 +2177,6 @@ _Py_GetConfig(void) static PyObject ** push_chunk(PyThreadState *tstate, int size) { - assert(tstate->datastack_top + size >= tstate->datastack_limit); - int allocate_size = DATA_STACK_CHUNK_SIZE; while (allocate_size < (int)sizeof(PyObject*)*(size + MINIMUM_OVERHEAD)) { allocate_size *= 2; @@ -2196,10 +2185,16 @@ push_chunk(PyThreadState *tstate, int size) if (new == NULL) { return NULL; } - tstate->datastack_chunk->top = tstate->datastack_top - &tstate->datastack_chunk->data[0]; + if (tstate->datastack_chunk) { + tstate->datastack_chunk->top = tstate->datastack_top - + &tstate->datastack_chunk->data[0]; + } tstate->datastack_chunk = new; tstate->datastack_limit = (PyObject **)(((char *)new) + allocate_size); - PyObject **res = &new->data[0]; + // When new is the "root" chunk (i.e. new->previous == NULL), we can keep + // _PyThreadState_PopFrame from freeing it later by "skipping" over the + // first element: + PyObject **res = &new->data[new->previous == NULL]; tstate->datastack_top = res + size; return res; } @@ -2212,9 +2207,6 @@ _PyThreadState_BumpFramePointerSlow(PyThreadState *tstate, size_t size) PyObject **top = base + size; if (top >= tstate->datastack_limit) { base = push_chunk(tstate, (int)size); - if (base == NULL) { - return NULL; - } } else { tstate->datastack_top = top; @@ -2244,16 +2236,20 @@ _PyThreadState_PushFrame(PyThreadState *tstate, PyFunctionObject *func, PyObject void _PyThreadState_PopFrame(PyThreadState *tstate, InterpreterFrame * frame) { + assert(tstate->datastack_chunk); PyObject **base = (PyObject **)frame; if (base == &tstate->datastack_chunk->data[0]) { _PyStackChunk *chunk = tstate->datastack_chunk; _PyStackChunk *previous = chunk->previous; + // push_chunk ensures that the root chunk is never popped: + assert(previous); tstate->datastack_top = &previous->data[previous->top]; tstate->datastack_chunk = previous; _PyObject_VirtualFree(chunk, chunk->size); tstate->datastack_limit = (PyObject **)(((char *)previous) + previous->size); } else { + assert(tstate->datastack_top); assert(tstate->datastack_top >= base); tstate->datastack_top = base; } From webhook-mailer at python.org Wed Dec 29 06:45:18 2021 From: webhook-mailer at python.org (miss-islington) Date: Wed, 29 Dec 2021 11:45:18 -0000 Subject: [Python-checkins] [3.10] bpo-46120: State that `|` is preferred over `Union` (GH-30222) (GH-30250) Message-ID: https://github.com/python/cpython/commit/ed1671ced7c9b951dfc16a0cf32a2b4eab914cf1 commit: ed1671ced7c9b951dfc16a0cf32a2b4eab914cf1 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-29T03:45:14-08:00 summary: [3.10] bpo-46120: State that `|` is preferred over `Union` (GH-30222) (GH-30250) Co-authored-by: ?ric Co-authored-by: Guido van Rossum (cherry picked from commit 1b30660c3b40da557050948ac8635f2dc50c4ee2) Co-authored-by: Nikita Sobolev Automerge-Triggered-By: GH:gpshead files: A Misc/NEWS.d/next/Documentation/2021-12-21-12-45-57.bpo-46120.PE0DmJ.rst M Doc/library/typing.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 3adb495ff7933..29bdb80ad22c6 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -625,7 +625,7 @@ These can be used as types in annotations using ``[]``, each having a unique syn Union type; ``Union[X, Y]`` is equivalent to ``X | Y`` and means either X or Y. - To define a union, use e.g. ``Union[int, str]`` or the shorthand ``int | str``. Details: + To define a union, use e.g. ``Union[int, str]`` or the shorthand ``int | str``. Using that shorthand is recommended. Details: * The arguments must be types and there must be at least one. diff --git a/Misc/NEWS.d/next/Documentation/2021-12-21-12-45-57.bpo-46120.PE0DmJ.rst b/Misc/NEWS.d/next/Documentation/2021-12-21-12-45-57.bpo-46120.PE0DmJ.rst new file mode 100644 index 0000000000000..17f67472e2ab0 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-12-21-12-45-57.bpo-46120.PE0DmJ.rst @@ -0,0 +1 @@ +State that ``|`` is preferred for readability over ``Union`` in the :mod:`typing` docs. From webhook-mailer at python.org Wed Dec 29 08:52:42 2021 From: webhook-mailer at python.org (corona10) Date: Wed, 29 Dec 2021 13:52:42 -0000 Subject: [Python-checkins] bpo-46176: mmap module adding MAP_STACK constant. (GH-30252) Message-ID: https://github.com/python/cpython/commit/66c47b63a0df3143fe48d6efc1183eecda2a363d commit: 66c47b63a0df3143fe48d6efc1183eecda2a363d branch: main author: David CARLIER committer: corona10 date: 2021-12-29T22:52:29+09:00 summary: bpo-46176: mmap module adding MAP_STACK constant. (GH-30252) files: A Misc/NEWS.d/next/Library/2021-12-25-11-11-21.bpo-46176.EOY9wd.rst M Doc/library/mmap.rst M Modules/mmapmodule.c diff --git a/Doc/library/mmap.rst b/Doc/library/mmap.rst index c1ebd80abd977..d19580cd7ee5c 100644 --- a/Doc/library/mmap.rst +++ b/Doc/library/mmap.rst @@ -367,8 +367,12 @@ MAP_* Constants MAP_ANON MAP_ANONYMOUS MAP_POPULATE + MAP_STACK These are the various flags that can be passed to :meth:`mmap.mmap`. Note that some options might not be present on some systems. .. versionchanged:: 3.10 Added MAP_POPULATE constant. + + .. versionadded:: 3.11 + Added MAP_STACK constant. diff --git a/Misc/NEWS.d/next/Library/2021-12-25-11-11-21.bpo-46176.EOY9wd.rst b/Misc/NEWS.d/next/Library/2021-12-25-11-11-21.bpo-46176.EOY9wd.rst new file mode 100644 index 0000000000000..4a50c2617200e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-25-11-11-21.bpo-46176.EOY9wd.rst @@ -0,0 +1 @@ +Adding the ``MAP_STACK`` constant for the mmap module. \ No newline at end of file diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c index 399cb0a99ad65..742bcb3d145fa 100644 --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -1637,6 +1637,11 @@ mmap_exec(PyObject *module) #endif #ifdef MAP_POPULATE ADD_INT_MACRO(module, MAP_POPULATE); +#endif +#ifdef MAP_STACK + // Mostly a no-op on Linux and NetBSD, but useful on OpenBSD + // for stack usage (even on x86 arch) + ADD_INT_MACRO(module, MAP_STACK); #endif if (PyModule_AddIntConstant(module, "PAGESIZE", (long)my_getpagesize()) < 0 ) { return -1; From webhook-mailer at python.org Wed Dec 29 14:39:58 2021 From: webhook-mailer at python.org (ambv) Date: Wed, 29 Dec 2021 19:39:58 -0000 Subject: [Python-checkins] bpo-46185: Fix wrong version ref. in macOS installer ReadMe (GH-30278) Message-ID: https://github.com/python/cpython/commit/bc87ac6d0b13116f525215f8a31b46506bc8d629 commit: bc87ac6d0b13116f525215f8a31b46506bc8d629 branch: main author: Erlend Egeberg Aasland committer: ambv date: 2021-12-29T20:39:49+01:00 summary: bpo-46185: Fix wrong version ref. in macOS installer ReadMe (GH-30278) files: M Mac/BuildScript/resources/ReadMe.rtf diff --git a/Mac/BuildScript/resources/ReadMe.rtf b/Mac/BuildScript/resources/ReadMe.rtf index 2a954083bf127..8d699395f304c 100644 --- a/Mac/BuildScript/resources/ReadMe.rtf +++ b/Mac/BuildScript/resources/ReadMe.rtf @@ -26,7 +26,7 @@ This package includes its own private copy of OpenSSL 1.1.1. The trust certifi \f0\i0 command line utility are not used as defaults by the Python \f3 ssl \f0 module. A sample command script is included in -\f3 /Applications/Python 3.9 +\f3 /Applications/Python 3.11 \f0 to install a curated bundle of default root certificates from the third-party \f3 certifi \f0 package ({\field{\*\fldinst{HYPERLINK "https://pypi.org/project/certifi/"}}{\fldrslt https://pypi.org/project/certifi/}}). Double-click on From webhook-mailer at python.org Wed Dec 29 14:40:17 2021 From: webhook-mailer at python.org (ambv) Date: Wed, 29 Dec 2021 19:40:17 -0000 Subject: [Python-checkins] [3.10] bpo-46185: Fix wrong version ref. in macOS installer ReadMe (GH-30280) Message-ID: https://github.com/python/cpython/commit/c31fdef1e71ff1598f213b1b4ad1a565e47d7864 commit: c31fdef1e71ff1598f213b1b4ad1a565e47d7864 branch: 3.10 author: Erlend Egeberg Aasland committer: ambv date: 2021-12-29T20:40:11+01:00 summary: [3.10] bpo-46185: Fix wrong version ref. in macOS installer ReadMe (GH-30280) files: M Mac/BuildScript/resources/ReadMe.rtf diff --git a/Mac/BuildScript/resources/ReadMe.rtf b/Mac/BuildScript/resources/ReadMe.rtf index 7934dd1a4bea5..4edfa5f3069f4 100644 --- a/Mac/BuildScript/resources/ReadMe.rtf +++ b/Mac/BuildScript/resources/ReadMe.rtf @@ -20,7 +20,7 @@ This package includes its own private copy of OpenSSL 1.1.1. The trust certifi \f0\i0 command line utility are not used as defaults by the Python \f3 ssl \f0 module. A sample command script is included in -\f3 /Applications/Python 3.9 +\f3 /Applications/Python 3.10 \f0 to install a curated bundle of default root certificates from the third-party \f3 certifi \f0 package ({\field{\*\fldinst{HYPERLINK "https://pypi.org/project/certifi/"}}{\fldrslt https://pypi.org/project/certifi/}}). Double-click on From webhook-mailer at python.org Wed Dec 29 17:20:47 2021 From: webhook-mailer at python.org (benjaminp) Date: Wed, 29 Dec 2021 22:20:47 -0000 Subject: [Python-checkins] closes docs: remove references to Py_USING_MEMORY_DEBUGGER (GH-30284) Message-ID: https://github.com/python/cpython/commit/8e11237c5d24e649b26cc928b52bc37f2fde9c7a commit: 8e11237c5d24e649b26cc928b52bc37f2fde9c7a branch: main author: Carlos Damazio committer: benjaminp date: 2021-12-29T16:20:42-06:00 summary: closes docs: remove references to Py_USING_MEMORY_DEBUGGER (GH-30284) files: M Misc/README.valgrind diff --git a/Misc/README.valgrind b/Misc/README.valgrind index b483b2ea60a4d..ee9bfdf859d7f 100644 --- a/Misc/README.valgrind +++ b/Misc/README.valgrind @@ -12,12 +12,9 @@ can be used to force the usage of the malloc() allocator of the C library. If you don't want to read about the details of using Valgrind, there are still two things you must do to suppress the warnings. First, you must use a suppressions file. One is supplied in -Misc/valgrind-python.supp. Second, you must do one of the following: - - * Uncomment Py_USING_MEMORY_DEBUGGER in Objects/obmalloc.c, - then rebuild Python - * Uncomment the lines in Misc/valgrind-python.supp that - suppress the warnings for PyObject_Free and PyObject_Realloc +Misc/valgrind-python.supp. Second, you must uncomment the lines in +Misc/valgrind-python.supp that suppress the warnings for PyObject_Free and +PyObject_Realloc. If you want to use Valgrind more effectively and catch even more memory leaks, you will need to configure python --without-pymalloc. From webhook-mailer at python.org Wed Dec 29 17:47:46 2021 From: webhook-mailer at python.org (miss-islington) Date: Wed, 29 Dec 2021 22:47:46 -0000 Subject: [Python-checkins] closes docs: remove references to Py_USING_MEMORY_DEBUGGER (GH-30284) Message-ID: https://github.com/python/cpython/commit/864caaabe4264798afd0e9fde0fc875c7208429d commit: 864caaabe4264798afd0e9fde0fc875c7208429d branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-29T14:47:37-08:00 summary: closes docs: remove references to Py_USING_MEMORY_DEBUGGER (GH-30284) (cherry picked from commit 8e11237c5d24e649b26cc928b52bc37f2fde9c7a) Co-authored-by: Carlos Damazio files: M Misc/README.valgrind diff --git a/Misc/README.valgrind b/Misc/README.valgrind index b483b2ea60a4d..ee9bfdf859d7f 100644 --- a/Misc/README.valgrind +++ b/Misc/README.valgrind @@ -12,12 +12,9 @@ can be used to force the usage of the malloc() allocator of the C library. If you don't want to read about the details of using Valgrind, there are still two things you must do to suppress the warnings. First, you must use a suppressions file. One is supplied in -Misc/valgrind-python.supp. Second, you must do one of the following: - - * Uncomment Py_USING_MEMORY_DEBUGGER in Objects/obmalloc.c, - then rebuild Python - * Uncomment the lines in Misc/valgrind-python.supp that - suppress the warnings for PyObject_Free and PyObject_Realloc +Misc/valgrind-python.supp. Second, you must uncomment the lines in +Misc/valgrind-python.supp that suppress the warnings for PyObject_Free and +PyObject_Realloc. If you want to use Valgrind more effectively and catch even more memory leaks, you will need to configure python --without-pymalloc. From webhook-mailer at python.org Wed Dec 29 18:01:26 2021 From: webhook-mailer at python.org (benjaminp) Date: Wed, 29 Dec 2021 23:01:26 -0000 Subject: [Python-checkins] closes bpo-38522 docs: remove references to Py_USING_MEMORY_DEBUGGER (GH-30284) (GH-30295) Message-ID: https://github.com/python/cpython/commit/9f0e40fae5191c3e3ed6109bd2e2f97aa0ac8d64 commit: 9f0e40fae5191c3e3ed6109bd2e2f97aa0ac8d64 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: benjaminp date: 2021-12-29T17:01:17-06:00 summary: closes bpo-38522 docs: remove references to Py_USING_MEMORY_DEBUGGER (GH-30284) (GH-30295) (cherry picked from commit 8e11237c5d24e649b26cc928b52bc37f2fde9c7a) Co-authored-by: Carlos Damazio Co-authored-by: Carlos Damazio files: M Misc/README.valgrind diff --git a/Misc/README.valgrind b/Misc/README.valgrind index b483b2ea60a4d..ee9bfdf859d7f 100644 --- a/Misc/README.valgrind +++ b/Misc/README.valgrind @@ -12,12 +12,9 @@ can be used to force the usage of the malloc() allocator of the C library. If you don't want to read about the details of using Valgrind, there are still two things you must do to suppress the warnings. First, you must use a suppressions file. One is supplied in -Misc/valgrind-python.supp. Second, you must do one of the following: - - * Uncomment Py_USING_MEMORY_DEBUGGER in Objects/obmalloc.c, - then rebuild Python - * Uncomment the lines in Misc/valgrind-python.supp that - suppress the warnings for PyObject_Free and PyObject_Realloc +Misc/valgrind-python.supp. Second, you must uncomment the lines in +Misc/valgrind-python.supp that suppress the warnings for PyObject_Free and +PyObject_Realloc. If you want to use Valgrind more effectively and catch even more memory leaks, you will need to configure python --without-pymalloc. From webhook-mailer at python.org Wed Dec 29 20:30:18 2021 From: webhook-mailer at python.org (corona10) Date: Thu, 30 Dec 2021 01:30:18 -0000 Subject: [Python-checkins] bpo-43424: Deprecate `webbrowser.MacOSXOSAScript._name` attribute (GH-30241) Message-ID: https://github.com/python/cpython/commit/d12bec69931503be78cd555cf7bc22ad6f4f2bd5 commit: d12bec69931503be78cd555cf7bc22ad6f4f2bd5 branch: main author: Nikita Sobolev committer: corona10 date: 2021-12-30T10:30:13+09:00 summary: bpo-43424: Deprecate `webbrowser.MacOSXOSAScript._name` attribute (GH-30241) files: A Misc/NEWS.d/next/Library/2021-12-23-14-36-58.bpo-43424.d9x2JZ.rst M Doc/library/webbrowser.rst M Lib/test/test_webbrowser.py M Lib/webbrowser.py diff --git a/Doc/library/webbrowser.rst b/Doc/library/webbrowser.rst index 19b3c463bb817..1dc59306164ec 100644 --- a/Doc/library/webbrowser.rst +++ b/Doc/library/webbrowser.rst @@ -197,6 +197,11 @@ Browser controllers provide these methods which parallel three of the module-level convenience functions: +.. attribute:: name + + System-dependent name for the browser. + + .. method:: controller.open(url, new=0, autoraise=True) Display *url* using the browser handled by this controller. If *new* is 1, a new diff --git a/Lib/test/test_webbrowser.py b/Lib/test/test_webbrowser.py index 673cc995d3f5a..dbfd2e5a0f280 100644 --- a/Lib/test/test_webbrowser.py +++ b/Lib/test/test_webbrowser.py @@ -304,7 +304,7 @@ def test_environment(self): webbrowser = import_helper.import_fresh_module('webbrowser') try: browser = webbrowser.get().name - except (webbrowser.Error, AttributeError) as err: + except webbrowser.Error as err: self.skipTest(str(err)) with os_helper.EnvironmentVarGuard() as env: env["BROWSER"] = browser @@ -316,7 +316,7 @@ def test_environment_preferred(self): try: webbrowser.get() least_preferred_browser = webbrowser.get(webbrowser._tryorder[-1]).name - except (webbrowser.Error, AttributeError, IndexError) as err: + except (webbrowser.Error, IndexError) as err: self.skipTest(str(err)) with os_helper.EnvironmentVarGuard() as env: diff --git a/Lib/webbrowser.py b/Lib/webbrowser.py index 3244f206aade6..02d2036906178 100755 --- a/Lib/webbrowser.py +++ b/Lib/webbrowser.py @@ -666,19 +666,33 @@ def open(self, url, new=0, autoraise=True): return not rc class MacOSXOSAScript(BaseBrowser): - def __init__(self, name): - self._name = name + def __init__(self, name='default'): + super().__init__(name) + + @property + def _name(self): + warnings.warn(f'{self.__class__.__name__}._name is deprecated in 3.11' + f' use {self.__class__.__name__}.name instead.', + DeprecationWarning, stacklevel=2) + return self.name + + @_name.setter + def _name(self, val): + warnings.warn(f'{self.__class__.__name__}._name is deprecated in 3.11' + f' use {self.__class__.__name__}.name instead.', + DeprecationWarning, stacklevel=2) + self.name = val def open(self, url, new=0, autoraise=True): - if self._name == 'default': + if self.name == 'default': script = 'open location "%s"' % url.replace('"', '%22') # opens in default browser else: - script = ''' + script = f''' tell application "%s" activate open location "%s" end - '''%(self._name, url.replace('"', '%22')) + '''%(self.name, url.replace('"', '%22')) osapipe = os.popen("osascript", "w") if osapipe is None: diff --git a/Misc/NEWS.d/next/Library/2021-12-23-14-36-58.bpo-43424.d9x2JZ.rst b/Misc/NEWS.d/next/Library/2021-12-23-14-36-58.bpo-43424.d9x2JZ.rst new file mode 100644 index 0000000000000..aa5f8d4211c37 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-23-14-36-58.bpo-43424.d9x2JZ.rst @@ -0,0 +1 @@ +Deprecate :attr:`webbrowser.MacOSXOSAScript._name` and use ``name`` instead. From webhook-mailer at python.org Wed Dec 29 22:36:06 2021 From: webhook-mailer at python.org (corona10) Date: Thu, 30 Dec 2021 03:36:06 -0000 Subject: [Python-checkins] bpo-46085: Fix iterator cache mechanism of OrderedDict. (GH-30290) Message-ID: https://github.com/python/cpython/commit/fb44d0589615590b1e7895ba78a038e96b15a219 commit: fb44d0589615590b1e7895ba78a038e96b15a219 branch: main author: Dong-hee Na committer: corona10 date: 2021-12-30T12:35:45+09:00 summary: bpo-46085: Fix iterator cache mechanism of OrderedDict. (GH-30290) files: A Misc/NEWS.d/next/Core and Builtins/2021-12-30-00-23-41.bpo-46085.bDuJqu.rst M Objects/odictobject.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-30-00-23-41.bpo-46085.bDuJqu.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-30-00-23-41.bpo-46085.bDuJqu.rst new file mode 100644 index 0000000000000..a2093f75c3b62 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-30-00-23-41.bpo-46085.bDuJqu.rst @@ -0,0 +1 @@ +Fix iterator cache mechanism of :class:`OrderedDict`. diff --git a/Objects/odictobject.c b/Objects/odictobject.c index 9af45c685ab3b..e27bcecd75ca3 100644 --- a/Objects/odictobject.c +++ b/Objects/odictobject.c @@ -1249,6 +1249,7 @@ PyDoc_STRVAR(odict_reversed__doc__, "od.__reversed__() <==> reversed(od)"); #define _odict_ITER_REVERSED 1 #define _odict_ITER_KEYS 2 #define _odict_ITER_VALUES 4 +#define _odict_ITER_ITEMS (_odict_ITER_KEYS|_odict_ITER_VALUES) /* forward */ static PyObject * odictiter_new(PyODictObject *, int); @@ -1666,7 +1667,7 @@ odictiter_dealloc(odictiterobject *di) _PyObject_GC_UNTRACK(di); Py_XDECREF(di->di_odict); Py_XDECREF(di->di_current); - if (di->kind & (_odict_ITER_KEYS | _odict_ITER_VALUES)) { + if ((di->kind & _odict_ITER_ITEMS) == _odict_ITER_ITEMS) { Py_DECREF(di->di_result); } PyObject_GC_Del(di); @@ -1872,15 +1873,16 @@ odictiter_new(PyODictObject *od, int kind) if (di == NULL) return NULL; - if (kind & (_odict_ITER_KEYS | _odict_ITER_VALUES)){ + if ((kind & _odict_ITER_ITEMS) == _odict_ITER_ITEMS) { di->di_result = PyTuple_Pack(2, Py_None, Py_None); if (di->di_result == NULL) { Py_DECREF(di); return NULL; } } - else + else { di->di_result = NULL; + } di->kind = kind; node = reversed ? _odict_LAST(od) : _odict_FIRST(od); From webhook-mailer at python.org Thu Dec 30 00:29:13 2021 From: webhook-mailer at python.org (miss-islington) Date: Thu, 30 Dec 2021 05:29:13 -0000 Subject: [Python-checkins] bpo-46085: Fix iterator cache mechanism of OrderedDict. (GH-30290) Message-ID: https://github.com/python/cpython/commit/1b37268ef10bd20c30d349b8401c88215c8a6be8 commit: 1b37268ef10bd20c30d349b8401c88215c8a6be8 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-29T21:29:03-08:00 summary: bpo-46085: Fix iterator cache mechanism of OrderedDict. (GH-30290) (cherry picked from commit fb44d0589615590b1e7895ba78a038e96b15a219) Co-authored-by: Dong-hee Na files: A Misc/NEWS.d/next/Core and Builtins/2021-12-30-00-23-41.bpo-46085.bDuJqu.rst M Objects/odictobject.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-30-00-23-41.bpo-46085.bDuJqu.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-30-00-23-41.bpo-46085.bDuJqu.rst new file mode 100644 index 0000000000000..a2093f75c3b62 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-30-00-23-41.bpo-46085.bDuJqu.rst @@ -0,0 +1 @@ +Fix iterator cache mechanism of :class:`OrderedDict`. diff --git a/Objects/odictobject.c b/Objects/odictobject.c index 6c7f1175cd652..c0ccb16bc3d2e 100644 --- a/Objects/odictobject.c +++ b/Objects/odictobject.c @@ -1288,6 +1288,7 @@ PyDoc_STRVAR(odict_reversed__doc__, "od.__reversed__() <==> reversed(od)"); #define _odict_ITER_REVERSED 1 #define _odict_ITER_KEYS 2 #define _odict_ITER_VALUES 4 +#define _odict_ITER_ITEMS (_odict_ITER_KEYS|_odict_ITER_VALUES) /* forward */ static PyObject * odictiter_new(PyODictObject *, int); @@ -1705,7 +1706,7 @@ odictiter_dealloc(odictiterobject *di) _PyObject_GC_UNTRACK(di); Py_XDECREF(di->di_odict); Py_XDECREF(di->di_current); - if (di->kind & (_odict_ITER_KEYS | _odict_ITER_VALUES)) { + if ((di->kind & _odict_ITER_ITEMS) == _odict_ITER_ITEMS) { Py_DECREF(di->di_result); } PyObject_GC_Del(di); @@ -1911,15 +1912,16 @@ odictiter_new(PyODictObject *od, int kind) if (di == NULL) return NULL; - if (kind & (_odict_ITER_KEYS | _odict_ITER_VALUES)){ + if ((kind & _odict_ITER_ITEMS) == _odict_ITER_ITEMS) { di->di_result = PyTuple_Pack(2, Py_None, Py_None); if (di->di_result == NULL) { Py_DECREF(di); return NULL; } } - else + else { di->di_result = NULL; + } di->kind = kind; node = reversed ? _odict_LAST(od) : _odict_FIRST(od); From webhook-mailer at python.org Thu Dec 30 00:29:23 2021 From: webhook-mailer at python.org (miss-islington) Date: Thu, 30 Dec 2021 05:29:23 -0000 Subject: [Python-checkins] bpo-46085: Fix iterator cache mechanism of OrderedDict. (GH-30290) Message-ID: https://github.com/python/cpython/commit/2d4049da1f61df5cb4314d7e10b54fa556880b0e commit: 2d4049da1f61df5cb4314d7e10b54fa556880b0e branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-12-29T21:29:19-08:00 summary: bpo-46085: Fix iterator cache mechanism of OrderedDict. (GH-30290) (cherry picked from commit fb44d0589615590b1e7895ba78a038e96b15a219) Co-authored-by: Dong-hee Na files: A Misc/NEWS.d/next/Core and Builtins/2021-12-30-00-23-41.bpo-46085.bDuJqu.rst M Objects/odictobject.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-30-00-23-41.bpo-46085.bDuJqu.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-30-00-23-41.bpo-46085.bDuJqu.rst new file mode 100644 index 0000000000000..a2093f75c3b62 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-30-00-23-41.bpo-46085.bDuJqu.rst @@ -0,0 +1 @@ +Fix iterator cache mechanism of :class:`OrderedDict`. diff --git a/Objects/odictobject.c b/Objects/odictobject.c index b9f2169a72a8a..f3980aba93776 100644 --- a/Objects/odictobject.c +++ b/Objects/odictobject.c @@ -1290,6 +1290,7 @@ PyDoc_STRVAR(odict_reversed__doc__, "od.__reversed__() <==> reversed(od)"); #define _odict_ITER_REVERSED 1 #define _odict_ITER_KEYS 2 #define _odict_ITER_VALUES 4 +#define _odict_ITER_ITEMS (_odict_ITER_KEYS|_odict_ITER_VALUES) /* forward */ static PyObject * odictiter_new(PyODictObject *, int); @@ -1708,7 +1709,7 @@ odictiter_dealloc(odictiterobject *di) _PyObject_GC_UNTRACK(di); Py_XDECREF(di->di_odict); Py_XDECREF(di->di_current); - if (di->kind & (_odict_ITER_KEYS | _odict_ITER_VALUES)) { + if ((di->kind & _odict_ITER_ITEMS) == _odict_ITER_ITEMS) { Py_DECREF(di->di_result); } PyObject_GC_Del(di); @@ -1914,15 +1915,16 @@ odictiter_new(PyODictObject *od, int kind) if (di == NULL) return NULL; - if (kind & (_odict_ITER_KEYS | _odict_ITER_VALUES)){ + if ((kind & _odict_ITER_ITEMS) == _odict_ITER_ITEMS) { di->di_result = PyTuple_Pack(2, Py_None, Py_None); if (di->di_result == NULL) { Py_DECREF(di); return NULL; } } - else + else { di->di_result = NULL; + } di->kind = kind; node = reversed ? _odict_LAST(od) : _odict_FIRST(od); From webhook-mailer at python.org Thu Dec 30 02:45:15 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Thu, 30 Dec 2021 07:45:15 -0000 Subject: [Python-checkins] bpo-45853: Fix misspelling and unused import in pathlib (GH-30292) Message-ID: https://github.com/python/cpython/commit/8d7644fa64213207b8dc6f555cb8a02bfabeced2 commit: 8d7644fa64213207b8dc6f555cb8a02bfabeced2 branch: main author: andrei kulakov committer: serhiy-storchaka date: 2021-12-30T09:45:06+02:00 summary: bpo-45853: Fix misspelling and unused import in pathlib (GH-30292) files: M Lib/pathlib.py diff --git a/Lib/pathlib.py b/Lib/pathlib.py index 621fba0e75c0f..f1a33178e2958 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -8,7 +8,7 @@ import sys import warnings from _collections_abc import Sequence -from errno import EINVAL, ENOENT, ENOTDIR, EBADF, ELOOP +from errno import ENOENT, ENOTDIR, EBADF, ELOOP from operator import attrgetter from stat import S_ISDIR, S_ISLNK, S_ISREG, S_ISSOCK, S_ISBLK, S_ISCHR, S_ISFIFO from urllib.parse import quote_from_bytes as urlquote_from_bytes @@ -28,7 +28,7 @@ _WINERROR_CANT_RESOLVE_FILENAME = 1921 # broken symlink pointing to itself # EBADF - guard against macOS `stat` throwing EBADF -_IGNORED_ERROS = (ENOENT, ENOTDIR, EBADF, ELOOP) +_IGNORED_ERRNOS = (ENOENT, ENOTDIR, EBADF, ELOOP) _IGNORED_WINERRORS = ( _WINERROR_NOT_READY, @@ -36,7 +36,7 @@ _WINERROR_CANT_RESOLVE_FILENAME) def _ignore_error(exception): - return (getattr(exception, 'errno', None) in _IGNORED_ERROS or + return (getattr(exception, 'errno', None) in _IGNORED_ERRNOS or getattr(exception, 'winerror', None) in _IGNORED_WINERRORS) From webhook-mailer at python.org Thu Dec 30 15:24:58 2021 From: webhook-mailer at python.org (Mariatta) Date: Thu, 30 Dec 2021 20:24:58 -0000 Subject: [Python-checkins] Delete `FUNDING.yml`, since there's an organisation default (#30294) Message-ID: https://github.com/python/cpython/commit/30ee33d6bed37172f6ef97596bd98a5d78275ffb commit: 30ee33d6bed37172f6ef97596bd98a5d78275ffb branch: main author: Nikita Sobolev committer: Mariatta date: 2021-12-30T12:24:46-08:00 summary: Delete `FUNDING.yml`, since there's an organisation default (#30294) files: D .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index b08459313accf..0000000000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,2 +0,0 @@ -custom: https://www.python.org/psf/donations/python-dev/ -github: [python] From webhook-mailer at python.org Thu Dec 30 16:18:42 2021 From: webhook-mailer at python.org (Mariatta) Date: Thu, 30 Dec 2021 21:18:42 -0000 Subject: [Python-checkins] bpo-46184: remove `netlify.toml` (#30272) Message-ID: https://github.com/python/cpython/commit/fbaf2e604cd354f1ebc6be029480010c6715a8ca commit: fbaf2e604cd354f1ebc6be029480010c6715a8ca branch: main author: Nikita Sobolev committer: Mariatta date: 2021-12-30T13:18:37-08:00 summary: bpo-46184: remove `netlify.toml` (#30272) * bpo-46184: remove `netlify.toml` * Delete runtime.txt * Delete requirements.txt * Revert "Delete requirements.txt" This reverts commit 9aa4f0631f9d206ed7fddf37b43a24ec4e90fa7c. files: D Doc/runtime.txt D netlify.toml diff --git a/Doc/runtime.txt b/Doc/runtime.txt deleted file mode 100644 index 548d71365f0ec..0000000000000 --- a/Doc/runtime.txt +++ /dev/null @@ -1 +0,0 @@ -3.7 \ No newline at end of file diff --git a/netlify.toml b/netlify.toml deleted file mode 100644 index 387c8f954ada3..0000000000000 --- a/netlify.toml +++ /dev/null @@ -1,4 +0,0 @@ -[build] - base = "Doc/" - command = "make html" - publish = "Doc/build/html" \ No newline at end of file From webhook-mailer at python.org Thu Dec 30 16:26:23 2021 From: webhook-mailer at python.org (Mariatta) Date: Thu, 30 Dec 2021 21:26:23 -0000 Subject: [Python-checkins] bpo-46178: remove unusued `.travis.yml` file (#30257) Message-ID: https://github.com/python/cpython/commit/82c2b54a35f85d87639201d1431ae6584b079e13 commit: 82c2b54a35f85d87639201d1431ae6584b079e13 branch: main author: Nikita Sobolev committer: Mariatta date: 2021-12-30T13:26:01-08:00 summary: bpo-46178: remove unusued `.travis.yml` file (#30257) * bpo-46178: remove unusued `.travis.yml` file * Delete 2021-12-26-12-35-41.bpo-46178.Aw1TZg.rst files: D .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index b2f7e27458711..0000000000000 --- a/.travis.yml +++ /dev/null @@ -1,169 +0,0 @@ -language: c -dist: bionic - -# To cache doc-building dependencies and C compiler output. -cache: - - pip - - ccache - - directories: - - $HOME/multissl - -env: - global: - - OPENSSL=1.1.1k - - OPENSSL_DIR="$HOME/multissl/openssl/${OPENSSL}" - - PATH="${OPENSSL_DIR}/bin:$PATH" - - CFLAGS="-I${OPENSSL_DIR}/include" - - LDFLAGS="-L${OPENSSL_DIR}/lib" - # Set rpath with env var instead of -Wl,-rpath linker flag - # OpenSSL ignores LDFLAGS when linking bin/openssl - - LD_RUN_PATH="${OPENSSL_DIR}/lib" - - PYTHONSTRICTEXTENSIONBUILD=1 - -branches: - only: - - main - - /^\d\.\d+$/ - - buildbot-custom - -matrix: - fast_finish: true - allow_failures: - - env: OPTIONAL=true - include: - - name: "CPython tests" - os: linux - language: c - compiler: clang - # gcc also works, but to keep the # of concurrent builds down, we use one C - # compiler here and the other to run the coverage build. Clang is preferred - # in this instance for its better error messages. - env: TESTING=cpython - addons: - apt: - packages: - - gdb - - xvfb - - name: "Documentation build" - os: linux - language: python - # Build the docs against a stable version of Python so code bugs don't hold up doc-related PRs. - python: 3.6 - env: TESTING=docs - before_script: - - cd Doc - - make venv PYTHON=python - script: - - make check html SPHINXOPTS="-q -W -j4" - - name: "Documentation tests" - os: linux - language: c - compiler: clang - env: TESTING=doctest - addons: - apt: - packages: - - xvfb - before_script: - - ./configure - - make -j4 - - make -C Doc/ PYTHON=../python venv - script: - xvfb-run make -C Doc/ PYTHON=../python SPHINXOPTS="-q -W -j4" doctest - - -before_install: - - set -e - - | - # Check short-circuit conditions - if [[ "${TESTING}" != "docs" && "${TESTING}" != "doctest" ]] - then - if [[ "$TRAVIS_PULL_REQUEST" == "false" ]] - then - echo "Not a PR, doing full build." - else - # Pull requests are slightly complicated because $TRAVIS_COMMIT_RANGE - # may include more changes than desired if the history is convoluted. - # Instead, explicitly fetch the base branch and compare against the - # merge-base commit. - git fetch -q origin +refs/heads/$TRAVIS_BRANCH - changes=$(git diff --name-only HEAD $(git merge-base HEAD FETCH_HEAD)) - echo "Files changed:" - echo "$changes" - if ! echo "$changes" | grep -qvE '(\.rst$)|(^Doc)|(^Misc)' - then - echo "Only docs were updated, stopping build process." - exit - fi - fi - fi - -install: - - | - # Install OpenSSL as necessary - # Note: doctest needs OpenSSL - if [[ "${TESTING}" != "docs" ]] - then - # clang complains about unused-parameter a lot, redirect stderr - python3 Tools/ssl/multissltests.py --steps=library \ - --base-directory ${HOME}/multissl \ - --openssl ${OPENSSL} >/dev/null 2>&1 - fi - - openssl version - -# Travis provides only 2 cores, so don't overdo the parallelism and waste memory. -before_script: - # -Og is much faster than -O0 - - CFLAGS="${CFLAGS} -Og" ./configure --with-pydebug - - eval "$(pyenv init -)" - - pyenv global 3.8 - - PYTHON_FOR_REGEN=python3.8 make -j4 regen-all - - make regen-stdlib-module-names - - changes=`git status --porcelain` - - | - # Check for changes in regenerated files - if ! test -z "$changes" - then - echo "Generated files not up to date" - echo "$changes" - exit 1 - fi - - make -j4 - - make pythoninfo - -script: - # Using the built Python as patchcheck.py is built around the idea of using - # a checkout-build of CPython to know things like what base branch the changes - # should be compared against. - # Only run on Linux as the check only needs to be run once. - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./python Tools/scripts/patchcheck.py --travis $TRAVIS_PULL_REQUEST; fi - # Check that all symbols exported by libpython start with "Py" or "_Py" - - make smelly - # Check that all symbols in the limited abi are present - - make check-limited-abi - # `-r -w` implicitly provided through `make buildbottest`. - - | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then - XVFB_RUN=xvfb-run; - fi - $XVFB_RUN make buildbottest TESTOPTS="-j4 -uall,-cpu" -notifications: - email: false - irc: - channels: - # This is set to a secure variable to prevent forks from notifying the - # IRC channel whenever they fail a build. This can be removed when travis - # implements https://github.com/travis-ci/travis-ci/issues/1094. - # The actual value here is: irc.freenode.net#python-dev - - secure: "s7kAkpcom2yUJ8XqyjFI0obJmhAGrn1xmoivdaPdgBIA++X47TBp1x4pgDsbEsoalef7bEwa4l07KdT4qa+DOd/c4QxaWom7fbN3BuLVsZuVfODnl79+gYq/TAbGfyH+yDs18DXrUfPgwD7C5aW32ugsqAOd4iWzfGJQ5OrOZzqzGjYdYQUEkJFXgxDEIb4aHvxNDWGO3Po9uKISrhb5saQ0l776yLo1Ur7M4oxl8RTbCdgX0vf5TzPg52BgvZpOgt3DHOUYPeiJLKNjAE6ibg0U95sEvMfHX77nz4aFY4/3UI6FFaRla34rZ+mYKrn0TdxOhera1QOgPmM6HzdO4K44FpfK1DS0Xxk9U9/uApq+cG0bU3W+cVUHDBe5+90lpRBAXHeHCgT7TI8gec614aiT8lEr3+yH8OBRYGzkjNK8E2LJZ/SxnVxDe7aLF6AWcoWLfS6/ziAIBFQ5Nc4U72CT8fGVSkl8ywPiRlvixKdvTODMSZo0jMqlfZSNaAPTsNRx4wu5Uis4qekwe32Fz4aB6KGpsuuVjBi+H6v0RKxNJNGY3JKDiEH2TK0UE2auJ5GvLW48aUVFcQMB7euCWYXlSWVRHh3WLU8QXF29Dw4JduRZqUpOdRgMHU79UHRq+mkE0jAS/nBcS6CvsmxCpTSrfVYuMOu32yt18QQoTyU=" - on_success: change - on_failure: always - skip_join: true - webhooks: - urls: - # For the same reasons as above for IRC, we encrypt the webhook address - # for Zulip. The actual value is: - # https://python.zulipchat.com/api/v1/external/travis?api_key=&stream=core%2Ftest+runs - - secure: "vLz2TodSL7wQ8DsIu86koRS9i4dsK40PH8+wzY93PBCCAzJAz113LTxK3/9PamMv+ObDRUSe5OpXcquE3d5Gwpu8IymF113qK0I3uNr+O3FtmKlj/Kd1P/V+z4pTpS3zh3lW9gyKV9EMWXIWS0IYKKZQU144XqUlIiucWK2jHJF/cSz2cRAx/6Kx68X4mZwEC7hiMOF4ZsWUMbCglM89ybeS0pr0kK9mmh88qsPyRQov3mRKswmVPlePk7clVLNAL43qSe3SzmrmACZfQ9KJYmpYnr/cjo2b6svYHcQBAwAUarZZ9KBMXeV7HwGWsSXAvHH2ynR0P++braBHGEMTGMSitdVWzFTmeiHnrkp08WAB+uFs54iEx3VklTk9bCzozTm2S94TRxbrsG9SypMvQxG570JV6P2XYuR+taCb/GMtMqrtGQm2e1Ht+nDLtiUb+/+rwEbicJJ13knptOQZI4tPOZESI/kXkORkSNwFfLSNLSl9jTlMmO7KjAAPApURHEdx26RbItAn8mIX2NcHTRjKn2qV4h3C54nmHmKWn/ZudHHJc6ieZSEUBoaLGAYmcWJRqrM6jiy2h9I9TRrCKAiGh5jT47FYKLwosTtV245l/ZhDb6eTVfEFT6TSLEoyfx9cCtTUvfMtXYl8eN9wlFYYpH8MSWbMD14eEkKBTWg=" - on_success: change - on_failure: always From webhook-mailer at python.org Thu Dec 30 19:16:35 2021 From: webhook-mailer at python.org (Mariatta) Date: Fri, 31 Dec 2021 00:16:35 -0000 Subject: [Python-checkins] bpo-46178: Remove/rename redundant Travis CI code (#30309) Message-ID: https://github.com/python/cpython/commit/2cf7d02b99ce8cebd26d330aa8aac2ee369d4600 commit: 2cf7d02b99ce8cebd26d330aa8aac2ee369d4600 branch: main author: Hugo van Kemenade committer: Mariatta date: 2021-12-30T16:16:27-08:00 summary: bpo-46178: Remove/rename redundant Travis CI code (#30309) files: M .azure-pipelines/posix-steps.yml M Doc/library/unittest.rst M Lib/test/test_urllib2net.py M README.rst M Tools/scripts/patchcheck.py diff --git a/.azure-pipelines/posix-steps.yml b/.azure-pipelines/posix-steps.yml index b6dde593019e6..2a3680897302e 100644 --- a/.azure-pipelines/posix-steps.yml +++ b/.azure-pipelines/posix-steps.yml @@ -66,7 +66,7 @@ steps: COMMAND: make - ${{ if eq(parameters.patchcheck, 'true') }}: - - script: ./python Tools/scripts/patchcheck.py --travis true + - script: ./python Tools/scripts/patchcheck.py --ci true displayName: 'Run patchcheck.py' condition: and(succeeded(), eq(variables['Build.Reason'], 'PullRequest')) diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst index bf7a1e87928a6..22723f42d048f 100644 --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -72,8 +72,9 @@ test runner a GUI tool for test discovery and execution. This is intended largely for ease of use for those new to unit testing. For production environments it is recommended that tests be driven by a continuous integration system such as - `Buildbot `_, `Jenkins `_ - or `Travis-CI `_, or `AppVeyor `_. + `Buildbot `_, `Jenkins `_, + `GitHub Actions `_, or + `AppVeyor `_. .. _unittest-minimal-example: diff --git a/Lib/test/test_urllib2net.py b/Lib/test/test_urllib2net.py index aa41811560c78..04cfb492e4549 100644 --- a/Lib/test/test_urllib2net.py +++ b/Lib/test/test_urllib2net.py @@ -28,13 +28,6 @@ def wrapped(*args, **kwargs): return _retry_thrice(func, exc, *args, **kwargs) return wrapped -# bpo-35411: FTP tests of test_urllib2net randomly fail -# with "425 Security: Bad IP connecting" on Travis CI -skip_ftp_test_on_travis = unittest.skipIf('TRAVIS' in os.environ, - 'bpo-35411: skip FTP test ' - 'on Travis CI') - - # Connecting to remote hosts is flaky. Make it more robust by retrying # the connection several times. _urlopen_with_retry = _wrap_with_retry_thrice(urllib.request.urlopen, @@ -139,7 +132,6 @@ def setUp(self): # XXX The rest of these tests aren't very good -- they don't check much. # They do sometimes catch some major disasters, though. - @skip_ftp_test_on_travis def test_ftp(self): urls = [ 'ftp://www.pythontest.net/README', @@ -339,7 +331,6 @@ def test_http_timeout(self): FTP_HOST = 'ftp://www.pythontest.net/' - @skip_ftp_test_on_travis def test_ftp_basic(self): self.assertIsNone(socket.getdefaulttimeout()) with socket_helper.transient_internet(self.FTP_HOST, timeout=None): @@ -347,7 +338,6 @@ def test_ftp_basic(self): self.addCleanup(u.close) self.assertIsNone(u.fp.fp.raw._sock.gettimeout()) - @skip_ftp_test_on_travis def test_ftp_default_timeout(self): self.assertIsNone(socket.getdefaulttimeout()) with socket_helper.transient_internet(self.FTP_HOST): @@ -359,7 +349,6 @@ def test_ftp_default_timeout(self): socket.setdefaulttimeout(None) self.assertEqual(u.fp.fp.raw._sock.gettimeout(), 60) - @skip_ftp_test_on_travis def test_ftp_no_timeout(self): self.assertIsNone(socket.getdefaulttimeout()) with socket_helper.transient_internet(self.FTP_HOST): @@ -371,7 +360,6 @@ def test_ftp_no_timeout(self): socket.setdefaulttimeout(None) self.assertIsNone(u.fp.fp.raw._sock.gettimeout()) - @skip_ftp_test_on_travis def test_ftp_timeout(self): with socket_helper.transient_internet(self.FTP_HOST): u = _urlopen_with_retry(self.FTP_HOST, timeout=60) diff --git a/README.rst b/README.rst index 9f84432a55c97..d4b6621a80554 100644 --- a/README.rst +++ b/README.rst @@ -1,10 +1,6 @@ This is Python version 3.11.0 alpha 3 ===================================== -.. image:: https://travis-ci.com/python/cpython.svg?branch=main - :alt: CPython build status on Travis CI - :target: https://travis-ci.com/python/cpython - .. image:: https://github.com/python/cpython/workflows/Tests/badge.svg :alt: CPython build status on GitHub Actions :target: https://github.com/python/cpython/actions diff --git a/Tools/scripts/patchcheck.py b/Tools/scripts/patchcheck.py index 8e59c78a4c584..4cab66c8e97be 100755 --- a/Tools/scripts/patchcheck.py +++ b/Tools/scripts/patchcheck.py @@ -245,7 +245,7 @@ def regenerated_pyconfig_h_in(file_paths): else: return "not needed" -def travis(pull_request): +def ci(pull_request): if pull_request == 'false': print('Not a pull request; skipping') return @@ -301,10 +301,10 @@ def main(): if __name__ == '__main__': import argparse parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument('--travis', + parser.add_argument('--ci', help='Perform pass/fail checks') args = parser.parse_args() - if args.travis: - travis(args.travis) + if args.ci: + ci(args.ci) else: main() From webhook-mailer at python.org Thu Dec 30 21:00:57 2021 From: webhook-mailer at python.org (jaraco) Date: Fri, 31 Dec 2021 02:00:57 -0000 Subject: [Python-checkins] bpo-46118: Move importlib.resources to its own package. (#30176) Message-ID: https://github.com/python/cpython/commit/e712a5b277866a71c195f38c1b5d87d9126dba3e commit: e712a5b277866a71c195f38c1b5d87d9126dba3e branch: main author: Jason R. Coombs committer: jaraco date: 2021-12-30T21:00:48-05:00 summary: bpo-46118: Move importlib.resources to its own package. (#30176) * bpo-46118: Move importlib.resources to its own package. * Expand compatibility shims with documentation and explicit imports. files: A Lib/importlib/resources/__init__.py A Lib/importlib/resources/_adapters.py A Lib/importlib/resources/_common.py A Lib/importlib/resources/_itertools.py A Lib/importlib/resources/_legacy.py A Lib/importlib/resources/abc.py A Lib/importlib/resources/readers.py A Lib/importlib/resources/simple.py A Misc/NEWS.d/next/Library/2021-12-17-16-27-44.bpo-46118.euAy0E.rst D Lib/importlib/_adapters.py D Lib/importlib/_common.py D Lib/importlib/_itertools.py D Lib/importlib/_legacy.py D Lib/importlib/resources.py M Lib/importlib/abc.py M Lib/importlib/readers.py M Lib/importlib/simple.py M Lib/test/test_importlib/test_compatibilty_files.py diff --git a/Lib/importlib/abc.py b/Lib/importlib/abc.py index f10441608ad71..3fa151f390ba7 100644 --- a/Lib/importlib/abc.py +++ b/Lib/importlib/abc.py @@ -14,8 +14,19 @@ from ._abc import Loader import abc import warnings -from typing import BinaryIO, Iterable, Text -from typing import Protocol, runtime_checkable + +# for compatibility with Python 3.10 +from .resources.abc import ResourceReader, Traversable, TraversableResources + + +__all__ = [ + 'Loader', 'Finder', 'MetaPathFinder', 'PathEntryFinder', + 'ResourceLoader', 'InspectLoader', 'ExecutionLoader', + 'FileLoader', 'SourceLoader', + + # for compatibility with Python 3.10 + 'ResourceReader', 'Traversable', 'TraversableResources', +] def _register(abstract_cls, *classes): @@ -307,136 +318,3 @@ def set_data(self, path, data): """ _register(SourceLoader, machinery.SourceFileLoader) - - -class ResourceReader(metaclass=abc.ABCMeta): - """Abstract base class for loaders to provide resource reading support.""" - - @abc.abstractmethod - def open_resource(self, resource: Text) -> BinaryIO: - """Return an opened, file-like object for binary reading. - - The 'resource' argument is expected to represent only a file name. - If the resource cannot be found, FileNotFoundError is raised. - """ - # This deliberately raises FileNotFoundError instead of - # NotImplementedError so that if this method is accidentally called, - # it'll still do the right thing. - raise FileNotFoundError - - @abc.abstractmethod - def resource_path(self, resource: Text) -> Text: - """Return the file system path to the specified resource. - - The 'resource' argument is expected to represent only a file name. - If the resource does not exist on the file system, raise - FileNotFoundError. - """ - # This deliberately raises FileNotFoundError instead of - # NotImplementedError so that if this method is accidentally called, - # it'll still do the right thing. - raise FileNotFoundError - - @abc.abstractmethod - def is_resource(self, path: Text) -> bool: - """Return True if the named 'path' is a resource. - - Files are resources, directories are not. - """ - raise FileNotFoundError - - @abc.abstractmethod - def contents(self) -> Iterable[str]: - """Return an iterable of entries in `package`.""" - raise FileNotFoundError - - - at runtime_checkable -class Traversable(Protocol): - """ - An object with a subset of pathlib.Path methods suitable for - traversing directories and opening files. - """ - - @abc.abstractmethod - def iterdir(self): - """ - Yield Traversable objects in self - """ - - def read_bytes(self): - """ - Read contents of self as bytes - """ - with self.open('rb') as strm: - return strm.read() - - def read_text(self, encoding=None): - """ - Read contents of self as text - """ - with self.open(encoding=encoding) as strm: - return strm.read() - - @abc.abstractmethod - def is_dir(self) -> bool: - """ - Return True if self is a directory - """ - - @abc.abstractmethod - def is_file(self) -> bool: - """ - Return True if self is a file - """ - - @abc.abstractmethod - def joinpath(self, child): - """ - Return Traversable child in self - """ - - def __truediv__(self, child): - """ - Return Traversable child in self - """ - return self.joinpath(child) - - @abc.abstractmethod - def open(self, mode='r', *args, **kwargs): - """ - mode may be 'r' or 'rb' to open as text or binary. Return a handle - suitable for reading (same as pathlib.Path.open). - - When opening as text, accepts encoding parameters such as those - accepted by io.TextIOWrapper. - """ - - @abc.abstractproperty - def name(self) -> str: - """ - The base name of this object without any parent references. - """ - - -class TraversableResources(ResourceReader): - """ - The required interface for providing traversable - resources. - """ - - @abc.abstractmethod - def files(self): - """Return a Traversable object for the loaded package.""" - - def open_resource(self, resource): - return self.files().joinpath(resource).open('rb') - - def resource_path(self, resource): - raise FileNotFoundError(resource) - - def is_resource(self, path): - return self.files().joinpath(path).is_file() - - def contents(self): - return (item.name for item in self.files().iterdir()) diff --git a/Lib/importlib/readers.py b/Lib/importlib/readers.py index b470a2062b2b3..df7fb92e5cd9f 100644 --- a/Lib/importlib/readers.py +++ b/Lib/importlib/readers.py @@ -1,122 +1,12 @@ -import collections -import operator -import pathlib -import zipfile +""" +Compatibility shim for .resources.readers as found on Python 3.10. -from . import abc +Consumers that can rely on Python 3.11 should use the other +module directly. +""" -from ._itertools import unique_everseen +from .resources.readers import ( + FileReader, ZipReader, MultiplexedPath, NamespaceReader, +) - -def remove_duplicates(items): - return iter(collections.OrderedDict.fromkeys(items)) - - -class FileReader(abc.TraversableResources): - def __init__(self, loader): - self.path = pathlib.Path(loader.path).parent - - def resource_path(self, resource): - """ - Return the file system path to prevent - `resources.path()` from creating a temporary - copy. - """ - return str(self.path.joinpath(resource)) - - def files(self): - return self.path - - -class ZipReader(abc.TraversableResources): - def __init__(self, loader, module): - _, _, name = module.rpartition('.') - self.prefix = loader.prefix.replace('\\', '/') + name + '/' - self.archive = loader.archive - - def open_resource(self, resource): - try: - return super().open_resource(resource) - except KeyError as exc: - raise FileNotFoundError(exc.args[0]) - - def is_resource(self, path): - # workaround for `zipfile.Path.is_file` returning true - # for non-existent paths. - target = self.files().joinpath(path) - return target.is_file() and target.exists() - - def files(self): - return zipfile.Path(self.archive, self.prefix) - - -class MultiplexedPath(abc.Traversable): - """ - Given a series of Traversable objects, implement a merged - version of the interface across all objects. Useful for - namespace packages which may be multihomed at a single - name. - """ - - def __init__(self, *paths): - self._paths = list(map(pathlib.Path, remove_duplicates(paths))) - if not self._paths: - message = 'MultiplexedPath must contain at least one path' - raise FileNotFoundError(message) - if not all(path.is_dir() for path in self._paths): - raise NotADirectoryError('MultiplexedPath only supports directories') - - def iterdir(self): - files = (file for path in self._paths for file in path.iterdir()) - return unique_everseen(files, key=operator.attrgetter('name')) - - def read_bytes(self): - raise FileNotFoundError(f'{self} is not a file') - - def read_text(self, *args, **kwargs): - raise FileNotFoundError(f'{self} is not a file') - - def is_dir(self): - return True - - def is_file(self): - return False - - def joinpath(self, child): - # first try to find child in current paths - for file in self.iterdir(): - if file.name == child: - return file - # if it does not exist, construct it with the first path - return self._paths[0] / child - - __truediv__ = joinpath - - def open(self, *args, **kwargs): - raise FileNotFoundError(f'{self} is not a file') - - @property - def name(self): - return self._paths[0].name - - def __repr__(self): - paths = ', '.join(f"'{path}'" for path in self._paths) - return f'MultiplexedPath({paths})' - - -class NamespaceReader(abc.TraversableResources): - def __init__(self, namespace_path): - if 'NamespacePath' not in str(namespace_path): - raise ValueError('Invalid path') - self.path = MultiplexedPath(*list(namespace_path)) - - def resource_path(self, resource): - """ - Return the file system path to prevent - `resources.path()` from creating a temporary - copy. - """ - return str(self.path.joinpath(resource)) - - def files(self): - return self.path +__all__ = ['FileReader', 'ZipReader', 'MultiplexedPath', 'NamespaceReader'] diff --git a/Lib/importlib/resources.py b/Lib/importlib/resources/__init__.py similarity index 92% rename from Lib/importlib/resources.py rename to Lib/importlib/resources/__init__.py index 5b3bc0228d9ac..34e3a9950cc55 100644 --- a/Lib/importlib/resources.py +++ b/Lib/importlib/resources/__init__.py @@ -17,7 +17,7 @@ Resource, ) -from importlib.abc import ResourceReader +from .abc import ResourceReader __all__ = [ diff --git a/Lib/importlib/_adapters.py b/Lib/importlib/resources/_adapters.py similarity index 100% rename from Lib/importlib/_adapters.py rename to Lib/importlib/resources/_adapters.py diff --git a/Lib/importlib/_common.py b/Lib/importlib/resources/_common.py similarity index 100% rename from Lib/importlib/_common.py rename to Lib/importlib/resources/_common.py diff --git a/Lib/importlib/_itertools.py b/Lib/importlib/resources/_itertools.py similarity index 100% rename from Lib/importlib/_itertools.py rename to Lib/importlib/resources/_itertools.py diff --git a/Lib/importlib/_legacy.py b/Lib/importlib/resources/_legacy.py similarity index 100% rename from Lib/importlib/_legacy.py rename to Lib/importlib/resources/_legacy.py diff --git a/Lib/importlib/resources/abc.py b/Lib/importlib/resources/abc.py new file mode 100644 index 0000000000000..e9efdab5ea830 --- /dev/null +++ b/Lib/importlib/resources/abc.py @@ -0,0 +1,136 @@ +import abc +from typing import BinaryIO, Iterable, Text +from typing import runtime_checkable, Protocol + + +class ResourceReader(metaclass=abc.ABCMeta): + """Abstract base class for loaders to provide resource reading support.""" + + @abc.abstractmethod + def open_resource(self, resource: Text) -> BinaryIO: + """Return an opened, file-like object for binary reading. + + The 'resource' argument is expected to represent only a file name. + If the resource cannot be found, FileNotFoundError is raised. + """ + # This deliberately raises FileNotFoundError instead of + # NotImplementedError so that if this method is accidentally called, + # it'll still do the right thing. + raise FileNotFoundError + + @abc.abstractmethod + def resource_path(self, resource: Text) -> Text: + """Return the file system path to the specified resource. + + The 'resource' argument is expected to represent only a file name. + If the resource does not exist on the file system, raise + FileNotFoundError. + """ + # This deliberately raises FileNotFoundError instead of + # NotImplementedError so that if this method is accidentally called, + # it'll still do the right thing. + raise FileNotFoundError + + @abc.abstractmethod + def is_resource(self, path: Text) -> bool: + """Return True if the named 'path' is a resource. + + Files are resources, directories are not. + """ + raise FileNotFoundError + + @abc.abstractmethod + def contents(self) -> Iterable[str]: + """Return an iterable of entries in `package`.""" + raise FileNotFoundError + + + at runtime_checkable +class Traversable(Protocol): + """ + An object with a subset of pathlib.Path methods suitable for + traversing directories and opening files. + """ + + @abc.abstractmethod + def iterdir(self): + """ + Yield Traversable objects in self + """ + + def read_bytes(self): + """ + Read contents of self as bytes + """ + with self.open('rb') as strm: + return strm.read() + + def read_text(self, encoding=None): + """ + Read contents of self as text + """ + with self.open(encoding=encoding) as strm: + return strm.read() + + @abc.abstractmethod + def is_dir(self) -> bool: + """ + Return True if self is a directory + """ + + @abc.abstractmethod + def is_file(self) -> bool: + """ + Return True if self is a file + """ + + @abc.abstractmethod + def joinpath(self, child): + """ + Return Traversable child in self + """ + + def __truediv__(self, child): + """ + Return Traversable child in self + """ + return self.joinpath(child) + + @abc.abstractmethod + def open(self, mode='r', *args, **kwargs): + """ + mode may be 'r' or 'rb' to open as text or binary. Return a handle + suitable for reading (same as pathlib.Path.open). + + When opening as text, accepts encoding parameters such as those + accepted by io.TextIOWrapper. + """ + + @abc.abstractproperty + def name(self) -> str: + """ + The base name of this object without any parent references. + """ + + +class TraversableResources(ResourceReader): + """ + The required interface for providing traversable + resources. + """ + + @abc.abstractmethod + def files(self): + """Return a Traversable object for the loaded package.""" + + def open_resource(self, resource): + return self.files().joinpath(resource).open('rb') + + def resource_path(self, resource): + raise FileNotFoundError(resource) + + def is_resource(self, path): + return self.files().joinpath(path).is_file() + + def contents(self): + return (item.name for item in self.files().iterdir()) diff --git a/Lib/importlib/resources/readers.py b/Lib/importlib/resources/readers.py new file mode 100644 index 0000000000000..b470a2062b2b3 --- /dev/null +++ b/Lib/importlib/resources/readers.py @@ -0,0 +1,122 @@ +import collections +import operator +import pathlib +import zipfile + +from . import abc + +from ._itertools import unique_everseen + + +def remove_duplicates(items): + return iter(collections.OrderedDict.fromkeys(items)) + + +class FileReader(abc.TraversableResources): + def __init__(self, loader): + self.path = pathlib.Path(loader.path).parent + + def resource_path(self, resource): + """ + Return the file system path to prevent + `resources.path()` from creating a temporary + copy. + """ + return str(self.path.joinpath(resource)) + + def files(self): + return self.path + + +class ZipReader(abc.TraversableResources): + def __init__(self, loader, module): + _, _, name = module.rpartition('.') + self.prefix = loader.prefix.replace('\\', '/') + name + '/' + self.archive = loader.archive + + def open_resource(self, resource): + try: + return super().open_resource(resource) + except KeyError as exc: + raise FileNotFoundError(exc.args[0]) + + def is_resource(self, path): + # workaround for `zipfile.Path.is_file` returning true + # for non-existent paths. + target = self.files().joinpath(path) + return target.is_file() and target.exists() + + def files(self): + return zipfile.Path(self.archive, self.prefix) + + +class MultiplexedPath(abc.Traversable): + """ + Given a series of Traversable objects, implement a merged + version of the interface across all objects. Useful for + namespace packages which may be multihomed at a single + name. + """ + + def __init__(self, *paths): + self._paths = list(map(pathlib.Path, remove_duplicates(paths))) + if not self._paths: + message = 'MultiplexedPath must contain at least one path' + raise FileNotFoundError(message) + if not all(path.is_dir() for path in self._paths): + raise NotADirectoryError('MultiplexedPath only supports directories') + + def iterdir(self): + files = (file for path in self._paths for file in path.iterdir()) + return unique_everseen(files, key=operator.attrgetter('name')) + + def read_bytes(self): + raise FileNotFoundError(f'{self} is not a file') + + def read_text(self, *args, **kwargs): + raise FileNotFoundError(f'{self} is not a file') + + def is_dir(self): + return True + + def is_file(self): + return False + + def joinpath(self, child): + # first try to find child in current paths + for file in self.iterdir(): + if file.name == child: + return file + # if it does not exist, construct it with the first path + return self._paths[0] / child + + __truediv__ = joinpath + + def open(self, *args, **kwargs): + raise FileNotFoundError(f'{self} is not a file') + + @property + def name(self): + return self._paths[0].name + + def __repr__(self): + paths = ', '.join(f"'{path}'" for path in self._paths) + return f'MultiplexedPath({paths})' + + +class NamespaceReader(abc.TraversableResources): + def __init__(self, namespace_path): + if 'NamespacePath' not in str(namespace_path): + raise ValueError('Invalid path') + self.path = MultiplexedPath(*list(namespace_path)) + + def resource_path(self, resource): + """ + Return the file system path to prevent + `resources.path()` from creating a temporary + copy. + """ + return str(self.path.joinpath(resource)) + + def files(self): + return self.path diff --git a/Lib/importlib/resources/simple.py b/Lib/importlib/resources/simple.py new file mode 100644 index 0000000000000..da073cbdb11e6 --- /dev/null +++ b/Lib/importlib/resources/simple.py @@ -0,0 +1,116 @@ +""" +Interface adapters for low-level readers. +""" + +import abc +import io +import itertools +from typing import BinaryIO, List + +from .abc import Traversable, TraversableResources + + +class SimpleReader(abc.ABC): + """ + The minimum, low-level interface required from a resource + provider. + """ + + @abc.abstractproperty + def package(self): + # type: () -> str + """ + The name of the package for which this reader loads resources. + """ + + @abc.abstractmethod + def children(self): + # type: () -> List['SimpleReader'] + """ + Obtain an iterable of SimpleReader for available + child containers (e.g. directories). + """ + + @abc.abstractmethod + def resources(self): + # type: () -> List[str] + """ + Obtain available named resources for this virtual package. + """ + + @abc.abstractmethod + def open_binary(self, resource): + # type: (str) -> BinaryIO + """ + Obtain a File-like for a named resource. + """ + + @property + def name(self): + return self.package.split('.')[-1] + + +class ResourceHandle(Traversable): + """ + Handle to a named resource in a ResourceReader. + """ + + def __init__(self, parent, name): + # type: (ResourceContainer, str) -> None + self.parent = parent + self.name = name # type: ignore + + def is_file(self): + return True + + def is_dir(self): + return False + + def open(self, mode='r', *args, **kwargs): + stream = self.parent.reader.open_binary(self.name) + if 'b' not in mode: + stream = io.TextIOWrapper(*args, **kwargs) + return stream + + def joinpath(self, name): + raise RuntimeError("Cannot traverse into a resource") + + +class ResourceContainer(Traversable): + """ + Traversable container for a package's resources via its reader. + """ + + def __init__(self, reader): + # type: (SimpleReader) -> None + self.reader = reader + + def is_dir(self): + return True + + def is_file(self): + return False + + def iterdir(self): + files = (ResourceHandle(self, name) for name in self.reader.resources) + dirs = map(ResourceContainer, self.reader.children()) + return itertools.chain(files, dirs) + + def open(self, *args, **kwargs): + raise IsADirectoryError() + + def joinpath(self, name): + return next( + traversable for traversable in self.iterdir() if traversable.name == name + ) + + +class TraversableReader(TraversableResources, SimpleReader): + """ + A TraversableResources based on SimpleReader. Resource providers + may derive from this class to provide the TraversableResources + interface by supplying the SimpleReader interface. + """ + + def files(self): + return ResourceContainer(self) diff --git a/Lib/importlib/simple.py b/Lib/importlib/simple.py index da073cbdb11e6..845bb90364784 100644 --- a/Lib/importlib/simple.py +++ b/Lib/importlib/simple.py @@ -1,116 +1,14 @@ """ -Interface adapters for low-level readers. -""" - -import abc -import io -import itertools -from typing import BinaryIO, List - -from .abc import Traversable, TraversableResources - - -class SimpleReader(abc.ABC): - """ - The minimum, low-level interface required from a resource - provider. - """ - - @abc.abstractproperty - def package(self): - # type: () -> str - """ - The name of the package for which this reader loads resources. - """ - - @abc.abstractmethod - def children(self): - # type: () -> List['SimpleReader'] - """ - Obtain an iterable of SimpleReader for available - child containers (e.g. directories). - """ - - @abc.abstractmethod - def resources(self): - # type: () -> List[str] - """ - Obtain available named resources for this virtual package. - """ - - @abc.abstractmethod - def open_binary(self, resource): - # type: (str) -> BinaryIO - """ - Obtain a File-like for a named resource. - """ - - @property - def name(self): - return self.package.split('.')[-1] - - -class ResourceHandle(Traversable): - """ - Handle to a named resource in a ResourceReader. - """ - - def __init__(self, parent, name): - # type: (ResourceContainer, str) -> None - self.parent = parent - self.name = name # type: ignore - - def is_file(self): - return True - - def is_dir(self): - return False - - def open(self, mode='r', *args, **kwargs): - stream = self.parent.reader.open_binary(self.name) - if 'b' not in mode: - stream = io.TextIOWrapper(*args, **kwargs) - return stream - - def joinpath(self, name): - raise RuntimeError("Cannot traverse into a resource") - - -class ResourceContainer(Traversable): - """ - Traversable container for a package's resources via its reader. - """ - - def __init__(self, reader): - # type: (SimpleReader) -> None - self.reader = reader - - def is_dir(self): - return True - - def is_file(self): - return False - - def iterdir(self): - files = (ResourceHandle(self, name) for name in self.reader.resources) - dirs = map(ResourceContainer, self.reader.children()) - return itertools.chain(files, dirs) - - def open(self, *args, **kwargs): - raise IsADirectoryError() - - def joinpath(self, name): - return next( - traversable for traversable in self.iterdir() if traversable.name == name - ) +Compatibility shim for .resources.simple as found on Python 3.10. +Consumers that can rely on Python 3.11 should use the other +module directly. +""" -class TraversableReader(TraversableResources, SimpleReader): - """ - A TraversableResources based on SimpleReader. Resource providers - may derive from this class to provide the TraversableResources - interface by supplying the SimpleReader interface. - """ +from .resources.simple import ( + SimpleReader, ResourceHandle, ResourceContainer, TraversableReader, +) - def files(self): - return ResourceContainer(self) +__all__ = [ + 'SimpleReader', 'ResourceHandle', 'ResourceContainer', 'TraversableReader', +] diff --git a/Lib/test/test_importlib/test_compatibilty_files.py b/Lib/test/test_importlib/test_compatibilty_files.py index d703c060c4407..9a823f2d93058 100644 --- a/Lib/test/test_importlib/test_compatibilty_files.py +++ b/Lib/test/test_importlib/test_compatibilty_files.py @@ -3,7 +3,7 @@ from importlib import resources -from importlib._adapters import ( +from importlib.resources._adapters import ( CompatibilityFiles, wrap_spec, ) diff --git a/Misc/NEWS.d/next/Library/2021-12-17-16-27-44.bpo-46118.euAy0E.rst b/Misc/NEWS.d/next/Library/2021-12-17-16-27-44.bpo-46118.euAy0E.rst new file mode 100644 index 0000000000000..c53e5765b9785 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-17-16-27-44.bpo-46118.euAy0E.rst @@ -0,0 +1 @@ +Moved importlib.resources and its related functionality to a package. From webhook-mailer at python.org Thu Dec 30 21:17:19 2021 From: webhook-mailer at python.org (jaraco) Date: Fri, 31 Dec 2021 02:17:19 -0000 Subject: [Python-checkins] bpo-46109: Separate out files relating to importlib.resources (GH-30160) Message-ID: https://github.com/python/cpython/commit/99945c6b5cf280bd90075cffae942af44941abcc commit: 99945c6b5cf280bd90075cffae942af44941abcc branch: main author: Jason R. Coombs committer: jaraco date: 2021-12-30T21:17:05-05:00 summary: bpo-46109: Separate out files relating to importlib.resources (GH-30160) * Separate out files relating to importlib.resources * Update Introduction to direct readers to the submodule documentation. * Create separate file for abcs relating to resources. * Move abc docs back to where they were. files: A Doc/library/importlib.resources.abc.rst A Doc/library/importlib.resources.rst A Misc/NEWS.d/next/Documentation/2021-12-16-21-13-55.bpo-46109.0-RNzu.rst M Doc/library/importlib.rst M Doc/library/modules.rst diff --git a/Doc/library/importlib.resources.abc.rst b/Doc/library/importlib.resources.abc.rst new file mode 100644 index 0000000000000..6b0e1e04c8852 --- /dev/null +++ b/Doc/library/importlib.resources.abc.rst @@ -0,0 +1,385 @@ +.. class:: ResourceReader + + *Superseded by TraversableResources* + + An :term:`abstract base class` to provide the ability to read + *resources*. + + From the perspective of this ABC, a *resource* is a binary + artifact that is shipped within a package. Typically this is + something like a data file that lives next to the ``__init__.py`` + file of the package. The purpose of this class is to help abstract + out the accessing of such data files so that it does not matter if + the package and its data file(s) are stored in a e.g. zip file + versus on the file system. + + For any of methods of this class, a *resource* argument is + expected to be a :term:`path-like object` which represents + conceptually just a file name. This means that no subdirectory + paths should be included in the *resource* argument. This is + because the location of the package the reader is for, acts as the + "directory". Hence the metaphor for directories and file + names is packages and resources, respectively. This is also why + instances of this class are expected to directly correlate to + a specific package (instead of potentially representing multiple + packages or a module). + + Loaders that wish to support resource reading are expected to + provide a method called ``get_resource_reader(fullname)`` which + returns an object implementing this ABC's interface. If the module + specified by fullname is not a package, this method should return + :const:`None`. An object compatible with this ABC should only be + returned when the specified module is a package. + + .. versionadded:: 3.7 + + .. abstractmethod:: open_resource(resource) + + Returns an opened, :term:`file-like object` for binary reading + of the *resource*. + + If the resource cannot be found, :exc:`FileNotFoundError` is + raised. + + .. abstractmethod:: resource_path(resource) + + Returns the file system path to the *resource*. + + If the resource does not concretely exist on the file system, + raise :exc:`FileNotFoundError`. + + .. abstractmethod:: is_resource(name) + + Returns ``True`` if the named *name* is considered a resource. + :exc:`FileNotFoundError` is raised if *name* does not exist. + + .. abstractmethod:: contents() + + Returns an :term:`iterable` of strings over the contents of + the package. Do note that it is not required that all names + returned by the iterator be actual resources, e.g. it is + acceptable to return names for which :meth:`is_resource` would + be false. + + Allowing non-resource names to be returned is to allow for + situations where how a package and its resources are stored + are known a priori and the non-resource names would be useful. + For instance, returning subdirectory names is allowed so that + when it is known that the package and resources are stored on + the file system then those subdirectory names can be used + directly. + + The abstract method returns an iterable of no items. + + +.. class:: ResourceLoader + + An abstract base class for a :term:`loader` which implements the optional + :pep:`302` protocol for loading arbitrary resources from the storage + back-end. + + .. deprecated:: 3.7 + This ABC is deprecated in favour of supporting resource loading + through :class:`importlib.abc.ResourceReader`. + + .. abstractmethod:: get_data(path) + + An abstract method to return the bytes for the data located at *path*. + Loaders that have a file-like storage back-end + that allows storing arbitrary data + can implement this abstract method to give direct access + to the data stored. :exc:`OSError` is to be raised if the *path* cannot + be found. The *path* is expected to be constructed using a module's + :attr:`__file__` attribute or an item from a package's :attr:`__path__`. + + .. versionchanged:: 3.4 + Raises :exc:`OSError` instead of :exc:`NotImplementedError`. + + +.. class:: InspectLoader + + An abstract base class for a :term:`loader` which implements the optional + :pep:`302` protocol for loaders that inspect modules. + + .. method:: get_code(fullname) + + Return the code object for a module, or ``None`` if the module does not + have a code object (as would be the case, for example, for a built-in + module). Raise an :exc:`ImportError` if loader cannot find the + requested module. + + .. note:: + While the method has a default implementation, it is suggested that + it be overridden if possible for performance. + + .. index:: + single: universal newlines; importlib.abc.InspectLoader.get_source method + + .. versionchanged:: 3.4 + No longer abstract and a concrete implementation is provided. + + .. abstractmethod:: get_source(fullname) + + An abstract method to return the source of a module. It is returned as + a text string using :term:`universal newlines`, translating all + recognized line separators into ``'\n'`` characters. Returns ``None`` + if no source is available (e.g. a built-in module). Raises + :exc:`ImportError` if the loader cannot find the module specified. + + .. versionchanged:: 3.4 + Raises :exc:`ImportError` instead of :exc:`NotImplementedError`. + + .. method:: is_package(fullname) + + An optional method to return a true value if the module is a package, a + false value otherwise. :exc:`ImportError` is raised if the + :term:`loader` cannot find the module. + + .. versionchanged:: 3.4 + Raises :exc:`ImportError` instead of :exc:`NotImplementedError`. + + .. staticmethod:: source_to_code(data, path='') + + Create a code object from Python source. + + The *data* argument can be whatever the :func:`compile` function + supports (i.e. string or bytes). The *path* argument should be + the "path" to where the source code originated from, which can be an + abstract concept (e.g. location in a zip file). + + With the subsequent code object one can execute it in a module by + running ``exec(code, module.__dict__)``. + + .. versionadded:: 3.4 + + .. versionchanged:: 3.5 + Made the method static. + + .. method:: exec_module(module) + + Implementation of :meth:`Loader.exec_module`. + + .. versionadded:: 3.4 + + .. method:: load_module(fullname) + + Implementation of :meth:`Loader.load_module`. + + .. deprecated:: 3.4 + use :meth:`exec_module` instead. + + +.. class:: ExecutionLoader + + An abstract base class which inherits from :class:`InspectLoader` that, + when implemented, helps a module to be executed as a script. The ABC + represents an optional :pep:`302` protocol. + + .. abstractmethod:: get_filename(fullname) + + An abstract method that is to return the value of :attr:`__file__` for + the specified module. If no path is available, :exc:`ImportError` is + raised. + + If source code is available, then the method should return the path to + the source file, regardless of whether a bytecode was used to load the + module. + + .. versionchanged:: 3.4 + Raises :exc:`ImportError` instead of :exc:`NotImplementedError`. + + +.. class:: FileLoader(fullname, path) + + An abstract base class which inherits from :class:`ResourceLoader` and + :class:`ExecutionLoader`, providing concrete implementations of + :meth:`ResourceLoader.get_data` and :meth:`ExecutionLoader.get_filename`. + + The *fullname* argument is a fully resolved name of the module the loader is + to handle. The *path* argument is the path to the file for the module. + + .. versionadded:: 3.3 + + .. attribute:: name + + The name of the module the loader can handle. + + .. attribute:: path + + Path to the file of the module. + + .. method:: load_module(fullname) + + Calls super's ``load_module()``. + + .. deprecated:: 3.4 + Use :meth:`Loader.exec_module` instead. + + .. abstractmethod:: get_filename(fullname) + + Returns :attr:`path`. + + .. abstractmethod:: get_data(path) + + Reads *path* as a binary file and returns the bytes from it. + + +.. class:: SourceLoader + + An abstract base class for implementing source (and optionally bytecode) + file loading. The class inherits from both :class:`ResourceLoader` and + :class:`ExecutionLoader`, requiring the implementation of: + + * :meth:`ResourceLoader.get_data` + * :meth:`ExecutionLoader.get_filename` + Should only return the path to the source file; sourceless + loading is not supported. + + The abstract methods defined by this class are to add optional bytecode + file support. Not implementing these optional methods (or causing them to + raise :exc:`NotImplementedError`) causes the loader to + only work with source code. Implementing the methods allows the loader to + work with source *and* bytecode files; it does not allow for *sourceless* + loading where only bytecode is provided. Bytecode files are an + optimization to speed up loading by removing the parsing step of Python's + compiler, and so no bytecode-specific API is exposed. + + .. method:: path_stats(path) + + Optional abstract method which returns a :class:`dict` containing + metadata about the specified path. Supported dictionary keys are: + + - ``'mtime'`` (mandatory): an integer or floating-point number + representing the modification time of the source code; + - ``'size'`` (optional): the size in bytes of the source code. + + Any other keys in the dictionary are ignored, to allow for future + extensions. If the path cannot be handled, :exc:`OSError` is raised. + + .. versionadded:: 3.3 + + .. versionchanged:: 3.4 + Raise :exc:`OSError` instead of :exc:`NotImplementedError`. + + .. method:: path_mtime(path) + + Optional abstract method which returns the modification time for the + specified path. + + .. deprecated:: 3.3 + This method is deprecated in favour of :meth:`path_stats`. You don't + have to implement it, but it is still available for compatibility + purposes. Raise :exc:`OSError` if the path cannot be handled. + + .. versionchanged:: 3.4 + Raise :exc:`OSError` instead of :exc:`NotImplementedError`. + + .. method:: set_data(path, data) + + Optional abstract method which writes the specified bytes to a file + path. Any intermediate directories which do not exist are to be created + automatically. + + When writing to the path fails because the path is read-only + (:attr:`errno.EACCES`/:exc:`PermissionError`), do not propagate the + exception. + + .. versionchanged:: 3.4 + No longer raises :exc:`NotImplementedError` when called. + + .. method:: get_code(fullname) + + Concrete implementation of :meth:`InspectLoader.get_code`. + + .. method:: exec_module(module) + + Concrete implementation of :meth:`Loader.exec_module`. + + .. versionadded:: 3.4 + + .. method:: load_module(fullname) + + Concrete implementation of :meth:`Loader.load_module`. + + .. deprecated:: 3.4 + Use :meth:`exec_module` instead. + + .. method:: get_source(fullname) + + Concrete implementation of :meth:`InspectLoader.get_source`. + + .. method:: is_package(fullname) + + Concrete implementation of :meth:`InspectLoader.is_package`. A module + is determined to be a package if its file path (as provided by + :meth:`ExecutionLoader.get_filename`) is a file named + ``__init__`` when the file extension is removed **and** the module name + itself does not end in ``__init__``. + + +.. class:: Traversable + + An object with a subset of pathlib.Path methods suitable for + traversing directories and opening files. + + .. versionadded:: 3.9 + + .. attribute:: name + + Abstract. The base name of this object without any parent references. + + .. abstractmethod:: iterdir() + + Yield Traversable objects in self. + + .. abstractmethod:: is_dir() + + Return True if self is a directory. + + .. abstractmethod:: is_file() + + Return True if self is a file. + + .. abstractmethod:: joinpath(child) + + Return Traversable child in self. + + .. abstractmethod:: __truediv__(child) + + Return Traversable child in self. + + .. abstractmethod:: open(mode='r', *args, **kwargs) + + *mode* may be 'r' or 'rb' to open as text or binary. Return a handle + suitable for reading (same as :attr:`pathlib.Path.open`). + + When opening as text, accepts encoding parameters such as those + accepted by :attr:`io.TextIOWrapper`. + + .. method:: read_bytes() + + Read contents of self as bytes. + + .. method:: read_text(encoding=None) + + Read contents of self as text. + + +.. class:: TraversableResources + + An abstract base class for resource readers capable of serving + the :meth:`importlib.resources.files` interface. Subclasses + :class:`importlib.abc.ResourceReader` and provides + concrete implementations of the :class:`importlib.abc.ResourceReader`'s + abstract methods. Therefore, any loader supplying + :class:`importlib.abc.TraversableReader` also supplies ResourceReader. + + Loaders that wish to support resource reading are expected to + implement this interface. + + .. versionadded:: 3.9 + + .. abstractmethod:: files() + + Returns a :class:`importlib.abc.Traversable` object for the loaded + package. diff --git a/Doc/library/importlib.resources.rst b/Doc/library/importlib.resources.rst new file mode 100644 index 0000000000000..f62d15dd6fdc9 --- /dev/null +++ b/Doc/library/importlib.resources.rst @@ -0,0 +1,185 @@ +:mod:`importlib.resources` -- Resources +--------------------------------------- + +.. module:: importlib.resources + :synopsis: Package resource reading, opening, and access + +**Source code:** :source:`Lib/importlib/resources.py` + +-------------- + +.. versionadded:: 3.7 + +This module leverages Python's import system to provide access to *resources* +within *packages*. If you can import a package, you can access resources +within that package. Resources can be opened or read, in either binary or +text mode. + +Resources are roughly akin to files inside directories, though it's important +to keep in mind that this is just a metaphor. Resources and packages **do +not** have to exist as physical files and directories on the file system. + +.. note:: + + This module provides functionality similar to `pkg_resources + `_ `Basic + Resource Access + `_ + without the performance overhead of that package. This makes reading + resources included in packages easier, with more stable and consistent + semantics. + + The standalone backport of this module provides more information + on `using importlib.resources + `_ and + `migrating from pkg_resources to importlib.resources + `_ + and + `migrating legacy usage `_. + +Loaders that wish to support resource reading should implement a +``get_resource_reader(fullname)`` method as specified by +:class:`importlib.abc.ResourceReader`. + +The following types are defined. + +.. data:: Package + + The ``Package`` type is defined as ``Union[str, ModuleType]``. This means + that where the function describes accepting a ``Package``, you can pass in + either a string or a module. Module objects must have a resolvable + ``__spec__.submodule_search_locations`` that is not ``None``. + +.. data:: Resource + + This type describes the resource names passed into the various functions + in this package. This is defined as ``Union[str, os.PathLike]``. + + +The following functions are available. + + +.. function:: files(package) + + Returns an :class:`importlib.resources.abc.Traversable` object + representing the resource container for the package (think directory) + and its resources (think files). A Traversable may contain other + containers (think subdirectories). + + *package* is either a name or a module object which conforms to the + ``Package`` requirements. + + .. versionadded:: 3.9 + +.. function:: as_file(traversable) + + Given a :class:`importlib.resources.abc.Traversable` object representing + a file, typically from :func:`importlib.resources.files`, return + a context manager for use in a :keyword:`with` statement. + The context manager provides a :class:`pathlib.Path` object. + + Exiting the context manager cleans up any temporary file created when the + resource was extracted from e.g. a zip file. + + Use ``as_file`` when the Traversable methods + (``read_text``, etc) are insufficient and an actual file on + the file system is required. + + .. versionadded:: 3.9 + +.. function:: open_binary(package, resource) + + Open for binary reading the *resource* within *package*. + + *package* is either a name or a module object which conforms to the + ``Package`` requirements. *resource* is the name of the resource to open + within *package*; it may not contain path separators and it may not have + sub-resources (i.e. it cannot be a directory). This function returns a + ``typing.BinaryIO`` instance, a binary I/O stream open for reading. + + .. deprecated:: 3.11 + + +.. function:: open_text(package, resource, encoding='utf-8', errors='strict') + + Open for text reading the *resource* within *package*. By default, the + resource is opened for reading as UTF-8. + + *package* is either a name or a module object which conforms to the + ``Package`` requirements. *resource* is the name of the resource to open + within *package*; it may not contain path separators and it may not have + sub-resources (i.e. it cannot be a directory). *encoding* and *errors* + have the same meaning as with built-in :func:`open`. + + This function returns a ``typing.TextIO`` instance, a text I/O stream open + for reading. + + .. deprecated:: 3.11 + + +.. function:: read_binary(package, resource) + + Read and return the contents of the *resource* within *package* as + ``bytes``. + + *package* is either a name or a module object which conforms to the + ``Package`` requirements. *resource* is the name of the resource to open + within *package*; it may not contain path separators and it may not have + sub-resources (i.e. it cannot be a directory). This function returns the + contents of the resource as :class:`bytes`. + + .. deprecated:: 3.11 + + +.. function:: read_text(package, resource, encoding='utf-8', errors='strict') + + Read and return the contents of *resource* within *package* as a ``str``. + By default, the contents are read as strict UTF-8. + + *package* is either a name or a module object which conforms to the + ``Package`` requirements. *resource* is the name of the resource to open + within *package*; it may not contain path separators and it may not have + sub-resources (i.e. it cannot be a directory). *encoding* and *errors* + have the same meaning as with built-in :func:`open`. This function + returns the contents of the resource as :class:`str`. + + .. deprecated:: 3.11 + + +.. function:: path(package, resource) + + Return the path to the *resource* as an actual file system path. This + function returns a context manager for use in a :keyword:`with` statement. + The context manager provides a :class:`pathlib.Path` object. + + Exiting the context manager cleans up any temporary file created when the + resource needs to be extracted from e.g. a zip file. + + *package* is either a name or a module object which conforms to the + ``Package`` requirements. *resource* is the name of the resource to open + within *package*; it may not contain path separators and it may not have + sub-resources (i.e. it cannot be a directory). + + .. deprecated:: 3.11 + + +.. function:: is_resource(package, name) + + Return ``True`` if there is a resource named *name* in the package, + otherwise ``False``. Remember that directories are *not* resources! + *package* is either a name or a module object which conforms to the + ``Package`` requirements. + + .. deprecated:: 3.11 + + +.. function:: contents(package) + + Return an iterable over the named items within the package. The iterable + returns :class:`str` resources (e.g. files) and non-resources + (e.g. directories). The iterable does not recurse into subdirectories. + + *package* is either a name or a module object which conforms to the + ``Package`` requirements. + + .. deprecated:: 3.11 diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst index 347e08e4a2846..23d908196669f 100644 --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -13,10 +13,13 @@ -------------- + Introduction ------------ -The purpose of the :mod:`importlib` package is two-fold. One is to provide the +The purpose of the :mod:`importlib` package is three-fold. + +One is to provide the implementation of the :keyword:`import` statement (and thus, by extension, the :func:`__import__` function) in Python source code. This provides an implementation of :keyword:`!import` which is portable to any Python @@ -27,6 +30,14 @@ Two, the components to implement :keyword:`import` are exposed in this package, making it easier for users to create their own custom objects (known generically as an :term:`importer`) to participate in the import process. +Three, the package contains modules exposing additional functionality for +managing aspects of Python packages: + +* :mod:`importlib.metadata` presents access to metadata from third-party + distributions. +* :mod:`importlib.resources` provides routines for accessing non-code + "resources" from Python packages. + .. seealso:: :ref:`import` @@ -495,578 +506,7 @@ ABC hierarchy:: The import machinery now takes care of this automatically. -.. class:: ResourceReader - - *Superseded by TraversableResources* - - An :term:`abstract base class` to provide the ability to read - *resources*. - - From the perspective of this ABC, a *resource* is a binary - artifact that is shipped within a package. Typically this is - something like a data file that lives next to the ``__init__.py`` - file of the package. The purpose of this class is to help abstract - out the accessing of such data files so that it does not matter if - the package and its data file(s) are stored in a e.g. zip file - versus on the file system. - - For any of methods of this class, a *resource* argument is - expected to be a :term:`path-like object` which represents - conceptually just a file name. This means that no subdirectory - paths should be included in the *resource* argument. This is - because the location of the package the reader is for, acts as the - "directory". Hence the metaphor for directories and file - names is packages and resources, respectively. This is also why - instances of this class are expected to directly correlate to - a specific package (instead of potentially representing multiple - packages or a module). - - Loaders that wish to support resource reading are expected to - provide a method called ``get_resource_reader(fullname)`` which - returns an object implementing this ABC's interface. If the module - specified by fullname is not a package, this method should return - :const:`None`. An object compatible with this ABC should only be - returned when the specified module is a package. - - .. versionadded:: 3.7 - - .. abstractmethod:: open_resource(resource) - - Returns an opened, :term:`file-like object` for binary reading - of the *resource*. - - If the resource cannot be found, :exc:`FileNotFoundError` is - raised. - - .. abstractmethod:: resource_path(resource) - - Returns the file system path to the *resource*. - - If the resource does not concretely exist on the file system, - raise :exc:`FileNotFoundError`. - - .. abstractmethod:: is_resource(name) - - Returns ``True`` if the named *name* is considered a resource. - :exc:`FileNotFoundError` is raised if *name* does not exist. - - .. abstractmethod:: contents() - - Returns an :term:`iterable` of strings over the contents of - the package. Do note that it is not required that all names - returned by the iterator be actual resources, e.g. it is - acceptable to return names for which :meth:`is_resource` would - be false. - - Allowing non-resource names to be returned is to allow for - situations where how a package and its resources are stored - are known a priori and the non-resource names would be useful. - For instance, returning subdirectory names is allowed so that - when it is known that the package and resources are stored on - the file system then those subdirectory names can be used - directly. - - The abstract method returns an iterable of no items. - - -.. class:: ResourceLoader - - An abstract base class for a :term:`loader` which implements the optional - :pep:`302` protocol for loading arbitrary resources from the storage - back-end. - - .. deprecated:: 3.7 - This ABC is deprecated in favour of supporting resource loading - through :class:`importlib.abc.ResourceReader`. - - .. abstractmethod:: get_data(path) - - An abstract method to return the bytes for the data located at *path*. - Loaders that have a file-like storage back-end - that allows storing arbitrary data - can implement this abstract method to give direct access - to the data stored. :exc:`OSError` is to be raised if the *path* cannot - be found. The *path* is expected to be constructed using a module's - :attr:`__file__` attribute or an item from a package's :attr:`__path__`. - - .. versionchanged:: 3.4 - Raises :exc:`OSError` instead of :exc:`NotImplementedError`. - - -.. class:: InspectLoader - - An abstract base class for a :term:`loader` which implements the optional - :pep:`302` protocol for loaders that inspect modules. - - .. method:: get_code(fullname) - - Return the code object for a module, or ``None`` if the module does not - have a code object (as would be the case, for example, for a built-in - module). Raise an :exc:`ImportError` if loader cannot find the - requested module. - - .. note:: - While the method has a default implementation, it is suggested that - it be overridden if possible for performance. - - .. index:: - single: universal newlines; importlib.abc.InspectLoader.get_source method - - .. versionchanged:: 3.4 - No longer abstract and a concrete implementation is provided. - - .. abstractmethod:: get_source(fullname) - - An abstract method to return the source of a module. It is returned as - a text string using :term:`universal newlines`, translating all - recognized line separators into ``'\n'`` characters. Returns ``None`` - if no source is available (e.g. a built-in module). Raises - :exc:`ImportError` if the loader cannot find the module specified. - - .. versionchanged:: 3.4 - Raises :exc:`ImportError` instead of :exc:`NotImplementedError`. - - .. method:: is_package(fullname) - - An optional method to return a true value if the module is a package, a - false value otherwise. :exc:`ImportError` is raised if the - :term:`loader` cannot find the module. - - .. versionchanged:: 3.4 - Raises :exc:`ImportError` instead of :exc:`NotImplementedError`. - - .. staticmethod:: source_to_code(data, path='') - - Create a code object from Python source. - - The *data* argument can be whatever the :func:`compile` function - supports (i.e. string or bytes). The *path* argument should be - the "path" to where the source code originated from, which can be an - abstract concept (e.g. location in a zip file). - - With the subsequent code object one can execute it in a module by - running ``exec(code, module.__dict__)``. - - .. versionadded:: 3.4 - - .. versionchanged:: 3.5 - Made the method static. - - .. method:: exec_module(module) - - Implementation of :meth:`Loader.exec_module`. - - .. versionadded:: 3.4 - - .. method:: load_module(fullname) - - Implementation of :meth:`Loader.load_module`. - - .. deprecated:: 3.4 - use :meth:`exec_module` instead. - - -.. class:: ExecutionLoader - - An abstract base class which inherits from :class:`InspectLoader` that, - when implemented, helps a module to be executed as a script. The ABC - represents an optional :pep:`302` protocol. - - .. abstractmethod:: get_filename(fullname) - - An abstract method that is to return the value of :attr:`__file__` for - the specified module. If no path is available, :exc:`ImportError` is - raised. - - If source code is available, then the method should return the path to - the source file, regardless of whether a bytecode was used to load the - module. - - .. versionchanged:: 3.4 - Raises :exc:`ImportError` instead of :exc:`NotImplementedError`. - - -.. class:: FileLoader(fullname, path) - - An abstract base class which inherits from :class:`ResourceLoader` and - :class:`ExecutionLoader`, providing concrete implementations of - :meth:`ResourceLoader.get_data` and :meth:`ExecutionLoader.get_filename`. - - The *fullname* argument is a fully resolved name of the module the loader is - to handle. The *path* argument is the path to the file for the module. - - .. versionadded:: 3.3 - - .. attribute:: name - - The name of the module the loader can handle. - - .. attribute:: path - - Path to the file of the module. - - .. method:: load_module(fullname) - - Calls super's ``load_module()``. - - .. deprecated:: 3.4 - Use :meth:`Loader.exec_module` instead. - - .. abstractmethod:: get_filename(fullname) - - Returns :attr:`path`. - - .. abstractmethod:: get_data(path) - - Reads *path* as a binary file and returns the bytes from it. - - -.. class:: SourceLoader - - An abstract base class for implementing source (and optionally bytecode) - file loading. The class inherits from both :class:`ResourceLoader` and - :class:`ExecutionLoader`, requiring the implementation of: - - * :meth:`ResourceLoader.get_data` - * :meth:`ExecutionLoader.get_filename` - Should only return the path to the source file; sourceless - loading is not supported. - - The abstract methods defined by this class are to add optional bytecode - file support. Not implementing these optional methods (or causing them to - raise :exc:`NotImplementedError`) causes the loader to - only work with source code. Implementing the methods allows the loader to - work with source *and* bytecode files; it does not allow for *sourceless* - loading where only bytecode is provided. Bytecode files are an - optimization to speed up loading by removing the parsing step of Python's - compiler, and so no bytecode-specific API is exposed. - - .. method:: path_stats(path) - - Optional abstract method which returns a :class:`dict` containing - metadata about the specified path. Supported dictionary keys are: - - - ``'mtime'`` (mandatory): an integer or floating-point number - representing the modification time of the source code; - - ``'size'`` (optional): the size in bytes of the source code. - - Any other keys in the dictionary are ignored, to allow for future - extensions. If the path cannot be handled, :exc:`OSError` is raised. - - .. versionadded:: 3.3 - - .. versionchanged:: 3.4 - Raise :exc:`OSError` instead of :exc:`NotImplementedError`. - - .. method:: path_mtime(path) - - Optional abstract method which returns the modification time for the - specified path. - - .. deprecated:: 3.3 - This method is deprecated in favour of :meth:`path_stats`. You don't - have to implement it, but it is still available for compatibility - purposes. Raise :exc:`OSError` if the path cannot be handled. - - .. versionchanged:: 3.4 - Raise :exc:`OSError` instead of :exc:`NotImplementedError`. - - .. method:: set_data(path, data) - - Optional abstract method which writes the specified bytes to a file - path. Any intermediate directories which do not exist are to be created - automatically. - - When writing to the path fails because the path is read-only - (:attr:`errno.EACCES`/:exc:`PermissionError`), do not propagate the - exception. - - .. versionchanged:: 3.4 - No longer raises :exc:`NotImplementedError` when called. - - .. method:: get_code(fullname) - - Concrete implementation of :meth:`InspectLoader.get_code`. - - .. method:: exec_module(module) - - Concrete implementation of :meth:`Loader.exec_module`. - - .. versionadded:: 3.4 - - .. method:: load_module(fullname) - - Concrete implementation of :meth:`Loader.load_module`. - - .. deprecated:: 3.4 - Use :meth:`exec_module` instead. - - .. method:: get_source(fullname) - - Concrete implementation of :meth:`InspectLoader.get_source`. - - .. method:: is_package(fullname) - - Concrete implementation of :meth:`InspectLoader.is_package`. A module - is determined to be a package if its file path (as provided by - :meth:`ExecutionLoader.get_filename`) is a file named - ``__init__`` when the file extension is removed **and** the module name - itself does not end in ``__init__``. - - -.. class:: Traversable - - An object with a subset of pathlib.Path methods suitable for - traversing directories and opening files. - - .. versionadded:: 3.9 - - .. attribute:: name - - Abstract. The base name of this object without any parent references. - - .. abstractmethod:: iterdir() - - Yield Traversable objects in self. - - .. abstractmethod:: is_dir() - - Return True if self is a directory. - - .. abstractmethod:: is_file() - - Return True if self is a file. - - .. abstractmethod:: joinpath(child) - - Return Traversable child in self. - - .. abstractmethod:: __truediv__(child) - - Return Traversable child in self. - - .. abstractmethod:: open(mode='r', *args, **kwargs) - - *mode* may be 'r' or 'rb' to open as text or binary. Return a handle - suitable for reading (same as :attr:`pathlib.Path.open`). - - When opening as text, accepts encoding parameters such as those - accepted by :attr:`io.TextIOWrapper`. - - .. method:: read_bytes() - - Read contents of self as bytes. - - .. method:: read_text(encoding=None) - - Read contents of self as text. - - -.. class:: TraversableResources - - An abstract base class for resource readers capable of serving - the :meth:`importlib.resources.files` interface. Subclasses - :class:`importlib.abc.ResourceReader` and provides - concrete implementations of the :class:`importlib.abc.ResourceReader`'s - abstract methods. Therefore, any loader supplying - :class:`importlib.abc.TraversableReader` also supplies ResourceReader. - - Loaders that wish to support resource reading are expected to - implement this interface. - - .. versionadded:: 3.9 - - .. abstractmethod:: files() - - Returns a :class:`importlib.abc.Traversable` object for the loaded - package. - - -:mod:`importlib.resources` -- Resources ---------------------------------------- - -.. module:: importlib.resources - :synopsis: Package resource reading, opening, and access - -**Source code:** :source:`Lib/importlib/resources.py` - --------------- - -.. versionadded:: 3.7 - -This module leverages Python's import system to provide access to *resources* -within *packages*. If you can import a package, you can access resources -within that package. Resources can be opened or read, in either binary or -text mode. - -Resources are roughly akin to files inside directories, though it's important -to keep in mind that this is just a metaphor. Resources and packages **do -not** have to exist as physical files and directories on the file system. - -.. note:: - - This module provides functionality similar to `pkg_resources - `_ `Basic - Resource Access - `_ - without the performance overhead of that package. This makes reading - resources included in packages easier, with more stable and consistent - semantics. - - The standalone backport of this module provides more information - on `using importlib.resources - `_ and - `migrating from pkg_resources to importlib.resources - `_ - and - `migrating legacy usage `_. - -Loaders that wish to support resource reading should implement a -``get_resource_reader(fullname)`` method as specified by -:class:`importlib.abc.ResourceReader`. - -The following types are defined. - -.. data:: Package - - The ``Package`` type is defined as ``Union[str, ModuleType]``. This means - that where the function describes accepting a ``Package``, you can pass in - either a string or a module. Module objects must have a resolvable - ``__spec__.submodule_search_locations`` that is not ``None``. - -.. data:: Resource - - This type describes the resource names passed into the various functions - in this package. This is defined as ``Union[str, os.PathLike]``. - - -The following functions are available. - - -.. function:: files(package) - - Returns an :class:`importlib.resources.abc.Traversable` object - representing the resource container for the package (think directory) - and its resources (think files). A Traversable may contain other - containers (think subdirectories). - - *package* is either a name or a module object which conforms to the - ``Package`` requirements. - - .. versionadded:: 3.9 - -.. function:: as_file(traversable) - - Given a :class:`importlib.resources.abc.Traversable` object representing - a file, typically from :func:`importlib.resources.files`, return - a context manager for use in a :keyword:`with` statement. - The context manager provides a :class:`pathlib.Path` object. - - Exiting the context manager cleans up any temporary file created when the - resource was extracted from e.g. a zip file. - - Use ``as_file`` when the Traversable methods - (``read_text``, etc) are insufficient and an actual file on - the file system is required. - - .. versionadded:: 3.9 - -.. function:: open_binary(package, resource) - - Open for binary reading the *resource* within *package*. - - *package* is either a name or a module object which conforms to the - ``Package`` requirements. *resource* is the name of the resource to open - within *package*; it may not contain path separators and it may not have - sub-resources (i.e. it cannot be a directory). This function returns a - ``typing.BinaryIO`` instance, a binary I/O stream open for reading. - - .. deprecated:: 3.11 - - -.. function:: open_text(package, resource, encoding='utf-8', errors='strict') - - Open for text reading the *resource* within *package*. By default, the - resource is opened for reading as UTF-8. - - *package* is either a name or a module object which conforms to the - ``Package`` requirements. *resource* is the name of the resource to open - within *package*; it may not contain path separators and it may not have - sub-resources (i.e. it cannot be a directory). *encoding* and *errors* - have the same meaning as with built-in :func:`open`. - - This function returns a ``typing.TextIO`` instance, a text I/O stream open - for reading. - - .. deprecated:: 3.11 - - -.. function:: read_binary(package, resource) - - Read and return the contents of the *resource* within *package* as - ``bytes``. - - *package* is either a name or a module object which conforms to the - ``Package`` requirements. *resource* is the name of the resource to open - within *package*; it may not contain path separators and it may not have - sub-resources (i.e. it cannot be a directory). This function returns the - contents of the resource as :class:`bytes`. - - .. deprecated:: 3.11 - - -.. function:: read_text(package, resource, encoding='utf-8', errors='strict') - - Read and return the contents of *resource* within *package* as a ``str``. - By default, the contents are read as strict UTF-8. - - *package* is either a name or a module object which conforms to the - ``Package`` requirements. *resource* is the name of the resource to open - within *package*; it may not contain path separators and it may not have - sub-resources (i.e. it cannot be a directory). *encoding* and *errors* - have the same meaning as with built-in :func:`open`. This function - returns the contents of the resource as :class:`str`. - - .. deprecated:: 3.11 - - -.. function:: path(package, resource) - - Return the path to the *resource* as an actual file system path. This - function returns a context manager for use in a :keyword:`with` statement. - The context manager provides a :class:`pathlib.Path` object. - - Exiting the context manager cleans up any temporary file created when the - resource needs to be extracted from e.g. a zip file. - - *package* is either a name or a module object which conforms to the - ``Package`` requirements. *resource* is the name of the resource to open - within *package*; it may not contain path separators and it may not have - sub-resources (i.e. it cannot be a directory). - - .. deprecated:: 3.11 - - -.. function:: is_resource(package, name) - - Return ``True`` if there is a resource named *name* in the package, - otherwise ``False``. Remember that directories are *not* resources! - *package* is either a name or a module object which conforms to the - ``Package`` requirements. - - .. deprecated:: 3.11 - - -.. function:: contents(package) - - Return an iterable over the named items within the package. The iterable - returns :class:`str` resources (e.g. files) and non-resources - (e.g. directories). The iterable does not recurse into subdirectories. - - *package* is either a name or a module object which conforms to the - ``Package`` requirements. - - .. deprecated:: 3.11 +.. include:: importlib.resources.abc.rst :mod:`importlib.machinery` -- Importers and path hooks diff --git a/Doc/library/modules.rst b/Doc/library/modules.rst index 565ce0525c2c9..131dfca9576a3 100644 --- a/Doc/library/modules.rst +++ b/Doc/library/modules.rst @@ -17,4 +17,5 @@ The full list of modules described in this chapter is: modulefinder.rst runpy.rst importlib.rst + importlib.resources.rst importlib.metadata.rst diff --git a/Misc/NEWS.d/next/Documentation/2021-12-16-21-13-55.bpo-46109.0-RNzu.rst b/Misc/NEWS.d/next/Documentation/2021-12-16-21-13-55.bpo-46109.0-RNzu.rst new file mode 100644 index 0000000000000..78d5149c80022 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-12-16-21-13-55.bpo-46109.0-RNzu.rst @@ -0,0 +1,2 @@ +Extracted ``importlib.resources`` and ``importlib.resources.abc`` documentation into +separate files. From webhook-mailer at python.org Thu Dec 30 22:39:28 2021 From: webhook-mailer at python.org (jaraco) Date: Fri, 31 Dec 2021 03:39:28 -0000 Subject: [Python-checkins] bpo-46118: Make sure importlib.resources is included. (GH-30311) Message-ID: https://github.com/python/cpython/commit/35628e4cde71e54afe12aea50c74069afe2c3389 commit: 35628e4cde71e54afe12aea50c74069afe2c3389 branch: main author: Jason R. Coombs committer: jaraco date: 2021-12-30T22:39:24-05:00 summary: bpo-46118: Make sure importlib.resources is included. (GH-30311) files: M Makefile.pre.in diff --git a/Makefile.pre.in b/Makefile.pre.in index ed77bebfab901..fbd4c3a23fd81 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1911,7 +1911,7 @@ LIBSUBDIRS= asyncio \ html \ http \ idlelib idlelib/Icons \ - importlib importlib/metadata \ + importlib importlib/resources importlib/metadata \ json \ lib2to3 lib2to3/fixes lib2to3/pgen2 \ logging \ From webhook-mailer at python.org Fri Dec 31 04:57:33 2021 From: webhook-mailer at python.org (scoder) Date: Fri, 31 Dec 2021 09:57:33 -0000 Subject: [Python-checkins] bpo-45321: Add missing error codes to module `xml.parsers.expat.errors` (GH-30188) Message-ID: https://github.com/python/cpython/commit/e18d81569fa0564f3bc7bcfd2fce26ec91ba0a6e commit: e18d81569fa0564f3bc7bcfd2fce26ec91ba0a6e branch: main author: Sebastian Pipping committer: scoder date: 2021-12-31T10:57:00+01:00 summary: bpo-45321: Add missing error codes to module `xml.parsers.expat.errors` (GH-30188) The idea is to ensure that module `xml.parsers.expat.errors` contains all known error codes and messages, even when CPython is compiled or run with an outdated version of libexpat. https://bugs.python.org/issue45321 files: A Misc/NEWS.d/next/Library/2021-12-19-00-00-48.bpo-45321.OyuhaY.rst M Doc/library/pyexpat.rst M Modules/pyexpat.c diff --git a/Doc/library/pyexpat.rst b/Doc/library/pyexpat.rst index 034e579315de0..d6581e21b01c0 100644 --- a/Doc/library/pyexpat.rst +++ b/Doc/library/pyexpat.rst @@ -867,6 +867,40 @@ The ``errors`` module has the following attributes: .. data:: XML_ERROR_SUSPEND_PE +.. data:: XML_ERROR_RESERVED_PREFIX_XML + + An attempt was made to + undeclare reserved namespace prefix ``xml`` + or to bind it to another namespace URI. + + +.. data:: XML_ERROR_RESERVED_PREFIX_XMLNS + + An attempt was made to declare or undeclare reserved namespace prefix ``xmlns``. + + +.. data:: XML_ERROR_RESERVED_NAMESPACE_URI + + An attempt was made to bind the URI of one the reserved namespace + prefixes ``xml`` and ``xmlns`` to another namespace prefix. + + +.. data:: XML_ERROR_INVALID_ARGUMENT + + This should not be reported to Python applications. + + +.. data:: XML_ERROR_NO_BUFFER + + This should not be reported to Python applications. + + +.. data:: XML_ERROR_AMPLIFICATION_LIMIT_BREACH + + The limit on input amplification factor (from DTD and entities) + has been breached. + + .. rubric:: Footnotes .. [1] The encoding string included in XML output should conform to the diff --git a/Misc/NEWS.d/next/Library/2021-12-19-00-00-48.bpo-45321.OyuhaY.rst b/Misc/NEWS.d/next/Library/2021-12-19-00-00-48.bpo-45321.OyuhaY.rst new file mode 100644 index 0000000000000..171bf8a43e645 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-19-00-00-48.bpo-45321.OyuhaY.rst @@ -0,0 +1 @@ +Added missing error codes to module ``xml.parsers.expat.errors``. diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c index b3d9bdda7e7ac..f2baab757f90c 100644 --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -1650,16 +1650,95 @@ add_submodule(PyObject *mod, const char *fullname) return submodule; } +struct ErrorInfo { + const char * name; /* Error constant name, e.g. "XML_ERROR_NO_MEMORY" */ + const char * description; /* Error description as returned by XML_ErrorString() */ +}; + +static +struct ErrorInfo error_info_of[] = { + {NULL, NULL}, /* XML_ERROR_NONE (value 0) is not exposed */ + + {"XML_ERROR_NO_MEMORY", "out of memory"}, + {"XML_ERROR_SYNTAX", "syntax error"}, + {"XML_ERROR_NO_ELEMENTS", "no element found"}, + {"XML_ERROR_INVALID_TOKEN", "not well-formed (invalid token)"}, + {"XML_ERROR_UNCLOSED_TOKEN", "unclosed token"}, + {"XML_ERROR_PARTIAL_CHAR", "partial character"}, + {"XML_ERROR_TAG_MISMATCH", "mismatched tag"}, + {"XML_ERROR_DUPLICATE_ATTRIBUTE", "duplicate attribute"}, + {"XML_ERROR_JUNK_AFTER_DOC_ELEMENT", "junk after document element"}, + {"XML_ERROR_PARAM_ENTITY_REF", "illegal parameter entity reference"}, + {"XML_ERROR_UNDEFINED_ENTITY", "undefined entity"}, + {"XML_ERROR_RECURSIVE_ENTITY_REF", "recursive entity reference"}, + {"XML_ERROR_ASYNC_ENTITY", "asynchronous entity"}, + {"XML_ERROR_BAD_CHAR_REF", "reference to invalid character number"}, + {"XML_ERROR_BINARY_ENTITY_REF", "reference to binary entity"}, + {"XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF", "reference to external entity in attribute"}, + {"XML_ERROR_MISPLACED_XML_PI", "XML or text declaration not at start of entity"}, + {"XML_ERROR_UNKNOWN_ENCODING", "unknown encoding"}, + {"XML_ERROR_INCORRECT_ENCODING", "encoding specified in XML declaration is incorrect"}, + {"XML_ERROR_UNCLOSED_CDATA_SECTION", "unclosed CDATA section"}, + {"XML_ERROR_EXTERNAL_ENTITY_HANDLING", "error in processing external entity reference"}, + {"XML_ERROR_NOT_STANDALONE", "document is not standalone"}, + {"XML_ERROR_UNEXPECTED_STATE", "unexpected parser state - please send a bug report"}, + {"XML_ERROR_ENTITY_DECLARED_IN_PE", "entity declared in parameter entity"}, + {"XML_ERROR_FEATURE_REQUIRES_XML_DTD", "requested feature requires XML_DTD support in Expat"}, + {"XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING", "cannot change setting once parsing has begun"}, + + /* Added in Expat 1.95.7. */ + {"XML_ERROR_UNBOUND_PREFIX", "unbound prefix"}, + + /* Added in Expat 1.95.8. */ + {"XML_ERROR_UNDECLARING_PREFIX", "must not undeclare prefix"}, + {"XML_ERROR_INCOMPLETE_PE", "incomplete markup in parameter entity"}, + {"XML_ERROR_XML_DECL", "XML declaration not well-formed"}, + {"XML_ERROR_TEXT_DECL", "text declaration not well-formed"}, + {"XML_ERROR_PUBLICID", "illegal character(s) in public id"}, + {"XML_ERROR_SUSPENDED", "parser suspended"}, + {"XML_ERROR_NOT_SUSPENDED", "parser not suspended"}, + {"XML_ERROR_ABORTED", "parsing aborted"}, + {"XML_ERROR_FINISHED", "parsing finished"}, + {"XML_ERROR_SUSPEND_PE", "cannot suspend in external parameter entity"}, + + /* Added in 2.0.0. */ + {"XML_ERROR_RESERVED_PREFIX_XML", "reserved prefix (xml) must not be undeclared or bound to another namespace name"}, + {"XML_ERROR_RESERVED_PREFIX_XMLNS", "reserved prefix (xmlns) must not be declared or undeclared"}, + {"XML_ERROR_RESERVED_NAMESPACE_URI", "prefix must not be bound to one of the reserved namespace names"}, + + /* Added in 2.2.1. */ + {"XML_ERROR_INVALID_ARGUMENT", "invalid argument"}, + + /* Added in 2.3.0. */ + {"XML_ERROR_NO_BUFFER", "a successful prior call to function XML_GetBuffer is required"}, + + /* Added in 2.4.0. */ + {"XML_ERROR_AMPLIFICATION_LIMIT_BREACH", "limit on input amplification factor (from DTD and entities) breached"} +}; + static int add_error(PyObject *errors_module, PyObject *codes_dict, - PyObject *rev_codes_dict, const char *name, int value) + PyObject *rev_codes_dict, size_t error_index) { - const char *error_string = XML_ErrorString(value); + const char * const name = error_info_of[error_index].name; + const int error_code = (int)error_index; + + /* NOTE: This keeps the source of truth regarding error + * messages with libexpat and (by definiton) in bulletproof sync + * with the other uses of the XML_ErrorString function + * elsewhere within this file. pyexpat's copy of the messages + * only acts as a fallback in case of outdated runtime libexpat, + * where it returns NULL. */ + const char *error_string = XML_ErrorString(error_code); + if (error_string == NULL) { + error_string = error_info_of[error_index].description; + } + if (PyModule_AddStringConstant(errors_module, name, error_string) < 0) { return -1; } - PyObject *num = PyLong_FromLong(value); + PyObject *num = PyLong_FromLong(error_code); if (num == NULL) { return -1; } @@ -1699,53 +1778,16 @@ add_errors_module(PyObject *mod) goto error; } -#define ADD_CONST(name) do { \ - if (add_error(errors_module, codes_dict, rev_codes_dict, \ - #name, name) < 0) { \ - goto error; \ - } \ - } while(0) + size_t error_index = 0; + for (; error_index < sizeof(error_info_of) / sizeof(struct ErrorInfo); error_index++) { + if (error_info_of[error_index].name == NULL) { + continue; + } - ADD_CONST(XML_ERROR_NO_MEMORY); - ADD_CONST(XML_ERROR_SYNTAX); - ADD_CONST(XML_ERROR_NO_ELEMENTS); - ADD_CONST(XML_ERROR_INVALID_TOKEN); - ADD_CONST(XML_ERROR_UNCLOSED_TOKEN); - ADD_CONST(XML_ERROR_PARTIAL_CHAR); - ADD_CONST(XML_ERROR_TAG_MISMATCH); - ADD_CONST(XML_ERROR_DUPLICATE_ATTRIBUTE); - ADD_CONST(XML_ERROR_JUNK_AFTER_DOC_ELEMENT); - ADD_CONST(XML_ERROR_PARAM_ENTITY_REF); - ADD_CONST(XML_ERROR_UNDEFINED_ENTITY); - ADD_CONST(XML_ERROR_RECURSIVE_ENTITY_REF); - ADD_CONST(XML_ERROR_ASYNC_ENTITY); - ADD_CONST(XML_ERROR_BAD_CHAR_REF); - ADD_CONST(XML_ERROR_BINARY_ENTITY_REF); - ADD_CONST(XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF); - ADD_CONST(XML_ERROR_MISPLACED_XML_PI); - ADD_CONST(XML_ERROR_UNKNOWN_ENCODING); - ADD_CONST(XML_ERROR_INCORRECT_ENCODING); - ADD_CONST(XML_ERROR_UNCLOSED_CDATA_SECTION); - ADD_CONST(XML_ERROR_EXTERNAL_ENTITY_HANDLING); - ADD_CONST(XML_ERROR_NOT_STANDALONE); - ADD_CONST(XML_ERROR_UNEXPECTED_STATE); - ADD_CONST(XML_ERROR_ENTITY_DECLARED_IN_PE); - ADD_CONST(XML_ERROR_FEATURE_REQUIRES_XML_DTD); - ADD_CONST(XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING); - /* Added in Expat 1.95.7. */ - ADD_CONST(XML_ERROR_UNBOUND_PREFIX); - /* Added in Expat 1.95.8. */ - ADD_CONST(XML_ERROR_UNDECLARING_PREFIX); - ADD_CONST(XML_ERROR_INCOMPLETE_PE); - ADD_CONST(XML_ERROR_XML_DECL); - ADD_CONST(XML_ERROR_TEXT_DECL); - ADD_CONST(XML_ERROR_PUBLICID); - ADD_CONST(XML_ERROR_SUSPENDED); - ADD_CONST(XML_ERROR_NOT_SUSPENDED); - ADD_CONST(XML_ERROR_ABORTED); - ADD_CONST(XML_ERROR_FINISHED); - ADD_CONST(XML_ERROR_SUSPEND_PE); -#undef ADD_CONST + if (add_error(errors_module, codes_dict, rev_codes_dict, error_index) < 0) { + goto error; + } + } if (PyModule_AddStringConstant(errors_module, "__doc__", "Constants used to describe " From webhook-mailer at python.org Fri Dec 31 14:52:35 2021 From: webhook-mailer at python.org (mdickinson) Date: Fri, 31 Dec 2021 19:52:35 -0000 Subject: [Python-checkins] bpo-37295: More direct computation of power-of-two factor in math.comb (GH-30313) Message-ID: https://github.com/python/cpython/commit/0b58bac3e7877d722bdbd3c38913dba2cb212f13 commit: 0b58bac3e7877d722bdbd3c38913dba2cb212f13 branch: main author: Mark Dickinson committer: mdickinson date: 2021-12-31T19:52:27Z summary: bpo-37295: More direct computation of power-of-two factor in math.comb (GH-30313) Co-authored-by: Serhiy Storchaka files: M Modules/mathmodule.c diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index c4a23b6514f6b..952c51304a9fc 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -3462,7 +3462,7 @@ Python code to generate the values: reduced_fac_odd_part = fac_odd_part % (2**64) print(f"{reduced_fac_odd_part:#018x}u") */ -static uint64_t reduced_factorial_odd_part[] = { +static const uint64_t reduced_factorial_odd_part[] = { 0x0000000000000001u, 0x0000000000000001u, 0x0000000000000001u, 0x0000000000000003u, 0x0000000000000003u, 0x000000000000000fu, 0x000000000000002du, 0x000000000000013bu, 0x000000000000013bu, 0x0000000000000b13u, 0x000000000000375fu, 0x0000000000026115u, @@ -3494,7 +3494,7 @@ Python code to generate the values: inverted_fac_odd_part = pow(fac_odd_part, -1, 2**64) print(f"{inverted_fac_odd_part:#018x}u") */ -static uint64_t inverted_factorial_odd_part[] = { +static const uint64_t inverted_factorial_odd_part[] = { 0x0000000000000001u, 0x0000000000000001u, 0x0000000000000001u, 0xaaaaaaaaaaaaaaabu, 0xaaaaaaaaaaaaaaabu, 0xeeeeeeeeeeeeeeefu, 0x4fa4fa4fa4fa4fa5u, 0x2ff2ff2ff2ff2ff3u, 0x2ff2ff2ff2ff2ff3u, 0x938cc70553e3771bu, 0xb71c27cddd93e49fu, 0xb38e3229fcdee63du, @@ -3514,6 +3514,25 @@ static uint64_t inverted_factorial_odd_part[] = { 0x547fb1b8ab9d0ba3u, 0x8f15a826498852e3u, 0x32e1a03f38880283u, 0x3de4cce63283f0c1u, }; +/* exponent of the largest power of 2 dividing factorial(n), for n in range(68) + +Python code to generate the values: + +import math + +for n in range(68): + fac = math.factorial(n) + fac_trailing_zeros = (fac & -fac).bit_length() - 1 + print(fac_trailing_zeros) +*/ + +static const uint8_t factorial_trailing_zeros[] = { + 0, 0, 1, 1, 3, 3, 4, 4, 7, 7, 8, 8, 10, 10, 11, 11, // 0-15 + 15, 15, 16, 16, 18, 18, 19, 19, 22, 22, 23, 23, 25, 25, 26, 26, // 16-31 + 31, 31, 32, 32, 34, 34, 35, 35, 38, 38, 39, 39, 41, 41, 42, 42, // 32-47 + 46, 46, 47, 47, 49, 49, 50, 50, 53, 53, 54, 54, 56, 56, 57, 57, // 48-63 + 63, 63, 64, 64, // 64-67 +}; /*[clinic input] math.comb @@ -3588,15 +3607,14 @@ math_comb_impl(PyObject *module, PyObject *n, PyObject *k) where 2**shift is the largest power of two dividing comb(n, k) and comb_odd_part is comb(n, k) >> shift. comb_odd_part can be calculated efficiently via arithmetic modulo 2**64, using three - lookups and two uint64_t multiplications, while the necessary - shift can be computed via Kummer's theorem: it's the number of - carries when adding k to n - k in binary, which in turn is the - number of set bits of n ^ k ^ (n - k). + lookups and two uint64_t multiplications. */ uint64_t comb_odd_part = reduced_factorial_odd_part[ni] * inverted_factorial_odd_part[ki] * inverted_factorial_odd_part[ni - ki]; - int shift = _Py_popcount32((uint32_t)(ni ^ ki ^ (ni - ki))); + int shift = factorial_trailing_zeros[ni] + - factorial_trailing_zeros[ki] + - factorial_trailing_zeros[ni - ki]; result = PyLong_FromUnsignedLongLong(comb_odd_part << shift); goto done; }