Coverage Report

Created: 2022-07-08 09:39

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