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