Coverage Report

Created: 2026-03-23 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Objects/classobject.c
Line
Count
Source
1
/* Class object implementation (dead now except for methods) */
2
3
#include "Python.h"
4
#include "pycore_call.h"          // _PyObject_VectorcallTstate()
5
#include "pycore_ceval.h"         // _PyEval_GetBuiltin()
6
#include "pycore_freelist.h"
7
#include "pycore_object.h"
8
#include "pycore_pyerrors.h"
9
#include "pycore_pystate.h"       // _PyThreadState_GET()
10
#include "pycore_symtable.h"      // _Py_Mangle()
11
#include "pycore_weakref.h"       // FT_CLEAR_WEAKREFS()
12
13
14
#include "clinic/classobject.c.h"
15
16
43.2M
#define _PyMethodObject_CAST(op) _Py_CAST(PyMethodObject*, (op))
17
112
#define TP_DESCR_GET(t) ((t)->tp_descr_get)
18
19
/*[clinic input]
20
class method "PyMethodObject *" "&PyMethod_Type"
21
[clinic start generated code]*/
22
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b16e47edf6107c23]*/
23
24
25
PyObject *
26
PyMethod_Function(PyObject *im)
27
0
{
28
0
    if (!PyMethod_Check(im)) {
29
0
        PyErr_BadInternalCall();
30
0
        return NULL;
31
0
    }
32
0
    return ((PyMethodObject *)im)->im_func;
33
0
}
34
35
PyObject *
36
PyMethod_Self(PyObject *im)
37
0
{
38
0
    if (!PyMethod_Check(im)) {
39
0
        PyErr_BadInternalCall();
40
0
        return NULL;
41
0
    }
42
0
    return ((PyMethodObject *)im)->im_self;
43
0
}
44
45
46
static PyObject *
47
method_vectorcall(PyObject *method, PyObject *const *args,
48
                  size_t nargsf, PyObject *kwnames)
49
33.5M
{
50
33.5M
    assert(Py_IS_TYPE(method, &PyMethod_Type));
51
52
33.5M
    PyThreadState *tstate = _PyThreadState_GET();
53
33.5M
    PyObject *self = PyMethod_GET_SELF(method);
54
33.5M
    PyObject *func = PyMethod_GET_FUNCTION(method);
55
33.5M
    return _PyObject_VectorcallPrepend(tstate, func, self, args, nargsf, kwnames);
56
33.5M
}
57
58
59
/* Method objects are used for bound instance methods returned by
60
   instancename.methodname. ClassName.methodname returns an ordinary
61
   function.
62
*/
63
64
PyObject *
65
PyMethod_New(PyObject *func, PyObject *self)
66
41.5M
{
67
41.5M
    if (self == NULL) {
68
0
        PyErr_BadInternalCall();
69
0
        return NULL;
70
0
    }
71
41.5M
    PyMethodObject *im = _Py_FREELIST_POP(PyMethodObject, pymethodobjects);
72
41.5M
    if (im == NULL) {
73
972k
        im = PyObject_GC_New(PyMethodObject, &PyMethod_Type);
74
972k
        if (im == NULL) {
75
0
            return NULL;
76
0
        }
77
972k
    }
78
41.5M
    im->im_weakreflist = NULL;
79
41.5M
    im->im_func = Py_NewRef(func);
80
41.5M
    im->im_self = Py_NewRef(self);
81
41.5M
    im->vectorcall = method_vectorcall;
82
41.5M
    _PyObject_GC_TRACK(im);
83
41.5M
    return (PyObject *)im;
84
41.5M
}
85
86
/*[clinic input]
87
method.__reduce__
88
[clinic start generated code]*/
89
90
static PyObject *
91
method___reduce___impl(PyMethodObject *self)
92
/*[clinic end generated code: output=6c04506d0fa6fdcb input=143a0bf5e96de6e8]*/
93
0
{
94
0
    PyObject *funcself = PyMethod_GET_SELF(self);
95
0
    PyObject *func = PyMethod_GET_FUNCTION(self);
96
0
    PyObject *funcname = PyObject_GetAttr(func, &_Py_ID(__name__));
97
0
    if (funcname == NULL) {
98
0
        return NULL;
99
0
    }
100
0
    if (_Py_IsPrivateName(funcname)) {
101
0
        PyObject *classname = PyType_Check(funcself)
102
0
            ? PyType_GetName((PyTypeObject *)funcself)
103
0
            : PyType_GetName(Py_TYPE(funcself));
104
0
        if (classname == NULL) {
105
0
            Py_DECREF(funcname);
106
0
            return NULL;
107
0
        }
108
0
        Py_SETREF(funcname, _Py_Mangle(classname, funcname));
109
0
        Py_DECREF(classname);
110
0
        if (funcname == NULL) {
111
0
            return NULL;
112
0
        }
113
0
    }
114
0
    return Py_BuildValue(
115
0
            "N(ON)", _PyEval_GetBuiltin(&_Py_ID(getattr)), funcself, funcname);
116
0
}
117
118
static PyMethodDef method_methods[] = {
119
    METHOD___REDUCE___METHODDEF
120
    {NULL, NULL}
121
};
122
123
/* Descriptors for PyMethod attributes */
124
125
/* im_func and im_self are stored in the PyMethod object */
126
127
#define MO_OFF(x) offsetof(PyMethodObject, x)
128
129
static PyMemberDef method_memberlist[] = {
130
    {"__func__", _Py_T_OBJECT, MO_OFF(im_func), Py_READONLY,
131
     "the function (or other callable) implementing a method"},
132
    {"__self__", _Py_T_OBJECT, MO_OFF(im_self), Py_READONLY,
133
     "the instance to which a method is bound"},
134
    {NULL}      /* Sentinel */
135
};
136
137
/* Christian Tismer argued convincingly that method attributes should
138
   (nearly) always override function attributes.
139
   The one exception is __doc__; there's a default __doc__ which
140
   should only be used for the class, not for instances */
