Skip to content

Commit

Permalink
[3.12] gh-106719: Fix __annotations__ getter and setter in the type a…
Browse files Browse the repository at this point in the history
…nd module types (GH-106720) (GH-106848)

gh-106719: Fix __annotations__ getter and setter in the type and module types (GH-106720)

No longer suppress arbitrary errors. Simplify the code.
(cherry picked from commit e1c295e)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
  • Loading branch information
miss-islington and serhiy-storchaka committed Jul 18, 2023
1 parent e903c16 commit d671c65
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 47 deletions.
@@ -0,0 +1,2 @@
No longer suppress arbitrary errors in the ``__annotations__`` getter and
setter in the type and module types.
48 changes: 21 additions & 27 deletions Objects/moduleobject.c
Expand Up @@ -935,26 +935,20 @@ static PyObject *
module_get_annotations(PyModuleObject *m, void *Py_UNUSED(ignored))
{
PyObject *dict = PyObject_GetAttr((PyObject *)m, &_Py_ID(__dict__));

if ((dict == NULL) || !PyDict_Check(dict)) {
if (dict == NULL) {
return NULL;
}
if (!PyDict_Check(dict)) {
PyErr_Format(PyExc_TypeError, "<module>.__dict__ is not a dictionary");
Py_XDECREF(dict);
Py_DECREF(dict);
return NULL;
}

PyObject *annotations;
/* there's no _PyDict_GetItemId without WithError, so let's LBYL. */
if (PyDict_Contains(dict, &_Py_ID(__annotations__))) {
annotations = PyDict_GetItemWithError(dict, &_Py_ID(__annotations__));
/*
** _PyDict_GetItemIdWithError could still fail,
** for instance with a well-timed Ctrl-C or a MemoryError.
** so let's be totally safe.
*/
if (annotations) {
Py_INCREF(annotations);
}
} else {
PyObject *annotations = PyDict_GetItemWithError(dict, &_Py_ID(__annotations__));
if (annotations) {
Py_INCREF(annotations);
}
else if (!PyErr_Occurred()) {
annotations = PyDict_New();
if (annotations) {
int result = PyDict_SetItem(
Expand All @@ -973,28 +967,28 @@ module_set_annotations(PyModuleObject *m, PyObject *value, void *Py_UNUSED(ignor
{
int ret = -1;
PyObject *dict = PyObject_GetAttr((PyObject *)m, &_Py_ID(__dict__));

if ((dict == NULL) || !PyDict_Check(dict)) {
if (dict == NULL) {
return -1;
}
if (!PyDict_Check(dict)) {
PyErr_Format(PyExc_TypeError, "<module>.__dict__ is not a dictionary");
goto exit;
}

if (value != NULL) {
/* set */
ret = PyDict_SetItem(dict, &_Py_ID(__annotations__), value);
goto exit;
}

/* delete */
if (!PyDict_Contains(dict, &_Py_ID(__annotations__))) {
PyErr_Format(PyExc_AttributeError, "__annotations__");
goto exit;
else {
/* delete */
ret = PyDict_DelItem(dict, &_Py_ID(__annotations__));
if (ret < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) {
PyErr_SetString(PyExc_AttributeError, "__annotations__");
}
}

ret = PyDict_DelItem(dict, &_Py_ID(__annotations__));

exit:
Py_XDECREF(dict);
Py_DECREF(dict);
return ret;
}

Expand Down
32 changes: 12 additions & 20 deletions Objects/typeobject.c
Expand Up @@ -1449,24 +1449,17 @@ type_get_annotations(PyTypeObject *type, void *context)
}

PyObject *annotations;
/* there's no _PyDict_GetItemId without WithError, so let's LBYL. */
PyObject *dict = lookup_tp_dict(type);
if (PyDict_Contains(dict, &_Py_ID(__annotations__))) {
annotations = PyDict_GetItemWithError(dict, &_Py_ID(__annotations__));
/*
** PyDict_GetItemWithError could still fail,
** for instance with a well-timed Ctrl-C or a MemoryError.
** so let's be totally safe.
*/
if (annotations) {
if (Py_TYPE(annotations)->tp_descr_get) {
annotations = Py_TYPE(annotations)->tp_descr_get(
annotations, NULL, (PyObject *)type);
} else {
Py_INCREF(annotations);
}
annotations = PyDict_GetItemWithError(dict, &_Py_ID(__annotations__));
if (annotations) {
if (Py_TYPE(annotations)->tp_descr_get) {
annotations = Py_TYPE(annotations)->tp_descr_get(
annotations, NULL, (PyObject *)type);
} else {
Py_INCREF(annotations);
}
} else {
}
else if (!PyErr_Occurred()) {
annotations = PyDict_New();
if (annotations) {
int result = PyDict_SetItem(
Expand Down Expand Up @@ -1498,11 +1491,10 @@ type_set_annotations(PyTypeObject *type, PyObject *value, void *context)
result = PyDict_SetItem(dict, &_Py_ID(__annotations__), value);
} else {
/* delete */
if (!PyDict_Contains(dict, &_Py_ID(__annotations__))) {
PyErr_Format(PyExc_AttributeError, "__annotations__");
return -1;
}
result = PyDict_DelItem(dict, &_Py_ID(__annotations__));
if (result < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) {
PyErr_SetString(PyExc_AttributeError, "__annotations__");
}
}

if (result == 0) {
Expand Down

0 comments on commit d671c65

Please sign in to comment.