blob: dbab4cd4da2c6329aab0535dc4c65734bce334db [file] [log] [blame]
Tim Peters6d6c1a32001-08-02 04:15:00 +00001/* Descriptors -- a new, flexible way to describe attributes */
2
3#include "Python.h"
Victor Stinnerbcda8f12018-11-21 22:27:47 +01004#include "pycore_object.h"
Victor Stinner621cebe2018-11-12 16:53:38 +01005#include "pycore_pystate.h"
Victor Stinnerec13b932018-11-25 23:56:17 +01006#include "pycore_tupleobject.h"
Tim Peters6d6c1a32001-08-02 04:15:00 +00007#include "structmember.h" /* Why is this not included in Python.h? */
8
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02009/*[clinic input]
10class mappingproxy "mappingproxyobject *" "&PyDictProxy_Type"
11class property "propertyobject *" "&PyProperty_Type"
12[clinic start generated code]*/
13/*[clinic end generated code: output=da39a3ee5e6b4b0d input=556352653fd4c02e]*/
14
Tim Peters6d6c1a32001-08-02 04:15:00 +000015static void
16descr_dealloc(PyDescrObject *descr)
17{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000018 _PyObject_GC_UNTRACK(descr);
19 Py_XDECREF(descr->d_type);
20 Py_XDECREF(descr->d_name);
Antoine Pitrou9d574812011-12-12 13:47:25 +010021 Py_XDECREF(descr->d_qualname);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000022 PyObject_GC_Del(descr);
Tim Peters6d6c1a32001-08-02 04:15:00 +000023}
24
Walter Dörwaldd7fb7642007-06-11 16:36:59 +000025static PyObject *
Tim Peters6d6c1a32001-08-02 04:15:00 +000026descr_name(PyDescrObject *descr)
27{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000028 if (descr->d_name != NULL && PyUnicode_Check(descr->d_name))
29 return descr->d_name;
30 return NULL;
Tim Peters6d6c1a32001-08-02 04:15:00 +000031}
32
33static PyObject *
Serhiy Storchakaef1585e2015-12-25 20:01:53 +020034descr_repr(PyDescrObject *descr, const char *format)
Tim Peters6d6c1a32001-08-02 04:15:00 +000035{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000036 PyObject *name = NULL;
37 if (descr->d_name != NULL && PyUnicode_Check(descr->d_name))
38 name = descr->d_name;
Walter Dörwaldd7fb7642007-06-11 16:36:59 +000039
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000040 return PyUnicode_FromFormat(format, name, "?", descr->d_type->tp_name);
Tim Peters6d6c1a32001-08-02 04:15:00 +000041}
42
43static PyObject *
44method_repr(PyMethodDescrObject *descr)
45{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000046 return descr_repr((PyDescrObject *)descr,
47 "<method '%V' of '%s' objects>");
Tim Peters6d6c1a32001-08-02 04:15:00 +000048}
49
50static PyObject *
51member_repr(PyMemberDescrObject *descr)
52{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000053 return descr_repr((PyDescrObject *)descr,
54 "<member '%V' of '%s' objects>");
Tim Peters6d6c1a32001-08-02 04:15:00 +000055}
56
57static PyObject *
58getset_repr(PyGetSetDescrObject *descr)
59{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000060 return descr_repr((PyDescrObject *)descr,
61 "<attribute '%V' of '%s' objects>");
Tim Peters6d6c1a32001-08-02 04:15:00 +000062}
63
64static PyObject *
Armin Rigoc6686b72005-11-07 08:38:00 +000065wrapperdescr_repr(PyWrapperDescrObject *descr)
Tim Peters6d6c1a32001-08-02 04:15:00 +000066{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000067 return descr_repr((PyDescrObject *)descr,
68 "<slot wrapper '%V' of '%s' objects>");
Tim Peters6d6c1a32001-08-02 04:15:00 +000069}
70
71static int
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +000072descr_check(PyDescrObject *descr, PyObject *obj, PyObject **pres)
Tim Peters6d6c1a32001-08-02 04:15:00 +000073{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000074 if (obj == NULL) {
75 Py_INCREF(descr);
76 *pres = (PyObject *)descr;
77 return 1;
78 }
79 if (!PyObject_TypeCheck(obj, descr->d_type)) {
80 PyErr_Format(PyExc_TypeError,
Inada Naoki62f95882019-04-01 17:56:11 +090081 "descriptor '%V' for '%.100s' objects "
82 "doesn't apply to a '%.100s' object",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000083 descr_name((PyDescrObject *)descr), "?",
84 descr->d_type->tp_name,
85 obj->ob_type->tp_name);
86 *pres = NULL;
87 return 1;
88 }
89 return 0;
Tim Peters6d6c1a32001-08-02 04:15:00 +000090}
91
92static PyObject *
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +000093classmethod_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type)
Tim Petersbca1cbc2002-12-09 22:56:13 +000094{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000095 /* Ensure a valid type. Class methods ignore obj. */
96 if (type == NULL) {
97 if (obj != NULL)
98 type = (PyObject *)obj->ob_type;
99 else {
100 /* Wot - no type?! */
101 PyErr_Format(PyExc_TypeError,
Inada Naoki62f95882019-04-01 17:56:11 +0900102 "descriptor '%V' for type '%.100s' "
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000103 "needs either an object or a type",
104 descr_name((PyDescrObject *)descr), "?",
105 PyDescr_TYPE(descr)->tp_name);
106 return NULL;
107 }
108 }
109 if (!PyType_Check(type)) {
110 PyErr_Format(PyExc_TypeError,
Inada Naoki62f95882019-04-01 17:56:11 +0900111 "descriptor '%V' for type '%.100s' "
112 "needs a type, not a '%.100s' as arg 2",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000113 descr_name((PyDescrObject *)descr), "?",
114 PyDescr_TYPE(descr)->tp_name,
115 type->ob_type->tp_name);
116 return NULL;
117 }
118 if (!PyType_IsSubtype((PyTypeObject *)type, PyDescr_TYPE(descr))) {
119 PyErr_Format(PyExc_TypeError,
Inada Naoki62f95882019-04-01 17:56:11 +0900120 "descriptor '%V' requires a subtype of '%.100s' "
121 "but received '%.100s'",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000122 descr_name((PyDescrObject *)descr), "?",
123 PyDescr_TYPE(descr)->tp_name,
124 ((PyTypeObject *)type)->tp_name);
125 return NULL;
126 }
Andrew Svetlov3ba3a3e2012-12-25 13:32:35 +0200127 return PyCFunction_NewEx(descr->d_method, type, NULL);
Tim Petersbca1cbc2002-12-09 22:56:13 +0000128}
129
130static PyObject *
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +0000131method_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000132{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000133 PyObject *res;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000134
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000135 if (descr_check((PyDescrObject *)descr, obj, &res))
136 return res;
Andrew Svetlov3ba3a3e2012-12-25 13:32:35 +0200137 return PyCFunction_NewEx(descr->d_method, obj, NULL);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000138}
139
140static PyObject *
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +0000141member_get(PyMemberDescrObject *descr, PyObject *obj, PyObject *type)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000142{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000143 PyObject *res;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000144
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000145 if (descr_check((PyDescrObject *)descr, obj, &res))
146 return res;
Steve Dowerb82e17e2019-05-23 08:45:22 -0700147
148 if (descr->d_member->flags & READ_RESTRICTED) {
149 if (PySys_Audit("object.__getattr__", "Os",
150 obj ? obj : Py_None, descr->d_member->name) < 0) {
151 return NULL;
152 }
153 }
154
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000155 return PyMember_GetOne((char *)obj, descr->d_member);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000156}
157
158static PyObject *
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +0000159getset_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *type)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000160{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000161 PyObject *res;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000162
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000163 if (descr_check((PyDescrObject *)descr, obj, &res))
164 return res;
165 if (descr->d_getset->get != NULL)
166 return descr->d_getset->get(obj, descr->d_getset->closure);
167 PyErr_Format(PyExc_AttributeError,
168 "attribute '%V' of '%.100s' objects is not readable",
169 descr_name((PyDescrObject *)descr), "?",
170 PyDescr_TYPE(descr)->tp_name);
171 return NULL;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000172}
173
174static PyObject *
Armin Rigoc6686b72005-11-07 08:38:00 +0000175wrapperdescr_get(PyWrapperDescrObject *descr, PyObject *obj, PyObject *type)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000176{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000177 PyObject *res;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000178
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000179 if (descr_check((PyDescrObject *)descr, obj, &res))
180 return res;
181 return PyWrapper_New((PyObject *)descr, obj);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000182}
183
184static int
185descr_setcheck(PyDescrObject *descr, PyObject *obj, PyObject *value,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000186 int *pres)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000187{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000188 assert(obj != NULL);
189 if (!PyObject_TypeCheck(obj, descr->d_type)) {
190 PyErr_Format(PyExc_TypeError,
191 "descriptor '%V' for '%.100s' objects "
Inada Naoki62f95882019-04-01 17:56:11 +0900192 "doesn't apply to a '%.100s' object",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000193 descr_name(descr), "?",
194 descr->d_type->tp_name,
195 obj->ob_type->tp_name);
196 *pres = -1;
197 return 1;
198 }
199 return 0;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000200}
201
202static int
203member_set(PyMemberDescrObject *descr, PyObject *obj, PyObject *value)
204{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000205 int res;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000206
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000207 if (descr_setcheck((PyDescrObject *)descr, obj, value, &res))
208 return res;
209 return PyMember_SetOne((char *)obj, descr->d_member, value);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000210}
211
212static int
213getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value)
214{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000215 int res;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000216
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000217 if (descr_setcheck((PyDescrObject *)descr, obj, value, &res))
218 return res;
219 if (descr->d_getset->set != NULL)
220 return descr->d_getset->set(obj, value,
221 descr->d_getset->closure);
222 PyErr_Format(PyExc_AttributeError,
223 "attribute '%V' of '%.100s' objects is not writable",
224 descr_name((PyDescrObject *)descr), "?",
225 PyDescr_TYPE(descr)->tp_name);
226 return -1;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000227}
228
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200229
230/* Vectorcall functions for each of the PyMethodDescr calling conventions.
231 *
232 * First, common helpers
233 */
234static const char *
235get_name(PyObject *func) {
236 assert(PyObject_TypeCheck(func, &PyMethodDescr_Type));
237 return ((PyMethodDescrObject *)func)->d_method->ml_name;
238}
239
240typedef void (*funcptr)(void);
241
242static inline int
243method_check_args(PyObject *func, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
244{
245 assert(!PyErr_Occurred());
246 assert(PyObject_TypeCheck(func, &PyMethodDescr_Type));
247 if (nargs < 1) {
248 PyErr_Format(PyExc_TypeError,
249 "descriptor '%.200s' of '%.100s' "
250 "object needs an argument",
251 get_name(func), PyDescr_TYPE(func)->tp_name);
252 return -1;
253 }
254 PyObject *self = args[0];
255 if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
256 (PyObject *)PyDescr_TYPE(func)))
257 {
258 PyErr_Format(PyExc_TypeError,
259 "descriptor '%.200s' for '%.100s' objects "
260 "doesn't apply to a '%.100s' object",
261 get_name(func), PyDescr_TYPE(func)->tp_name,
262 Py_TYPE(self)->tp_name);
263 return -1;
264 }
265 if (kwnames && PyTuple_GET_SIZE(kwnames)) {
266 PyErr_Format(PyExc_TypeError,
267 "%.200s() takes no keyword arguments", get_name(func));
268 return -1;
269 }
270 return 0;
271}
272
273static inline funcptr
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100274method_enter_call(PyThreadState *tstate, PyObject *func)
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200275{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100276 if (_Py_EnterRecursiveCall(tstate, " while calling a Python object")) {
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200277 return NULL;
278 }
279 return (funcptr)((PyMethodDescrObject *)func)->d_method->ml_meth;
280}
281
282/* Now the actual vectorcall functions */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000283static PyObject *
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200284method_vectorcall_VARARGS(
285 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000286{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100287 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200288 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200289 if (method_check_args(func, args, nargs, kwnames)) {
INADA Naoki5566bbb2017-02-03 07:43:03 +0900290 return NULL;
291 }
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200292 PyObject *argstuple = _PyTuple_FromArray(args+1, nargs-1);
293 if (argstuple == NULL) {
INADA Naoki5566bbb2017-02-03 07:43:03 +0900294 return NULL;
295 }
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100296 PyCFunction meth = (PyCFunction)method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200297 if (meth == NULL) {
298 Py_DECREF(argstuple);
299 return NULL;
300 }
301 PyObject *result = meth(args[0], argstuple);
302 Py_DECREF(argstuple);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100303 _Py_LeaveRecursiveCall(tstate);
INADA Naoki5566bbb2017-02-03 07:43:03 +0900304 return result;
305}
306
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200307static PyObject *
308method_vectorcall_VARARGS_KEYWORDS(
309 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
310{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100311 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200312 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
313 if (method_check_args(func, args, nargs, NULL)) {
314 return NULL;
315 }
316 PyObject *argstuple = _PyTuple_FromArray(args+1, nargs-1);
317 if (argstuple == NULL) {
318 return NULL;
319 }
320 PyObject *result = NULL;
321 /* Create a temporary dict for keyword arguments */
322 PyObject *kwdict = NULL;
323 if (kwnames != NULL && PyTuple_GET_SIZE(kwnames) > 0) {
324 kwdict = _PyStack_AsDict(args + nargs, kwnames);
325 if (kwdict == NULL) {
326 goto exit;
327 }
328 }
329 PyCFunctionWithKeywords meth = (PyCFunctionWithKeywords)
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100330 method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200331 if (meth == NULL) {
332 goto exit;
333 }
334 result = meth(args[0], argstuple, kwdict);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100335 _Py_LeaveRecursiveCall(tstate);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200336exit:
337 Py_DECREF(argstuple);
338 Py_XDECREF(kwdict);
339 return result;
340}
341
342static PyObject *
343method_vectorcall_FASTCALL(
344 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
345{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100346 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200347 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
348 if (method_check_args(func, args, nargs, kwnames)) {
349 return NULL;
350 }
351 _PyCFunctionFast meth = (_PyCFunctionFast)
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100352 method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200353 if (meth == NULL) {
354 return NULL;
355 }
356 PyObject *result = meth(args[0], args+1, nargs-1);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100357 _Py_LeaveRecursiveCall(tstate);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200358 return result;
359}
360
361static PyObject *
362method_vectorcall_FASTCALL_KEYWORDS(
363 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
364{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100365 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200366 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
367 if (method_check_args(func, args, nargs, NULL)) {
368 return NULL;
369 }
370 _PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords)
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100371 method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200372 if (meth == NULL) {
373 return NULL;
374 }
375 PyObject *result = meth(args[0], args+1, nargs-1, kwnames);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100376 _Py_LeaveRecursiveCall(tstate);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200377 return result;
378}
379
380static PyObject *
381method_vectorcall_NOARGS(
382 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
383{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100384 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200385 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
386 if (method_check_args(func, args, nargs, kwnames)) {
387 return NULL;
388 }
389 if (nargs != 1) {
390 PyErr_Format(PyExc_TypeError,
391 "%.200s() takes no arguments (%zd given)", get_name(func), nargs-1);
392 return NULL;
393 }
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100394 PyCFunction meth = (PyCFunction)method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200395 if (meth == NULL) {
396 return NULL;
397 }
398 PyObject *result = meth(args[0], NULL);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100399 _Py_LeaveRecursiveCall(tstate);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200400 return result;
401}
402
403static PyObject *
404method_vectorcall_O(
405 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
406{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100407 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200408 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
409 if (method_check_args(func, args, nargs, kwnames)) {
410 return NULL;
411 }
412 if (nargs != 2) {
413 PyErr_Format(PyExc_TypeError,
414 "%.200s() takes exactly one argument (%zd given)",
415 get_name(func), nargs-1);
416 return NULL;
417 }
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100418 PyCFunction meth = (PyCFunction)method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200419 if (meth == NULL) {
420 return NULL;
421 }
422 PyObject *result = meth(args[0], args[1]);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100423 _Py_LeaveRecursiveCall(tstate);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200424 return result;
425}
426
427
Jeroen Demeyer3f345c32019-06-07 12:20:24 +0200428/* Instances of classmethod_descriptor are unlikely to be called directly.
429 For one, the analogous class "classmethod" (for Python classes) is not
430 callable. Second, users are not likely to access a classmethod_descriptor
431 directly, since it means pulling it from the class __dict__.
432
433 This is just an excuse to say that this doesn't need to be optimized:
434 we implement this simply by calling __get__ and then calling the result.
435*/
Tim Peters6d6c1a32001-08-02 04:15:00 +0000436static PyObject *
Tim Petersbca1cbc2002-12-09 22:56:13 +0000437classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000438 PyObject *kwds)
Tim Petersbca1cbc2002-12-09 22:56:13 +0000439{
Jeroen Demeyer3f345c32019-06-07 12:20:24 +0200440 Py_ssize_t argc = PyTuple_GET_SIZE(args);
Benjamin Peterson7295c6a2012-05-01 09:51:09 -0400441 if (argc < 1) {
442 PyErr_Format(PyExc_TypeError,
443 "descriptor '%V' of '%.100s' "
444 "object needs an argument",
445 descr_name((PyDescrObject *)descr), "?",
446 PyDescr_TYPE(descr)->tp_name);
447 return NULL;
448 }
Jeroen Demeyer3f345c32019-06-07 12:20:24 +0200449 PyObject *self = PyTuple_GET_ITEM(args, 0);
450 PyObject *bound = classmethod_get(descr, NULL, self);
451 if (bound == NULL) {
Benjamin Peterson7295c6a2012-05-01 09:51:09 -0400452 return NULL;
453 }
Jeroen Demeyer3f345c32019-06-07 12:20:24 +0200454 PyObject *res = _PyObject_FastCallDict(bound, _PyTuple_ITEMS(args)+1,
455 argc-1, kwds);
456 Py_DECREF(bound);
457 return res;
Tim Petersbca1cbc2002-12-09 22:56:13 +0000458}
459
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300460Py_LOCAL_INLINE(PyObject *)
461wrapperdescr_raw_call(PyWrapperDescrObject *descr, PyObject *self,
462 PyObject *args, PyObject *kwds)
463{
464 wrapperfunc wrapper = descr->d_base->wrapper;
465
466 if (descr->d_base->flags & PyWrapperFlag_KEYWORDS) {
Serhiy Storchaka1c607152018-11-27 21:34:27 +0200467 wrapperfunc_kwds wk = (wrapperfunc_kwds)(void(*)(void))wrapper;
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300468 return (*wk)(self, args, descr->d_wrapped, kwds);
469 }
470
471 if (kwds != NULL && (!PyDict_Check(kwds) || PyDict_GET_SIZE(kwds) != 0)) {
472 PyErr_Format(PyExc_TypeError,
473 "wrapper %s() takes no keyword arguments",
474 descr->d_base->name);
475 return NULL;
476 }
477 return (*wrapper)(self, args, descr->d_wrapped);
478}
479
Tim Petersbca1cbc2002-12-09 22:56:13 +0000480static PyObject *
Tim Peters6d6c1a32001-08-02 04:15:00 +0000481wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
482{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000483 Py_ssize_t argc;
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300484 PyObject *self, *result;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000485
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000486 /* Make sure that the first argument is acceptable as 'self' */
487 assert(PyTuple_Check(args));
488 argc = PyTuple_GET_SIZE(args);
489 if (argc < 1) {
490 PyErr_Format(PyExc_TypeError,
491 "descriptor '%V' of '%.100s' "
492 "object needs an argument",
493 descr_name((PyDescrObject *)descr), "?",
494 PyDescr_TYPE(descr)->tp_name);
495 return NULL;
496 }
497 self = PyTuple_GET_ITEM(args, 0);
Victor Stinner3249dec2011-05-01 23:19:15 +0200498 if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
Victor Stinnerd9561312011-05-01 23:31:36 +0200499 (PyObject *)PyDescr_TYPE(descr))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000500 PyErr_Format(PyExc_TypeError,
501 "descriptor '%V' "
502 "requires a '%.100s' object "
503 "but received a '%.100s'",
504 descr_name((PyDescrObject *)descr), "?",
505 PyDescr_TYPE(descr)->tp_name,
506 self->ob_type->tp_name);
507 return NULL;
508 }
Tim Peters6d6c1a32001-08-02 04:15:00 +0000509
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300510 args = PyTuple_GetSlice(args, 1, argc);
511 if (args == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000512 return NULL;
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300513 }
514 result = wrapperdescr_raw_call(descr, self, args, kwds);
515 Py_DECREF(args);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000516 return result;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000517}
518
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300519
Tim Peters6d6c1a32001-08-02 04:15:00 +0000520static PyObject *
Guido van Rossum6f799372001-09-20 20:46:19 +0000521method_get_doc(PyMethodDescrObject *descr, void *closure)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000522{
Larry Hastings2623c8c2014-02-08 22:15:29 -0800523 return _PyType_GetDocFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc);
Larry Hastings5c661892014-01-24 06:17:25 -0800524}
525
526static PyObject *
527method_get_text_signature(PyMethodDescrObject *descr, void *closure)
528{
Larry Hastings2623c8c2014-02-08 22:15:29 -0800529 return _PyType_GetTextSignatureFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000530}
531
Antoine Pitrou9d574812011-12-12 13:47:25 +0100532static PyObject *
533calculate_qualname(PyDescrObject *descr)
534{
535 PyObject *type_qualname, *res;
536 _Py_IDENTIFIER(__qualname__);
537
538 if (descr->d_name == NULL || !PyUnicode_Check(descr->d_name)) {
539 PyErr_SetString(PyExc_TypeError,
540 "<descriptor>.__name__ is not a unicode object");
541 return NULL;
542 }
543
544 type_qualname = _PyObject_GetAttrId((PyObject *)descr->d_type,
545 &PyId___qualname__);
546 if (type_qualname == NULL)
547 return NULL;
548
549 if (!PyUnicode_Check(type_qualname)) {
550 PyErr_SetString(PyExc_TypeError, "<descriptor>.__objclass__."
551 "__qualname__ is not a unicode object");
552 Py_XDECREF(type_qualname);
553 return NULL;
554 }
555
556 res = PyUnicode_FromFormat("%S.%S", type_qualname, descr->d_name);
557 Py_DECREF(type_qualname);
558 return res;
559}
560
561static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +0200562descr_get_qualname(PyDescrObject *descr, void *Py_UNUSED(ignored))
Antoine Pitrou9d574812011-12-12 13:47:25 +0100563{
564 if (descr->d_qualname == NULL)
565 descr->d_qualname = calculate_qualname(descr);
566 Py_XINCREF(descr->d_qualname);
567 return descr->d_qualname;
568}
569
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100570static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530571descr_reduce(PyDescrObject *descr, PyObject *Py_UNUSED(ignored))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100572{
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100573 _Py_IDENTIFIER(getattr);
Serhiy Storchakabb86bf42018-12-11 08:28:18 +0200574 return Py_BuildValue("N(OO)", _PyEval_GetBuiltinId(&PyId_getattr),
575 PyDescr_TYPE(descr), PyDescr_NAME(descr));
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100576}
577
578static PyMethodDef descr_methods[] = {
579 {"__reduce__", (PyCFunction)descr_reduce, METH_NOARGS, NULL},
580 {NULL, NULL}
581};
582
Guido van Rossum6f799372001-09-20 20:46:19 +0000583static PyMemberDef descr_members[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000584 {"__objclass__", T_OBJECT, offsetof(PyDescrObject, d_type), READONLY},
585 {"__name__", T_OBJECT, offsetof(PyDescrObject, d_name), READONLY},
586 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +0000587};
588
Guido van Rossum32d34c82001-09-20 21:45:26 +0000589static PyGetSetDef method_getset[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000590 {"__doc__", (getter)method_get_doc},
Antoine Pitrou9d574812011-12-12 13:47:25 +0100591 {"__qualname__", (getter)descr_get_qualname},
Larry Hastings5c661892014-01-24 06:17:25 -0800592 {"__text_signature__", (getter)method_get_text_signature},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000593 {0}
Guido van Rossum6f799372001-09-20 20:46:19 +0000594};
595
596static PyObject *
597member_get_doc(PyMemberDescrObject *descr, void *closure)
598{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000599 if (descr->d_member->doc == NULL) {
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200600 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000601 }
602 return PyUnicode_FromString(descr->d_member->doc);
Guido van Rossum6f799372001-09-20 20:46:19 +0000603}
604
Guido van Rossum32d34c82001-09-20 21:45:26 +0000605static PyGetSetDef member_getset[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000606 {"__doc__", (getter)member_get_doc},
Antoine Pitrou9d574812011-12-12 13:47:25 +0100607 {"__qualname__", (getter)descr_get_qualname},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000608 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +0000609};
610
611static PyObject *
Guido van Rossum32d34c82001-09-20 21:45:26 +0000612getset_get_doc(PyGetSetDescrObject *descr, void *closure)
613{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000614 if (descr->d_getset->doc == NULL) {
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200615 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000616 }
617 return PyUnicode_FromString(descr->d_getset->doc);
Guido van Rossum32d34c82001-09-20 21:45:26 +0000618}
619
620static PyGetSetDef getset_getset[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000621 {"__doc__", (getter)getset_get_doc},
Antoine Pitrou9d574812011-12-12 13:47:25 +0100622 {"__qualname__", (getter)descr_get_qualname},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000623 {0}
Guido van Rossum32d34c82001-09-20 21:45:26 +0000624};
625
626static PyObject *
Armin Rigoc6686b72005-11-07 08:38:00 +0000627wrapperdescr_get_doc(PyWrapperDescrObject *descr, void *closure)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000628{
Larry Hastings2623c8c2014-02-08 22:15:29 -0800629 return _PyType_GetDocFromInternalDoc(descr->d_base->name, descr->d_base->doc);
Larry Hastings5c661892014-01-24 06:17:25 -0800630}
631
632static PyObject *
633wrapperdescr_get_text_signature(PyWrapperDescrObject *descr, void *closure)
634{
Larry Hastings2623c8c2014-02-08 22:15:29 -0800635 return _PyType_GetTextSignatureFromInternalDoc(descr->d_base->name, descr->d_base->doc);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000636}
637
Armin Rigoc6686b72005-11-07 08:38:00 +0000638static PyGetSetDef wrapperdescr_getset[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000639 {"__doc__", (getter)wrapperdescr_get_doc},
Antoine Pitrou9d574812011-12-12 13:47:25 +0100640 {"__qualname__", (getter)descr_get_qualname},
Larry Hastings5c661892014-01-24 06:17:25 -0800641 {"__text_signature__", (getter)wrapperdescr_get_text_signature},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000642 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +0000643};
644
Guido van Rossum048eb752001-10-02 21:24:57 +0000645static int
646descr_traverse(PyObject *self, visitproc visit, void *arg)
647{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000648 PyDescrObject *descr = (PyDescrObject *)self;
649 Py_VISIT(descr->d_type);
650 return 0;
Guido van Rossum048eb752001-10-02 21:24:57 +0000651}
652
Christian Heimesa22e8bd2007-11-29 22:35:39 +0000653PyTypeObject PyMethodDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000654 PyVarObject_HEAD_INIT(&PyType_Type, 0)
655 "method_descriptor",
656 sizeof(PyMethodDescrObject),
657 0,
658 (destructor)descr_dealloc, /* tp_dealloc */
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200659 offsetof(PyMethodDescrObject, vectorcall), /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000660 0, /* tp_getattr */
661 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200662 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000663 (reprfunc)method_repr, /* tp_repr */
664 0, /* tp_as_number */
665 0, /* tp_as_sequence */
666 0, /* tp_as_mapping */
667 0, /* tp_hash */
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200668 PyVectorcall_Call, /* tp_call */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000669 0, /* tp_str */
670 PyObject_GenericGetAttr, /* tp_getattro */
671 0, /* tp_setattro */
672 0, /* tp_as_buffer */
Jeroen Demeyereb65e242019-05-28 14:42:53 +0200673 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200674 _Py_TPFLAGS_HAVE_VECTORCALL |
Jeroen Demeyereb65e242019-05-28 14:42:53 +0200675 Py_TPFLAGS_METHOD_DESCRIPTOR, /* tp_flags */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000676 0, /* tp_doc */
677 descr_traverse, /* tp_traverse */
678 0, /* tp_clear */
679 0, /* tp_richcompare */
680 0, /* tp_weaklistoffset */
681 0, /* tp_iter */
682 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100683 descr_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000684 descr_members, /* tp_members */
685 method_getset, /* tp_getset */
686 0, /* tp_base */
687 0, /* tp_dict */
688 (descrgetfunc)method_get, /* tp_descr_get */
689 0, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000690};
691
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +0000692/* This is for METH_CLASS in C, not for "f = classmethod(f)" in Python! */
Christian Heimesa22e8bd2007-11-29 22:35:39 +0000693PyTypeObject PyClassMethodDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000694 PyVarObject_HEAD_INIT(&PyType_Type, 0)
695 "classmethod_descriptor",
696 sizeof(PyMethodDescrObject),
697 0,
698 (destructor)descr_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200699 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000700 0, /* tp_getattr */
701 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200702 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000703 (reprfunc)method_repr, /* tp_repr */
704 0, /* tp_as_number */
705 0, /* tp_as_sequence */
706 0, /* tp_as_mapping */
707 0, /* tp_hash */
708 (ternaryfunc)classmethoddescr_call, /* tp_call */
709 0, /* tp_str */
710 PyObject_GenericGetAttr, /* tp_getattro */
711 0, /* tp_setattro */
712 0, /* tp_as_buffer */
713 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
714 0, /* tp_doc */
715 descr_traverse, /* tp_traverse */
716 0, /* tp_clear */
717 0, /* tp_richcompare */
718 0, /* tp_weaklistoffset */
719 0, /* tp_iter */
720 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100721 descr_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000722 descr_members, /* tp_members */
723 method_getset, /* tp_getset */
724 0, /* tp_base */
725 0, /* tp_dict */
726 (descrgetfunc)classmethod_get, /* tp_descr_get */
727 0, /* tp_descr_set */
Tim Petersbca1cbc2002-12-09 22:56:13 +0000728};
729
Christian Heimesa22e8bd2007-11-29 22:35:39 +0000730PyTypeObject PyMemberDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000731 PyVarObject_HEAD_INIT(&PyType_Type, 0)
732 "member_descriptor",
733 sizeof(PyMemberDescrObject),
734 0,
735 (destructor)descr_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200736 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000737 0, /* tp_getattr */
738 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200739 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000740 (reprfunc)member_repr, /* tp_repr */
741 0, /* tp_as_number */
742 0, /* tp_as_sequence */
743 0, /* tp_as_mapping */
744 0, /* tp_hash */
745 0, /* tp_call */
746 0, /* tp_str */
747 PyObject_GenericGetAttr, /* tp_getattro */
748 0, /* tp_setattro */
749 0, /* tp_as_buffer */
750 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
751 0, /* tp_doc */
752 descr_traverse, /* tp_traverse */
753 0, /* tp_clear */
754 0, /* tp_richcompare */
755 0, /* tp_weaklistoffset */
756 0, /* tp_iter */
757 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100758 descr_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000759 descr_members, /* tp_members */
760 member_getset, /* tp_getset */
761 0, /* tp_base */
762 0, /* tp_dict */
763 (descrgetfunc)member_get, /* tp_descr_get */
764 (descrsetfunc)member_set, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000765};
766
Christian Heimesa22e8bd2007-11-29 22:35:39 +0000767PyTypeObject PyGetSetDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000768 PyVarObject_HEAD_INIT(&PyType_Type, 0)
769 "getset_descriptor",
770 sizeof(PyGetSetDescrObject),
771 0,
772 (destructor)descr_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200773 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000774 0, /* tp_getattr */
775 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200776 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000777 (reprfunc)getset_repr, /* tp_repr */
778 0, /* tp_as_number */
779 0, /* tp_as_sequence */
780 0, /* tp_as_mapping */
781 0, /* tp_hash */
782 0, /* tp_call */
783 0, /* tp_str */
784 PyObject_GenericGetAttr, /* tp_getattro */
785 0, /* tp_setattro */
786 0, /* tp_as_buffer */
787 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
788 0, /* tp_doc */
789 descr_traverse, /* tp_traverse */
790 0, /* tp_clear */
791 0, /* tp_richcompare */
792 0, /* tp_weaklistoffset */
793 0, /* tp_iter */
794 0, /* tp_iternext */
795 0, /* tp_methods */
796 descr_members, /* tp_members */
797 getset_getset, /* tp_getset */
798 0, /* tp_base */
799 0, /* tp_dict */
800 (descrgetfunc)getset_get, /* tp_descr_get */
801 (descrsetfunc)getset_set, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000802};
803
Guido van Rossumf4593e02001-10-03 12:09:30 +0000804PyTypeObject PyWrapperDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000805 PyVarObject_HEAD_INIT(&PyType_Type, 0)
806 "wrapper_descriptor",
807 sizeof(PyWrapperDescrObject),
808 0,
809 (destructor)descr_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200810 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000811 0, /* tp_getattr */
812 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200813 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000814 (reprfunc)wrapperdescr_repr, /* tp_repr */
815 0, /* tp_as_number */
816 0, /* tp_as_sequence */
817 0, /* tp_as_mapping */
818 0, /* tp_hash */
819 (ternaryfunc)wrapperdescr_call, /* tp_call */
820 0, /* tp_str */
821 PyObject_GenericGetAttr, /* tp_getattro */
822 0, /* tp_setattro */
823 0, /* tp_as_buffer */
Jeroen Demeyereb65e242019-05-28 14:42:53 +0200824 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
825 Py_TPFLAGS_METHOD_DESCRIPTOR, /* tp_flags */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000826 0, /* tp_doc */
827 descr_traverse, /* tp_traverse */
828 0, /* tp_clear */
829 0, /* tp_richcompare */
830 0, /* tp_weaklistoffset */
831 0, /* tp_iter */
832 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100833 descr_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000834 descr_members, /* tp_members */
835 wrapperdescr_getset, /* tp_getset */
836 0, /* tp_base */
837 0, /* tp_dict */
838 (descrgetfunc)wrapperdescr_get, /* tp_descr_get */
839 0, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000840};
841
842static PyDescrObject *
Jeremy Hyltonaf68c872005-12-10 18:50:16 +0000843descr_new(PyTypeObject *descrtype, PyTypeObject *type, const char *name)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000844{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000845 PyDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000846
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000847 descr = (PyDescrObject *)PyType_GenericAlloc(descrtype, 0);
848 if (descr != NULL) {
849 Py_XINCREF(type);
850 descr->d_type = type;
851 descr->d_name = PyUnicode_InternFromString(name);
852 if (descr->d_name == NULL) {
853 Py_DECREF(descr);
854 descr = NULL;
855 }
Benjamin Petersonf2fe7f02011-12-17 08:02:20 -0500856 else {
857 descr->d_qualname = NULL;
858 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000859 }
860 return descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000861}
862
863PyObject *
864PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method)
865{
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200866 /* Figure out correct vectorcall function to use */
867 vectorcallfunc vectorcall;
868 switch (method->ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O | METH_KEYWORDS))
869 {
870 case METH_VARARGS:
871 vectorcall = method_vectorcall_VARARGS;
872 break;
873 case METH_VARARGS | METH_KEYWORDS:
874 vectorcall = method_vectorcall_VARARGS_KEYWORDS;
875 break;
876 case METH_FASTCALL:
877 vectorcall = method_vectorcall_FASTCALL;
878 break;
879 case METH_FASTCALL | METH_KEYWORDS:
880 vectorcall = method_vectorcall_FASTCALL_KEYWORDS;
881 break;
882 case METH_NOARGS:
883 vectorcall = method_vectorcall_NOARGS;
884 break;
885 case METH_O:
886 vectorcall = method_vectorcall_O;
887 break;
888 default:
889 PyErr_SetString(PyExc_SystemError, "bad call flags");
890 return NULL;
891 }
892
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000893 PyMethodDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000894
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000895 descr = (PyMethodDescrObject *)descr_new(&PyMethodDescr_Type,
896 type, method->ml_name);
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200897 if (descr != NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000898 descr->d_method = method;
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200899 descr->vectorcall = vectorcall;
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200900 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000901 return (PyObject *)descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000902}
903
904PyObject *
Tim Petersbca1cbc2002-12-09 22:56:13 +0000905PyDescr_NewClassMethod(PyTypeObject *type, PyMethodDef *method)
906{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000907 PyMethodDescrObject *descr;
Tim Petersbca1cbc2002-12-09 22:56:13 +0000908
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000909 descr = (PyMethodDescrObject *)descr_new(&PyClassMethodDescr_Type,
910 type, method->ml_name);
911 if (descr != NULL)
912 descr->d_method = method;
913 return (PyObject *)descr;
Tim Petersbca1cbc2002-12-09 22:56:13 +0000914}
915
916PyObject *
Guido van Rossum6f799372001-09-20 20:46:19 +0000917PyDescr_NewMember(PyTypeObject *type, PyMemberDef *member)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000918{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000919 PyMemberDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000920
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000921 descr = (PyMemberDescrObject *)descr_new(&PyMemberDescr_Type,
922 type, member->name);
923 if (descr != NULL)
924 descr->d_member = member;
925 return (PyObject *)descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000926}
927
928PyObject *
Guido van Rossum32d34c82001-09-20 21:45:26 +0000929PyDescr_NewGetSet(PyTypeObject *type, PyGetSetDef *getset)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000930{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000931 PyGetSetDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000932
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000933 descr = (PyGetSetDescrObject *)descr_new(&PyGetSetDescr_Type,
934 type, getset->name);
935 if (descr != NULL)
936 descr->d_getset = getset;
937 return (PyObject *)descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000938}
939
940PyObject *
941PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped)
942{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000943 PyWrapperDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000944
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000945 descr = (PyWrapperDescrObject *)descr_new(&PyWrapperDescr_Type,
946 type, base->name);
947 if (descr != NULL) {
948 descr->d_base = base;
949 descr->d_wrapped = wrapped;
950 }
951 return (PyObject *)descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000952}
953
Tim Peters6d6c1a32001-08-02 04:15:00 +0000954
Victor Stinner0db176f2012-04-16 00:16:30 +0200955/* --- mappingproxy: read-only proxy for mappings --- */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000956
957/* This has no reason to be in this file except that adding new files is a
958 bit of a pain */
959
960typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000961 PyObject_HEAD
Victor Stinner0db176f2012-04-16 00:16:30 +0200962 PyObject *mapping;
963} mappingproxyobject;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000964
Martin v. Löwis18e16552006-02-15 17:27:45 +0000965static Py_ssize_t
Victor Stinner0db176f2012-04-16 00:16:30 +0200966mappingproxy_len(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000967{
Victor Stinner0db176f2012-04-16 00:16:30 +0200968 return PyObject_Size(pp->mapping);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000969}
970
971static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +0200972mappingproxy_getitem(mappingproxyobject *pp, PyObject *key)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000973{
Victor Stinner0db176f2012-04-16 00:16:30 +0200974 return PyObject_GetItem(pp->mapping, key);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000975}
976
Victor Stinner0db176f2012-04-16 00:16:30 +0200977static PyMappingMethods mappingproxy_as_mapping = {
978 (lenfunc)mappingproxy_len, /* mp_length */
979 (binaryfunc)mappingproxy_getitem, /* mp_subscript */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000980 0, /* mp_ass_subscript */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000981};
982
983static int
Victor Stinner0db176f2012-04-16 00:16:30 +0200984mappingproxy_contains(mappingproxyobject *pp, PyObject *key)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000985{
Victor Stinner0db176f2012-04-16 00:16:30 +0200986 if (PyDict_CheckExact(pp->mapping))
987 return PyDict_Contains(pp->mapping, key);
988 else
989 return PySequence_Contains(pp->mapping, key);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000990}
991
Victor Stinner0db176f2012-04-16 00:16:30 +0200992static PySequenceMethods mappingproxy_as_sequence = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000993 0, /* sq_length */
994 0, /* sq_concat */
995 0, /* sq_repeat */
996 0, /* sq_item */
997 0, /* sq_slice */
998 0, /* sq_ass_item */
999 0, /* sq_ass_slice */
Victor Stinner0db176f2012-04-16 00:16:30 +02001000 (objobjproc)mappingproxy_contains, /* sq_contains */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001001 0, /* sq_inplace_concat */
1002 0, /* sq_inplace_repeat */
Tim Peters6d6c1a32001-08-02 04:15:00 +00001003};
1004
1005static PyObject *
Jeroen Demeyerb1263d52019-06-28 11:49:00 +02001006mappingproxy_get(mappingproxyobject *pp, PyObject *const *args, Py_ssize_t nargs)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001007{
Jeroen Demeyerb1263d52019-06-28 11:49:00 +02001008 /* newargs: mapping, key, default=None */
1009 PyObject *newargs[3];
1010 newargs[0] = pp->mapping;
1011 newargs[2] = Py_None;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001012
Jeroen Demeyerb1263d52019-06-28 11:49:00 +02001013 if (!_PyArg_UnpackStack(args, nargs, "get", 1, 2,
1014 &newargs[1], &newargs[2]))
1015 {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001016 return NULL;
Jeroen Demeyerb1263d52019-06-28 11:49:00 +02001017 }
1018 _Py_IDENTIFIER(get);
1019 return _PyObject_VectorcallMethodId(&PyId_get, newargs,
1020 3 | PY_VECTORCALL_ARGUMENTS_OFFSET,
1021 NULL);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001022}
1023
1024static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301025mappingproxy_keys(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001026{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001027 _Py_IDENTIFIER(keys);
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001028 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId_keys);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001029}
1030
1031static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301032mappingproxy_values(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001033{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001034 _Py_IDENTIFIER(values);
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001035 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId_values);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001036}
1037
1038static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301039mappingproxy_items(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001040{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001041 _Py_IDENTIFIER(items);
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001042 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId_items);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001043}
1044
1045static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301046mappingproxy_copy(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001047{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001048 _Py_IDENTIFIER(copy);
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001049 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId_copy);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001050}
1051
Victor Stinner0db176f2012-04-16 00:16:30 +02001052/* WARNING: mappingproxy methods must not give access
1053 to the underlying mapping */
1054
1055static PyMethodDef mappingproxy_methods[] = {
Zackery Spytz43d564c2019-08-13 23:51:06 -06001056 {"get", (PyCFunction)(void(*)(void))mappingproxy_get, METH_FASTCALL,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001057 PyDoc_STR("D.get(k[,d]) -> D[k] if k in D, else d."
Victor Stinner0db176f2012-04-16 00:16:30 +02001058 " d defaults to None.")},
1059 {"keys", (PyCFunction)mappingproxy_keys, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001060 PyDoc_STR("D.keys() -> list of D's keys")},
Victor Stinner0db176f2012-04-16 00:16:30 +02001061 {"values", (PyCFunction)mappingproxy_values, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001062 PyDoc_STR("D.values() -> list of D's values")},
Victor Stinner0db176f2012-04-16 00:16:30 +02001063 {"items", (PyCFunction)mappingproxy_items, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001064 PyDoc_STR("D.items() -> list of D's (key, value) pairs, as 2-tuples")},
Victor Stinner0db176f2012-04-16 00:16:30 +02001065 {"copy", (PyCFunction)mappingproxy_copy, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001066 PyDoc_STR("D.copy() -> a shallow copy of D")},
1067 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001068};
1069
1070static void
Victor Stinner0db176f2012-04-16 00:16:30 +02001071mappingproxy_dealloc(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001072{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001073 _PyObject_GC_UNTRACK(pp);
Victor Stinner0db176f2012-04-16 00:16:30 +02001074 Py_DECREF(pp->mapping);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001075 PyObject_GC_Del(pp);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001076}
1077
1078static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001079mappingproxy_getiter(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001080{
Victor Stinner0db176f2012-04-16 00:16:30 +02001081 return PyObject_GetIter(pp->mapping);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001082}
1083
Neil Schemenauer26775122001-10-21 22:26:43 +00001084static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001085mappingproxy_str(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001086{
Victor Stinner0db176f2012-04-16 00:16:30 +02001087 return PyObject_Str(pp->mapping);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001088}
1089
Ezio Melottiac53ab62010-12-18 14:59:43 +00001090static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001091mappingproxy_repr(mappingproxyobject *pp)
Ezio Melottiac53ab62010-12-18 14:59:43 +00001092{
Victor Stinner0db176f2012-04-16 00:16:30 +02001093 return PyUnicode_FromFormat("mappingproxy(%R)", pp->mapping);
Ezio Melottiac53ab62010-12-18 14:59:43 +00001094}
1095
Guido van Rossum048eb752001-10-02 21:24:57 +00001096static int
Victor Stinner0db176f2012-04-16 00:16:30 +02001097mappingproxy_traverse(PyObject *self, visitproc visit, void *arg)
Guido van Rossum048eb752001-10-02 21:24:57 +00001098{
Victor Stinner0db176f2012-04-16 00:16:30 +02001099 mappingproxyobject *pp = (mappingproxyobject *)self;
1100 Py_VISIT(pp->mapping);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001101 return 0;
Guido van Rossum048eb752001-10-02 21:24:57 +00001102}
1103
Raymond Hettinger29a6d442002-08-31 15:51:04 +00001104static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001105mappingproxy_richcompare(mappingproxyobject *v, PyObject *w, int op)
Raymond Hettinger29a6d442002-08-31 15:51:04 +00001106{
Victor Stinner0db176f2012-04-16 00:16:30 +02001107 return PyObject_RichCompare(v->mapping, w, op);
1108}
1109
1110static int
1111mappingproxy_check_mapping(PyObject *mapping)
1112{
1113 if (!PyMapping_Check(mapping)
1114 || PyList_Check(mapping)
1115 || PyTuple_Check(mapping)) {
1116 PyErr_Format(PyExc_TypeError,
1117 "mappingproxy() argument must be a mapping, not %s",
1118 Py_TYPE(mapping)->tp_name);
1119 return -1;
1120 }
1121 return 0;
1122}
1123
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001124/*[clinic input]
1125@classmethod
1126mappingproxy.__new__ as mappingproxy_new
Victor Stinner0db176f2012-04-16 00:16:30 +02001127
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001128 mapping: object
1129
1130[clinic start generated code]*/
1131
1132static PyObject *
1133mappingproxy_new_impl(PyTypeObject *type, PyObject *mapping)
1134/*[clinic end generated code: output=65f27f02d5b68fa7 input=d2d620d4f598d4f8]*/
1135{
1136 mappingproxyobject *mappingproxy;
Victor Stinner0db176f2012-04-16 00:16:30 +02001137
1138 if (mappingproxy_check_mapping(mapping) == -1)
1139 return NULL;
1140
1141 mappingproxy = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type);
1142 if (mappingproxy == NULL)
1143 return NULL;
1144 Py_INCREF(mapping);
1145 mappingproxy->mapping = mapping;
1146 _PyObject_GC_TRACK(mappingproxy);
1147 return (PyObject *)mappingproxy;
Raymond Hettinger29a6d442002-08-31 15:51:04 +00001148}
1149
Tim Peters6d6c1a32001-08-02 04:15:00 +00001150PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001151PyDictProxy_New(PyObject *mapping)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001152{
Victor Stinner0db176f2012-04-16 00:16:30 +02001153 mappingproxyobject *pp;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001154
Victor Stinner0db176f2012-04-16 00:16:30 +02001155 if (mappingproxy_check_mapping(mapping) == -1)
1156 return NULL;
1157
1158 pp = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001159 if (pp != NULL) {
Victor Stinner0db176f2012-04-16 00:16:30 +02001160 Py_INCREF(mapping);
1161 pp->mapping = mapping;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001162 _PyObject_GC_TRACK(pp);
1163 }
1164 return (PyObject *)pp;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001165}
1166
1167
1168/* --- Wrapper object for "slot" methods --- */
1169
1170/* This has no reason to be in this file except that adding new files is a
1171 bit of a pain */
1172
1173typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001174 PyObject_HEAD
1175 PyWrapperDescrObject *descr;
1176 PyObject *self;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001177} wrapperobject;
1178
Benjamin Petersoneff61f62011-09-01 16:32:31 -04001179#define Wrapper_Check(v) (Py_TYPE(v) == &_PyMethodWrapper_Type)
Mark Dickinson211c6252009-02-01 10:28:51 +00001180
Tim Peters6d6c1a32001-08-02 04:15:00 +00001181static void
1182wrapper_dealloc(wrapperobject *wp)
1183{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001184 PyObject_GC_UnTrack(wp);
Jeroen Demeyer351c6742019-05-10 19:21:11 +02001185 Py_TRASHCAN_BEGIN(wp, wrapper_dealloc)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001186 Py_XDECREF(wp->descr);
1187 Py_XDECREF(wp->self);
1188 PyObject_GC_Del(wp);
Jeroen Demeyer351c6742019-05-10 19:21:11 +02001189 Py_TRASHCAN_END
Tim Peters6d6c1a32001-08-02 04:15:00 +00001190}
1191
Mark Dickinson211c6252009-02-01 10:28:51 +00001192static PyObject *
1193wrapper_richcompare(PyObject *a, PyObject *b, int op)
Armin Rigoc6686b72005-11-07 08:38:00 +00001194{
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001195 wrapperobject *wa, *wb;
1196 int eq;
Mark Dickinson211c6252009-02-01 10:28:51 +00001197
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001198 assert(a != NULL && b != NULL);
Mark Dickinson211c6252009-02-01 10:28:51 +00001199
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001200 /* both arguments should be wrapperobjects */
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001201 if ((op != Py_EQ && op != Py_NE)
1202 || !Wrapper_Check(a) || !Wrapper_Check(b))
1203 {
stratakise8b19652017-11-02 11:32:54 +01001204 Py_RETURN_NOTIMPLEMENTED;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001205 }
Mark Dickinson211c6252009-02-01 10:28:51 +00001206
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001207 wa = (wrapperobject *)a;
1208 wb = (wrapperobject *)b;
1209 eq = (wa->descr == wb->descr && wa->self == wb->self);
1210 if (eq == (op == Py_EQ)) {
1211 Py_RETURN_TRUE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001212 }
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001213 else {
1214 Py_RETURN_FALSE;
1215 }
Armin Rigoc6686b72005-11-07 08:38:00 +00001216}
1217
Benjamin Peterson8f67d082010-10-17 20:54:53 +00001218static Py_hash_t
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001219wrapper_hash(wrapperobject *wp)
1220{
Benjamin Peterson8f67d082010-10-17 20:54:53 +00001221 Py_hash_t x, y;
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001222 x = _Py_HashPointer(wp->self);
1223 y = _Py_HashPointer(wp->descr);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001224 x = x ^ y;
1225 if (x == -1)
1226 x = -2;
1227 return x;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001228}
1229
Armin Rigoc6686b72005-11-07 08:38:00 +00001230static PyObject *
1231wrapper_repr(wrapperobject *wp)
1232{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001233 return PyUnicode_FromFormat("<method-wrapper '%s' of %s object at %p>",
1234 wp->descr->d_base->name,
1235 wp->self->ob_type->tp_name,
1236 wp->self);
Armin Rigoc6686b72005-11-07 08:38:00 +00001237}
1238
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001239static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301240wrapper_reduce(wrapperobject *wp, PyObject *Py_UNUSED(ignored))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001241{
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001242 _Py_IDENTIFIER(getattr);
Serhiy Storchakabb86bf42018-12-11 08:28:18 +02001243 return Py_BuildValue("N(OO)", _PyEval_GetBuiltinId(&PyId_getattr),
1244 wp->self, PyDescr_NAME(wp->descr));
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001245}
1246
1247static PyMethodDef wrapper_methods[] = {
1248 {"__reduce__", (PyCFunction)wrapper_reduce, METH_NOARGS, NULL},
1249 {NULL, NULL}
1250};
1251
Armin Rigoc6686b72005-11-07 08:38:00 +00001252static PyMemberDef wrapper_members[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001253 {"__self__", T_OBJECT, offsetof(wrapperobject, self), READONLY},
1254 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001255};
1256
1257static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001258wrapper_objclass(wrapperobject *wp, void *Py_UNUSED(ignored))
Armin Rigoc6686b72005-11-07 08:38:00 +00001259{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001260 PyObject *c = (PyObject *)PyDescr_TYPE(wp->descr);
Armin Rigoc6686b72005-11-07 08:38:00 +00001261
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001262 Py_INCREF(c);
1263 return c;
Armin Rigoc6686b72005-11-07 08:38:00 +00001264}
1265
1266static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001267wrapper_name(wrapperobject *wp, void *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001268{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001269 const char *s = wp->descr->d_base->name;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001270
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001271 return PyUnicode_FromString(s);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001272}
1273
1274static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001275wrapper_doc(wrapperobject *wp, void *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001276{
Larry Hastings2623c8c2014-02-08 22:15:29 -08001277 return _PyType_GetDocFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc);
Larry Hastings5c661892014-01-24 06:17:25 -08001278}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001279
Larry Hastings5c661892014-01-24 06:17:25 -08001280static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001281wrapper_text_signature(wrapperobject *wp, void *Py_UNUSED(ignored))
Larry Hastings5c661892014-01-24 06:17:25 -08001282{
Larry Hastings2623c8c2014-02-08 22:15:29 -08001283 return _PyType_GetTextSignatureFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001284}
1285
Antoine Pitrou9d574812011-12-12 13:47:25 +01001286static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001287wrapper_qualname(wrapperobject *wp, void *Py_UNUSED(ignored))
Antoine Pitrou9d574812011-12-12 13:47:25 +01001288{
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001289 return descr_get_qualname((PyDescrObject *)wp->descr, NULL);
Antoine Pitrou9d574812011-12-12 13:47:25 +01001290}
1291
Guido van Rossum32d34c82001-09-20 21:45:26 +00001292static PyGetSetDef wrapper_getsets[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001293 {"__objclass__", (getter)wrapper_objclass},
1294 {"__name__", (getter)wrapper_name},
Antoine Pitrou9d574812011-12-12 13:47:25 +01001295 {"__qualname__", (getter)wrapper_qualname},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001296 {"__doc__", (getter)wrapper_doc},
Larry Hastings5c661892014-01-24 06:17:25 -08001297 {"__text_signature__", (getter)wrapper_text_signature},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001298 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001299};
1300
1301static PyObject *
1302wrapper_call(wrapperobject *wp, PyObject *args, PyObject *kwds)
1303{
Serhiy Storchaka5e02c782017-09-21 14:25:36 +03001304 return wrapperdescr_raw_call(wp->descr, wp->self, args, kwds);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001305}
1306
Guido van Rossum048eb752001-10-02 21:24:57 +00001307static int
1308wrapper_traverse(PyObject *self, visitproc visit, void *arg)
1309{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001310 wrapperobject *wp = (wrapperobject *)self;
1311 Py_VISIT(wp->descr);
1312 Py_VISIT(wp->self);
1313 return 0;
Guido van Rossum048eb752001-10-02 21:24:57 +00001314}
1315
Benjamin Petersoneff61f62011-09-01 16:32:31 -04001316PyTypeObject _PyMethodWrapper_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001317 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1318 "method-wrapper", /* tp_name */
1319 sizeof(wrapperobject), /* tp_basicsize */
1320 0, /* tp_itemsize */
1321 /* methods */
1322 (destructor)wrapper_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001323 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001324 0, /* tp_getattr */
1325 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001326 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001327 (reprfunc)wrapper_repr, /* tp_repr */
1328 0, /* tp_as_number */
1329 0, /* tp_as_sequence */
1330 0, /* tp_as_mapping */
1331 (hashfunc)wrapper_hash, /* tp_hash */
1332 (ternaryfunc)wrapper_call, /* tp_call */
1333 0, /* tp_str */
1334 PyObject_GenericGetAttr, /* tp_getattro */
1335 0, /* tp_setattro */
1336 0, /* tp_as_buffer */
1337 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1338 0, /* tp_doc */
1339 wrapper_traverse, /* tp_traverse */
1340 0, /* tp_clear */
1341 wrapper_richcompare, /* tp_richcompare */
1342 0, /* tp_weaklistoffset */
1343 0, /* tp_iter */
1344 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001345 wrapper_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001346 wrapper_members, /* tp_members */
1347 wrapper_getsets, /* tp_getset */
1348 0, /* tp_base */
1349 0, /* tp_dict */
1350 0, /* tp_descr_get */
1351 0, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +00001352};
1353
1354PyObject *
1355PyWrapper_New(PyObject *d, PyObject *self)
1356{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001357 wrapperobject *wp;
1358 PyWrapperDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001359
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001360 assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type));
1361 descr = (PyWrapperDescrObject *)d;
Victor Stinner3249dec2011-05-01 23:19:15 +02001362 assert(_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
Victor Stinnerd9561312011-05-01 23:31:36 +02001363 (PyObject *)PyDescr_TYPE(descr)));
Tim Peters6d6c1a32001-08-02 04:15:00 +00001364
Benjamin Petersoneff61f62011-09-01 16:32:31 -04001365 wp = PyObject_GC_New(wrapperobject, &_PyMethodWrapper_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001366 if (wp != NULL) {
1367 Py_INCREF(descr);
1368 wp->descr = descr;
1369 Py_INCREF(self);
1370 wp->self = self;
1371 _PyObject_GC_TRACK(wp);
1372 }
1373 return (PyObject *)wp;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001374}
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001375
1376
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001377/* A built-in 'property' type */
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001378
1379/*
Serhiy Storchakad741a882015-06-11 00:06:39 +03001380class property(object):
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001381
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001382 def __init__(self, fget=None, fset=None, fdel=None, doc=None):
1383 if doc is None and fget is not None and hasattr(fget, "__doc__"):
Serhiy Storchakad741a882015-06-11 00:06:39 +03001384 doc = fget.__doc__
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001385 self.__get = fget
1386 self.__set = fset
1387 self.__del = fdel
1388 self.__doc__ = doc
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001389
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001390 def __get__(self, inst, type=None):
1391 if inst is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001392 return self
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001393 if self.__get is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001394 raise AttributeError, "unreadable attribute"
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001395 return self.__get(inst)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001396
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001397 def __set__(self, inst, value):
1398 if self.__set is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001399 raise AttributeError, "can't set attribute"
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001400 return self.__set(inst, value)
Guido van Rossumba2485f2001-12-10 18:03:34 +00001401
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001402 def __delete__(self, inst):
1403 if self.__del is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001404 raise AttributeError, "can't delete attribute"
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001405 return self.__del(inst)
Guido van Rossumba2485f2001-12-10 18:03:34 +00001406
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001407*/
1408
1409typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001410 PyObject_HEAD
1411 PyObject *prop_get;
1412 PyObject *prop_set;
1413 PyObject *prop_del;
1414 PyObject *prop_doc;
1415 int getter_doc;
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001416} propertyobject;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001417
Christian Heimes0449f632007-12-15 01:27:15 +00001418static PyObject * property_copy(PyObject *, PyObject *, PyObject *,
Benjamin Peterson93964832010-06-28 03:07:10 +00001419 PyObject *);
Christian Heimes0449f632007-12-15 01:27:15 +00001420
Tim Peters66c1a522001-09-24 21:17:50 +00001421static PyMemberDef property_members[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001422 {"fget", T_OBJECT, offsetof(propertyobject, prop_get), READONLY},
1423 {"fset", T_OBJECT, offsetof(propertyobject, prop_set), READONLY},
1424 {"fdel", T_OBJECT, offsetof(propertyobject, prop_del), READONLY},
Raymond Hettingereac503a2015-05-13 01:09:59 -07001425 {"__doc__", T_OBJECT, offsetof(propertyobject, prop_doc), 0},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001426 {0}
Tim Peters66c1a522001-09-24 21:17:50 +00001427};
1428
Christian Heimes0449f632007-12-15 01:27:15 +00001429
Guido van Rossum58da9312007-11-10 23:39:45 +00001430PyDoc_STRVAR(getter_doc,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001431 "Descriptor to change the getter on a property.");
Guido van Rossum58da9312007-11-10 23:39:45 +00001432
Neal Norwitz32dde222008-04-15 06:43:13 +00001433static PyObject *
Guido van Rossum58da9312007-11-10 23:39:45 +00001434property_getter(PyObject *self, PyObject *getter)
1435{
Benjamin Peterson93964832010-06-28 03:07:10 +00001436 return property_copy(self, getter, NULL, NULL);
Guido van Rossum58da9312007-11-10 23:39:45 +00001437}
1438
Christian Heimes0449f632007-12-15 01:27:15 +00001439
Guido van Rossum58da9312007-11-10 23:39:45 +00001440PyDoc_STRVAR(setter_doc,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001441 "Descriptor to change the setter on a property.");
Guido van Rossum58da9312007-11-10 23:39:45 +00001442
Neal Norwitz32dde222008-04-15 06:43:13 +00001443static PyObject *
Guido van Rossum58da9312007-11-10 23:39:45 +00001444property_setter(PyObject *self, PyObject *setter)
1445{
Benjamin Peterson93964832010-06-28 03:07:10 +00001446 return property_copy(self, NULL, setter, NULL);
Guido van Rossum58da9312007-11-10 23:39:45 +00001447}
1448
Christian Heimes0449f632007-12-15 01:27:15 +00001449
Guido van Rossum58da9312007-11-10 23:39:45 +00001450PyDoc_STRVAR(deleter_doc,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001451 "Descriptor to change the deleter on a property.");
Guido van Rossum58da9312007-11-10 23:39:45 +00001452
Neal Norwitz32dde222008-04-15 06:43:13 +00001453static PyObject *
Guido van Rossum58da9312007-11-10 23:39:45 +00001454property_deleter(PyObject *self, PyObject *deleter)
1455{
Benjamin Peterson93964832010-06-28 03:07:10 +00001456 return property_copy(self, NULL, NULL, deleter);
Guido van Rossum58da9312007-11-10 23:39:45 +00001457}
1458
1459
Guido van Rossum58da9312007-11-10 23:39:45 +00001460static PyMethodDef property_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001461 {"getter", property_getter, METH_O, getter_doc},
1462 {"setter", property_setter, METH_O, setter_doc},
1463 {"deleter", property_deleter, METH_O, deleter_doc},
1464 {0}
Guido van Rossum58da9312007-11-10 23:39:45 +00001465};
1466
Tim Peters66c1a522001-09-24 21:17:50 +00001467
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001468static void
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001469property_dealloc(PyObject *self)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001470{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001471 propertyobject *gs = (propertyobject *)self;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001472
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001473 _PyObject_GC_UNTRACK(self);
1474 Py_XDECREF(gs->prop_get);
1475 Py_XDECREF(gs->prop_set);
1476 Py_XDECREF(gs->prop_del);
1477 Py_XDECREF(gs->prop_doc);
1478 self->ob_type->tp_free(self);
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001479}
1480
1481static PyObject *
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001482property_descr_get(PyObject *self, PyObject *obj, PyObject *type)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001483{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001484 if (obj == NULL || obj == Py_None) {
1485 Py_INCREF(self);
1486 return self;
1487 }
Victor Stinnere972c132018-10-01 03:03:22 -07001488
1489 propertyobject *gs = (propertyobject *)self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001490 if (gs->prop_get == NULL) {
1491 PyErr_SetString(PyExc_AttributeError, "unreadable attribute");
1492 return NULL;
1493 }
Victor Stinnere972c132018-10-01 03:03:22 -07001494
Jeroen Demeyer196a5302019-07-04 12:31:34 +02001495 return _PyObject_CallOneArg(gs->prop_get, obj);
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001496}
1497
1498static int
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001499property_descr_set(PyObject *self, PyObject *obj, PyObject *value)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001500{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001501 propertyobject *gs = (propertyobject *)self;
1502 PyObject *func, *res;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001503
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001504 if (value == NULL)
1505 func = gs->prop_del;
1506 else
1507 func = gs->prop_set;
1508 if (func == NULL) {
1509 PyErr_SetString(PyExc_AttributeError,
1510 value == NULL ?
1511 "can't delete attribute" :
1512 "can't set attribute");
1513 return -1;
1514 }
1515 if (value == NULL)
Jeroen Demeyer196a5302019-07-04 12:31:34 +02001516 res = _PyObject_CallOneArg(func, obj);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001517 else
Benjamin Peterson9b955de2010-12-07 04:04:02 +00001518 res = PyObject_CallFunctionObjArgs(func, obj, value, NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001519 if (res == NULL)
1520 return -1;
1521 Py_DECREF(res);
1522 return 0;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001523}
1524
Christian Heimes0449f632007-12-15 01:27:15 +00001525static PyObject *
Benjamin Peterson93964832010-06-28 03:07:10 +00001526property_copy(PyObject *old, PyObject *get, PyObject *set, PyObject *del)
Christian Heimes0449f632007-12-15 01:27:15 +00001527{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001528 propertyobject *pold = (propertyobject *)old;
Benjamin Peterson93964832010-06-28 03:07:10 +00001529 PyObject *new, *type, *doc;
Christian Heimes0449f632007-12-15 01:27:15 +00001530
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001531 type = PyObject_Type(old);
1532 if (type == NULL)
1533 return NULL;
Christian Heimes0449f632007-12-15 01:27:15 +00001534
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001535 if (get == NULL || get == Py_None) {
1536 Py_XDECREF(get);
1537 get = pold->prop_get ? pold->prop_get : Py_None;
1538 }
1539 if (set == NULL || set == Py_None) {
1540 Py_XDECREF(set);
1541 set = pold->prop_set ? pold->prop_set : Py_None;
1542 }
1543 if (del == NULL || del == Py_None) {
1544 Py_XDECREF(del);
1545 del = pold->prop_del ? pold->prop_del : Py_None;
1546 }
Benjamin Peterson93964832010-06-28 03:07:10 +00001547 if (pold->getter_doc && get != Py_None) {
1548 /* make _init use __doc__ from getter */
1549 doc = Py_None;
1550 }
1551 else {
1552 doc = pold->prop_doc ? pold->prop_doc : Py_None;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001553 }
R. David Murrayb18500d2009-05-04 22:59:07 +00001554
Victor Stinner5abaa2b2016-12-09 16:22:32 +01001555 new = PyObject_CallFunctionObjArgs(type, get, set, del, doc, NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001556 Py_DECREF(type);
1557 if (new == NULL)
1558 return NULL;
1559 return new;
Christian Heimes0449f632007-12-15 01:27:15 +00001560}
1561
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001562/*[clinic input]
1563property.__init__ as property_init
1564
1565 fget: object(c_default="NULL") = None
1566 function to be used for getting an attribute value
1567 fset: object(c_default="NULL") = None
1568 function to be used for setting an attribute value
1569 fdel: object(c_default="NULL") = None
1570 function to be used for del'ing an attribute
1571 doc: object(c_default="NULL") = None
1572 docstring
1573
1574Property attribute.
1575
1576Typical use is to define a managed attribute x:
1577
1578class C(object):
1579 def getx(self): return self._x
1580 def setx(self, value): self._x = value
1581 def delx(self): del self._x
1582 x = property(getx, setx, delx, "I'm the 'x' property.")
1583
1584Decorators make defining new properties or modifying existing ones easy:
1585
1586class C(object):
1587 @property
1588 def x(self):
1589 "I am the 'x' property."
1590 return self._x
1591 @x.setter
1592 def x(self, value):
1593 self._x = value
1594 @x.deleter
1595 def x(self):
1596 del self._x
1597[clinic start generated code]*/
1598
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001599static int
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001600property_init_impl(propertyobject *self, PyObject *fget, PyObject *fset,
1601 PyObject *fdel, PyObject *doc)
1602/*[clinic end generated code: output=01a960742b692b57 input=dfb5dbbffc6932d5]*/
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001603{
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001604 if (fget == Py_None)
1605 fget = NULL;
1606 if (fset == Py_None)
1607 fset = NULL;
1608 if (fdel == Py_None)
1609 fdel = NULL;
Tim Peters66c1a522001-09-24 21:17:50 +00001610
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001611 Py_XINCREF(fget);
1612 Py_XINCREF(fset);
1613 Py_XINCREF(fdel);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001614 Py_XINCREF(doc);
Christian Heimes0449f632007-12-15 01:27:15 +00001615
Oren Milmand019bc82018-02-13 12:28:33 +02001616 Py_XSETREF(self->prop_get, fget);
1617 Py_XSETREF(self->prop_set, fset);
1618 Py_XSETREF(self->prop_del, fdel);
1619 Py_XSETREF(self->prop_doc, doc);
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001620 self->getter_doc = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001621
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001622 /* if no docstring given and the getter has one, use that one */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001623 if ((doc == NULL || doc == Py_None) && fget != NULL) {
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001624 _Py_IDENTIFIER(__doc__);
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001625 PyObject *get_doc;
1626 int rc = _PyObject_LookupAttrId(fget, &PyId___doc__, &get_doc);
1627 if (rc <= 0) {
1628 return rc;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001629 }
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001630 if (Py_TYPE(self) == &PyProperty_Type) {
1631 Py_XSETREF(self->prop_doc, get_doc);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001632 }
1633 else {
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001634 /* If this is a property subclass, put __doc__
1635 in dict of the subclass instance instead,
1636 otherwise it gets shadowed by __doc__ in the
1637 class's dict. */
1638 int err = _PyObject_SetAttrId((PyObject *)self, &PyId___doc__, get_doc);
1639 Py_DECREF(get_doc);
1640 if (err < 0)
1641 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001642 }
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001643 self->getter_doc = 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001644 }
1645
1646 return 0;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001647}
1648
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -05001649static PyObject *
1650property_get___isabstractmethod__(propertyobject *prop, void *closure)
1651{
1652 int res = _PyObject_IsAbstract(prop->prop_get);
1653 if (res == -1) {
1654 return NULL;
1655 }
1656 else if (res) {
1657 Py_RETURN_TRUE;
1658 }
1659
1660 res = _PyObject_IsAbstract(prop->prop_set);
1661 if (res == -1) {
1662 return NULL;
1663 }
1664 else if (res) {
1665 Py_RETURN_TRUE;
1666 }
1667
1668 res = _PyObject_IsAbstract(prop->prop_del);
1669 if (res == -1) {
1670 return NULL;
1671 }
1672 else if (res) {
1673 Py_RETURN_TRUE;
1674 }
1675 Py_RETURN_FALSE;
1676}
1677
1678static PyGetSetDef property_getsetlist[] = {
1679 {"__isabstractmethod__",
1680 (getter)property_get___isabstractmethod__, NULL,
1681 NULL,
1682 NULL},
1683 {NULL} /* Sentinel */
1684};
1685
Guido van Rossum048eb752001-10-02 21:24:57 +00001686static int
1687property_traverse(PyObject *self, visitproc visit, void *arg)
1688{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001689 propertyobject *pp = (propertyobject *)self;
1690 Py_VISIT(pp->prop_get);
1691 Py_VISIT(pp->prop_set);
1692 Py_VISIT(pp->prop_del);
1693 Py_VISIT(pp->prop_doc);
1694 return 0;
Guido van Rossum048eb752001-10-02 21:24:57 +00001695}
1696
Raymond Hettingerd4be6912015-05-13 11:12:33 -07001697static int
1698property_clear(PyObject *self)
1699{
1700 propertyobject *pp = (propertyobject *)self;
1701 Py_CLEAR(pp->prop_doc);
1702 return 0;
1703}
1704
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001705#include "clinic/descrobject.c.h"
1706
1707PyTypeObject PyDictProxy_Type = {
1708 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1709 "mappingproxy", /* tp_name */
1710 sizeof(mappingproxyobject), /* tp_basicsize */
1711 0, /* tp_itemsize */
1712 /* methods */
1713 (destructor)mappingproxy_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001714 0, /* tp_vectorcall_offset */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001715 0, /* tp_getattr */
1716 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001717 0, /* tp_as_async */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001718 (reprfunc)mappingproxy_repr, /* tp_repr */
1719 0, /* tp_as_number */
1720 &mappingproxy_as_sequence, /* tp_as_sequence */
1721 &mappingproxy_as_mapping, /* tp_as_mapping */
1722 0, /* tp_hash */
1723 0, /* tp_call */
1724 (reprfunc)mappingproxy_str, /* tp_str */
1725 PyObject_GenericGetAttr, /* tp_getattro */
1726 0, /* tp_setattro */
1727 0, /* tp_as_buffer */
1728 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1729 0, /* tp_doc */
1730 mappingproxy_traverse, /* tp_traverse */
1731 0, /* tp_clear */
1732 (richcmpfunc)mappingproxy_richcompare, /* tp_richcompare */
1733 0, /* tp_weaklistoffset */
1734 (getiterfunc)mappingproxy_getiter, /* tp_iter */
1735 0, /* tp_iternext */
1736 mappingproxy_methods, /* tp_methods */
1737 0, /* tp_members */
1738 0, /* tp_getset */
1739 0, /* tp_base */
1740 0, /* tp_dict */
1741 0, /* tp_descr_get */
1742 0, /* tp_descr_set */
1743 0, /* tp_dictoffset */
1744 0, /* tp_init */
1745 0, /* tp_alloc */
1746 mappingproxy_new, /* tp_new */
1747};
1748
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001749PyTypeObject PyProperty_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001750 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1751 "property", /* tp_name */
1752 sizeof(propertyobject), /* tp_basicsize */
1753 0, /* tp_itemsize */
1754 /* methods */
1755 property_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001756 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001757 0, /* tp_getattr */
1758 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001759 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001760 0, /* tp_repr */
1761 0, /* tp_as_number */
1762 0, /* tp_as_sequence */
1763 0, /* tp_as_mapping */
1764 0, /* tp_hash */
1765 0, /* tp_call */
1766 0, /* tp_str */
1767 PyObject_GenericGetAttr, /* tp_getattro */
1768 0, /* tp_setattro */
1769 0, /* tp_as_buffer */
1770 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1771 Py_TPFLAGS_BASETYPE, /* tp_flags */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001772 property_init__doc__, /* tp_doc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001773 property_traverse, /* tp_traverse */
Raymond Hettingerd4be6912015-05-13 11:12:33 -07001774 (inquiry)property_clear, /* tp_clear */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001775 0, /* tp_richcompare */
1776 0, /* tp_weaklistoffset */
1777 0, /* tp_iter */
1778 0, /* tp_iternext */
1779 property_methods, /* tp_methods */
1780 property_members, /* tp_members */
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -05001781 property_getsetlist, /* tp_getset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001782 0, /* tp_base */
1783 0, /* tp_dict */
1784 property_descr_get, /* tp_descr_get */
1785 property_descr_set, /* tp_descr_set */
1786 0, /* tp_dictoffset */
1787 property_init, /* tp_init */
1788 PyType_GenericAlloc, /* tp_alloc */
1789 PyType_GenericNew, /* tp_new */
1790 PyObject_GC_Del, /* tp_free */
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001791};