summaryrefslogtreecommitdiffstats
path: root/Objects/funcobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/funcobject.c')
-rw-r--r--Objects/funcobject.c221
1 files changed, 163 insertions, 58 deletions
diff --git a/Objects/funcobject.c b/Objects/funcobject.c
index 51b6c9d..2292a9e 100644
--- a/Objects/funcobject.c
+++ b/Objects/funcobject.c
@@ -3,7 +3,6 @@
#include "Python.h"
#include "code.h"
-#include "eval.h"
#include "structmember.h"
PyObject *
@@ -24,11 +23,12 @@ PyFunction_New(PyObject *code, PyObject *globals)
op->func_name = ((PyCodeObject *)code)->co_name;
Py_INCREF(op->func_name);
op->func_defaults = NULL; /* No default arguments */
+ op->func_kwdefaults = NULL; /* No keyword only defaults */
op->func_closure = NULL;
consts = ((PyCodeObject *)code)->co_consts;
if (PyTuple_Size(consts) >= 1) {
doc = PyTuple_GetItem(consts, 0);
- if (!PyString_Check(doc) && !PyUnicode_Check(doc))
+ if (!PyUnicode_Check(doc))
doc = Py_None;
}
else
@@ -37,12 +37,13 @@ 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.
*/
if (!__name__) {
- __name__ = PyString_InternFromString("__name__");
+ __name__ = PyUnicode_InternFromString("__name__");
if (!__name__) {
Py_DECREF(op);
return NULL;
@@ -122,6 +123,38 @@ PyFunction_SetDefaults(PyObject *op, PyObject *defaults)
}
PyObject *
+PyFunction_GetKwDefaults(PyObject *op)
+{
+ if (!PyFunction_Check(op)) {
+ PyErr_BadInternalCall();
+ return NULL;
+ }
+ return ((PyFunctionObject *) op) -> func_kwdefaults;
+}
+
+int
+PyFunction_SetKwDefaults(PyObject *op, PyObject *defaults)
+{
+ if (!PyFunction_Check(op)) {
+ PyErr_BadInternalCall();
+ return -1;
+ }
+ if (defaults == Py_None)
+ defaults = NULL;
+ else if (defaults && PyDict_Check(defaults)) {
+ Py_INCREF(defaults);
+ }
+ else {
+ PyErr_SetString(PyExc_SystemError,
+ "non-dict keyword only default args");
+ return -1;
+ }
+ Py_XDECREF(((PyFunctionObject *)op) -> func_kwdefaults);
+ ((PyFunctionObject *) op) -> func_kwdefaults = defaults;
+ return 0;
+}
+
+PyObject *
PyFunction_GetClosure(PyObject *op)
{
if (!PyFunction_Check(op)) {
@@ -154,40 +187,55 @@ 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)
static PyMemberDef func_memberlist[] = {
- {"func_closure", T_OBJECT, OFF(func_closure),
+ {"__closure__", T_OBJECT, OFF(func_closure),
RESTRICTED|READONLY},
- {"__closure__", T_OBJECT, OFF(func_closure),
- RESTRICTED|READONLY},
- {"func_doc", T_OBJECT, OFF(func_doc), PY_WRITE_RESTRICTED},
{"__doc__", T_OBJECT, OFF(func_doc), PY_WRITE_RESTRICTED},
- {"func_globals", T_OBJECT, OFF(func_globals),
- RESTRICTED|READONLY},
- {"__globals__", T_OBJECT, OFF(func_globals),
+ {"__globals__", T_OBJECT, OFF(func_globals),
RESTRICTED|READONLY},
{"__module__", T_OBJECT, OFF(func_module), PY_WRITE_RESTRICTED},
{NULL} /* Sentinel */
};
-static int
-restricted(void)
-{
- if (!PyEval_GetRestricted())
- return 0;
- PyErr_SetString(PyExc_RuntimeError,
- "function attributes not accessible in restricted mode");
- return 1;
-}
-
static PyObject *
func_get_dict(PyFunctionObject *op)
{
- if (restricted())
- return NULL;
if (op->func_dict == NULL) {
op->func_dict = PyDict_New();
if (op->func_dict == NULL)
@@ -202,8 +250,6 @@ func_set_dict(PyFunctionObject *op, PyObject *value)
{
PyObject *tmp;
- if (restricted())
- return -1;
/* It is illegal to del f.func_dict */
if (value == NULL) {
PyErr_SetString(PyExc_TypeError,
@@ -226,8 +272,6 @@ func_set_dict(PyFunctionObject *op, PyObject *value)
static PyObject *
func_get_code(PyFunctionObject *op)
{
- if (restricted())
- return NULL;
Py_INCREF(op->func_code);
return op->func_code;
}
@@ -238,8 +282,6 @@ func_set_code(PyFunctionObject *op, PyObject *value)
PyObject *tmp;
Py_ssize_t nfree, nclosure;
- if (restricted())
- return -1;
/* Not legal to del f.func_code or to set it to anything
* other than a code object. */
if (value == NULL || !PyCode_Check(value)) {
@@ -252,9 +294,9 @@ func_set_code(PyFunctionObject *op, PyObject *value)
PyTuple_GET_SIZE(op->func_closure));
if (nclosure != nfree) {
PyErr_Format(PyExc_ValueError,
- "%s() requires a code object with %zd free vars,"
+ "%U() requires a code object with %zd free vars,"
" not %zd",
- PyString_AsString(op->func_name),
+ op->func_name,
nclosure, nfree);
return -1;
}
@@ -277,11 +319,9 @@ func_set_name(PyFunctionObject *op, PyObject *value)
{
PyObject *tmp;
- if (restricted())
- return -1;
/* Not legal to del f.func_name or to set it to anything
* other than a string object. */
- if (value == NULL || !PyString_Check(value)) {
+ if (value == NULL || !PyUnicode_Check(value)) {
PyErr_SetString(PyExc_TypeError,
"__name__ must be set to a string object");
return -1;
@@ -296,8 +336,6 @@ func_set_name(PyFunctionObject *op, PyObject *value)
static PyObject *
func_get_defaults(PyFunctionObject *op)
{
- if (restricted())
- return NULL;
if (op->func_defaults == NULL) {
Py_INCREF(Py_None);
return Py_None;
@@ -311,8 +349,6 @@ func_set_defaults(PyFunctionObject *op, PyObject *value)
{
PyObject *tmp;
- if (restricted())
- return -1;
/* Legal to del f.func_defaults.
* Can only set func_defaults to NULL or a tuple. */
if (value == Py_None)
@@ -329,16 +365,81 @@ func_set_defaults(PyFunctionObject *op, PyObject *value)
return 0;
}
+static PyObject *
+func_get_kwdefaults(PyFunctionObject *op)
+{
+ if (op->func_kwdefaults == NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ Py_INCREF(op->func_kwdefaults);
+ return op->func_kwdefaults;
+}
+
+static int
+func_set_kwdefaults(PyFunctionObject *op, PyObject *value)
+{
+ PyObject *tmp;
+
+ if (value == Py_None)
+ value = NULL;
+ /* Legal to del f.func_kwdefaults.
+ * Can only set func_kwdefaults to NULL or a dict. */
+ if (value != NULL && !PyDict_Check(value)) {
+ PyErr_SetString(PyExc_TypeError,
+ "__kwdefaults__ must be set to a dict object");
+ return -1;
+ }
+ tmp = op->func_kwdefaults;
+ Py_XINCREF(value);
+ op->func_kwdefaults = value;
+ Py_XDECREF(tmp);
+ 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,
+ "__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},
{"__code__", (getter)func_get_code, (setter)func_set_code},
- {"func_defaults", (getter)func_get_defaults,
- (setter)func_set_defaults},
{"__defaults__", (getter)func_get_defaults,
(setter)func_set_defaults},
- {"func_dict", (getter)func_get_dict, (setter)func_set_dict},
+ {"__kwdefaults__", (getter)func_get_kwdefaults,
+ (setter)func_set_kwdefaults},
+ {"__annotations__", (getter)func_get_annotations,
+ (setter)func_set_annotations},
{"__dict__", (getter)func_get_dict, (setter)func_set_dict},
- {"func_name", (getter)func_get_name, (setter)func_set_name},
{"__name__", (getter)func_get_name, (setter)func_set_name},
{NULL} /* Sentinel */
};
@@ -380,7 +481,7 @@ func_new(PyTypeObject* type, PyObject* args, PyObject* kw)
&PyDict_Type, &globals,
&name, &defaults, &closure))
return NULL;
- if (name != Py_None && !PyString_Check(name)) {
+ if (name != Py_None && !PyUnicode_Check(name)) {
PyErr_SetString(PyExc_TypeError,
"arg 3 (name) must be None or string");
return NULL;
@@ -408,9 +509,8 @@ func_new(PyTypeObject* type, PyObject* args, PyObject* kw)
nclosure = closure == Py_None ? 0 : PyTuple_GET_SIZE(closure);
if (nfree != nclosure)
return PyErr_Format(PyExc_ValueError,
- "%s requires closure of length %zd, not %zd",
- PyString_AS_STRING(code->co_name),
- nfree, nclosure);
+ "%U requires closure of length %zd, not %zd",
+ code->co_name, nfree, nclosure);
if (nclosure) {
Py_ssize_t i;
for (i = 0; i < nclosure; i++) {
@@ -456,18 +556,19 @@ func_dealloc(PyFunctionObject *op)
Py_XDECREF(op->func_module);
Py_DECREF(op->func_name);
Py_XDECREF(op->func_defaults);
+ Py_XDECREF(op->func_kwdefaults);
Py_XDECREF(op->func_doc);
Py_XDECREF(op->func_dict);
Py_XDECREF(op->func_closure);
+ Py_XDECREF(op->func_annotations);
PyObject_GC_Del(op);
}
static PyObject*
func_repr(PyFunctionObject *op)
{
- return PyString_FromFormat("<function %s at %p>",
- PyString_AsString(op->func_name),
- op);
+ return PyUnicode_FromFormat("<function %U at %p>",
+ op->func_name, op);
}
static int
@@ -477,10 +578,12 @@ func_traverse(PyFunctionObject *f, visitproc visit, void *arg)
Py_VISIT(f->func_globals);
Py_VISIT(f->func_module);
Py_VISIT(f->func_defaults);
+ Py_VISIT(f->func_kwdefaults);
Py_VISIT(f->func_doc);
Py_VISIT(f->func_name);
Py_VISIT(f->func_dict);
Py_VISIT(f->func_closure);
+ Py_VISIT(f->func_annotations);
return 0;
}
@@ -524,10 +627,11 @@ function_call(PyObject *func, PyObject *arg, PyObject *kw)
}
result = PyEval_EvalCodeEx(
- (PyCodeObject *)PyFunction_GET_CODE(func),
+ PyFunction_GET_CODE(func),
PyFunction_GET_GLOBALS(func), (PyObject *)NULL,
&PyTuple_GET_ITEM(arg, 0), PyTuple_GET_SIZE(arg),
k, nk, d, nd,
+ PyFunction_GET_KW_DEFAULTS(func),
PyFunction_GET_CLOSURE(func));
Py_XDECREF(kwtuple);
@@ -539,9 +643,11 @@ function_call(PyObject *func, PyObject *arg, PyObject *kw)
static PyObject *
func_descr_get(PyObject *func, PyObject *obj, PyObject *type)
{
- if (obj == Py_None)
- obj = NULL;
- return PyMethod_New(func, obj, type);
+ if (obj == Py_None || obj == NULL) {
+ Py_INCREF(func);
+ return func;
+ }
+ return PyMethod_New(func, obj);
}
PyTypeObject PyFunction_Type = {
@@ -553,7 +659,7 @@ PyTypeObject PyFunction_Type = {
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
- 0, /* tp_compare */
+ 0, /* tp_reserved */
(reprfunc)func_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
@@ -645,8 +751,7 @@ cm_descr_get(PyObject *self, PyObject *obj, PyObject *type)
}
if (type == NULL)
type = (PyObject *)(Py_TYPE(obj));
- return PyMethod_New(cm->cm_callable,
- type, (PyObject *)(Py_TYPE(type)));
+ return PyMethod_New(cm->cm_callable, type);
}
static int
@@ -699,7 +804,7 @@ PyTypeObject PyClassMethod_Type = {
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
- 0, /* tp_compare */
+ 0, /* tp_reserved */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
@@ -849,7 +954,7 @@ PyTypeObject PyStaticMethod_Type = {
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
- 0, /* tp_compare */
+ 0, /* tp_reserved */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */