[SEND_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
[SETUP_ANNOTATIONS] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[SET_ADD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
- [SET_FUNCTION_ATTRIBUTE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
+ [SET_FUNCTION_ATTRIBUTE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[SET_UPDATE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[STORE_ATTR] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[STORE_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IXC000, HAS_EXIT_FLAG | HAS_ESCAPES_FLAG },
[_CALL_KW_NON_PY] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
[_MAKE_CALLARGS_A_TUPLE] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG,
[_MAKE_FUNCTION] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
- [_SET_FUNCTION_ATTRIBUTE] = HAS_ARG_FLAG,
+ [_SET_FUNCTION_ATTRIBUTE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
[_RETURN_GENERATOR] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
[_BUILD_SLICE] = HAS_ARG_FLAG | HAS_ERROR_FLAG,
[_CONVERT_VALUE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
lamb = list(genexp)[0]
self.assertEqual(lamb(), 42)
+ def test_annotate_qualname(self):
+ code = """
+ def f() -> None:
+ def nested() -> None: pass
+ return nested
+ class Outer:
+ x: int
+ def method(self, x: int):
+ pass
+ """
+ ns = run_code(code)
+ method = ns["Outer"].method
+ self.assertEqual(ns["f"].__annotate__.__qualname__, "f.__annotate__")
+ self.assertEqual(ns["f"]().__annotate__.__qualname__, "f.<locals>.nested.__annotate__")
+ self.assertEqual(method.__annotate__.__qualname__, "Outer.method.__annotate__")
+ self.assertEqual(ns["Outer"].__annotate__.__qualname__, "Outer.__annotate__")
+
# gh-138349
def test_module_level_annotation_plus_listcomp(self):
cases = [
--- /dev/null
+Fix the ``__qualname__`` attribute of ``__annotate__`` functions on
+functions.
PyObject **ptr = (PyObject **)(((char *)func) + offset);
assert(*ptr == NULL);
*ptr = attr;
+ if (oparg == MAKE_FUNCTION_ANNOTATE && PyFunction_Check(attr)) {
+ // gh-137814: Fix the qualname of __annotate__ functions
+ PyFunctionObject *func_obj = (PyFunctionObject *)attr;
+ PyObject *fixed_qualname = PyUnicode_FromFormat("%U.__annotate__", ((PyFunctionObject *)func)->func_qualname);
+ ERROR_IF(fixed_qualname == NULL);
+ Py_SETREF(func_obj->func_qualname, fixed_qualname);
+ }
}
inst(RETURN_GENERATOR, (-- res)) {
PyObject **ptr = (PyObject **)(((char *)func) + offset);
assert(*ptr == NULL);
*ptr = attr;
+ if (oparg == MAKE_FUNCTION_ANNOTATE && PyFunction_Check(attr)) {
+ PyFunctionObject *func_obj = (PyFunctionObject *)attr;
+ stack_pointer[-2] = func_out;
+ stack_pointer += -1;
+ assert(WITHIN_STACK_BOUNDS());
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyObject *fixed_qualname = PyUnicode_FromFormat("%U.__annotate__", ((PyFunctionObject *)func)->func_qualname);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ if (fixed_qualname == NULL) {
+ JUMP_TO_ERROR();
+ }
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ Py_SETREF(func_obj->func_qualname, fixed_qualname);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ stack_pointer += 1;
+ }
stack_pointer[-2] = func_out;
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
PyObject **ptr = (PyObject **)(((char *)func) + offset);
assert(*ptr == NULL);
*ptr = attr;
+ if (oparg == MAKE_FUNCTION_ANNOTATE && PyFunction_Check(attr)) {
+ PyFunctionObject *func_obj = (PyFunctionObject *)attr;
+ stack_pointer[-2] = func_out;
+ stack_pointer += -1;
+ assert(WITHIN_STACK_BOUNDS());
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyObject *fixed_qualname = PyUnicode_FromFormat("%U.__annotate__", ((PyFunctionObject *)func)->func_qualname);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ if (fixed_qualname == NULL) {
+ JUMP_TO_LABEL(error);
+ }
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ Py_SETREF(func_obj->func_qualname, fixed_qualname);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ stack_pointer += 1;
+ }
stack_pointer[-2] = func_out;
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());