Skip to content

Commit d671c65

Browse files
[3.12] gh-106719: Fix __annotations__ getter and setter in the type and 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 <[email protected]>
1 parent e903c16 commit d671c65

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
@@ -935,26 +935,20 @@ static PyObject *
935935
module_get_annotations(PyModuleObject *m, void *Py_UNUSED(ignored))
936936
{
937937
PyObject *dict = PyObject_GetAttr((PyObject *)m, &_Py_ID(__dict__));
938-
939-
if ((dict == NULL) || !PyDict_Check(dict)) {
938+
if (dict == NULL) {
939+
return NULL;
940+
}
941+
if (!PyDict_Check(dict)) {
940942
PyErr_Format(PyExc_TypeError, "<module>.__dict__ is not a dictionary");
941-
Py_XDECREF(dict);
943+
Py_DECREF(dict);
942944
return NULL;
943945
}
944946

945-
PyObject *annotations;
946-
/* there's no _PyDict_GetItemId without WithError, so let's LBYL. */
947-
if (PyDict_Contains(dict, &_Py_ID(__annotations__))) {
948-
annotations = PyDict_GetItemWithError(dict, &_Py_ID(__annotations__));
949-
/*
950-
** _PyDict_GetItemIdWithError could still fail,
951-
** for instance with a well-timed Ctrl-C or a MemoryError.
952-
** so let's be totally safe.
953-
*/
954-
if (annotations) {
955-
Py_INCREF(annotations);
956-
}
957-
} else {
947+
PyObject *annotations = PyDict_GetItemWithError(dict, &_Py_ID(__annotations__));
948+
if (annotations) {
949+
Py_INCREF(annotations);
950+
}
951+
else if (!PyErr_Occurred()) {
958952
annotations = PyDict_New();
959953
if (annotations) {
960954
int result = PyDict_SetItem(
@@ -973,28 +967,28 @@ module_set_annotations(PyModuleObject *m, PyObject *value, void *Py_UNUSED(ignor
973967
{
974968
int ret = -1;
975969
PyObject *dict = PyObject_GetAttr((PyObject *)m, &_Py_ID(__dict__));
976-
977-
if ((dict == NULL) || !PyDict_Check(dict)) {
970+
if (dict == NULL) {
971+
return -1;
972+
}
973+
if (!PyDict_Check(dict)) {
978974
PyErr_Format(PyExc_TypeError, "<module>.__dict__ is not a dictionary");
979975
goto exit;
980976
}
981977

982978
if (value != NULL) {
983979
/* set */
984980
ret = PyDict_SetItem(dict, &_Py_ID(__annotations__), value);
985-
goto exit;
986981
}
987-
988-
/* delete */
989-
if (!PyDict_Contains(dict, &_Py_ID(__annotations__))) {
990-
PyErr_Format(PyExc_AttributeError, "__annotations__");
991-
goto exit;
982+
else {
983+
/* delete */
984+
ret = PyDict_DelItem(dict, &_Py_ID(__annotations__));
985+
if (ret < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) {
986+
PyErr_SetString(PyExc_AttributeError, "__annotations__");
987+
}
992988
}
993989

994-
ret = PyDict_DelItem(dict, &_Py_ID(__annotations__));
995-
996990
exit:
997-
Py_XDECREF(dict);
991+
Py_DECREF(dict);
998992
return ret;
999993
}
1000994

Objects/typeobject.c

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

14511451
PyObject *annotations;
1452-
/* there's no _PyDict_GetItemId without WithError, so let's LBYL. */
14531452
PyObject *dict = lookup_tp_dict(type);
1454-
if (PyDict_Contains(dict, &_Py_ID(__annotations__))) {
1455-
annotations = PyDict_GetItemWithError(dict, &_Py_ID(__annotations__));
1456-
/*
1457-
** PyDict_GetItemWithError could still fail,
1458-
** for instance with a well-timed Ctrl-C or a MemoryError.
1459-
** so let's be totally safe.
1460-
*/
1461-
if (annotations) {
1462-
if (Py_TYPE(annotations)->tp_descr_get) {
1463-
annotations = Py_TYPE(annotations)->tp_descr_get(
1464-
annotations, NULL, (PyObject *)type);
1465-
} else {
1466-
Py_INCREF(annotations);
1467-
}
1453+
annotations = PyDict_GetItemWithError(dict, &_Py_ID(__annotations__));
1454+
if (annotations) {
1455+
if (Py_TYPE(annotations)->tp_descr_get) {
1456+
annotations = Py_TYPE(annotations)->tp_descr_get(
1457+
annotations, NULL, (PyObject *)type);
1458+
} else {
1459+
Py_INCREF(annotations);
14681460
}
1469-
} else {
1461+
}
1462+
else if (!PyErr_Occurred()) {
14701463
annotations = PyDict_New();
14711464
if (annotations) {
14721465
int result = PyDict_SetItem(
@@ -1498,11 +1491,10 @@ type_set_annotations(PyTypeObject *type, PyObject *value, void *context)
14981491
result = PyDict_SetItem(dict, &_Py_ID(__annotations__), value);
14991492
} else {
15001493
/* delete */
1501-
if (!PyDict_Contains(dict, &_Py_ID(__annotations__))) {
1502-
PyErr_Format(PyExc_AttributeError, "__annotations__");
1503-
return -1;
1504-
}
15051494
result = PyDict_DelItem(dict, &_Py_ID(__annotations__));
1495+
if (result < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) {
1496+
PyErr_SetString(PyExc_AttributeError, "__annotations__");
1497+
}
15061498
}
15071499

15081500
if (result == 0) {

0 commit comments

Comments
 (0)