141
142
static PyObject *
143
method_get_doc(PyObject *self, void *context)
144
20
{
145
20
    PyMethodObject *im = _PyMethodObject_CAST(self);
146
20
    return PyObject_GetAttr(im->im_func, &_Py_ID(__doc__));
147
20
}
148
149
static PyGetSetDef method_getset[] = {
150
    {"__doc__", method_get_doc, NULL, NULL},
151
    {0}
152
};
153
154
static PyObject *
155
method_getattro(PyObject *obj, PyObject *name)
156
240
{
157
240
    PyMethodObject *im = (PyMethodObject *)obj;
158
240
    PyTypeObject *tp = Py_TYPE(obj);
159
240
    PyObject *descr = NULL;
160
161
240
    {
162
240
        if (!_PyType_IsReady(tp)) {
163
0
            if (PyType_Ready(tp) < 0)
164
0
                return NULL;
165
0
        }
166
240
        descr = _PyType_LookupRef(tp, name);
167
240
    }
168
169
240
    if (descr != NULL) {
170
112
        descrgetfunc f = TP_DESCR_GET(Py_TYPE(descr));
171
112
        if (f != NULL) {
172
112
            PyObject *res = f(descr, obj, (PyObject *)Py_TYPE(obj));
173
112
            Py_DECREF(descr);
174
112
            return res;
175
112
        }
176
0
        else {
177
0
            return descr;
178
0
        }
179
112
    }
180
181
128
    return PyObject_GetAttr(im->im_func, name);
182
240
}
183
184
/*[clinic input]
185
@classmethod
186
method.__new__ as method_new
187
    function: object
188
    instance: object
189
    /
190
191
Create a bound instance method object.
192
[clinic start generated code]*/
193
194
static PyObject *
195
method_new_impl(PyTypeObject *type, PyObject *function, PyObject *instance)
196
/*[clinic end generated code: output=d33ef4ebf702e1f7 input=4e32facc3c3108ae]*/
197
20
{
198
20
    if (!PyCallable_Check(function)) {
199
0
        PyErr_SetString(PyExc_TypeError,
200
0
                        "first argument must be callable");
201
0
        return NULL;
202
0
    }
203
20
    if (instance == NULL || instance == Py_None) {
204
0
        PyErr_SetString(PyExc_TypeError,
205
0
            "instance must not be None");
206
0
        return NULL;
207
0
    }
208
209
20
    return PyMethod_New(function, instance);
210
20
}
211
212
static void
213
method_dealloc(PyObject *self)
214
41.4M
{
215
41.4M
    PyMethodObject *im = _PyMethodObject_CAST(self);
216
41.4M
    _PyObject_GC_UNTRACK(im);
217
41.4M
    FT_CLEAR_WEAKREFS(self, im->im_weakreflist);
218
41.4M
    Py_DECREF(im->im_func);
219
41.4M
    Py_XDECREF(im->im_self);
220
41.4M
    assert(Py_IS_TYPE(self, &PyMethod_Type));
221
41.4M
    _Py_FREELIST_FREE(pymethodobjects, (PyObject *)im, PyObject_GC_Del);
222
41.4M
}
223
224
static PyObject *
225
method_richcompare(PyObject *self, PyObject *other, int op)
226
0
{
227
0
    PyMethodObject *a, *b;
228
0
    PyObject *res;
229
0
    int eq;
230
231
0
    if ((op != Py_EQ && op != Py_NE) ||
232
0
        !PyMethod_Check(self) ||
233
0
        !PyMethod_Check(other))
234
0
    {
235
0
        Py_RETURN_NOTIMPLEMENTED;
236
0
    }
237
0
    a = (PyMethodObject *)self;
238
0
    b = (PyMethodObject *)other;
239
0
    eq = PyObject_RichCompareBool(a->im_func, b->im_func, Py_EQ);
240
0
    if (eq == 1) {
241
0
        eq = (a->im_self == b->im_self);
242
0
    }
243
0
    else if (eq < 0)
244
0
        return NULL;
245
0
    if (op == Py_EQ)
246
0
        res = eq ? Py_True : Py_False;
247
0
    else
248
0
        res = eq ? Py_False : Py_True;
249
0
    return Py_NewRef(res);
250
0
}
251
252
static PyObject *
253
method_repr(PyObject *op)
254
0
{
255
0
    PyMethodObject *a = _PyMethodObject_CAST(op);
256
0
    PyObject *self = a->im_self;
257
0
    PyObject *func = a->im_func;
258
0
    PyObject *funcname, *result;
259
0
    const char *defname = "?";
260
261
0
    if (PyObject_GetOptionalAttr(func, &_Py_ID(__qualname__), &funcname) < 0 ||
262
0
        (funcname == NULL &&
263
0
         PyObject_GetOptionalAttr(func, &_Py_ID(__name__), &funcname) < 0))
264
0
    {
265
0
        return NULL;
266
0
    }
267
268
0
    if (funcname != NULL && !PyUnicode_Check(funcname)) {
269
0
        Py_SETREF(funcname, NULL);
270
0
    }
271
272
    /* XXX Shouldn't use repr()/%R here! */
273
0
    result = PyUnicode_FromFormat("<bound method %V of %R>",
274
0
                                  funcname, defname, self);
275
276
0
    Py_XDECREF(funcname);
277
0
    return result;
278
0
}
279
280
static Py_hash_t
281
method_hash(PyObject *self)
282
0
{
283
0
    PyMethodObject *a = _PyMethodObject_CAST(self);
284
0
    Py_hash_t x = PyObject_GenericHash(a->im_self);
285
0
    Py_hash_t y = PyObject_Hash(a->im_func);
286
0
    if (y == -1) {
287
0
        return -1;
288
0
    }
289
290
0
    x = x ^ y;
291
0
    if (x == -1) {
292
0
        x = -2;
293
0
    }
294
0
    return x;
295
0
}
296
297
static int
298
method_traverse(PyObject *self, visitproc visit, void *arg)
299
1.79M
{
300
1.79M
    PyMethodObject *im = _PyMethodObject_CAST(self);
301
1.79M
    Py_VISIT(im->im_func);
302
1.79M
    Py_VISIT(im->im_self);
303
1.79M
    return 0;
304
1.79M
}
305
306
static PyObject *
307
method_descr_get(PyObject *meth, PyObject *obj, PyObject *cls)
308
29
{
309
29
    Py_INCREF(meth);
310
29
    return meth;
311
29
}
312
313
PyTypeObject PyMethod_Type = {
314
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
315
    .tp_name = "method",
316
    .tp_basicsize = sizeof(PyMethodObject),
317
    .tp_dealloc = method_dealloc,
318
    .tp_vectorcall_offset = offsetof(PyMethodObject, vectorcall),
319
    .tp_repr = method_repr,
320
    .tp_hash = method_hash,
321
    .tp_call = PyVectorcall_Call,
322
    .tp_getattro = method_getattro,
323
    .tp_setattro = PyObject_GenericSetAttr,
324
    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
325
                Py_TPFLAGS_HAVE_VECTORCALL,
326
    .tp_doc = method_new__doc__,
327
    .tp_traverse = method_traverse,
328
    .tp_richcompare = method_richcompare,
329
    .tp_weaklistoffset = offsetof(PyMethodObject, im_weakreflist),
330
    .tp_methods = method_methods,
331
    .tp_members = method_memberlist,
332
    .tp_getset = method_getset,
333
    .tp_descr_get = method_descr_get,
334
    .tp_new = method_new,
335
};
336
337
/* ------------------------------------------------------------------------
338
 * instance method
339
 */
