summaryrefslogtreecommitdiffstats
path: root/Objects/funcobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/funcobject.c')
-rw-r--r--Objects/funcobject.c675
1 files changed, 262 insertions, 413 deletions
diff --git a/Objects/funcobject.c b/Objects/funcobject.c
index b6ffc2a..c62de9c 100644
--- a/Objects/funcobject.c
+++ b/Objects/funcobject.c
@@ -2,85 +2,65 @@
/* Function object implementation */
#include "Python.h"
-#include "pycore_object.h"
-#include "pycore_pymem.h"
-#include "pycore_pystate.h"
-#include "pycore_tupleobject.h"
#include "code.h"
+#include "eval.h"
#include "structmember.h"
PyObject *
-PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname)
+PyFunction_New(PyObject *code, PyObject *globals)
{
- PyFunctionObject *op;
- PyObject *doc, *consts, *module;
- static PyObject *__name__ = NULL;
-
- if (__name__ == NULL) {
- __name__ = PyUnicode_InternFromString("__name__");
- if (__name__ == NULL)
- return NULL;
- }
-
- op = PyObject_GC_New(PyFunctionObject, &PyFunction_Type);
- if (op == NULL)
- return NULL;
-
- op->func_weakreflist = NULL;
- Py_INCREF(code);
- op->func_code = code;
- Py_INCREF(globals);
- op->func_globals = 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;
- op->vectorcall = _PyFunction_Vectorcall;
-
- consts = ((PyCodeObject *)code)->co_consts;
- if (PyTuple_Size(consts) >= 1) {
- doc = PyTuple_GetItem(consts, 0);
- if (!PyUnicode_Check(doc))
+ PyFunctionObject *op = PyObject_GC_New(PyFunctionObject,
+ &PyFunction_Type);
+ static PyObject *__name__ = 0;
+ if (op != NULL) {
+ PyObject *doc;
+ PyObject *consts;
+ PyObject *module;
+ op->func_weakreflist = NULL;
+ Py_INCREF(code);
+ op->func_code = code;
+ Py_INCREF(globals);
+ op->func_globals = globals;
+ op->func_name = ((PyCodeObject *)code)->co_name;
+ Py_INCREF(op->func_name);
+ op->func_defaults = NULL; /* No default arguments */
+ 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))
+ doc = Py_None;
+ }
+ else
doc = Py_None;
+ Py_INCREF(doc);
+ op->func_doc = doc;
+ op->func_dict = NULL;
+ op->func_module = NULL;
+
+ /* __module__: If module name is in globals, use it.
+ Otherwise, use None.
+ */
+ if (!__name__) {
+ __name__ = PyString_InternFromString("__name__");
+ if (!__name__) {
+ Py_DECREF(op);
+ return NULL;
+ }
+ }
+ module = PyDict_GetItem(globals, __name__);
+ if (module) {
+ Py_INCREF(module);
+ op->func_module = module;
+ }
}
else
- doc = Py_None;
- Py_INCREF(doc);
- 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. */
- module = PyDict_GetItemWithError(globals, __name__);
- if (module) {
- Py_INCREF(module);
- op->func_module = module;
- }
- else if (PyErr_Occurred()) {
- Py_DECREF(op);
return NULL;
- }
- if (qualname)
- op->func_qualname = qualname;
- else
- op->func_qualname = op->func_name;
- Py_INCREF(op->func_qualname);
-
_PyObject_GC_TRACK(op);
return (PyObject *)op;
}
PyObject *
-PyFunction_New(PyObject *code, PyObject *globals)
-{
- return PyFunction_NewWithQualName(code, globals, NULL);
-}
-
-PyObject *
PyFunction_GetCode(PyObject *op)
{
if (!PyFunction_Check(op)) {
@@ -141,37 +121,6 @@ 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_XSETREF(((PyFunctionObject *)op)->func_kwdefaults, defaults);
- return 0;
-}
-
-PyObject *
PyFunction_GetClosure(PyObject *op)
{
if (!PyFunction_Check(op)) {
@@ -203,67 +152,92 @@ 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_XSETREF(((PyFunctionObject *)op)->func_annotations, annotations);
- return 0;
-}
-
/* Methods */
#define OFF(x) offsetof(PyFunctionObject, x)
static PyMemberDef func_memberlist[] = {
- {"__closure__", T_OBJECT, OFF(func_closure),
+ {"func_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},
- {"__globals__", T_OBJECT, OFF(func_globals),
+ {"func_globals", T_OBJECT, OFF(func_globals),
+ RESTRICTED|READONLY},
+ {"__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_code(PyFunctionObject *op, void *Py_UNUSED(ignored))
+func_get_dict(PyFunctionObject *op)
{
- if (PySys_Audit("object.__getattr__", "Os", op, "__code__") < 0) {
+ if (restricted())
return NULL;
+ if (op->func_dict == NULL) {
+ op->func_dict = PyDict_New();
+ if (op->func_dict == NULL)
+ return NULL;
+ }
+ Py_INCREF(op->func_dict);
+ return op->func_dict;
+}
+
+static int
+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,
+ "function's dictionary may not be deleted");
+ return -1;
+ }
+ /* Can only set func_dict to a dictionary */
+ if (!PyDict_Check(value)) {
+ PyErr_SetString(PyExc_TypeError,
+ "setting function's dictionary to a non-dict");
+ return -1;
}
+ tmp = op->func_dict;
+ Py_INCREF(value);
+ op->func_dict = value;
+ Py_XDECREF(tmp);
+ return 0;
+}
+static PyObject *
+func_get_code(PyFunctionObject *op)
+{
+ if (restricted())
+ return NULL;
Py_INCREF(op->func_code);
return op->func_code;
}
static int
-func_set_code(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored))
+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)) {
@@ -271,88 +245,72 @@ func_set_code(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored))
"__code__ must be set to a code object");
return -1;
}
-
- if (PySys_Audit("object.__setattr__", "OsO",
- op, "__code__", value) < 0) {
- return -1;
- }
-
nfree = PyCode_GetNumFree((PyCodeObject *)value);
nclosure = (op->func_closure == NULL ? 0 :
PyTuple_GET_SIZE(op->func_closure));
if (nclosure != nfree) {
PyErr_Format(PyExc_ValueError,
- "%U() requires a code object with %zd free vars,"
+ "%s() requires a code object with %zd free vars,"
" not %zd",
- op->func_name,
+ PyString_AsString(op->func_name),
nclosure, nfree);
return -1;
}
+ tmp = op->func_code;
Py_INCREF(value);
- Py_XSETREF(op->func_code, value);
+ op->func_code = value;
+ Py_DECREF(tmp);
return 0;
}
static PyObject *
-func_get_name(PyFunctionObject *op, void *Py_UNUSED(ignored))
+func_get_name(PyFunctionObject *op)
{
Py_INCREF(op->func_name);
return op->func_name;
}
static int
-func_set_name(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored))
+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 || !PyUnicode_Check(value)) {
+ if (value == NULL || !PyString_Check(value)) {
PyErr_SetString(PyExc_TypeError,
"__name__ must be set to a string object");
return -1;
}
+ tmp = op->func_name;
Py_INCREF(value);
- Py_XSETREF(op->func_name, value);
- return 0;
-}
-
-static PyObject *
-func_get_qualname(PyFunctionObject *op, void *Py_UNUSED(ignored))
-{
- Py_INCREF(op->func_qualname);
- return op->func_qualname;
-}
-
-static int
-func_set_qualname(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored))
-{
- /* Not legal to del f.__qualname__ or to set it to anything
- * other than a string object. */
- if (value == NULL || !PyUnicode_Check(value)) {
- PyErr_SetString(PyExc_TypeError,
- "__qualname__ must be set to a string object");
- return -1;
- }
- Py_INCREF(value);
- Py_XSETREF(op->func_qualname, value);
+ op->func_name = value;
+ Py_DECREF(tmp);
return 0;
}
static PyObject *
-func_get_defaults(PyFunctionObject *op, void *Py_UNUSED(ignored))
+func_get_defaults(PyFunctionObject *op)
{
- if (PySys_Audit("object.__getattr__", "Os", op, "__defaults__") < 0) {
+ if (restricted())
return NULL;
- }
if (op->func_defaults == NULL) {
- Py_RETURN_NONE;
+ Py_INCREF(Py_None);
+ return Py_None;
}
Py_INCREF(op->func_defaults);
return op->func_defaults;
}
static int
-func_set_defaults(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored))
+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)
@@ -362,115 +320,37 @@ func_set_defaults(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored
"__defaults__ must be set to a tuple object");
return -1;
}
- if (value) {
- if (PySys_Audit("object.__setattr__", "OsO",
- op, "__defaults__", value) < 0) {
- return -1;
- }
- } else if (PySys_Audit("object.__delattr__", "Os",
- op, "__defaults__") < 0) {
- return -1;
- }
-
- Py_XINCREF(value);
- Py_XSETREF(op->func_defaults, value);
- return 0;
-}
-
-static PyObject *
-func_get_kwdefaults(PyFunctionObject *op, void *Py_UNUSED(ignored))
-{
- if (PySys_Audit("object.__getattr__", "Os",
- op, "__kwdefaults__") < 0) {
- return NULL;
- }
- if (op->func_kwdefaults == NULL) {
- Py_RETURN_NONE;
- }
- Py_INCREF(op->func_kwdefaults);
- return op->func_kwdefaults;
-}
-
-static int
-func_set_kwdefaults(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored))
-{
- 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;
- }
- if (value) {
- if (PySys_Audit("object.__setattr__", "OsO",
- op, "__kwdefaults__", value) < 0) {
- return -1;
- }
- } else if (PySys_Audit("object.__delattr__", "Os",
- op, "__kwdefaults__") < 0) {
- return -1;
- }
-
- Py_XINCREF(value);
- Py_XSETREF(op->func_kwdefaults, value);
- return 0;
-}
-
-static PyObject *
-func_get_annotations(PyFunctionObject *op, void *Py_UNUSED(ignored))
-{
- 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, void *Py_UNUSED(ignored))
-{
- 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_defaults;
Py_XINCREF(value);
- Py_XSETREF(op->func_annotations, value);
+ op->func_defaults = 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},
- {"__kwdefaults__", (getter)func_get_kwdefaults,
- (setter)func_set_kwdefaults},
- {"__annotations__", (getter)func_get_annotations,
- (setter)func_set_annotations},
- {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
+ {"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},
{"__name__", (getter)func_get_name, (setter)func_set_name},
- {"__qualname__", (getter)func_get_qualname, (setter)func_set_qualname},
{NULL} /* Sentinel */
};
-/*[clinic input]
-class function "PyFunctionObject *" "&PyFunction_Type"
-[clinic start generated code]*/
-/*[clinic end generated code: output=da39a3ee5e6b4b0d input=70af9c90aa2e71b0]*/
-
-#include "clinic/funcobject.c.h"
+PyDoc_STRVAR(func_doc,
+"function(code, globals[, name[, argdefs[, closure]]])\n\
+\n\
+Create a function object from a code object and a dictionary.\n\
+The optional name string overrides the name from the code object.\n\
+The optional argdefs tuple specifies the default argument values.\n\
+The optional closure tuple supplies the bindings for free variables.");
-/* function.__new__() maintains the following invariants for closures.
- The closure must correspond to the free variables of the code object.
+/* func_new() maintains the following invariants for closures. The
+ closure must correspond to the free variables of the code object.
if len(code.co_freevars) == 0:
closure = NULL
@@ -479,32 +359,26 @@ class function "PyFunctionObject *" "&PyFunction_Type"
for every elt in closure, type(elt) == cell
*/
-/*[clinic input]
-@classmethod
-function.__new__ as func_new
- code: object(type="PyCodeObject *", subclass_of="&PyCode_Type")
- a code object
- globals: object(subclass_of="&PyDict_Type")
- the globals dictionary
- name: object = None
- a string that overrides the name from the code object
- argdefs as defaults: object = None
- a tuple that specifies the default argument values
- closure: object = None
- a tuple that supplies the bindings for free variables
-
-Create a function object.
-[clinic start generated code]*/
-
static PyObject *
-func_new_impl(PyTypeObject *type, PyCodeObject *code, PyObject *globals,
- PyObject *name, PyObject *defaults, PyObject *closure)
-/*[clinic end generated code: output=99c6d9da3a24e3be input=93611752fc2daf11]*/
+func_new(PyTypeObject* type, PyObject* args, PyObject* kw)
{
+ PyCodeObject *code;
+ PyObject *globals;
+ PyObject *name = Py_None;
+ PyObject *defaults = Py_None;
+ PyObject *closure = Py_None;
PyFunctionObject *newfunc;
Py_ssize_t nfree, nclosure;
-
- if (name != Py_None && !PyUnicode_Check(name)) {
+ static char *kwlist[] = {"code", "globals", "name",
+ "argdefs", "closure", 0};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kw, "O!O!|OOO:function",
+ kwlist,
+ &PyCode_Type, &code,
+ &PyDict_Type, &globals,
+ &name, &defaults, &closure))
+ return NULL;
+ if (name != Py_None && !PyString_Check(name)) {
PyErr_SetString(PyExc_TypeError,
"arg 3 (name) must be None or string");
return NULL;
@@ -532,8 +406,9 @@ func_new_impl(PyTypeObject *type, PyCodeObject *code, PyObject *globals,
nclosure = closure == Py_None ? 0 : PyTuple_GET_SIZE(closure);
if (nfree != nclosure)
return PyErr_Format(PyExc_ValueError,
- "%U requires closure of length %zd, not %zd",
- code->co_name, nfree, nclosure);
+ "%s requires closure of length %zd, not %zd",
+ PyString_AS_STRING(code->co_name),
+ nfree, nclosure);
if (nclosure) {
Py_ssize_t i;
for (i = 0; i < nclosure; i++) {
@@ -545,9 +420,6 @@ func_new_impl(PyTypeObject *type, PyCodeObject *code, PyObject *globals,
}
}
}
- if (PySys_Audit("function.__new__", "O", code) < 0) {
- return NULL;
- }
newfunc = (PyFunctionObject *)PyFunction_New((PyObject *)code,
globals);
@@ -570,39 +442,29 @@ func_new_impl(PyTypeObject *type, PyCodeObject *code, PyObject *globals,
return (PyObject *)newfunc;
}
-static int
-func_clear(PyFunctionObject *op)
-{
- Py_CLEAR(op->func_code);
- Py_CLEAR(op->func_globals);
- Py_CLEAR(op->func_module);
- Py_CLEAR(op->func_name);
- Py_CLEAR(op->func_defaults);
- Py_CLEAR(op->func_kwdefaults);
- Py_CLEAR(op->func_doc);
- Py_CLEAR(op->func_dict);
- Py_CLEAR(op->func_closure);
- Py_CLEAR(op->func_annotations);
- Py_CLEAR(op->func_qualname);
- return 0;
-}
-
static void
func_dealloc(PyFunctionObject *op)
{
_PyObject_GC_UNTRACK(op);
- if (op->func_weakreflist != NULL) {
+ if (op->func_weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *) op);
- }
- (void)func_clear(op);
+ Py_DECREF(op->func_code);
+ Py_DECREF(op->func_globals);
+ Py_XDECREF(op->func_module);
+ Py_DECREF(op->func_name);
+ Py_XDECREF(op->func_defaults);
+ Py_XDECREF(op->func_doc);
+ Py_XDECREF(op->func_dict);
+ Py_XDECREF(op->func_closure);
PyObject_GC_Del(op);
}
static PyObject*
func_repr(PyFunctionObject *op)
{
- return PyUnicode_FromFormat("<function %U at %p>",
- op->func_qualname, op);
+ return PyString_FromFormat("<function %s at %p>",
+ PyString_AsString(op->func_name),
+ op);
}
static int
@@ -612,25 +474,71 @@ 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);
- Py_VISIT(f->func_qualname);
return 0;
}
+static PyObject *
+function_call(PyObject *func, PyObject *arg, PyObject *kw)
+{
+ PyObject *result;
+ PyObject *argdefs;
+ PyObject *kwtuple = NULL;
+ PyObject **d, **k;
+ Py_ssize_t nk, nd;
+
+ argdefs = PyFunction_GET_DEFAULTS(func);
+ if (argdefs != NULL && PyTuple_Check(argdefs)) {
+ d = &PyTuple_GET_ITEM((PyTupleObject *)argdefs, 0);
+ nd = PyTuple_GET_SIZE(argdefs);
+ }
+ else {
+ d = NULL;
+ nd = 0;
+ }
+
+ if (kw != NULL && PyDict_Check(kw)) {
+ Py_ssize_t pos, i;
+ nk = PyDict_Size(kw);
+ kwtuple = PyTuple_New(2*nk);
+ if (kwtuple == NULL)
+ return NULL;
+ k = &PyTuple_GET_ITEM(kwtuple, 0);
+ pos = i = 0;
+ while (PyDict_Next(kw, &pos, &k[i], &k[i+1])) {
+ Py_INCREF(k[i]);
+ Py_INCREF(k[i+1]);
+ i += 2;
+ }
+ nk = i/2;
+ }
+ else {
+ k = NULL;
+ nk = 0;
+ }
+
+ result = PyEval_EvalCodeEx(
+ (PyCodeObject *)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_CLOSURE(func));
+
+ Py_XDECREF(kwtuple);
+
+ return result;
+}
+
/* Bind a function to an object */
static PyObject *
func_descr_get(PyObject *func, PyObject *obj, PyObject *type)
{
- if (obj == Py_None || obj == NULL) {
- Py_INCREF(func);
- return func;
- }
- return PyMethod_New(func, obj);
+ if (obj == Py_None)
+ obj = NULL;
+ return PyMethod_New(func, obj, type);
}
PyTypeObject PyFunction_Type = {
@@ -639,26 +547,24 @@ PyTypeObject PyFunction_Type = {
sizeof(PyFunctionObject),
0,
(destructor)func_dealloc, /* tp_dealloc */
- offsetof(PyFunctionObject, vectorcall), /* tp_vectorcall_offset */
+ 0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
- 0, /* tp_as_async */
+ 0, /* tp_compare */
(reprfunc)func_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
- PyVectorcall_Call, /* tp_call */
+ function_call, /* tp_call */
0, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ PyObject_GenericSetAttr, /* tp_setattro */
0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
- _Py_TPFLAGS_HAVE_VECTORCALL |
- Py_TPFLAGS_METHOD_DESCRIPTOR, /* tp_flags */
- func_new__doc__, /* tp_doc */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
+ func_doc, /* tp_doc */
(traverseproc)func_traverse, /* tp_traverse */
- (inquiry)func_clear, /* tp_clear */
+ 0, /* tp_clear */
0, /* tp_richcompare */
offsetof(PyFunctionObject, func_weakreflist), /* tp_weaklistoffset */
0, /* tp_iter */
@@ -700,7 +606,6 @@ PyTypeObject PyFunction_Type = {
typedef struct {
PyObject_HEAD
PyObject *cm_callable;
- PyObject *cm_dict;
} classmethod;
static void
@@ -708,7 +613,6 @@ cm_dealloc(classmethod *cm)
{
_PyObject_GC_UNTRACK((PyObject *)cm);
Py_XDECREF(cm->cm_callable);
- Py_XDECREF(cm->cm_dict);
Py_TYPE(cm)->tp_free((PyObject *)cm);
}
@@ -716,7 +620,6 @@ static int
cm_traverse(classmethod *cm, visitproc visit, void *arg)
{
Py_VISIT(cm->cm_callable);
- Py_VISIT(cm->cm_dict);
return 0;
}
@@ -724,7 +627,6 @@ static int
cm_clear(classmethod *cm)
{
Py_CLEAR(cm->cm_callable);
- Py_CLEAR(cm->cm_dict);
return 0;
}
@@ -741,11 +643,8 @@ cm_descr_get(PyObject *self, PyObject *obj, PyObject *type)
}
if (type == NULL)
type = (PyObject *)(Py_TYPE(obj));
- if (Py_TYPE(cm->cm_callable)->tp_descr_get != NULL) {
- return Py_TYPE(cm->cm_callable)->tp_descr_get(cm->cm_callable, type,
- NULL);
- }
- return PyMethod_New(cm->cm_callable, type);
+ return PyMethod_New(cm->cm_callable,
+ type, (PyObject *)(Py_TYPE(type)));
}
static int
@@ -754,12 +653,12 @@ cm_init(PyObject *self, PyObject *args, PyObject *kwds)
classmethod *cm = (classmethod *)self;
PyObject *callable;
- if (!_PyArg_NoKeywords("classmethod", kwds))
- return -1;
if (!PyArg_UnpackTuple(args, "classmethod", 1, 1, &callable))
return -1;
+ if (!_PyArg_NoKeywords("classmethod", kwds))
+ return -1;
Py_INCREF(callable);
- Py_XSETREF(cm->cm_callable, callable);
+ cm->cm_callable = callable;
return 0;
}
@@ -768,28 +667,6 @@ static PyMemberDef cm_memberlist[] = {
{NULL} /* Sentinel */
};
-static PyObject *
-cm_get___isabstractmethod__(classmethod *cm, void *closure)
-{
- int res = _PyObject_IsAbstract(cm->cm_callable);
- if (res == -1) {
- return NULL;
- }
- else if (res) {
- Py_RETURN_TRUE;
- }
- Py_RETURN_FALSE;
-}
-
-static PyGetSetDef cm_getsetlist[] = {
- {"__isabstractmethod__",
- (getter)cm_get___isabstractmethod__, NULL,
- NULL,
- NULL},
- {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict, NULL, NULL},
- {NULL} /* Sentinel */
-};
-
PyDoc_STRVAR(classmethod_doc,
"classmethod(function) -> method\n\
\n\
@@ -818,10 +695,10 @@ PyTypeObject PyClassMethod_Type = {
sizeof(classmethod),
0,
(destructor)cm_dealloc, /* tp_dealloc */
- 0, /* tp_vectorcall_offset */
+ 0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
- 0, /* tp_as_async */
+ 0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
@@ -829,7 +706,7 @@ PyTypeObject PyClassMethod_Type = {
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
- 0, /* tp_getattro */
+ PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
@@ -842,12 +719,12 @@ PyTypeObject PyClassMethod_Type = {
0, /* tp_iternext */
0, /* tp_methods */
cm_memberlist, /* tp_members */
- cm_getsetlist, /* tp_getset */
+ 0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
cm_descr_get, /* tp_descr_get */
0, /* tp_descr_set */
- offsetof(classmethod, cm_dict), /* tp_dictoffset */
+ 0, /* tp_dictoffset */
cm_init, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */
@@ -875,11 +752,10 @@ PyClassMethod_New(PyObject *callable)
class C:
@staticmethod
def f(arg1, arg2, ...):
- ...
+ ....
It can be called either on the class (e.g. C.f()) or on an instance
- (e.g. C().f()). Both the class and the instance are ignored, and
- neither is passed implicitly as the first argument to the method.
+ (e.g. C().f()); the instance is ignored except for its class.
Static methods in Python are similar to those found in Java or C++.
For a more advanced concept, see class methods above.
@@ -888,7 +764,6 @@ PyClassMethod_New(PyObject *callable)
typedef struct {
PyObject_HEAD
PyObject *sm_callable;
- PyObject *sm_dict;
} staticmethod;
static void
@@ -896,7 +771,6 @@ sm_dealloc(staticmethod *sm)
{
_PyObject_GC_UNTRACK((PyObject *)sm);
Py_XDECREF(sm->sm_callable);
- Py_XDECREF(sm->sm_dict);
Py_TYPE(sm)->tp_free((PyObject *)sm);
}
@@ -904,7 +778,6 @@ static int
sm_traverse(staticmethod *sm, visitproc visit, void *arg)
{
Py_VISIT(sm->sm_callable);
- Py_VISIT(sm->sm_dict);
return 0;
}
@@ -912,7 +785,6 @@ static int
sm_clear(staticmethod *sm)
{
Py_CLEAR(sm->sm_callable);
- Py_CLEAR(sm->sm_dict);
return 0;
}
@@ -936,12 +808,12 @@ sm_init(PyObject *self, PyObject *args, PyObject *kwds)
staticmethod *sm = (staticmethod *)self;
PyObject *callable;
- if (!_PyArg_NoKeywords("staticmethod", kwds))
- return -1;
if (!PyArg_UnpackTuple(args, "staticmethod", 1, 1, &callable))
return -1;
+ if (!_PyArg_NoKeywords("staticmethod", kwds))
+ return -1;
Py_INCREF(callable);
- Py_XSETREF(sm->sm_callable, callable);
+ sm->sm_callable = callable;
return 0;
}
@@ -950,28 +822,6 @@ static PyMemberDef sm_memberlist[] = {
{NULL} /* Sentinel */
};
-static PyObject *
-sm_get___isabstractmethod__(staticmethod *sm, void *closure)
-{
- int res = _PyObject_IsAbstract(sm->sm_callable);
- if (res == -1) {
- return NULL;
- }
- else if (res) {
- Py_RETURN_TRUE;
- }
- Py_RETURN_FALSE;
-}
-
-static PyGetSetDef sm_getsetlist[] = {
- {"__isabstractmethod__",
- (getter)sm_get___isabstractmethod__, NULL,
- NULL,
- NULL},
- {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict, NULL, NULL},
- {NULL} /* Sentinel */
-};
-
PyDoc_STRVAR(staticmethod_doc,
"staticmethod(function) -> method\n\
\n\
@@ -986,8 +836,7 @@ To declare a static method, use this idiom:\n\
...\n\
\n\
It can be called either on the class (e.g. C.f()) or on an instance\n\
-(e.g. C().f()). Both the class and the instance are ignored, and\n\
-neither is passed implicitly as the first argument to the method.\n\
+(e.g. C().f()). The instance is ignored except for its class.\n\
\n\
Static methods in Python are similar to those found in Java or C++.\n\
For a more advanced concept, see the classmethod builtin.");
@@ -998,10 +847,10 @@ PyTypeObject PyStaticMethod_Type = {
sizeof(staticmethod),
0,
(destructor)sm_dealloc, /* tp_dealloc */
- 0, /* tp_vectorcall_offset */
+ 0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
- 0, /* tp_as_async */
+ 0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
@@ -1009,7 +858,7 @@ PyTypeObject PyStaticMethod_Type = {
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
- 0, /* tp_getattro */
+ PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
@@ -1022,12 +871,12 @@ PyTypeObject PyStaticMethod_Type = {
0, /* tp_iternext */
0, /* tp_methods */
sm_memberlist, /* tp_members */
- sm_getsetlist, /* tp_getset */
+ 0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
sm_descr_get, /* tp_descr_get */
0, /* tp_descr_set */
- offsetof(staticmethod, sm_dict), /* tp_dictoffset */
+ 0, /* tp_dictoffset */
sm_init, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */