Skip to content

Commit e1c295e

Browse files
gh-106719: Fix __annotations__ getter and setter in the type and module types (GH-106720)
No longer suppress arbitrary errors. Simplify the code.
1 parent ece3b9d commit e1c295e

File tree

3 files changed

+35
-47
lines changed

3 files changed

+35
-47
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
No longer suppress arbitrary errors in the ``__annotations__`` getter and
2+
setter in the type and module types.

Objects/moduleobject.c

Lines changed: 21 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -937,26 +937,20 @@ static PyObject *
937937
module_get_annotations(PyModuleObject *m, void *Py_UNUSED(ignored))
938938
{
939939
PyObject *dict = PyObject_GetAttr((PyObject *)m, &_Py_ID(__dict__));
940-
941-
if ((dict == NULL) || !PyDict_Check(dict)) {
940+
if (dict == NULL) {
941+
return NULL;
942+
}
943+
if (!PyDict_Check(dict)) {
942944
PyErr_Format(PyExc_TypeError, "<module>.__dict__ is not a dictionary");
943-
Py_XDECREF(dict);
945+
Py_DECREF(dict);
944946
return NULL;
945947
}
946948

947-
PyObject *annotations;
948-
/* there's no _PyDict_GetItemId without WithError, so let's LBYL. */
949-
if (PyDict_Contains(dict, &_Py_ID(__annotations__))) {
950-
annotations = PyDict_GetItemWithError(dict, &_Py_ID(__annotations__));
951-
/*
952-
** _PyDict_GetItemIdWithError could still fail,
953-
** for instance with a well-timed Ctrl-C or a MemoryError.
954-
** so let's be totally safe.
955-
*/
956-
if (annotations) {
957-
Py_INCREF(annotations);
958-
}
959-
} else {
949+
PyObject *annotations = PyDict_GetItemWithError(dict, &_Py_ID(__annotations__));
950+
if (annotations) {
951+
Py_INCREF(annotations);
952+
}
953+
else if (!PyErr_Occurred()) {
960954
annotations = PyDict_New();
961955
if (annotations) {
962956
int result = PyDict_SetItem(
@@ -975,28 +969,28 @@ module_set_annotations(PyModuleObject *m, PyObject *value, void *Py_UNUSED(ignor
975969
{
976970
int ret = -1;
977971
PyObject *dict = PyObject_GetAttr((PyObject *)m, &_Py_ID(__dict__));
978-
979-
if ((dict == NULL) || !PyDict_Check(dict)) {
972+
if (dict == NULL) {
973+
return -1;
974+
}
975+
if (!PyDict_Check(dict)) {
980976
PyErr_Format(PyExc_TypeError, "<module>.__dict__ is not a dictionary");
981977
goto exit;
982978
}
983979

984980
if (value != NULL) {
985981
/* set */
986982
ret = PyDict_SetItem(dict, &_Py_ID(__annotations__), value);
987-
goto exit;
988983
}
989-
990-
/* delete */
991-
if (!PyDict_Contains(dict, &_Py_ID(__annotations__))) {
992-
PyErr_Format(PyExc_AttributeError, "__annotations__");
993-
goto exit;
984+
else {
985+
/* delete */
986+
ret = PyDict_DelItem(dict, &_Py_ID(__annotations__));
987+
if (ret < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) {
988+
PyErr_SetString(PyExc_AttributeError, "__annotations__");
989+
}
994990
}
995991

996-
ret = PyDict_DelItem(dict, &_Py_ID(__annotations__));
997-
998992
exit:
999-
Py_XDECREF(dict);
993+
Py_DECREF(dict);
1000994
return ret;
1001995
}
1002996

Objects/typeobject.c

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,24 +1451,17 @@ type_get_annotations(PyTypeObject *type, void *context)
14511451
}
14521452

14531453
PyObject *annotations;
1454-
/* there's no _PyDict_GetItemId without WithError, so let's LBYL. */
14551454
PyObject *dict = lookup_tp_dict(type);
1456-
if (PyDict_Contains(dict, &_Py_ID(__annotations__))) {
1457-
annotations = PyDict_GetItemWithError(dict, &_Py_ID(__annotations__));
1458-
/*
1459-
** PyDict_GetItemWithError could still fail,
1460-
** for instance with a well-timed Ctrl-C or a MemoryError.
1461-
** so let's be totally safe.
1462-
*/
1463-
if (annotations) {
1464-
if (Py_TYPE(annotations)->tp_descr_get) {
1465-
annotations = Py_TYPE(annotations)->tp_descr_get(
1466-
annotations, NULL, (PyObject *)type);
1467-
} else {
1468-
Py_INCREF(annotations);
1469-
}
1455+
annotations = PyDict_GetItemWithError(dict, &_Py_ID(__annotations__));
1456+
if (annotations) {
1457+
if (Py_TYPE(annotations)->tp_descr_get) {
1458+
annotations = Py_TYPE(annotations)->tp_descr_get(
1459+
annotations, NULL, (PyObject *)type);
1460+
} else {
1461+
Py_INCREF(annotations);
14701462
}
1471-
} else {
1463+
}
1464+
else if (!PyErr_Occurred()) {
14721465
annotations = PyDict_New();
14731466
if (annotations) {
14741467
int result = PyDict_SetItem(
@@ -1500,11 +1493,10 @@ type_set_annotations(PyTypeObject *type, PyObject *value, void *context)
15001493
result = PyDict_SetItem(dict, &_Py_ID(__annotations__), value);
15011494
} else {
15021495
/* delete */
1503-
if (!PyDict_Contains(dict, &_Py_ID(__annotations__))) {
1504-
PyErr_Format(PyExc_AttributeError, "__annotations__");
1505-
return -1;
1506-
}
15071496
result = PyDict_DelItem(dict, &_Py_ID(__annotations__));
1497+
if (result < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) {
1498+
PyErr_SetString(PyExc_AttributeError, "__annotations__");
1499+
}
15081500
}
15091501

15101502
if (result == 0) {

0 commit comments

Comments
 (0)