340
341
/*[clinic input]
342
class instancemethod "PyInstanceMethodObject *" "&PyInstanceMethod_Type"
343
[clinic start generated code]*/
344
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=28c9762a9016f4d2]*/
345
346
PyObject *
347
0
PyInstanceMethod_New(PyObject *func) {
348
0
    PyInstanceMethodObject *method;
349
0
    method = PyObject_GC_New(PyInstanceMethodObject,
350
0
                             &PyInstanceMethod_Type);
351
0
    if (method == NULL) return NULL;
352
0
    method->func = Py_NewRef(func);
353
0
    _PyObject_GC_TRACK(method);
354
0
    return (PyObject *)method;
355
0
}
356
357
PyObject *
358
PyInstanceMethod_Function(PyObject *im)
359
0
{
360
0
    if (!PyInstanceMethod_Check(im)) {
361
0
        PyErr_BadInternalCall();
362
0
        return NULL;
363
0
    }
364
0
    return PyInstanceMethod_GET_FUNCTION(im);
365
0
}
366
367
#define IMO_OFF(x) offsetof(PyInstanceMethodObject, x)
368
369
static PyMemberDef instancemethod_memberlist[] = {
370
    {"__func__", _Py_T_OBJECT, IMO_OFF(func), Py_READONLY,
371
     "the function (or other callable) implementing a method"},
372
    {NULL}      /* Sentinel */
373
};
374
375
static PyObject *
376
instancemethod_get_doc(PyObject *self, void *context)
377
0
{
378
0
    return PyObject_GetAttr(PyInstanceMethod_GET_FUNCTION(self),
379
0
                            &_Py_ID(__doc__));
380
0
}
381
382
static PyGetSetDef instancemethod_getset[] = {
383
    {"__doc__", instancemethod_get_doc, NULL, NULL},
384
    {0}
385
};
386
387
static PyObject *
388
instancemethod_getattro(PyObject *self, PyObject *name)
389
0
{
390
0
    PyTypeObject *tp = Py_TYPE(self);
391
0
    PyObject *descr = NULL;
392
393
0
    if (!_PyType_IsReady(tp)) {
394
0
        if (PyType_Ready(tp) < 0)
395
0
            return NULL;
396
0
    }
397
0
    descr = _PyType_LookupRef(tp, name);
398
399
0
    if (descr != NULL) {
400
0
        descrgetfunc f = TP_DESCR_GET(Py_TYPE(descr));
401
0
        if (f != NULL) {
402
0
            PyObject *res = f(descr, self, (PyObject *)Py_TYPE(self));
403
0
            Py_DECREF(descr);
404
0
            return res;
405
0
        }
406
0
        else {
407
0
            return descr;
408
0
        }
409
0
    }
410
411
0
    return PyObject_GetAttr(PyInstanceMethod_GET_FUNCTION(self), name);
412
0
}
413
414
static void
415
0
instancemethod_dealloc(PyObject *self) {
416
0
    _PyObject_GC_UNTRACK(self);
417
0
    Py_DECREF(PyInstanceMethod_GET_FUNCTION(self));
418
0
    PyObject_GC_Del(self);
419
0
}
420
421
static int
422
0
instancemethod_traverse(PyObject *self, visitproc visit, void *arg) {
423
0
    Py_VISIT(PyInstanceMethod_GET_FUNCTION(self));
424
0
    return 0;
425
0
}
426
427
static PyObject *
428
instancemethod_call(PyObject *self, PyObject *arg, PyObject *kw)
429
0
{
430
0
    return PyObject_Call(PyInstanceMethod_GET_FUNCTION(self), arg, kw);
431
0
}
432
433
static PyObject *
434
0
instancemethod_descr_get(PyObject *descr, PyObject *obj, PyObject *type) {
435
0
    PyObject *func = PyInstanceMethod_GET_FUNCTION(descr);
436
0
    if (obj == NULL) {
437
0
        return Py_NewRef(func);
438
0
    }
439
0
    else
440
0
        return PyMethod_New(func, obj);
441
0
}
442
443
static PyObject *
444
instancemethod_richcompare(PyObject *self, PyObject *other, int op)
445
0
{
446
0
    PyInstanceMethodObject *a, *b;
447
0
    PyObject *res;
448
0
    int eq;
449
450
0
    if ((op != Py_EQ && op != Py_NE) ||
451
0
        !PyInstanceMethod_Check(self) ||
452
0
        !PyInstanceMethod_Check(other))
453
0
    {
454
0
        Py_RETURN_NOTIMPLEMENTED;
455
0
    }
456
0
    a = (PyInstanceMethodObject *)self;
457
0
    b = (PyInstanceMethodObject *)other;
458
0
    eq = PyObject_RichCompareBool(a->func, b->func, Py_EQ);
459
0
    if (eq < 0)
460
0
        return NULL;
461
0
    if (op == Py_EQ)
462
0
        res = eq ? Py_True : Py_False;
463
0
    else
464
0
        res = eq ? Py_False : Py_True;
465
0
    return Py_NewRef(res);
466
0
}
467
468
static PyObject *
469
instancemethod_repr(PyObject *self)
470
0
{
471
0
    PyObject *func = PyInstanceMethod_Function(self);
472
0
    PyObject *funcname, *result;
473
0
    const char *defname = "?";
474
475
0
    if (func == NULL) {
476
0
        PyErr_BadInternalCall();
477
0
        return NULL;
478
0
    }
479
480
0
    if (PyObject_GetOptionalAttr(func, &_Py_ID(__name__), &funcname) < 0) {
481
0
        return NULL;
482
0
    }
483
0
    if (funcname != NULL && !PyUnicode_Check(funcname)) {
484
0
        Py_SETREF(funcname, NULL);
485
0
    }
486
487
0
    result = PyUnicode_FromFormat("<instancemethod %V at %p>",
488
0
                                  funcname, defname, self);
489
490
0
    Py_XDECREF(funcname);
491
0
    return result;
492
0
}
493
494
/*[clinic input]
495
@classmethod
496
instancemethod.__new__ as instancemethod_new
497
    function: object
498
    /
499
500
Bind a function to a class.
501
[clinic start generated code]*/
502
503
static PyObject *
504
instancemethod_new_impl(PyTypeObject *type, PyObject *function)
505
/*[clinic end generated code: output=5e0397b2bdb750be input=cfc54e8b973664a8]*/
506
0
{
507
0
    if (!PyCallable_Check(function)) {
508
0
        PyErr_SetString(PyExc_TypeError,
509
0
                        "first argument must be callable");
510
0
        return NULL;
511
0
    }
512
513
0
    return PyInstanceMethod_New(function);
514
0
}
515
516
PyTypeObject PyInstanceMethod_Type = {
517
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
518
    .tp_name = "instancemethod",
519
    .tp_basicsize = sizeof(PyInstanceMethodObject),
520
    .tp_dealloc = instancemethod_dealloc,
521
    .tp_repr = instancemethod_repr,
522
    .tp_call = instancemethod_call,
523
    .tp_getattro = instancemethod_getattro,
524
    .tp_setattro = PyObject_GenericSetAttr,
525
    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
526
    .tp_doc = instancemethod_new__doc__,
527
    .tp_traverse = instancemethod_traverse,
528
    .tp_richcompare = instancemethod_richcompare,
529
    .tp_members = instancemethod_memberlist,
530
    .tp_getset = instancemethod_getset,
531
    .tp_descr_get = instancemethod_descr_get,
532
    .tp_new = instancemethod_new,
533
};