diff options
Diffstat (limited to 'Objects/funcobject.c')
| -rw-r--r-- | Objects/funcobject.c | 221 |
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 */ |
