mirror of
https://github.com/python/cpython.git
synced 2025-07-24 19:54:21 +00:00
bpo-46841: Fix error message hacks in GET_AWAITABLE
(GH-31664)
This commit is contained in:
parent
03c2a36b2b
commit
586b24d3be
8 changed files with 37 additions and 32 deletions
|
@ -475,15 +475,24 @@ the original TOS1.
|
||||||
|
|
||||||
**Coroutine opcodes**
|
**Coroutine opcodes**
|
||||||
|
|
||||||
.. opcode:: GET_AWAITABLE
|
.. opcode:: GET_AWAITABLE (where)
|
||||||
|
|
||||||
Implements ``TOS = get_awaitable(TOS)``, where ``get_awaitable(o)``
|
Implements ``TOS = get_awaitable(TOS)``, where ``get_awaitable(o)``
|
||||||
returns ``o`` if ``o`` is a coroutine object or a generator object with
|
returns ``o`` if ``o`` is a coroutine object or a generator object with
|
||||||
the CO_ITERABLE_COROUTINE flag, or resolves
|
the CO_ITERABLE_COROUTINE flag, or resolves
|
||||||
``o.__await__``.
|
``o.__await__``.
|
||||||
|
|
||||||
|
If the ``where`` operand is nonzero, it indicates where the instruction
|
||||||
|
occurs:
|
||||||
|
|
||||||
|
* ``1`` After a call to ``__aenter__``
|
||||||
|
* ``2`` After a call to ``__aexit__``
|
||||||
|
|
||||||
.. versionadded:: 3.5
|
.. versionadded:: 3.5
|
||||||
|
|
||||||
|
.. versionchanged:: 3.11
|
||||||
|
Previously, this instruction did not have an oparg.
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: GET_AITER
|
.. opcode:: GET_AITER
|
||||||
|
|
||||||
|
|
16
Include/opcode.h
generated
16
Include/opcode.h
generated
|
@ -33,7 +33,6 @@ extern "C" {
|
||||||
#define GET_YIELD_FROM_ITER 69
|
#define GET_YIELD_FROM_ITER 69
|
||||||
#define PRINT_EXPR 70
|
#define PRINT_EXPR 70
|
||||||
#define LOAD_BUILD_CLASS 71
|
#define LOAD_BUILD_CLASS 71
|
||||||
#define GET_AWAITABLE 73
|
|
||||||
#define LOAD_ASSERTION_ERROR 74
|
#define LOAD_ASSERTION_ERROR 74
|
||||||
#define RETURN_GENERATOR 75
|
#define RETURN_GENERATOR 75
|
||||||
#define LIST_TO_TUPLE 82
|
#define LIST_TO_TUPLE 82
|
||||||
|
@ -86,6 +85,7 @@ extern "C" {
|
||||||
#define POP_JUMP_IF_NOT_NONE 128
|
#define POP_JUMP_IF_NOT_NONE 128
|
||||||
#define POP_JUMP_IF_NONE 129
|
#define POP_JUMP_IF_NONE 129
|
||||||
#define RAISE_VARARGS 130
|
#define RAISE_VARARGS 130
|
||||||
|
#define GET_AWAITABLE 131
|
||||||
#define MAKE_FUNCTION 132
|
#define MAKE_FUNCTION 132
|
||||||
#define BUILD_SLICE 133
|
#define BUILD_SLICE 133
|
||||||
#define JUMP_NO_INTERRUPT 134
|
#define JUMP_NO_INTERRUPT 134
|
||||||
|
@ -160,13 +160,13 @@ extern "C" {
|
||||||
#define PRECALL_BUILTIN_FAST_WITH_KEYWORDS 66
|
#define PRECALL_BUILTIN_FAST_WITH_KEYWORDS 66
|
||||||
#define PRECALL_NO_KW_LEN 67
|
#define PRECALL_NO_KW_LEN 67
|
||||||
#define PRECALL_NO_KW_ISINSTANCE 72
|
#define PRECALL_NO_KW_ISINSTANCE 72
|
||||||
#define PRECALL_NO_KW_LIST_APPEND 76
|
#define PRECALL_NO_KW_LIST_APPEND 73
|
||||||
#define PRECALL_NO_KW_METHOD_DESCRIPTOR_O 77
|
#define PRECALL_NO_KW_METHOD_DESCRIPTOR_O 76
|
||||||
#define PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS 78
|
#define PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS 77
|
||||||
#define PRECALL_NO_KW_STR_1 79
|
#define PRECALL_NO_KW_STR_1 78
|
||||||
#define PRECALL_NO_KW_TUPLE_1 80
|
#define PRECALL_NO_KW_TUPLE_1 79
|
||||||
#define PRECALL_NO_KW_TYPE_1 81
|
#define PRECALL_NO_KW_TYPE_1 80
|
||||||
#define PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST 131
|
#define PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST 81
|
||||||
#define PRECALL_BOUND_METHOD 140
|
#define PRECALL_BOUND_METHOD 140
|
||||||
#define PRECALL_PYFUNC 141
|
#define PRECALL_PYFUNC 141
|
||||||
#define RESUME_QUICK 143
|
#define RESUME_QUICK 143
|
||||||
|
|
|
@ -392,6 +392,7 @@ _code_type = type(_write_atomic.__code__)
|
||||||
# Python 3.11a5 3483 (Use inline caching for COMPARE_OP and BINARY_SUBSCR)
|
# Python 3.11a5 3483 (Use inline caching for COMPARE_OP and BINARY_SUBSCR)
|
||||||
# Python 3.11a5 3484 (Use inline caching for LOAD_ATTR, LOAD_METHOD, and
|
# Python 3.11a5 3484 (Use inline caching for LOAD_ATTR, LOAD_METHOD, and
|
||||||
# STORE_ATTR)
|
# STORE_ATTR)
|
||||||
|
# Python 3.11a5 3485 (Add an oparg to GET_AWAITABLE)
|
||||||
|
|
||||||
# Python 3.12 will start with magic number 3500
|
# Python 3.12 will start with magic number 3500
|
||||||
|
|
||||||
|
@ -406,7 +407,7 @@ _code_type = type(_write_atomic.__code__)
|
||||||
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
|
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
|
||||||
# in PC/launcher.c must also be updated.
|
# in PC/launcher.c must also be updated.
|
||||||
|
|
||||||
MAGIC_NUMBER = (3484).to_bytes(2, 'little') + b'\r\n'
|
MAGIC_NUMBER = (3485).to_bytes(2, 'little') + b'\r\n'
|
||||||
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
|
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
|
||||||
|
|
||||||
_PYCACHE = '__pycache__'
|
_PYCACHE = '__pycache__'
|
||||||
|
|
|
@ -92,7 +92,6 @@ def_op('GET_YIELD_FROM_ITER', 69)
|
||||||
def_op('PRINT_EXPR', 70)
|
def_op('PRINT_EXPR', 70)
|
||||||
def_op('LOAD_BUILD_CLASS', 71)
|
def_op('LOAD_BUILD_CLASS', 71)
|
||||||
|
|
||||||
def_op('GET_AWAITABLE', 73)
|
|
||||||
def_op('LOAD_ASSERTION_ERROR', 74)
|
def_op('LOAD_ASSERTION_ERROR', 74)
|
||||||
def_op('RETURN_GENERATOR', 75)
|
def_op('RETURN_GENERATOR', 75)
|
||||||
|
|
||||||
|
@ -153,7 +152,7 @@ jabs_op('JUMP_IF_NOT_EG_MATCH', 127)
|
||||||
jabs_op('POP_JUMP_IF_NOT_NONE', 128)
|
jabs_op('POP_JUMP_IF_NOT_NONE', 128)
|
||||||
jabs_op('POP_JUMP_IF_NONE', 129)
|
jabs_op('POP_JUMP_IF_NONE', 129)
|
||||||
def_op('RAISE_VARARGS', 130) # Number of raise arguments (1, 2, or 3)
|
def_op('RAISE_VARARGS', 130) # Number of raise arguments (1, 2, or 3)
|
||||||
|
def_op('GET_AWAITABLE', 131)
|
||||||
def_op('MAKE_FUNCTION', 132) # Flags
|
def_op('MAKE_FUNCTION', 132) # Flags
|
||||||
def_op('BUILD_SLICE', 133) # Number of items
|
def_op('BUILD_SLICE', 133) # Number of items
|
||||||
jabs_op('JUMP_NO_INTERRUPT', 134) # Target byte offset from beginning of code
|
jabs_op('JUMP_NO_INTERRUPT', 134) # Target byte offset from beginning of code
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Use an oparg to simplify the construction of helpful error messages in
|
||||||
|
:opcode:`GET_AWAITABLE`.
|
|
@ -95,7 +95,7 @@ static int check_args_iterable(PyThreadState *, PyObject *func, PyObject *vararg
|
||||||
static int check_except_type_valid(PyThreadState *tstate, PyObject* right);
|
static int check_except_type_valid(PyThreadState *tstate, PyObject* right);
|
||||||
static int check_except_star_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_kwargs_error(PyThreadState *, PyObject *func, PyObject *kwargs);
|
||||||
static void format_awaitable_error(PyThreadState *, PyTypeObject *, int, int);
|
static void format_awaitable_error(PyThreadState *, PyTypeObject *, int);
|
||||||
static int get_exception_handler(PyCodeObject *, int, int*, int*, int*);
|
static int get_exception_handler(PyCodeObject *, int, int*, int*, int*);
|
||||||
static _PyInterpreterFrame *
|
static _PyInterpreterFrame *
|
||||||
_PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func,
|
_PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func,
|
||||||
|
@ -2505,13 +2505,7 @@ handle_eval_breaker:
|
||||||
PyObject *iter = _PyCoro_GetAwaitableIter(iterable);
|
PyObject *iter = _PyCoro_GetAwaitableIter(iterable);
|
||||||
|
|
||||||
if (iter == NULL) {
|
if (iter == NULL) {
|
||||||
int opcode_at_minus_4 = 0;
|
format_awaitable_error(tstate, Py_TYPE(iterable), oparg);
|
||||||
if ((next_instr - first_instr) > 4) {
|
|
||||||
opcode_at_minus_4 = _Py_OPCODE(next_instr[-4]);
|
|
||||||
}
|
|
||||||
format_awaitable_error(tstate, Py_TYPE(iterable),
|
|
||||||
opcode_at_minus_4,
|
|
||||||
_Py_OPCODE(next_instr[-2]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_DECREF(iterable);
|
Py_DECREF(iterable);
|
||||||
|
@ -7638,16 +7632,16 @@ format_exc_unbound(PyThreadState *tstate, PyCodeObject *co, int oparg)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
format_awaitable_error(PyThreadState *tstate, PyTypeObject *type, int prevprevprevopcode, int prevopcode)
|
format_awaitable_error(PyThreadState *tstate, PyTypeObject *type, int oparg)
|
||||||
{
|
{
|
||||||
if (type->tp_as_async == NULL || type->tp_as_async->am_await == NULL) {
|
if (type->tp_as_async == NULL || type->tp_as_async->am_await == NULL) {
|
||||||
if (prevopcode == BEFORE_ASYNC_WITH) {
|
if (oparg == 1) {
|
||||||
_PyErr_Format(tstate, PyExc_TypeError,
|
_PyErr_Format(tstate, PyExc_TypeError,
|
||||||
"'async with' received an object from __aenter__ "
|
"'async with' received an object from __aenter__ "
|
||||||
"that does not implement __await__: %.100s",
|
"that does not implement __await__: %.100s",
|
||||||
type->tp_name);
|
type->tp_name);
|
||||||
}
|
}
|
||||||
else if (prevopcode == WITH_EXCEPT_START || (prevopcode == CALL && prevprevprevopcode == LOAD_CONST)) {
|
else if (oparg == 2) {
|
||||||
_PyErr_Format(tstate, PyExc_TypeError,
|
_PyErr_Format(tstate, PyExc_TypeError,
|
||||||
"'async with' received an object from __aexit__ "
|
"'async with' received an object from __aexit__ "
|
||||||
"that does not implement __await__: %.100s",
|
"that does not implement __await__: %.100s",
|
||||||
|
|
|
@ -1978,7 +1978,7 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (info->fb_type == ASYNC_WITH) {
|
if (info->fb_type == ASYNC_WITH) {
|
||||||
ADDOP(c, GET_AWAITABLE);
|
ADDOP_I(c, GET_AWAITABLE, 2);
|
||||||
ADDOP_LOAD_CONST(c, Py_None);
|
ADDOP_LOAD_CONST(c, Py_None);
|
||||||
ADD_YIELD_FROM(c, 1);
|
ADD_YIELD_FROM(c, 1);
|
||||||
}
|
}
|
||||||
|
@ -5353,7 +5353,7 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type,
|
||||||
ADDOP_I(c, CALL, 0);
|
ADDOP_I(c, CALL, 0);
|
||||||
|
|
||||||
if (is_async_generator && type != COMP_GENEXP) {
|
if (is_async_generator && type != COMP_GENEXP) {
|
||||||
ADDOP(c, GET_AWAITABLE);
|
ADDOP_I(c, GET_AWAITABLE, 0);
|
||||||
ADDOP_LOAD_CONST(c, Py_None);
|
ADDOP_LOAD_CONST(c, Py_None);
|
||||||
ADD_YIELD_FROM(c, 1);
|
ADD_YIELD_FROM(c, 1);
|
||||||
}
|
}
|
||||||
|
@ -5485,7 +5485,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos)
|
||||||
VISIT(c, expr, item->context_expr);
|
VISIT(c, expr, item->context_expr);
|
||||||
|
|
||||||
ADDOP(c, BEFORE_ASYNC_WITH);
|
ADDOP(c, BEFORE_ASYNC_WITH);
|
||||||
ADDOP(c, GET_AWAITABLE);
|
ADDOP_I(c, GET_AWAITABLE, 1);
|
||||||
ADDOP_LOAD_CONST(c, Py_None);
|
ADDOP_LOAD_CONST(c, Py_None);
|
||||||
ADD_YIELD_FROM(c, 1);
|
ADD_YIELD_FROM(c, 1);
|
||||||
|
|
||||||
|
@ -5522,7 +5522,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos)
|
||||||
SET_LOC(c, s);
|
SET_LOC(c, s);
|
||||||
if(!compiler_call_exit_with_nones(c))
|
if(!compiler_call_exit_with_nones(c))
|
||||||
return 0;
|
return 0;
|
||||||
ADDOP(c, GET_AWAITABLE);
|
ADDOP_I(c, GET_AWAITABLE, 2);
|
||||||
ADDOP_LOAD_CONST(c, Py_None);
|
ADDOP_LOAD_CONST(c, Py_None);
|
||||||
ADD_YIELD_FROM(c, 1);
|
ADD_YIELD_FROM(c, 1);
|
||||||
|
|
||||||
|
@ -5536,7 +5536,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos)
|
||||||
ADDOP_JUMP(c, SETUP_CLEANUP, cleanup);
|
ADDOP_JUMP(c, SETUP_CLEANUP, cleanup);
|
||||||
ADDOP(c, PUSH_EXC_INFO);
|
ADDOP(c, PUSH_EXC_INFO);
|
||||||
ADDOP(c, WITH_EXCEPT_START);
|
ADDOP(c, WITH_EXCEPT_START);
|
||||||
ADDOP(c, GET_AWAITABLE);
|
ADDOP_I(c, GET_AWAITABLE, 2);
|
||||||
ADDOP_LOAD_CONST(c, Py_None);
|
ADDOP_LOAD_CONST(c, Py_None);
|
||||||
ADD_YIELD_FROM(c, 1);
|
ADD_YIELD_FROM(c, 1);
|
||||||
compiler_with_except_finish(c, cleanup);
|
compiler_with_except_finish(c, cleanup);
|
||||||
|
@ -5710,7 +5710,7 @@ compiler_visit_expr1(struct compiler *c, expr_ty e)
|
||||||
}
|
}
|
||||||
|
|
||||||
VISIT(c, expr, e->v.Await.value);
|
VISIT(c, expr, e->v.Await.value);
|
||||||
ADDOP(c, GET_AWAITABLE);
|
ADDOP_I(c, GET_AWAITABLE, 0);
|
||||||
ADDOP_LOAD_CONST(c, Py_None);
|
ADDOP_LOAD_CONST(c, Py_None);
|
||||||
ADD_YIELD_FROM(c, 1);
|
ADD_YIELD_FROM(c, 1);
|
||||||
break;
|
break;
|
||||||
|
|
6
Python/opcode_targets.h
generated
6
Python/opcode_targets.h
generated
|
@ -72,15 +72,15 @@ static void *opcode_targets[256] = {
|
||||||
&&TARGET_PRINT_EXPR,
|
&&TARGET_PRINT_EXPR,
|
||||||
&&TARGET_LOAD_BUILD_CLASS,
|
&&TARGET_LOAD_BUILD_CLASS,
|
||||||
&&TARGET_PRECALL_NO_KW_ISINSTANCE,
|
&&TARGET_PRECALL_NO_KW_ISINSTANCE,
|
||||||
&&TARGET_GET_AWAITABLE,
|
&&TARGET_PRECALL_NO_KW_LIST_APPEND,
|
||||||
&&TARGET_LOAD_ASSERTION_ERROR,
|
&&TARGET_LOAD_ASSERTION_ERROR,
|
||||||
&&TARGET_RETURN_GENERATOR,
|
&&TARGET_RETURN_GENERATOR,
|
||||||
&&TARGET_PRECALL_NO_KW_LIST_APPEND,
|
|
||||||
&&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_O,
|
&&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_O,
|
||||||
&&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS,
|
&&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS,
|
||||||
&&TARGET_PRECALL_NO_KW_STR_1,
|
&&TARGET_PRECALL_NO_KW_STR_1,
|
||||||
&&TARGET_PRECALL_NO_KW_TUPLE_1,
|
&&TARGET_PRECALL_NO_KW_TUPLE_1,
|
||||||
&&TARGET_PRECALL_NO_KW_TYPE_1,
|
&&TARGET_PRECALL_NO_KW_TYPE_1,
|
||||||
|
&&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST,
|
||||||
&&TARGET_LIST_TO_TUPLE,
|
&&TARGET_LIST_TO_TUPLE,
|
||||||
&&TARGET_RETURN_VALUE,
|
&&TARGET_RETURN_VALUE,
|
||||||
&&TARGET_IMPORT_STAR,
|
&&TARGET_IMPORT_STAR,
|
||||||
|
@ -130,7 +130,7 @@ static void *opcode_targets[256] = {
|
||||||
&&TARGET_POP_JUMP_IF_NOT_NONE,
|
&&TARGET_POP_JUMP_IF_NOT_NONE,
|
||||||
&&TARGET_POP_JUMP_IF_NONE,
|
&&TARGET_POP_JUMP_IF_NONE,
|
||||||
&&TARGET_RAISE_VARARGS,
|
&&TARGET_RAISE_VARARGS,
|
||||||
&&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST,
|
&&TARGET_GET_AWAITABLE,
|
||||||
&&TARGET_MAKE_FUNCTION,
|
&&TARGET_MAKE_FUNCTION,
|
||||||
&&TARGET_BUILD_SLICE,
|
&&TARGET_BUILD_SLICE,
|
||||||
&&TARGET_JUMP_NO_INTERRUPT,
|
&&TARGET_JUMP_NO_INTERRUPT,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue