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

No longer suppress arbitrary errors. Simplify the code.
This commit is contained in:
Serhiy Storchaka 2023-07-18 08:56:58 +03:00 committed by GitHub
parent ece3b9d12a
commit e1c295e3da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 35 additions and 47 deletions

View File

@ -0,0 +1,2 @@
No longer suppress arbitrary errors in the ``__annotations__`` getter and
setter in the type and module types.

View File

@ -937,26 +937,20 @@ static PyObject *
module_get_annotations(PyModuleObject *m, void *Py_UNUSED(ignored)) module_get_annotations(PyModuleObject *m, void *Py_UNUSED(ignored))
{ {
PyObject *dict = PyObject_GetAttr((PyObject *)m, &_Py_ID(__dict__)); PyObject *dict = PyObject_GetAttr((PyObject *)m, &_Py_ID(__dict__));
if (dict == NULL) {
if ((dict == NULL) || !PyDict_Check(dict)) { return NULL;
}
if (!PyDict_Check(dict)) {
PyErr_Format(PyExc_TypeError, "<module>.__dict__ is not a dictionary"); PyErr_Format(PyExc_TypeError, "<module>.__dict__ is not a dictionary");
Py_XDECREF(dict); Py_DECREF(dict);
return NULL; return NULL;
} }
PyObject *annotations; PyObject *annotations = PyDict_GetItemWithError(dict, &_Py_ID(__annotations__));
/* there's no _PyDict_GetItemId without WithError, so let's LBYL. */ if (annotations) {
if (PyDict_Contains(dict, &_Py_ID(__annotations__))) { Py_INCREF(annotations);
annotations = PyDict_GetItemWithError(dict, &_Py_ID(__annotations__)); }
/* else if (!PyErr_Occurred()) {
** _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 {
annotations = PyDict_New(); annotations = PyDict_New();
if (annotations) { if (annotations) {
int result = PyDict_SetItem( int result = PyDict_SetItem(
@ -975,8 +969,10 @@ module_set_annotations(PyModuleObject *m, PyObject *value, void *Py_UNUSED(ignor
{ {
int ret = -1; int ret = -1;
PyObject *dict = PyObject_GetAttr((PyObject *)m, &_Py_ID(__dict__)); PyObject *dict = PyObject_GetAttr((PyObject *)m, &_Py_ID(__dict__));
if (dict == NULL) {
if ((dict == NULL) || !PyDict_Check(dict)) { return -1;
}
if (!PyDict_Check(dict)) {
PyErr_Format(PyExc_TypeError, "<module>.__dict__ is not a dictionary"); PyErr_Format(PyExc_TypeError, "<module>.__dict__ is not a dictionary");
goto exit; goto exit;
} }
@ -984,19 +980,17 @@ module_set_annotations(PyModuleObject *m, PyObject *value, void *Py_UNUSED(ignor
if (value != NULL) { if (value != NULL) {
/* set */ /* set */
ret = PyDict_SetItem(dict, &_Py_ID(__annotations__), value); ret = PyDict_SetItem(dict, &_Py_ID(__annotations__), value);
goto exit;
} }
else {
/* delete */ /* delete */
if (!PyDict_Contains(dict, &_Py_ID(__annotations__))) { ret = PyDict_DelItem(dict, &_Py_ID(__annotations__));
PyErr_Format(PyExc_AttributeError, "__annotations__"); if (ret < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) {
goto exit; PyErr_SetString(PyExc_AttributeError, "__annotations__");
}
} }
ret = PyDict_DelItem(dict, &_Py_ID(__annotations__));
exit: exit:
Py_XDECREF(dict); Py_DECREF(dict);
return ret; return ret;
} }

View File

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