mirror of
https://github.com/python/cpython.git
synced 2025-12-31 04:23:37 +00:00
gh-132261: Store annotations at hidden internal keys in the class dict (#132345)
This commit is contained in:
parent
e5f68fd29b
commit
07b8d3117f
16 changed files with 100 additions and 52 deletions
|
|
@ -1915,10 +1915,17 @@ type_get_annotate(PyObject *tp, void *Py_UNUSED(closure))
|
|||
|
||||
PyObject *annotate;
|
||||
PyObject *dict = PyType_GetDict(type);
|
||||
// First try __annotate__, in case that's been set explicitly
|
||||
if (PyDict_GetItemRef(dict, &_Py_ID(__annotate__), &annotate) < 0) {
|
||||
Py_DECREF(dict);
|
||||
return NULL;
|
||||
}
|
||||
if (!annotate) {
|
||||
if (PyDict_GetItemRef(dict, &_Py_ID(__annotate_func__), &annotate) < 0) {
|
||||
Py_DECREF(dict);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (annotate) {
|
||||
descrgetfunc get = Py_TYPE(annotate)->tp_descr_get;
|
||||
if (get) {
|
||||
|
|
@ -1927,7 +1934,7 @@ type_get_annotate(PyObject *tp, void *Py_UNUSED(closure))
|
|||
}
|
||||
else {
|
||||
annotate = Py_None;
|
||||
int result = PyDict_SetItem(dict, &_Py_ID(__annotate__), annotate);
|
||||
int result = PyDict_SetItem(dict, &_Py_ID(__annotate_func__), annotate);
|
||||
if (result < 0) {
|
||||
Py_DECREF(dict);
|
||||
return NULL;
|
||||
|
|
@ -1959,13 +1966,13 @@ type_set_annotate(PyObject *tp, PyObject *value, void *Py_UNUSED(closure))
|
|||
|
||||
PyObject *dict = PyType_GetDict(type);
|
||||
assert(PyDict_Check(dict));
|
||||
int result = PyDict_SetItem(dict, &_Py_ID(__annotate__), value);
|
||||
int result = PyDict_SetItem(dict, &_Py_ID(__annotate_func__), value);
|
||||
if (result < 0) {
|
||||
Py_DECREF(dict);
|
||||
return -1;
|
||||
}
|
||||
if (!Py_IsNone(value)) {
|
||||
if (PyDict_Pop(dict, &_Py_ID(__annotations__), NULL) == -1) {
|
||||
if (PyDict_Pop(dict, &_Py_ID(__annotations_cache__), NULL) == -1) {
|
||||
Py_DECREF(dict);
|
||||
PyType_Modified(type);
|
||||
return -1;
|
||||
|
|
@ -1987,10 +1994,18 @@ type_get_annotations(PyObject *tp, void *Py_UNUSED(closure))
|
|||
|
||||
PyObject *annotations;
|
||||
PyObject *dict = PyType_GetDict(type);
|
||||
// First try __annotations__ (e.g. for "from __future__ import annotations")
|
||||
if (PyDict_GetItemRef(dict, &_Py_ID(__annotations__), &annotations) < 0) {
|
||||
Py_DECREF(dict);
|
||||
return NULL;
|
||||
}
|
||||
if (!annotations) {
|
||||
if (PyDict_GetItemRef(dict, &_Py_ID(__annotations_cache__), &annotations) < 0) {
|
||||
Py_DECREF(dict);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (annotations) {
|
||||
descrgetfunc get = Py_TYPE(annotations)->tp_descr_get;
|
||||
if (get) {
|
||||
|
|
@ -1998,7 +2013,7 @@ type_get_annotations(PyObject *tp, void *Py_UNUSED(closure))
|
|||
}
|
||||
}
|
||||
else {
|
||||
PyObject *annotate = type_get_annotate(tp, NULL);
|
||||
PyObject *annotate = PyObject_GetAttrString((PyObject *)type, "__annotate__");
|
||||
if (annotate == NULL) {
|
||||
Py_DECREF(dict);
|
||||
return NULL;
|
||||
|
|
@ -2026,7 +2041,7 @@ type_get_annotations(PyObject *tp, void *Py_UNUSED(closure))
|
|||
Py_DECREF(annotate);
|
||||
if (annotations) {
|
||||
int result = PyDict_SetItem(
|
||||
dict, &_Py_ID(__annotations__), annotations);
|
||||
dict, &_Py_ID(__annotations_cache__), annotations);
|
||||
if (result) {
|
||||
Py_CLEAR(annotations);
|
||||
} else {
|
||||
|
|
@ -2053,10 +2068,10 @@ type_set_annotations(PyObject *tp, PyObject *value, void *Py_UNUSED(closure))
|
|||
PyObject *dict = PyType_GetDict(type);
|
||||
if (value != NULL) {
|
||||
/* set */
|
||||
result = PyDict_SetItem(dict, &_Py_ID(__annotations__), value);
|
||||
result = PyDict_SetItem(dict, &_Py_ID(__annotations_cache__), value);
|
||||
} else {
|
||||
/* delete */
|
||||
result = PyDict_Pop(dict, &_Py_ID(__annotations__), NULL);
|
||||
result = PyDict_Pop(dict, &_Py_ID(__annotations_cache__), NULL);
|
||||
if (result == 0) {
|
||||
PyErr_SetString(PyExc_AttributeError, "__annotations__");
|
||||
Py_DECREF(dict);
|
||||
|
|
@ -2067,6 +2082,11 @@ type_set_annotations(PyObject *tp, PyObject *value, void *Py_UNUSED(closure))
|
|||
Py_DECREF(dict);
|
||||
return -1;
|
||||
} else { // result can be 0 or 1
|
||||
if (PyDict_Pop(dict, &_Py_ID(__annotate_func__), NULL) < 0) {
|
||||
PyType_Modified(type);
|
||||
Py_DECREF(dict);
|
||||
return -1;
|
||||
}
|
||||
if (PyDict_Pop(dict, &_Py_ID(__annotate__), NULL) < 0) {
|
||||
PyType_Modified(type);
|
||||
Py_DECREF(dict);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue