summaryrefslogtreecommitdiffstats
path: root/Objects/funcobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/funcobject.c')
-rw-r--r--Objects/funcobject.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/Objects/funcobject.c b/Objects/funcobject.c
index 06a4fe9..63bdc21 100644
--- a/Objects/funcobject.c
+++ b/Objects/funcobject.c
@@ -38,6 +38,7 @@ PyFunction_New(PyObject *code, PyObject *globals)
op->func_doc = doc;
op->func_dict = NULL;
op->func_module = NULL;
+ op->func_annotations = NULL;
/* __module__: If module name is in globals, use it.
Otherwise, use None.
@@ -187,6 +188,38 @@ PyFunction_SetClosure(PyObject *op, PyObject *closure)
return 0;
}
+PyObject *
+PyFunction_GetAnnotations(PyObject *op)
+{
+ if (!PyFunction_Check(op)) {
+ PyErr_BadInternalCall();
+ return NULL;
+ }
+ return ((PyFunctionObject *) op) -> func_annotations;
+}
+
+int
+PyFunction_SetAnnotations(PyObject *op, PyObject *annotations)
+{
+ if (!PyFunction_Check(op)) {
+ PyErr_BadInternalCall();
+ return -1;
+ }
+ if (annotations == Py_None)
+ annotations = NULL;
+ else if (annotations && PyDict_Check(annotations)) {
+ Py_INCREF(annotations);
+ }
+ else {
+ PyErr_SetString(PyExc_SystemError,
+ "non-dict annotations");
+ return -1;
+ }
+ Py_XDECREF(((PyFunctionObject *)op) -> func_annotations);
+ ((PyFunctionObject *) op) -> func_annotations = annotations;
+ return 0;
+}
+
/* Methods */
#define OFF(x) offsetof(PyFunctionObject, x)
@@ -395,12 +428,48 @@ func_set_kwdefaults(PyFunctionObject *op, PyObject *value)
return 0;
}
+static PyObject *
+func_get_annotations(PyFunctionObject *op)
+{
+ if (op->func_annotations == NULL) {
+ op->func_annotations = PyDict_New();
+ if (op->func_annotations == NULL)
+ return NULL;
+ }
+ Py_INCREF(op->func_annotations);
+ return op->func_annotations;
+}
+
+static int
+func_set_annotations(PyFunctionObject *op, PyObject *value)
+{
+ PyObject *tmp;
+
+ if (value == Py_None)
+ value = NULL;
+ /* Legal to del f.func_annotations.
+ * Can only set func_annotations to NULL (through C api)
+ * or a dict. */
+ if (value != NULL && !PyDict_Check(value)) {
+ PyErr_SetString(PyExc_TypeError,
+ "func_annotations must be set to a dict object");
+ return -1;
+ }
+ tmp = op->func_annotations;
+ Py_XINCREF(value);
+ op->func_annotations = value;
+ Py_XDECREF(tmp);
+ return 0;
+}
+
static PyGetSetDef func_getsetlist[] = {
{"func_code", (getter)func_get_code, (setter)func_set_code},
{"func_defaults", (getter)func_get_defaults,
(setter)func_set_defaults},
{"func_kwdefaults", (getter)func_get_kwdefaults,
(setter)func_set_kwdefaults},
+ {"func_annotations", (getter)func_get_annotations,
+ (setter)func_set_annotations},
{"func_dict", (getter)func_get_dict, (setter)func_set_dict},
{"__dict__", (getter)func_get_dict, (setter)func_set_dict},
{"func_name", (getter)func_get_name, (setter)func_set_name},
@@ -524,6 +593,7 @@ func_dealloc(PyFunctionObject *op)
Py_XDECREF(op->func_doc);
Py_XDECREF(op->func_dict);
Py_XDECREF(op->func_closure);
+ Py_XDECREF(op->func_annotations);
PyObject_GC_Del(op);
}
@@ -546,6 +616,7 @@ func_traverse(PyFunctionObject *f, visitproc visit, void *arg)
Py_VISIT(f->func_name);
Py_VISIT(f->func_dict);
Py_VISIT(f->func_closure);
+ Py_VISIT(f->func_annotations);
return 0;
}