mirror of https://github.com/python/cpython
gh-91098: Use Argument Clinic for Object/classobject.c to fix docstrings (#31711)
Closes GH-91098. Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
This commit is contained in:
parent
014eb7fd02
commit
7fbc7f6128
|
@ -77,7 +77,9 @@ class Get_argspecTest(unittest.TestCase):
|
|||
tiptest(List.append, '(self, object, /)' + append_doc)
|
||||
tiptest([].append, '(object, /)' + append_doc)
|
||||
|
||||
tiptest(types.MethodType, "method(function, instance)")
|
||||
tiptest(types.MethodType,
|
||||
'(function, instance, /)\n'
|
||||
'Create a bound instance method object.')
|
||||
tiptest(SB(), default_tip)
|
||||
|
||||
p = re.compile('')
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Use Argument Clinic for the :class:`types.MethodType` constructor. Patch by
|
||||
Oleg Iarygin.
|
|
@ -7,8 +7,15 @@
|
|||
#include "pycore_pystate.h" // _PyThreadState_GET()
|
||||
#include "structmember.h" // PyMemberDef
|
||||
|
||||
#include "clinic/classobject.c.h"
|
||||
|
||||
#define TP_DESCR_GET(t) ((t)->tp_descr_get)
|
||||
|
||||
/*[clinic input]
|
||||
class method "PyMethodObject *" "&PyMethod_Type"
|
||||
[clinic start generated code]*/
|
||||
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b16e47edf6107c23]*/
|
||||
|
||||
|
||||
PyObject *
|
||||
PyMethod_Function(PyObject *im)
|
||||
|
@ -115,23 +122,26 @@ PyMethod_New(PyObject *func, PyObject *self)
|
|||
return (PyObject *)im;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
method_reduce(PyMethodObject *im, PyObject *Py_UNUSED(ignored))
|
||||
{
|
||||
PyObject *self = PyMethod_GET_SELF(im);
|
||||
PyObject *func = PyMethod_GET_FUNCTION(im);
|
||||
PyObject *funcname;
|
||||
/*[clinic input]
|
||||
method.__reduce__
|
||||
[clinic start generated code]*/
|
||||
|
||||
funcname = PyObject_GetAttr(func, &_Py_ID(__name__));
|
||||
static PyObject *
|
||||
method___reduce___impl(PyMethodObject *self)
|
||||
/*[clinic end generated code: output=6c04506d0fa6fdcb input=143a0bf5e96de6e8]*/
|
||||
{
|
||||
PyObject *funcself = PyMethod_GET_SELF(self);
|
||||
PyObject *func = PyMethod_GET_FUNCTION(self);
|
||||
PyObject *funcname = PyObject_GetAttr(func, &_Py_ID(__name__));
|
||||
if (funcname == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue(
|
||||
"N(ON)", _PyEval_GetBuiltin(&_Py_ID(getattr)), self, funcname);
|
||||
"N(ON)", _PyEval_GetBuiltin(&_Py_ID(getattr)), funcself, funcname);
|
||||
}
|
||||
|
||||
static PyMethodDef method_methods[] = {
|
||||
{"__reduce__", (PyCFunction)method_reduce, METH_NOARGS, NULL},
|
||||
METHOD___REDUCE___METHODDEF
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
@ -193,34 +203,32 @@ method_getattro(PyObject *obj, PyObject *name)
|
|||
return PyObject_GetAttr(im->im_func, name);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(method_doc,
|
||||
"method(function, instance)\n\
|
||||
\n\
|
||||
Create a bound instance method object.");
|
||||
/*[clinic input]
|
||||
@classmethod
|
||||
method.__new__ as method_new
|
||||
function: object
|
||||
instance: object
|
||||
/
|
||||
|
||||
Create a bound instance method object.
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
method_new(PyTypeObject* type, PyObject* args, PyObject *kw)
|
||||
method_new_impl(PyTypeObject *type, PyObject *function, PyObject *instance)
|
||||
/*[clinic end generated code: output=d33ef4ebf702e1f7 input=4e32facc3c3108ae]*/
|
||||
{
|
||||
PyObject *func;
|
||||
PyObject *self;
|
||||
|
||||
if (!_PyArg_NoKeywords("method", kw))
|
||||
return NULL;
|
||||
if (!PyArg_UnpackTuple(args, "method", 2, 2,
|
||||
&func, &self))
|
||||
return NULL;
|
||||
if (!PyCallable_Check(func)) {
|
||||
if (!PyCallable_Check(function)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"first argument must be callable");
|
||||
return NULL;
|
||||
}
|
||||
if (self == NULL || self == Py_None) {
|
||||
if (instance == NULL || instance == Py_None) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"self must not be None");
|
||||
"instance must not be None");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return PyMethod_New(func, self);
|
||||
return PyMethod_New(function, instance);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -322,50 +330,37 @@ method_descr_get(PyObject *meth, PyObject *obj, PyObject *cls)
|
|||
|
||||
PyTypeObject PyMethod_Type = {
|
||||
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
||||
"method",
|
||||
sizeof(PyMethodObject),
|
||||
0,
|
||||
(destructor)method_dealloc, /* tp_dealloc */
|
||||
offsetof(PyMethodObject, vectorcall), /* tp_vectorcall_offset */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_as_async */
|
||||
(reprfunc)method_repr, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
(hashfunc)method_hash, /* tp_hash */
|
||||
PyVectorcall_Call, /* tp_call */
|
||||
0, /* tp_str */
|
||||
method_getattro, /* tp_getattro */
|
||||
PyObject_GenericSetAttr, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
|
||||
Py_TPFLAGS_HAVE_VECTORCALL, /* tp_flags */
|
||||
method_doc, /* tp_doc */
|
||||
(traverseproc)method_traverse, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
method_richcompare, /* tp_richcompare */
|
||||
offsetof(PyMethodObject, im_weakreflist), /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
method_methods, /* tp_methods */
|
||||
method_memberlist, /* tp_members */
|
||||
method_getset, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
method_descr_get, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
0, /* tp_init */
|
||||
0, /* tp_alloc */
|
||||
method_new, /* tp_new */
|
||||
.tp_name = "method",
|
||||
.tp_basicsize = sizeof(PyMethodObject),
|
||||
.tp_dealloc = (destructor)method_dealloc,
|
||||
.tp_vectorcall_offset = offsetof(PyMethodObject, vectorcall),
|
||||
.tp_repr = (reprfunc)method_repr,
|
||||
.tp_hash = (hashfunc)method_hash,
|
||||
.tp_call = PyVectorcall_Call,
|
||||
.tp_getattro = method_getattro,
|
||||
.tp_setattro = PyObject_GenericSetAttr,
|
||||
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
|
||||
Py_TPFLAGS_HAVE_VECTORCALL,
|
||||
.tp_doc = method_new__doc__,
|
||||
.tp_traverse = (traverseproc)method_traverse,
|
||||
.tp_richcompare = method_richcompare,
|
||||
.tp_weaklistoffset = offsetof(PyMethodObject, im_weakreflist),
|
||||
.tp_methods = method_methods,
|
||||
.tp_members = method_memberlist,
|
||||
.tp_getset = method_getset,
|
||||
.tp_descr_get = method_descr_get,
|
||||
.tp_new = method_new,
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
* instance method
|
||||
*/
|
||||
|
||||
/*[clinic input]
|
||||
class instancemethod "PyInstanceMethodObject *" "&PyInstanceMethod_Type"
|
||||
[clinic start generated code]*/
|
||||
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=28c9762a9016f4d2]*/
|
||||
|
||||
PyObject *
|
||||
PyInstanceMethod_New(PyObject *func) {
|
||||
PyInstanceMethodObject *method;
|
||||
|
@ -516,67 +511,43 @@ instancemethod_repr(PyObject *self)
|
|||
return result;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(instancemethod_doc,
|
||||
"instancemethod(function)\n\
|
||||
\n\
|
||||
Bind a function to a class.");
|
||||
/*[clinic input]
|
||||
@classmethod
|
||||
instancemethod.__new__ as instancemethod_new
|
||||
function: object
|
||||
/
|
||||
|
||||
Bind a function to a class.
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
instancemethod_new(PyTypeObject* type, PyObject* args, PyObject *kw)
|
||||
instancemethod_new_impl(PyTypeObject *type, PyObject *function)
|
||||
/*[clinic end generated code: output=5e0397b2bdb750be input=cfc54e8b973664a8]*/
|
||||
{
|
||||
PyObject *func;
|
||||
|
||||
if (!_PyArg_NoKeywords("instancemethod", kw))
|
||||
return NULL;
|
||||
if (!PyArg_UnpackTuple(args, "instancemethod", 1, 1, &func))
|
||||
return NULL;
|
||||
if (!PyCallable_Check(func)) {
|
||||
if (!PyCallable_Check(function)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"first argument must be callable");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return PyInstanceMethod_New(func);
|
||||
return PyInstanceMethod_New(function);
|
||||
}
|
||||
|
||||
PyTypeObject PyInstanceMethod_Type = {
|
||||
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
||||
"instancemethod", /* tp_name */
|
||||
sizeof(PyInstanceMethodObject), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
instancemethod_dealloc, /* tp_dealloc */
|
||||
0, /* tp_vectorcall_offset */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_as_async */
|
||||
(reprfunc)instancemethod_repr, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
0, /* tp_hash */
|
||||
instancemethod_call, /* tp_call */
|
||||
0, /* tp_str */
|
||||
instancemethod_getattro, /* tp_getattro */
|
||||
PyObject_GenericSetAttr, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT
|
||||
| Py_TPFLAGS_HAVE_GC, /* tp_flags */
|
||||
instancemethod_doc, /* tp_doc */
|
||||
instancemethod_traverse, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
instancemethod_richcompare, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
0, /* tp_methods */
|
||||
instancemethod_memberlist, /* tp_members */
|
||||
instancemethod_getset, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
instancemethod_descr_get, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
0, /* tp_init */
|
||||
0, /* tp_alloc */
|
||||
instancemethod_new, /* tp_new */
|
||||
.tp_name = "instancemethod",
|
||||
.tp_basicsize = sizeof(PyInstanceMethodObject),
|
||||
.tp_dealloc = instancemethod_dealloc,
|
||||
.tp_repr = (reprfunc)instancemethod_repr,
|
||||
.tp_call = instancemethod_call,
|
||||
.tp_getattro = instancemethod_getattro,
|
||||
.tp_setattro = PyObject_GenericSetAttr,
|
||||
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
|
||||
.tp_doc = instancemethod_new__doc__,
|
||||
.tp_traverse = instancemethod_traverse,
|
||||
.tp_richcompare = instancemethod_richcompare,
|
||||
.tp_members = instancemethod_memberlist,
|
||||
.tp_getset = instancemethod_getset,
|
||||
.tp_descr_get = instancemethod_descr_get,
|
||||
.tp_new = instancemethod_new,
|
||||
};
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
/*[clinic input]
|
||||
preserve
|
||||
[clinic start generated code]*/
|
||||
|
||||
PyDoc_STRVAR(method___reduce____doc__,
|
||||
"__reduce__($self, /)\n"
|
||||
"--\n"
|
||||
"\n");
|
||||
|
||||
#define METHOD___REDUCE___METHODDEF \
|
||||
{"__reduce__", (PyCFunction)method___reduce__, METH_NOARGS, method___reduce____doc__},
|
||||
|
||||
static PyObject *
|
||||
method___reduce___impl(PyMethodObject *self);
|
||||
|
||||
static PyObject *
|
||||
method___reduce__(PyMethodObject *self, PyObject *Py_UNUSED(ignored))
|
||||
{
|
||||
return method___reduce___impl(self);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(method_new__doc__,
|
||||
"method(function, instance, /)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
"Create a bound instance method object.");
|
||||
|
||||
static PyObject *
|
||||
method_new_impl(PyTypeObject *type, PyObject *function, PyObject *instance);
|
||||
|
||||
static PyObject *
|
||||
method_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
PyObject *function;
|
||||
PyObject *instance;
|
||||
|
||||
if ((type == &PyMethod_Type ||
|
||||
type->tp_init == PyMethod_Type.tp_init) &&
|
||||
!_PyArg_NoKeywords("method", kwargs)) {
|
||||
goto exit;
|
||||
}
|
||||
if (!_PyArg_CheckPositional("method", PyTuple_GET_SIZE(args), 2, 2)) {
|
||||
goto exit;
|
||||
}
|
||||
function = PyTuple_GET_ITEM(args, 0);
|
||||
instance = PyTuple_GET_ITEM(args, 1);
|
||||
return_value = method_new_impl(type, function, instance);
|
||||
|
||||
exit:
|
||||
return return_value;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(instancemethod_new__doc__,
|
||||
"instancemethod(function, /)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
"Bind a function to a class.");
|
||||
|
||||
static PyObject *
|
||||
instancemethod_new_impl(PyTypeObject *type, PyObject *function);
|
||||
|
||||
static PyObject *
|
||||
instancemethod_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
PyObject *function;
|
||||
|
||||
if ((type == &PyInstanceMethod_Type ||
|
||||
type->tp_init == PyInstanceMethod_Type.tp_init) &&
|
||||
!_PyArg_NoKeywords("instancemethod", kwargs)) {
|
||||
goto exit;
|
||||
}
|
||||
if (!_PyArg_CheckPositional("instancemethod", PyTuple_GET_SIZE(args), 1, 1)) {
|
||||
goto exit;
|
||||
}
|
||||
function = PyTuple_GET_ITEM(args, 0);
|
||||
return_value = instancemethod_new_impl(type, function);
|
||||
|
||||
exit:
|
||||
return return_value;
|
||||
}
|
||||
/*[clinic end generated code: output=a230fe125f664416 input=a9049054013a1b77]*/
|
Loading…
Reference in New Issue