aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Objects/typeobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/typeobject.c')
-rw-r--r--Objects/typeobject.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index e1c8be4b815..ac4dc1da441 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -52,6 +52,7 @@ typedef struct PySlot_Offset {
/* alphabetical order */
_Py_IDENTIFIER(__abstractmethods__);
+_Py_IDENTIFIER(__annotations__);
_Py_IDENTIFIER(__class__);
_Py_IDENTIFIER(__class_getitem__);
_Py_IDENTIFIER(__classcell__);
@@ -930,6 +931,73 @@ type_set_doc(PyTypeObject *type, PyObject *value, void *context)
return _PyDict_SetItemId(type->tp_dict, &PyId___doc__, value);
}
+static PyObject *
+type_get_annotations(PyTypeObject *type, void *context)
+{
+ if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
+ PyErr_Format(PyExc_AttributeError, "type object '%s' has no attribute '__annotations__'", type->tp_name);
+ return NULL;
+ }
+
+ PyObject *annotations;
+ /* there's no _PyDict_GetItemId without WithError, so let's LBYL. */
+ if (_PyDict_ContainsId(type->tp_dict, &PyId___annotations__)) {
+ annotations = _PyDict_GetItemIdWithError(type->tp_dict, &PyId___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) {
+ if (Py_TYPE(annotations)->tp_descr_get) {
+ annotations = Py_TYPE(annotations)->tp_descr_get(annotations, NULL,
+ (PyObject *)type);
+ } else {
+ Py_INCREF(annotations);
+ }
+ }
+ } else {
+ annotations = PyDict_New();
+ if (annotations) {
+ int result = _PyDict_SetItemId(type->tp_dict, &PyId___annotations__, annotations);
+ if (result) {
+ Py_CLEAR(annotations);
+ } else {
+ PyType_Modified(type);
+ }
+ }
+ }
+ return annotations;
+}
+
+static int
+type_set_annotations(PyTypeObject *type, PyObject *value, void *context)
+{
+ if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
+ PyErr_Format(PyExc_TypeError, "can't set attributes of built-in/extension type '%s'", type->tp_name);
+ return -1;
+ }
+
+ int result;
+ if (value != NULL) {
+ /* set */
+ result = _PyDict_SetItemId(type->tp_dict, &PyId___annotations__, value);
+ } else {
+ /* delete */
+ if (!_PyDict_ContainsId(type->tp_dict, &PyId___annotations__)) {
+ PyErr_Format(PyExc_AttributeError, "__annotations__");
+ return -1;
+ }
+ result = _PyDict_DelItemId(type->tp_dict, &PyId___annotations__);
+ }
+
+ if (result == 0) {
+ PyType_Modified(type);
+ }
+ return result;
+}
+
+
/*[clinic input]
type.__instancecheck__ -> bool
@@ -973,6 +1041,7 @@ static PyGetSetDef type_getsets[] = {
{"__dict__", (getter)type_dict, NULL, NULL},
{"__doc__", (getter)type_get_doc, (setter)type_set_doc, NULL},
{"__text_signature__", (getter)type_get_text_signature, NULL, NULL},
+ {"__annotations__", (getter)type_get_annotations, (setter)type_set_annotations, NULL},
{0}
};