Skip to content

Commit 7fbc7f6

Browse files
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>
1 parent 014eb7f commit 7fbc7f6

File tree

4 files changed

+173
-115
lines changed

4 files changed

+173
-115
lines changed

Lib/idlelib/idle_test/test_calltip.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,9 @@ class SB: __call__ = None
7777
tiptest(List.append, '(self, object, /)' + append_doc)
7878
tiptest([].append, '(object, /)' + append_doc)
7979

80-
tiptest(types.MethodType, "method(function, instance)")
80+
tiptest(types.MethodType,
81+
'(function, instance, /)\n'
82+
'Create a bound instance method object.')
8183
tiptest(SB(), default_tip)
8284

8385
p = re.compile('')
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Use Argument Clinic for the :class:`types.MethodType` constructor. Patch by
2+
Oleg Iarygin.

Objects/classobject.c

Lines changed: 85 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,15 @@
77
#include "pycore_pystate.h" // _PyThreadState_GET()
88
#include "structmember.h" // PyMemberDef
99

10+
#include "clinic/classobject.c.h"
11+
1012
#define TP_DESCR_GET(t) ((t)->tp_descr_get)
1113

14+
/*[clinic input]
15+
class method "PyMethodObject *" "&PyMethod_Type"
16+
[clinic start generated code]*/
17+
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b16e47edf6107c23]*/
18+
1219

1320
PyObject *
1421
PyMethod_Function(PyObject *im)
@@ -115,23 +122,26 @@ PyMethod_New(PyObject *func, PyObject *self)
115122
return (PyObject *)im;
116123
}
117124

125+
/*[clinic input]
126+
method.__reduce__
127+
[clinic start generated code]*/
128+
118129
static PyObject *
119-
method_reduce(PyMethodObject *im, PyObject *Py_UNUSED(ignored))
130+
method___reduce___impl(PyMethodObject *self)
131+
/*[clinic end generated code: output=6c04506d0fa6fdcb input=143a0bf5e96de6e8]*/
120132
{
121-
PyObject *self = PyMethod_GET_SELF(im);
122-
PyObject *func = PyMethod_GET_FUNCTION(im);
123-
PyObject *funcname;
124-
125-
funcname = PyObject_GetAttr(func, &_Py_ID(__name__));
133+
PyObject *funcself = PyMethod_GET_SELF(self);
134+
PyObject *func = PyMethod_GET_FUNCTION(self);
135+
PyObject *funcname = PyObject_GetAttr(func, &_Py_ID(__name__));
126136
if (funcname == NULL) {
127137
return NULL;
128138
}
129139
return Py_BuildValue(
130-
"N(ON)", _PyEval_GetBuiltin(&_Py_ID(getattr)), self, funcname);
140+
"N(ON)", _PyEval_GetBuiltin(&_Py_ID(getattr)), funcself, funcname);
131141
}
132142

133143
static PyMethodDef method_methods[] = {
134-
{"__reduce__", (PyCFunction)method_reduce, METH_NOARGS, NULL},
144+
METHOD___REDUCE___METHODDEF
135145
{NULL, NULL}
136146
};
137147

@@ -193,34 +203,32 @@ method_getattro(PyObject *obj, PyObject *name)
193203
return PyObject_GetAttr(im->im_func, name);
194204
}
195205

