LCOV - code coverage report
Current view: top level - Objects - classobject.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 136 218 62.4 %
Date: 2022-07-07 18:19:46 Functions: 16 24 66.7 %

          Line data    Source code
       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           0 : PyMethod_Function(PyObject *im)
      22             : {
      23           0 :     if (!PyMethod_Check(im)) {
      24           0 :         PyErr_BadInternalCall();
      25           0 :         return NULL;
      26             :     }
      27           0 :     return ((PyMethodObject *)im)->im_func;
      28             : }
      29             : 
      30             : PyObject *
      31           0 : PyMethod_Self(PyObject *im)
      32             : {
      33           0 :     if (!PyMethod_Check(im)) {
      34           0 :         PyErr_BadInternalCall();
      35           0 :         return NULL;
      36             :     }
      37           0 :     return ((PyMethodObject *)im)->im_self;
      38             : }
      39             : 
      40             : 
      41             : static PyObject *
      42     9998710 : method_vectorcall(PyObject *method, PyObject *const *args,
      43             :                   size_t nargsf, PyObject *kwnames)
      44             : {
      45     9998710 :     assert(Py_IS_TYPE(method, &PyMethod_Type));
      46             : 
      47     9998710 :     PyThreadState *tstate = _PyThreadState_GET();
      48     9998710 :     PyObject *self = PyMethod_GET_SELF(method);
      49     9998710 :     PyObject *func = PyMethod_GET_FUNCTION(method);
      50     9998710 :     Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
      51             : 
      52             :     PyObject *result;
      53     9998710 :     if (nargsf & PY_VECTORCALL_ARGUMENTS_OFFSET) {
      54             :         /* PY_VECTORCALL_ARGUMENTS_OFFSET is set, so we are allowed to mutate the vector */
      55     3855030 :         PyObject **newargs = (PyObject**)args - 1;
      56     3855030 :         nargs += 1;
      57     3855030 :         PyObject *tmp = newargs[0];
      58     3855030 :         newargs[0] = self;
      59     3855030 :         result = _PyObject_VectorcallTstate(tstate, func, newargs,
      60             :                                             nargs, kwnames);
      61     3855030 :         newargs[0] = tmp;
      62             :     }
      63             :     else {
      64     6143680 :         Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames);
      65     6143680 :         Py_ssize_t totalargs = nargs + nkwargs;
      66     6143680 :         if (totalargs == 0) {
      67     3041100 :             return _PyObject_VectorcallTstate(tstate, func, &self, 1, NULL);
      68             :         }
      69             : 
      70             :         PyObject *newargs_stack[_PY_FASTCALL_SMALL_STACK];
      71             :         PyObject **newargs;
      72     3102580 :         if (totalargs <= (Py_ssize_t)Py_ARRAY_LENGTH(newargs_stack) - 1) {
      73     3024350 :             newargs = newargs_stack;
      74             :         }
      75             :         else {
      76       78234 :             newargs = PyMem_Malloc((totalargs+1) * sizeof(PyObject *));
      77       78234 :             if (newargs == NULL) {
      78           0 :                 _PyErr_NoMemory(tstate);
      79           0 :                 return NULL;
      80             :             }
      81             :         }
      82             :         /* use borrowed references */
      83     3102580 :         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     3102580 :         assert(args != NULL);
      88     3102580 :         memcpy(newargs + 1, args, totalargs * sizeof(PyObject *));
      89     3102580 :         result = _PyObject_VectorcallTstate(tstate, func,
      90     3102580 :                                             newargs, nargs+1, kwnames);
      91     3102540 :         if (newargs != newargs_stack) {
      92       78234 :             PyMem_Free(newargs);
      93             :         }
      94             :     }
      95     6957570 :     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    27823600 : PyMethod_New(PyObject *func, PyObject *self)
     106             : {
     107    27823600 :     if (self == NULL) {
     108           0 :         PyErr_BadInternalCall();
     109           0 :         return NULL;
     110             :     }
     111    27823600 :     PyMethodObject *im = PyObject_GC_New(PyMethodObject, &PyMethod_Type);
     112    27823600 :     if (im == NULL) {
     113           0 :         return NULL;
     114             :     }
     115    27823600 :     im->im_weakreflist = NULL;
     116    27823600 :     Py_INCREF(func);
     117    27823600 :     im->im_func = func;
     118    27823600 :     Py_INCREF(self);
     119    27823600 :     im->im_self = self;
     120    27823600 :     im->vectorcall = method_vectorcall;
     121    27823600 :     _PyObject_GC_TRACK(im);
     122    27823600 :     return (PyObject *)im;
     123             : }
     124             : 
     125             : /*[clinic input]
     126             : method.__reduce__
     127             : [clinic start generated code]*/
     128             : 
     129             : static PyObject *
     130         574 : method___reduce___impl(PyMethodObject *self)
     131             : /*[clinic end generated code: output=6c04506d0fa6fdcb input=143a0bf5e96de6e8]*/
     132             : {
     133         574 :     PyObject *funcself = PyMethod_GET_SELF(self);
     134         574 :     PyObject *func = PyMethod_GET_FUNCTION(self);
     135         574 :     PyObject *funcname = PyObject_GetAttr(func, &_Py_ID(__name__));
     136         574 :     if (funcname == NULL) {
     137           0 :         return NULL;
     138             :     }
     139         574 :     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      215301 : method_get_doc(PyMethodObject *im, void *context)
     169             : {
     170      215301 :     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      341905 : method_getattro(PyObject *obj, PyObject *name)
     180             : {
     181      341905 :     PyMethodObject *im = (PyMethodObject *)obj;
     182      341905 :     PyTypeObject *tp = Py_TYPE(obj);
     183      341905 :     PyObject *descr = NULL;
     184             : 
     185             :     {
     186      341905 :         if (tp->tp_dict == NULL) {
     187           0 :             if (PyType_Ready(tp) < 0)
     188           0 :                 return NULL;
     189             :         }
     190      341905 :         descr = _PyType_Lookup(tp, name);
     191             :     }
     192             : 
     193      341905 :     if (descr != NULL) {
     194      230010 :         descrgetfunc f = TP_DESCR_GET(Py_TYPE(descr));
     195      230010 :         if (f != NULL)
     196      229950 :             return f(descr, obj, (PyObject *)Py_TYPE(obj));
     197             :         else {
     198          60 :             Py_INCREF(descr);
     199          60 :             return descr;
     200             :         }
     201             :     }
     202             : 
     203      111895 :     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        1006 : method_new_impl(PyTypeObject *type, PyObject *function, PyObject *instance)
     218             : /*[clinic end generated code: output=d33ef4ebf702e1f7 input=4e32facc3c3108ae]*/
     219             : {
     220        1006 :     if (!PyCallable_Check(function)) {
     221           0 :         PyErr_SetString(PyExc_TypeError,
     222             :                         "first argument must be callable");
     223           0 :         return NULL;
     224             :     }
     225        1006 :     if (instance == NULL || instance == Py_None) {
     226           0 :         PyErr_SetString(PyExc_TypeError,
     227             :             "instance must not be None");
     228           0 :         return NULL;
     229             :     }
     230             : 
     231        1006 :     return PyMethod_New(function, instance);
     232             : }
     233             : 
     234             : static void
     235    27823300 : method_dealloc(PyMethodObject *im)
     236             : {
     237    27823300 :     _PyObject_GC_UNTRACK(im);
     238    27823300 :     if (im->im_weakreflist != NULL)
     239           1 :         PyObject_ClearWeakRefs((PyObject *)im);
     240    27823300 :     Py_DECREF(im->im_func);
     241    27823300 :     Py_XDECREF(im->im_self);
     242    27823300 :     PyObject_GC_Del(im);
     243    27823300 : }
     244             : 
     245             : static PyObject *
     246          79 : method_richcompare(PyObject *self, PyObject *other, int op)
     247             : {
     248             :     PyMethodObject *a, *b;
     249             :     PyObject *res;
     250             :     int eq;
     251             : 
     252         150 :     if ((op != Py_EQ && op != Py_NE) ||
     253         142 :         !PyMethod_Check(self) ||
     254          71 :         !PyMethod_Check(other))
     255             :     {
     256          12 :         Py_RETURN_NOTIMPLEMENTED;
     257             :     }
     258          67 :     a = (PyMethodObject *)self;
     259          67 :     b = (PyMethodObject *)other;
     260          67 :     eq = PyObject_RichCompareBool(a->im_func, b->im_func, Py_EQ);
     261          67 :     if (eq == 1) {
     262          65 :         eq = (a->im_self == b->im_self);
     263             :     }
     264           2 :     else if (eq < 0)
     265           0 :         return NULL;
     266          67 :     if (op == Py_EQ)
     267          34 :         res = eq ? Py_True : Py_False;
     268             :     else
     269          33 :         res = eq ? Py_False : Py_True;
     270          67 :     Py_INCREF(res);
     271          67 :     return res;
     272             : }
     273             : 
     274             : static PyObject *
     275        1796 : method_repr(PyMethodObject *a)
     276             : {
     277        1796 :     PyObject *self = a->im_self;
     278        1796 :     PyObject *func = a->im_func;
     279             :     PyObject *funcname, *result;
     280        1796 :     const char *defname = "?";
     281             : 
     282        1796 :     if (_PyObject_LookupAttr(func, &_Py_ID(__qualname__), &funcname) < 0 ||
     283        1799 :         (funcname == NULL &&
     284           3 :          _PyObject_LookupAttr(func, &_Py_ID(__name__), &funcname) < 0))
     285             :     {
     286           0 :         return NULL;
     287             :     }
     288             : 
     289        1796 :     if (funcname != NULL && !PyUnicode_Check(funcname)) {
     290           0 :         Py_DECREF(funcname);
     291           0 :         funcname = NULL;
     292             :     }
     293             : 
     294             :     /* XXX Shouldn't use repr()/%R here! */
     295        1796 :     result = PyUnicode_FromFormat("<bound method %V of %R>",
     296             :                                   funcname, defname, self);
     297             : 
     298        1796 :     Py_XDECREF(funcname);
     299        1796 :     return result;
     300             : }
     301             : 
     302             : static Py_hash_t
     303         100 : method_hash(PyMethodObject *a)
     304             : {
     305             :     Py_hash_t x, y;
     306         100 :     x = _Py_HashPointer(a->im_self);
     307         100 :     y = PyObject_Hash(a->im_func);
     308         100 :     if (y == -1)
     309           0 :         return -1;
     310         100 :     x = x ^ y;
     311         100 :     if (x == -1)
     312           0 :         x = -2;
     313         100 :     return x;
     314             : }
     315             : 
     316             : static int
     317     7823080 : method_traverse(PyMethodObject *im, visitproc visit, void *arg)
     318             : {
     319     7823080 :     Py_VISIT(im->im_func);
     320     7823070 :     Py_VISIT(im->im_self);
     321     7823070 :     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           2 : PyInstanceMethod_New(PyObject *func) {
     358             :     PyInstanceMethodObject *method;
     359           2 :     method = PyObject_GC_New(PyInstanceMethodObject,
     360             :                              &PyInstanceMethod_Type);
     361           2 :     if (method == NULL) return NULL;
     362           2 :     Py_INCREF(func);
     363           2 :     method->func = func;
     364           2 :     _PyObject_GC_TRACK(method);
     365           2 :     return (PyObject *)method;
     366             : }
     367             : 
     368             : PyObject *
     369           0 : PyInstanceMethod_Function(PyObject *im)
     370             : {
     371           0 :     if (!PyInstanceMethod_Check(im)) {
     372           0 :         PyErr_BadInternalCall();
     373           0 :         return NULL;
     374             :     }
     375           0 :     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           0 : instancemethod_get_doc(PyObject *self, void *context)
     388             : {
     389           0 :     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           0 : instancemethod_getattro(PyObject *self, PyObject *name)
     400             : {
     401           0 :     PyTypeObject *tp = Py_TYPE(self);
     402           0 :     PyObject *descr = NULL;
     403             : 
     404           0 :     if (tp->tp_dict == NULL) {
     405           0 :         if (PyType_Ready(tp) < 0)
     406           0 :             return NULL;
     407             :     }
     408           0 :     descr = _PyType_Lookup(tp, name);
     409             : 
     410           0 :     if (descr != NULL) {
     411           0 :         descrgetfunc f = TP_DESCR_GET(Py_TYPE(descr));
     412           0 :         if (f != NULL)
     413           0 :             return f(descr, self, (PyObject *)Py_TYPE(self));
     414             :         else {
     415           0 :             Py_INCREF(descr);
     416           0 :             return descr;
     417             :         }
     418             :     }
     419             : 
     420           0 :     return PyObject_GetAttr(PyInstanceMethod_GET_FUNCTION(self), name);
     421             : }
     422             : 
     423             : static void
     424           2 : instancemethod_dealloc(PyObject *self) {
     425           2 :     _PyObject_GC_UNTRACK(self);
     426           2 :     Py_DECREF(PyInstanceMethod_GET_FUNCTION(self));
     427           2 :     PyObject_GC_Del(self);
     428           2 : }
     429             : 
     430             : static int
     431         208 : instancemethod_traverse(PyObject *self, visitproc visit, void *arg) {
     432         208 :     Py_VISIT(PyInstanceMethod_GET_FUNCTION(self));
     433         208 :     return 0;
     434             : }
     435             : 
     436             : static PyObject *
     437           0 : instancemethod_call(PyObject *self, PyObject *arg, PyObject *kw)
     438             : {
     439           0 :     return PyObject_Call(PyInstanceMethod_GET_FUNCTION(self), arg, kw);
     440             : }
     441             : 
     442             : static PyObject *
     443           6 : instancemethod_descr_get(PyObject *descr, PyObject *obj, PyObject *type) {
     444           6 :     PyObject *func = PyInstanceMethod_GET_FUNCTION(descr);
     445           6 :     if (obj == NULL) {
     446           2 :         Py_INCREF(func);
     447           2 :         return func;
     448             :     }
     449             :     else
     450           4 :         return PyMethod_New(func, obj);
     451             : }
     452             : 
     453             : static PyObject *
     454           0 : instancemethod_richcompare(PyObject *self, PyObject *other, int op)
     455             : {
     456             :     PyInstanceMethodObject *a, *b;
     457             :     PyObject *res;
     458             :     int eq;
     459             : 
     460           0 :     if ((op != Py_EQ && op != Py_NE) ||
     461           0 :         !PyInstanceMethod_Check(self) ||
     462           0 :         !PyInstanceMethod_Check(other))
     463             :     {
     464           0 :         Py_RETURN_NOTIMPLEMENTED;
     465             :     }
     466           0 :     a = (PyInstanceMethodObject *)self;
     467           0 :     b = (PyInstanceMethodObject *)other;
     468           0 :     eq = PyObject_RichCompareBool(a->func, b->func, Py_EQ);
     469           0 :     if (eq < 0)
     470           0 :         return NULL;
     471           0 :     if (op == Py_EQ)
     472           0 :         res = eq ? Py_True : Py_False;
     473             :     else
     474           0 :         res = eq ? Py_False : Py_True;
     475           0 :     Py_INCREF(res);
     476           0 :     return res;
     477             : }
     478             : 
     479             : static PyObject *
     480           0 : instancemethod_repr(PyObject *self)
     481             : {
     482           0 :     PyObject *func = PyInstanceMethod_Function(self);
     483             :     PyObject *funcname, *result;
     484           0 :     const char *defname = "?";
     485             : 
     486           0 :     if (func == NULL) {
     487           0 :         PyErr_BadInternalCall();
     488           0 :         return NULL;
     489             :     }
     490             : 
     491           0 :     if (_PyObject_LookupAttr(func, &_Py_ID(__name__), &funcname) < 0) {
     492           0 :         return NULL;
     493             :     }
     494           0 :     if (funcname != NULL && !PyUnicode_Check(funcname)) {
     495           0 :         Py_DECREF(funcname);
     496           0 :         funcname = NULL;
     497             :     }
     498             : 
     499           0 :     result = PyUnicode_FromFormat("<instancemethod %V at %p>",
     500             :                                   funcname, defname, self);
     501             : 
     502           0 :     Py_XDECREF(funcname);
     503           0 :     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           2 : instancemethod_new_impl(PyTypeObject *type, PyObject *function)
     517             : /*[clinic end generated code: output=5e0397b2bdb750be input=cfc54e8b973664a8]*/
     518             : {
     519           2 :     if (!PyCallable_Check(function)) {
     520           0 :         PyErr_SetString(PyExc_TypeError,
     521             :                         "first argument must be callable");
     522           0 :         return NULL;
     523             :     }
     524             : 
     525           2 :     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             : };

Generated by: LCOV version 1.14