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