]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-91098: Use Argument Clinic for Object/classobject.c to fix docstrings (#31711)
authorOleg Iarygin <oleg@arhadthedev.net>
Tue, 19 Apr 2022 02:56:53 +0000 (05:56 +0300)
committerGitHub <noreply@github.com>
Tue, 19 Apr 2022 02:56:53 +0000 (19:56 -0700)
Closes GH-91098.

Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
Lib/idlelib/idle_test/test_calltip.py
Misc/NEWS.d/next/Core and Builtins/2022-03-07-11-51-51.bpo-46942.57obVi.rst [new file with mode: 0644]
Objects/classobject.c
Objects/clinic/classobject.c.h [new file with mode: 0644]

index e8d2bd17cb681170e7dbbe57d571ff4007b6db87..1ccb63b9dbd65f99c37787be9ced82811c89d3e0 100644 (file)
@@ -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('')
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-03-07-11-51-51.bpo-46942.57obVi.rst b/Misc/NEWS.d/next/Core and Builtins/2022-03-07-11-51-51.bpo-46942.57obVi.rst
new file mode 100644 (file)
index 0000000..930a901
--- /dev/null
@@ -0,0 +1,2 @@
+Use Argument Clinic for the :class:`types.MethodType` constructor.  Patch by
+Oleg Iarygin.
index c75ba572b9624510d1220d42f2f54c0ebff655cf..cf731358e41c447ffc43de88611d71438a7e90f6 100644 (file)
@@ -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;
 }
 
+/*[clinic input]
+method.__reduce__
+[clinic start generated code]*/
+
 static PyObject *
-method_reduce(PyMethodObject *im, PyObject *Py_UNUSED(ignored))
+method___reduce___impl(PyMethodObject *self)
+/*[clinic end generated code: output=6c04506d0fa6fdcb input=143a0bf5e96de6e8]*/
 {
-    PyObject *self = PyMethod_GET_SELF(im);
-    PyObject *func = PyMethod_GET_FUNCTION(im);
-    PyObject *funcname;
-
-    funcname = PyObject_GetAttr(func, &_Py_ID(__name__));
+    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,
 };
diff --git a/Objects/clinic/classobject.c.h b/Objects/clinic/classobject.c.h
new file mode 100644 (file)
index 0000000..a4f1900
--- /dev/null
@@ -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]*/