xref: /third_party/python/Objects/classobject.c (revision 7db96d56)
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]
15class method "PyMethodObject *" "&PyMethod_Type"
16[clinic start generated code]*/
17/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b16e47edf6107c23]*/
18
19
20PyObject *
21PyMethod_Function(PyObject *im)
22{
23    if (!PyMethod_Check(im)) {
24        PyErr_BadInternalCall();
25        return NULL;
26    }
27    return ((PyMethodObject *)im)->im_func;
28}
29
30PyObject *
31PyMethod_Self(PyObject *im)
32{
33    if (!PyMethod_Check(im)) {
34        PyErr_BadInternalCall();
35        return NULL;
36    }
37    return ((PyMethodObject *)im)->im_self;
38}
39
40
41static PyObject *
42method_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) {
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) ? 0 : PyTuple_GET_SIZE(kwnames);
65        Py_ssize_t totalargs = nargs + nkwargs;
66        if (totalargs == 0) {
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) {
73            newargs = newargs_stack;
74        }
75        else {
76            newargs = PyMem_Malloc((totalargs+1) * sizeof(PyObject *));
77            if (newargs == NULL) {
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) {
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
104PyObject *
105PyMethod_New(PyObject *func, PyObject *self)
106{
107    if (self == NULL) {
108        PyErr_BadInternalCall();
109        return NULL;
110    }
111    PyMethodObject *im = PyObject_GC_New(PyMethodObject, &PyMethod_Type);
112    if (im == NULL) {
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]
126method.__reduce__
127[clinic start generated code]*/
128
129static PyObject *
130method___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) {
137        return NULL;
138    }
139    return Py_BuildValue(
140            "N(ON)", _PyEval_GetBuiltin(&_Py_ID(getattr)), funcself, funcname);
141}
142
143static 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
154static 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
167static PyObject *
168method_get_doc(PyMethodObject *im, void *context)
169{
170    return PyObject_GetAttr(im->im_func, &_Py_ID(__doc__));
171}
172
173static PyGetSetDef method_getset[] = {
174    {"__doc__", (getter)method_get_doc, NULL, NULL},
175    {0}
176};
177
178static PyObject *
179method_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) {
187            if (PyType_Ready(tp) < 0)
188                return NULL;
189        }
190        descr = _PyType_Lookup(tp, name);
191    }
192
193    if (descr != NULL) {
194        descrgetfunc f = TP_DESCR_GET(Py_TYPE(descr));
195        if (f != NULL)
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
208method.__new__ as method_new
209    function: object
210    instance: object
211    /
212
213Create a bound instance method object.
214[clinic start generated code]*/
215
216static PyObject *
217method_new_impl(PyTypeObject *type, PyObject *function, PyObject *instance)
218/*[clinic end generated code: output=d33ef4ebf702e1f7 input=4e32facc3c3108ae]*/
219{
220    if (!PyCallable_Check(function)) {
221        PyErr_SetString(PyExc_TypeError,
222                        "first argument must be callable");
223        return NULL;
224    }
225    if (instance == NULL || instance == Py_None) {
226        PyErr_SetString(PyExc_TypeError,
227            "instance must not be None");
228        return NULL;
229    }
230
231    return PyMethod_New(function, instance);
232}
233
234static void
235method_dealloc(PyMethodObject *im)
236{
237    _PyObject_GC_UNTRACK(im);
238    if (im->im_weakreflist != NULL)
239        PyObject_ClearWeakRefs((PyObject *)im);
240    Py_DECREF(im->im_func);
241    Py_XDECREF(im->im_self);
242    PyObject_GC_Del(im);
243}
244
245static PyObject *
246method_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 != Py_NE) ||
253        !PyMethod_Check(self) ||
254        !PyMethod_Check(other))
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) {
262        eq = (a->im_self == b->im_self);
263    }
264    else if (eq < 0)
265        return NULL;
266    if (op == Py_EQ)
267        res = eq ? Py_True : Py_False;
268    else
269        res = eq ? Py_False : Py_True;
270    Py_INCREF(res);
271    return res;
272}
273
274static PyObject *
275method_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 ||
283        (funcname == NULL &&
284         _PyObject_LookupAttr(func, &_Py_ID(__name__), &funcname) < 0))
285    {
286        return NULL;
287    }
288
289    if (funcname != NULL && !PyUnicode_Check(funcname)) {
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
302static Py_hash_t
303method_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)
309        return -1;
310    x = x ^ y;
311    if (x == -1)
312        x = -2;
313    return x;
314}
315
316static int
317method_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
324PyTypeObject 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]
352class instancemethod "PyInstanceMethodObject *" "&PyInstanceMethod_Type"
353[clinic start generated code]*/
354/*[clinic end generated code: output=da39a3ee5e6b4b0d input=28c9762a9016f4d2]*/
355
356PyObject *
357PyInstanceMethod_New(PyObject *func) {
358    PyInstanceMethodObject *method;
359    method = PyObject_GC_New(PyInstanceMethodObject,
360                             &PyInstanceMethod_Type);
361    if (method == NULL) return NULL;
362    Py_INCREF(func);
363    method->func = func;
364    _PyObject_GC_TRACK(method);
365    return (PyObject *)method;
366}
367
368PyObject *
369PyInstanceMethod_Function(PyObject *im)
370{
371    if (!PyInstanceMethod_Check(im)) {
372        PyErr_BadInternalCall();
373        return NULL;
374    }
375    return PyInstanceMethod_GET_FUNCTION(im);
376}
377
378#define IMO_OFF(x) offsetof(PyInstanceMethodObject, x)
379
380static 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
386static PyObject *
387instancemethod_get_doc(PyObject *self, void *context)
388{
389    return PyObject_GetAttr(PyInstanceMethod_GET_FUNCTION(self),
390                            &_Py_ID(__doc__));
391}
392
393static PyGetSetDef instancemethod_getset[] = {
394    {"__doc__", (getter)instancemethod_get_doc, NULL, NULL},
395    {0}
396};
397
398static PyObject *
399instancemethod_getattro(PyObject *self, PyObject *name)
400{
401    PyTypeObject *tp = Py_TYPE(self);
402    PyObject *descr = NULL;
403
404    if (tp->tp_dict == NULL) {
405        if (PyType_Ready(tp) < 0)
406            return NULL;
407    }
408    descr = _PyType_Lookup(tp, name);
409
410    if (descr != NULL) {
411        descrgetfunc f = TP_DESCR_GET(Py_TYPE(descr));
412        if (f != NULL)
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
423static void
424instancemethod_dealloc(PyObject *self) {
425    _PyObject_GC_UNTRACK(self);
426    Py_DECREF(PyInstanceMethod_GET_FUNCTION(self));
427    PyObject_GC_Del(self);
428}
429
430static int
431instancemethod_traverse(PyObject *self, visitproc visit, void *arg) {
432    Py_VISIT(PyInstanceMethod_GET_FUNCTION(self));
433    return 0;
434}
435
436static PyObject *
437instancemethod_call(PyObject *self, PyObject *arg, PyObject *kw)
438{
439    return PyObject_Call(PyInstanceMethod_GET_FUNCTION(self), arg, kw);
440}
441
442static PyObject *
443instancemethod_descr_get(PyObject *descr, PyObject *obj, PyObject *type) {
444    PyObject *func = PyInstanceMethod_GET_FUNCTION(descr);
445    if (obj == NULL) {
446        Py_INCREF(func);
447        return func;
448    }
449    else
450        return PyMethod_New(func, obj);
451}
452
453static PyObject *
454instancemethod_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) ||
461        !PyInstanceMethod_Check(self) ||
462        !PyInstanceMethod_Check(other))
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)
470        return NULL;
471    if (op == Py_EQ)
472        res = eq ? Py_True : Py_False;
473    else
474        res = eq ? Py_False : Py_True;
475    Py_INCREF(res);
476    return res;
477}
478
479static PyObject *
480instancemethod_repr(PyObject *self)
481{
482    PyObject *func = PyInstanceMethod_Function(self);
483    PyObject *funcname, *result;
484    const char *defname = "?";
485
486    if (func == NULL) {
487        PyErr_BadInternalCall();
488        return NULL;
489    }
490
491    if (_PyObject_LookupAttr(func, &_Py_ID(__name__), &funcname) < 0) {
492        return NULL;
493    }
494    if (funcname != NULL && !PyUnicode_Check(funcname)) {
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
508instancemethod.__new__ as instancemethod_new
509    function: object
510    /
511
512Bind a function to a class.
513[clinic start generated code]*/
514
515static PyObject *
516instancemethod_new_impl(PyTypeObject *type, PyObject *function)
517/*[clinic end generated code: output=5e0397b2bdb750be input=cfc54e8b973664a8]*/
518{
519    if (!PyCallable_Check(function)) {
520        PyErr_SetString(PyExc_TypeError,
521                        "first argument must be callable");
522        return NULL;
523    }
524
525    return PyInstanceMethod_New(function);
526}
527
528PyTypeObject 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};
546