Skip to content

Commit da8be15

Browse files
bpo-46236: Fix PyFunction_GetAnnotations() returned tuple. (GH-30409)
Automerge-Triggered-By: GH:pablogsal (cherry picked from commit 46e4c25) Co-authored-by: Inada Naoki <[email protected]>
1 parent 7e951f3 commit da8be15

File tree

2 files changed

+34
-22
lines changed

2 files changed

+34
-22
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix a bug in :c:func:`PyFunction_GetAnnotations` that caused it to return a ``tuple`` instead of a ``dict``.

Objects/funcobject.c

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -221,14 +221,45 @@ PyFunction_SetClosure(PyObject *op, PyObject *closure)
221221
return 0;
222222
}
223223

224+
static PyObject *
225+
func_get_annotation_dict(PyFunctionObject *op)
226+
{
227+
if (op->func_annotations == NULL) {
228+
return NULL;
229+
}
230+
if (PyTuple_CheckExact(op->func_annotations)) {
231+
PyObject *ann_tuple = op->func_annotations;
232+
PyObject *ann_dict = PyDict_New();
233+
if (ann_dict == NULL) {
234+
return NULL;
235+
}
236+
237+
assert(PyTuple_GET_SIZE(ann_tuple) % 2 == 0);
238+
239+
for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(ann_tuple); i += 2) {
240+
int err = PyDict_SetItem(ann_dict,
241+
PyTuple_GET_ITEM(ann_tuple, i),
242+
PyTuple_GET_ITEM(ann_tuple, i + 1));
243+
244+
if (err < 0) {
245+
return NULL;
246+
}
247+
}
248+
Py_SETREF(op->func_annotations, ann_dict);
249+
}
250+
Py_INCREF(op->func_annotations);
251+
assert(PyDict_Check(op->func_annotations));
252+
return op->func_annotations;
253+
}
254+
224255
PyObject *
225256
PyFunction_GetAnnotations(PyObject *op)
226257
{
227258
if (!PyFunction_Check(op)) {
228259
PyErr_BadInternalCall();
229260
return NULL;
230261
}
231-
return ((PyFunctionObject *) op) -> func_annotations;
262+
return func_get_annotation_dict((PyFunctionObject *)op);
232263
}
233264

234265
int
@@ -443,27 +474,7 @@ func_get_annotations(PyFunctionObject *op, void *Py_UNUSED(ignored))
443474
if (op->func_annotations == NULL)
444475
return NULL;
445476
}
446-
if (PyTuple_CheckExact(op->func_annotations)) {
447-
PyObject *ann_tuple = op->func_annotations;
448-
PyObject *ann_dict = PyDict_New();
449-
if (ann_dict == NULL) {
450-
return NULL;
451-
}
452-
453-
assert(PyTuple_GET_SIZE(ann_tuple) % 2 == 0);
454-
455-
for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(ann_tuple); i += 2) {
456-
int err = PyDict_SetItem(ann_dict,
457-
PyTuple_GET_ITEM(ann_tuple, i),
458-
PyTuple_GET_ITEM(ann_tuple, i + 1));
459-
460-
if (err < 0)
461-
return NULL;
462-
}
463-
Py_SETREF(op->func_annotations, ann_dict);
464-
}
465-
Py_INCREF(op->func_annotations);
466-
return op->func_annotations;
477+
return func_get_annotation_dict(op);
467478
}
468479

469480
static int

0 commit comments

Comments
 (0)