196-
PyDoc_STRVAR(method_doc,
197-
"method(function, instance)\n\
198-
\n\
199-
Create a bound instance method object.");
206+
/*[clinic input]
207+
@classmethod
208+
method.__new__ as method_new
209+
function: object
210+
instance: object
211+
/
212+
213+
Create a bound instance method object.
214+
[clinic start generated code]*/
200215

201216
static PyObject *
202-
method_new(PyTypeObject* type, PyObject* args, PyObject *kw)
217+
method_new_impl(PyTypeObject *type, PyObject *function, PyObject *instance)
218+
/*[clinic end generated code: output=d33ef4ebf702e1f7 input=4e32facc3c3108ae]*/
203219
{
204-
PyObject *func;
205-
PyObject *self;
206-
207-
if (!_PyArg_NoKeywords("method", kw))
208-
return NULL;
209-
if (!PyArg_UnpackTuple(args, "method", 2, 2,
210-
&func, &self))
211-
return NULL;
212-
if (!PyCallable_Check(func)) {
220+
if (!PyCallable_Check(function)) {
213221
PyErr_SetString(PyExc_TypeError,
214222
"first argument must be callable");
215223
return NULL;
216224
}
217-
if (self == NULL || self == Py_None) {
225+
if (instance == NULL || instance == Py_None) {
218226
PyErr_SetString(PyExc_TypeError,
219-
"self must not be None");
227+
"instance must not be None");
220228
return NULL;
221229
}
222230

223-
return PyMethod_New(func, self);
231+
return PyMethod_New(function, instance);
224232
}
225233

226234
static void
@@ -322,50 +330,37 @@ method_descr_get(PyObject *meth, PyObject *obj, PyObject *cls)
322330

323331
PyTypeObject PyMethod_Type = {
324332
PyVarObject_HEAD_INIT(&PyType_Type, 0)
325-
"method",
326-
sizeof(PyMethodObject),
327-
0,
328-
(destructor)method_dealloc, /* tp_dealloc */
329-
offsetof(PyMethodObject, vectorcall), /* tp_vectorcall_offset */
330-
0, /* tp_getattr */
331-
0, /* tp_setattr */
332-
0, /* tp_as_async */
333-
(reprfunc)method_repr, /* tp_repr */
334-
0, /* tp_as_number */
335-
0, /* tp_as_sequence */
336-
0, /* tp_as_mapping */
337-
(hashfunc)method_hash, /* tp_hash */
338-
PyVectorcall_Call, /* tp_call */
339-
0, /* tp_str */
340-
method_getattro, /* tp_getattro */
341-
PyObject_GenericSetAttr, /* tp_setattro */
342-
0, /* tp_as_buffer */
343-
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
344-
Py_TPFLAGS_HAVE_VECTORCALL, /* tp_flags */
345-
method_doc, /* tp_doc */
346-
(traverseproc)method_traverse, /* tp_traverse */
347-
0, /* tp_clear */
348-
method_richcompare, /* tp_richcompare */
349-
offsetof(PyMethodObject, im_weakreflist), /* tp_weaklistoffset */
350-
0, /* tp_iter */
351-
0, /* tp_iternext */
352-
method_methods, /* tp_methods */
353-
method_memberlist, /* tp_members */
354-
method_getset, /* tp_getset */
355-
0, /* tp_base */
356-
0, /* tp_dict */
357-
method_descr_get, /* tp_descr_get */
358-
0, /* tp_descr_set */
359-
0, /* tp_dictoffset */
360-
0, /* tp_init */
361-
0, /* tp_alloc */
362-
method_new, /* tp_new */
333+
.tp_name = "method",
334+
.tp_basicsize = sizeof(PyMethodObject),
335+
.tp_dealloc = (destructor)method_dealloc,
336+
.tp_vectorcall_offset = offsetof(PyMethodObject, vectorcall),
337+
.tp_repr = (reprfunc)method_repr,
338+
.tp_hash = (hashfunc)method_hash,
339+
.tp_call = PyVectorcall_Call,
340+
.tp_getattro = method_getattro,
341+
.tp_setattro = PyObject_GenericSetAttr,
342+
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
343+
Py_TPFLAGS_HAVE_VECTORCALL,
344+
.tp_doc = method_new__doc__,
345+
.tp_traverse = (traverseproc)method_traverse,
346+
.tp_richcompare = method_richcompare,
347+
.tp_weaklistoffset = offsetof(PyMethodObject, im_weakreflist),
348+
.tp_methods = method_methods,
349+
.tp_members = method_memberlist,
350+
.tp_getset = method_getset,
351+
.tp_descr_get = method_descr_get,
352+
.tp_new = method_new,
363353
};
364354

365355
/* ------------------------------------------------------------------------
366356
* instance method
367357
*/
368358

359+
/*[clinic input]
360+
class instancemethod "PyInstanceMethodObject *" "&PyInstanceMethod_Type"
361+
[clinic start generated code]*/
362+
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=28c9762a9016f4d2]*/
363+
369364
PyObject *
370365
PyInstanceMethod_New(PyObject *func) {
371366
PyInstanceMethodObject *method;
@@ -516,67 +511,43 @@ instancemethod_repr(PyObject *self)
516511
return result;
517512
}
518513

519-
PyDoc_STRVAR(instancemethod_doc,
520-
"instancemethod(function)\n\
521-
\n\
522-
Bind a function to a class.");
514+
/*[clinic input]
515+
@classmethod
516+
instancemethod.__new__ as instancemethod_new
517+
function: object
518+
/
519+
520+
Bind a function to a class.
521+
[clinic start generated code]*/
523522

524523
static PyObject *
525-
instancemethod_new(PyTypeObject* type, PyObject* args, PyObject *kw)
524+
instancemethod_new_impl(PyTypeObject *type, PyObject *function)
525+
/*[clinic end generated code: output=5e0397b2bdb750be input=cfc54e8b973664a8]*/
526526
{
527-
PyObject *func;
528-
529-
if (!_PyArg_NoKeywords("instancemethod", kw))
530-
return NULL;
531-
if (!PyArg_UnpackTuple(args, "instancemethod", 1, 1, &func))
532-
return NULL;
533-
if (!PyCallable_Check(func)) {
527+
if (!PyCallable_Check(function)) {
534528
PyErr_SetString(PyExc_TypeError,
535529
"first argument must be callable");
536530
return NULL;
537531
}
538532

539-
return PyInstanceMethod_New(func);
533+
return PyInstanceMethod_New(function);
540534
}
541535

542536
PyTypeObject PyInstanceMethod_Type = {
543537
PyVarObject_HEAD_INIT(&PyType_Type, 0)
544-
"instancemethod", /* tp_name */
545-
sizeof(PyInstanceMethodObject), /* tp_basicsize */
546-
0, /* tp_itemsize */
547-
instancemethod_dealloc, /* tp_dealloc */
548-
0, /* tp_vectorcall_offset */
549-
0, /* tp_getattr */
550-
0, /* tp_setattr */
551-
0, /* tp_as_async */
552-
(reprfunc)instancemethod_repr, /* tp_repr */
553-
0, /* tp_as_number */
554-
0, /* tp_as_sequence */
555-
0, /* tp_as_mapping */
556-
0, /* tp_hash */
557-
instancemethod_call, /* tp_call */
558-
0, /* tp_str */
559-
instancemethod_getattro, /* tp_getattro */
560-
PyObject_GenericSetAttr, /* tp_setattro */
561-
0, /* tp_as_buffer */
562-
Py_TPFLAGS_DEFAULT
563-
| Py_TPFLAGS_HAVE_GC, /* tp_flags */
564-
instancemethod_doc, /* tp_doc */
565-
instancemethod_traverse, /* tp_traverse */
566-
0, /* tp_clear */
567-
instancemethod_richcompare, /* tp_richcompare */
568-
0, /* tp_weaklistoffset */
569-
0, /* tp_iter */
570-
0, /* tp_iternext */
571-
0, /* tp_methods */
572-
instancemethod_memberlist, /* tp_members */
573-
instancemethod_getset, /* tp_getset */
574-
0, /* tp_base */
575-
0, /* tp_dict */
576-
instancemethod_descr_get, /* tp_descr_get */
577-
0, /* tp_descr_set */
578-
0, /* tp_dictoffset */
579-
0, /* tp_init */
580-
0, /* tp_alloc */
581-
instancemethod_new, /* tp_new */
538+
.tp_name = "instancemethod",
539+
.tp_basicsize = sizeof(PyInstanceMethodObject),
540+
.tp_dealloc = instancemethod_dealloc,
541+
.tp_repr = (reprfunc)instancemethod_repr,
542+
.tp_call = instancemethod_call,
543+
.tp_getattro = instancemethod_getattro,
544+
.tp_setattro = PyObject_GenericSetAttr,
545+
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
546+
.tp_doc = instancemethod_new__doc__,
547+
.tp_traverse = instancemethod_traverse,
548+
.tp_richcompare = instancemethod_richcompare,
549+
.tp_members = instancemethod_memberlist,
550+
.tp_getset = instancemethod_getset,
551+
.tp_descr_get = instancemethod_descr_get,
552+
.tp_new = instancemethod_new,
582553
};

Objects/clinic/classobject.c.h

Lines changed: 83 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)