blob: c29cf7a4c44640d6c6f170779df204c1b8a9b27a [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 Stinnere5014be2020-04-14 17:52:15 +02004#include "pycore_ceval.h" // _Py_EnterRecursiveCall()
Victor Stinnerbcda8f12018-11-21 22:27:47 +01005#include "pycore_object.h"
Victor Stinnere5014be2020-04-14 17:52:15 +02006#include "pycore_pystate.h" // _PyThreadState_GET()
Victor Stinnerec13b932018-11-25 23:56:17 +01007#include "pycore_tupleobject.h"
Victor Stinner4a21e572020-04-15 02:35:41 +02008#include "structmember.h" // PyMemberDef
Tim Peters6d6c1a32001-08-02 04:15:00 +00009
Hai Shi46874c22020-01-30 17:20:25 -060010_Py_IDENTIFIER(getattr);
11
Serhiy Storchaka18b250f2017-03-19 08:51:07 +020012/*[clinic input]
13class mappingproxy "mappingproxyobject *" "&PyDictProxy_Type"
14class property "propertyobject *" "&PyProperty_Type"
15[clinic start generated code]*/
16/*[clinic end generated code: output=da39a3ee5e6b4b0d input=556352653fd4c02e]*/
17
Tim Peters6d6c1a32001-08-02 04:15:00 +000018static void
19descr_dealloc(PyDescrObject *descr)
20{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000021 _PyObject_GC_UNTRACK(descr);
22 Py_XDECREF(descr->d_type);
23 Py_XDECREF(descr->d_name);
Antoine Pitrou9d574812011-12-12 13:47:25 +010024 Py_XDECREF(descr->d_qualname);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000025 PyObject_GC_Del(descr);
Tim Peters6d6c1a32001-08-02 04:15:00 +000026}
27
Walter Dörwaldd7fb7642007-06-11 16:36:59 +000028static PyObject *
Tim Peters6d6c1a32001-08-02 04:15:00 +000029descr_name(PyDescrObject *descr)
30{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000031 if (descr->d_name != NULL && PyUnicode_Check(descr->d_name))
32 return descr->d_name;
33 return NULL;
Tim Peters6d6c1a32001-08-02 04:15:00 +000034}
35
36static PyObject *
Serhiy Storchakaef1585e2015-12-25 20:01:53 +020037descr_repr(PyDescrObject *descr, const char *format)
Tim Peters6d6c1a32001-08-02 04:15:00 +000038{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000039 PyObject *name = NULL;
40 if (descr->d_name != NULL && PyUnicode_Check(descr->d_name))
41 name = descr->d_name;
Walter Dörwaldd7fb7642007-06-11 16:36:59 +000042
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000043 return PyUnicode_FromFormat(format, name, "?", descr->d_type->tp_name);
Tim Peters6d6c1a32001-08-02 04:15:00 +000044}
45
46static PyObject *
47method_repr(PyMethodDescrObject *descr)
48{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000049 return descr_repr((PyDescrObject *)descr,
50 "<method '%V' of '%s' objects>");
Tim Peters6d6c1a32001-08-02 04:15:00 +000051}
52
53static PyObject *
54member_repr(PyMemberDescrObject *descr)
55{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000056 return descr_repr((PyDescrObject *)descr,
57 "<member '%V' of '%s' objects>");
Tim Peters6d6c1a32001-08-02 04:15:00 +000058}
59
60static PyObject *
61getset_repr(PyGetSetDescrObject *descr)
62{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000063 return descr_repr((PyDescrObject *)descr,
64 "<attribute '%V' of '%s' objects>");
Tim Peters6d6c1a32001-08-02 04:15:00 +000065}
66
67static PyObject *
Armin Rigoc6686b72005-11-07 08:38:00 +000068wrapperdescr_repr(PyWrapperDescrObject *descr)
Tim Peters6d6c1a32001-08-02 04:15:00 +000069{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000070 return descr_repr((PyDescrObject *)descr,
71 "<slot wrapper '%V' of '%s' objects>");
Tim Peters6d6c1a32001-08-02 04:15:00 +000072}
73
74static int
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +000075descr_check(PyDescrObject *descr, PyObject *obj, PyObject **pres)
Tim Peters6d6c1a32001-08-02 04:15:00 +000076{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000077 if (obj == NULL) {
78 Py_INCREF(descr);
79 *pres = (PyObject *)descr;
80 return 1;
81 }
82 if (!PyObject_TypeCheck(obj, descr->d_type)) {
83 PyErr_Format(PyExc_TypeError,
Inada Naoki62f95882019-04-01 17:56:11 +090084 "descriptor '%V' for '%.100s' objects "
85 "doesn't apply to a '%.100s' object",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000086 descr_name((PyDescrObject *)descr), "?",
87 descr->d_type->tp_name,
Victor Stinner58ac7002020-02-07 03:04:21 +010088 Py_TYPE(obj)->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000089 *pres = NULL;
90 return 1;
91 }
92 return 0;
Tim Peters6d6c1a32001-08-02 04:15:00 +000093}
94
95static PyObject *
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +000096classmethod_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type)
Tim Petersbca1cbc2002-12-09 22:56:13 +000097{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000098 /* Ensure a valid type. Class methods ignore obj. */
99 if (type == NULL) {
100 if (obj != NULL)
Victor Stinner58ac7002020-02-07 03:04:21 +0100101 type = (PyObject *)Py_TYPE(obj);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000102 else {
103 /* Wot - no type?! */
104 PyErr_Format(PyExc_TypeError,
Inada Naoki62f95882019-04-01 17:56:11 +0900105 "descriptor '%V' for type '%.100s' "
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000106 "needs either an object or a type",
107 descr_name((PyDescrObject *)descr), "?",
108 PyDescr_TYPE(descr)->tp_name);
109 return NULL;
110 }
111 }
112 if (!PyType_Check(type)) {
113 PyErr_Format(PyExc_TypeError,
Inada Naoki62f95882019-04-01 17:56:11 +0900114 "descriptor '%V' for type '%.100s' "
115 "needs a type, not a '%.100s' as arg 2",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000116 descr_name((PyDescrObject *)descr), "?",
117 PyDescr_TYPE(descr)->tp_name,
Victor Stinner58ac7002020-02-07 03:04:21 +0100118 Py_TYPE(type)->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000119 return NULL;
120 }
121 if (!PyType_IsSubtype((PyTypeObject *)type, PyDescr_TYPE(descr))) {
122 PyErr_Format(PyExc_TypeError,
Inada Naoki62f95882019-04-01 17:56:11 +0900123 "descriptor '%V' requires a subtype of '%.100s' "
124 "but received '%.100s'",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000125 descr_name((PyDescrObject *)descr), "?",
126 PyDescr_TYPE(descr)->tp_name,
127 ((PyTypeObject *)type)->tp_name);
128 return NULL;
129 }
Petr Viktorine1becf42020-05-07 15:39:59 +0200130 PyTypeObject *cls = NULL;
131 if (descr->d_method->ml_flags & METH_METHOD) {
132 cls = descr->d_common.d_type;
133 }
134 return PyCMethod_New(descr->d_method, type, NULL, cls);
Tim Petersbca1cbc2002-12-09 22:56:13 +0000135}
136
137static PyObject *
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +0000138method_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000139{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000140 PyObject *res;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000141
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000142 if (descr_check((PyDescrObject *)descr, obj, &res))
143 return res;
Petr Viktorine1becf42020-05-07 15:39:59 +0200144 if (descr->d_method->ml_flags & METH_METHOD) {
145 if (PyType_Check(type)) {
146 return PyCMethod_New(descr->d_method, obj, NULL, descr->d_common.d_type);
147 } else {
148 PyErr_Format(PyExc_TypeError,
149 "descriptor '%V' needs a type, not '%s', as arg 2",
150 descr_name((PyDescrObject *)descr),
151 Py_TYPE(type)->tp_name);
152 return NULL;
153 }
154 } else {
155 return PyCFunction_NewEx(descr->d_method, obj, NULL);
156 }
Tim Peters6d6c1a32001-08-02 04:15:00 +0000157}
158
159static PyObject *
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +0000160member_get(PyMemberDescrObject *descr, PyObject *obj, PyObject *type)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000161{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000162 PyObject *res;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000163
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000164 if (descr_check((PyDescrObject *)descr, obj, &res))
165 return res;
Steve Dowerb82e17e2019-05-23 08:45:22 -0700166
167 if (descr->d_member->flags & READ_RESTRICTED) {
168 if (PySys_Audit("object.__getattr__", "Os",
169 obj ? obj : Py_None, descr->d_member->name) < 0) {
170 return NULL;
171 }
172 }
173
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000174 return PyMember_GetOne((char *)obj, descr->d_member);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000175}
176
177static PyObject *
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +0000178getset_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *type)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000179{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000180 PyObject *res;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000181
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000182 if (descr_check((PyDescrObject *)descr, obj, &res))
183 return res;
184 if (descr->d_getset->get != NULL)
185 return descr->d_getset->get(obj, descr->d_getset->closure);
186 PyErr_Format(PyExc_AttributeError,
187 "attribute '%V' of '%.100s' objects is not readable",
188 descr_name((PyDescrObject *)descr), "?",
189 PyDescr_TYPE(descr)->tp_name);
190 return NULL;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000191}
192
193static PyObject *
Armin Rigoc6686b72005-11-07 08:38:00 +0000194wrapperdescr_get(PyWrapperDescrObject *descr, PyObject *obj, PyObject *type)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000195{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000196 PyObject *res;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000197
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000198 if (descr_check((PyDescrObject *)descr, obj, &res))
199 return res;
200 return PyWrapper_New((PyObject *)descr, obj);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000201}
202
203static int
204descr_setcheck(PyDescrObject *descr, PyObject *obj, PyObject *value,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000205 int *pres)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000206{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000207 assert(obj != NULL);
208 if (!PyObject_TypeCheck(obj, descr->d_type)) {
209 PyErr_Format(PyExc_TypeError,
210 "descriptor '%V' for '%.100s' objects "
Inada Naoki62f95882019-04-01 17:56:11 +0900211 "doesn't apply to a '%.100s' object",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000212 descr_name(descr), "?",
213 descr->d_type->tp_name,
Victor Stinner58ac7002020-02-07 03:04:21 +0100214 Py_TYPE(obj)->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000215 *pres = -1;
216 return 1;
217 }
218 return 0;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000219}
220
221static int
222member_set(PyMemberDescrObject *descr, PyObject *obj, PyObject *value)
223{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000224 int res;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000225
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000226 if (descr_setcheck((PyDescrObject *)descr, obj, value, &res))
227 return res;
228 return PyMember_SetOne((char *)obj, descr->d_member, value);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000229}
230
231static int
232getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value)
233{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000234 int res;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000235
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000236 if (descr_setcheck((PyDescrObject *)descr, obj, value, &res))
237 return res;
238 if (descr->d_getset->set != NULL)
239 return descr->d_getset->set(obj, value,
240 descr->d_getset->closure);
241 PyErr_Format(PyExc_AttributeError,
242 "attribute '%V' of '%.100s' objects is not writable",
243 descr_name((PyDescrObject *)descr), "?",
244 PyDescr_TYPE(descr)->tp_name);
245 return -1;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000246}
247
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200248
249/* Vectorcall functions for each of the PyMethodDescr calling conventions.
250 *
251 * First, common helpers
252 */
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200253static inline int
254method_check_args(PyObject *func, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
255{
256 assert(!PyErr_Occurred());
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200257 if (nargs < 1) {
Jeroen Demeyerbf17d412019-11-05 16:48:04 +0100258 PyObject *funcstr = _PyObject_FunctionStr(func);
259 if (funcstr != NULL) {
260 PyErr_Format(PyExc_TypeError,
261 "unbound method %U needs an argument", funcstr);
262 Py_DECREF(funcstr);
263 }
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200264 return -1;
265 }
266 PyObject *self = args[0];
Jeroen Demeyerbf17d412019-11-05 16:48:04 +0100267 PyObject *dummy;
268 if (descr_check((PyDescrObject *)func, self, &dummy)) {
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200269 return -1;
270 }
271 if (kwnames && PyTuple_GET_SIZE(kwnames)) {
Jeroen Demeyerbf17d412019-11-05 16:48:04 +0100272 PyObject *funcstr = _PyObject_FunctionStr(func);
273 if (funcstr != NULL) {
274 PyErr_Format(PyExc_TypeError,
275 "%U takes no keyword arguments", funcstr);
276 Py_DECREF(funcstr);
277 }
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200278 return -1;
279 }
280 return 0;
281}
282
Jeroen Demeyerbf17d412019-11-05 16:48:04 +0100283typedef void (*funcptr)(void);
284
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200285static inline funcptr
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100286method_enter_call(PyThreadState *tstate, PyObject *func)
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200287{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100288 if (_Py_EnterRecursiveCall(tstate, " while calling a Python object")) {
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200289 return NULL;
290 }
291 return (funcptr)((PyMethodDescrObject *)func)->d_method->ml_meth;
292}
293
294/* Now the actual vectorcall functions */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000295static PyObject *
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200296method_vectorcall_VARARGS(
297 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000298{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100299 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200300 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200301 if (method_check_args(func, args, nargs, kwnames)) {
INADA Naoki5566bbb2017-02-03 07:43:03 +0900302 return NULL;
303 }
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200304 PyObject *argstuple = _PyTuple_FromArray(args+1, nargs-1);
305 if (argstuple == NULL) {
INADA Naoki5566bbb2017-02-03 07:43:03 +0900306 return NULL;
307 }
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100308 PyCFunction meth = (PyCFunction)method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200309 if (meth == NULL) {
310 Py_DECREF(argstuple);
311 return NULL;
312 }
313 PyObject *result = meth(args[0], argstuple);
314 Py_DECREF(argstuple);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100315 _Py_LeaveRecursiveCall(tstate);
INADA Naoki5566bbb2017-02-03 07:43:03 +0900316 return result;
317}
318
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200319static PyObject *
320method_vectorcall_VARARGS_KEYWORDS(
321 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
322{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100323 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200324 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
325 if (method_check_args(func, args, nargs, NULL)) {
326 return NULL;
327 }
328 PyObject *argstuple = _PyTuple_FromArray(args+1, nargs-1);
329 if (argstuple == NULL) {
330 return NULL;
331 }
332 PyObject *result = NULL;
333 /* Create a temporary dict for keyword arguments */
334 PyObject *kwdict = NULL;
335 if (kwnames != NULL && PyTuple_GET_SIZE(kwnames) > 0) {
336 kwdict = _PyStack_AsDict(args + nargs, kwnames);
337 if (kwdict == NULL) {
338 goto exit;
339 }
340 }
341 PyCFunctionWithKeywords meth = (PyCFunctionWithKeywords)
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100342 method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200343 if (meth == NULL) {
344 goto exit;
345 }
346 result = meth(args[0], argstuple, kwdict);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100347 _Py_LeaveRecursiveCall(tstate);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200348exit:
349 Py_DECREF(argstuple);
350 Py_XDECREF(kwdict);
351 return result;
352}
353
354static PyObject *
Petr Viktorine1becf42020-05-07 15:39:59 +0200355method_vectorcall_FASTCALL_KEYWORDS_METHOD(
356 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
357{
358 PyThreadState *tstate = _PyThreadState_GET();
359 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
360 if (method_check_args(func, args, nargs, NULL)) {
361 return NULL;
362 }
363 NULL;
364 PyCMethod meth = (PyCMethod) method_enter_call(tstate, func);
365 if (meth == NULL) {
366 return NULL;
367 }
368 PyObject *result = meth(args[0],
369 ((PyMethodDescrObject *)func)->d_common.d_type,
370 args+1, nargs-1, kwnames);
371 Py_LeaveRecursiveCall();
372 return result;
373}
374
375static PyObject *
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200376method_vectorcall_FASTCALL(
377 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
378{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100379 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200380 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
381 if (method_check_args(func, args, nargs, kwnames)) {
382 return NULL;
383 }
384 _PyCFunctionFast meth = (_PyCFunctionFast)
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100385 method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200386 if (meth == NULL) {
387 return NULL;
388 }
389 PyObject *result = meth(args[0], args+1, nargs-1);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100390 _Py_LeaveRecursiveCall(tstate);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200391 return result;
392}
393
394static PyObject *
395method_vectorcall_FASTCALL_KEYWORDS(
396 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
397{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100398 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200399 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
400 if (method_check_args(func, args, nargs, NULL)) {
401 return NULL;
402 }
403 _PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords)
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100404 method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200405 if (meth == NULL) {
406 return NULL;
407 }
408 PyObject *result = meth(args[0], args+1, nargs-1, kwnames);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100409 _Py_LeaveRecursiveCall(tstate);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200410 return result;
411}
412
413static PyObject *
414method_vectorcall_NOARGS(
415 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
416{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100417 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200418 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
419 if (method_check_args(func, args, nargs, kwnames)) {
420 return NULL;
421 }
422 if (nargs != 1) {
Jeroen Demeyerbf17d412019-11-05 16:48:04 +0100423 PyObject *funcstr = _PyObject_FunctionStr(func);
424 if (funcstr != NULL) {
425 PyErr_Format(PyExc_TypeError,
426 "%U takes no arguments (%zd given)", funcstr, nargs-1);
427 Py_DECREF(funcstr);
428 }
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200429 return NULL;
430 }
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100431 PyCFunction meth = (PyCFunction)method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200432 if (meth == NULL) {
433 return NULL;
434 }
435 PyObject *result = meth(args[0], NULL);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100436 _Py_LeaveRecursiveCall(tstate);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200437 return result;
438}
439
440static PyObject *
441method_vectorcall_O(
442 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
443{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100444 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200445 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
446 if (method_check_args(func, args, nargs, kwnames)) {
447 return NULL;
448 }
449 if (nargs != 2) {
Jeroen Demeyerbf17d412019-11-05 16:48:04 +0100450 PyObject *funcstr = _PyObject_FunctionStr(func);
451 if (funcstr != NULL) {
452 PyErr_Format(PyExc_TypeError,
453 "%U takes exactly one argument (%zd given)",
454 funcstr, nargs-1);
455 Py_DECREF(funcstr);
456 }
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200457 return NULL;
458 }
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100459 PyCFunction meth = (PyCFunction)method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200460 if (meth == NULL) {
461 return NULL;
462 }
463 PyObject *result = meth(args[0], args[1]);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100464 _Py_LeaveRecursiveCall(tstate);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200465 return result;
466}
467
468
Jeroen Demeyer3f345c32019-06-07 12:20:24 +0200469/* Instances of classmethod_descriptor are unlikely to be called directly.
470 For one, the analogous class "classmethod" (for Python classes) is not
471 callable. Second, users are not likely to access a classmethod_descriptor
472 directly, since it means pulling it from the class __dict__.
473
474 This is just an excuse to say that this doesn't need to be optimized:
475 we implement this simply by calling __get__ and then calling the result.
476*/
Tim Peters6d6c1a32001-08-02 04:15:00 +0000477static PyObject *
Tim Petersbca1cbc2002-12-09 22:56:13 +0000478classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000479 PyObject *kwds)
Tim Petersbca1cbc2002-12-09 22:56:13 +0000480{
Jeroen Demeyer3f345c32019-06-07 12:20:24 +0200481 Py_ssize_t argc = PyTuple_GET_SIZE(args);
Benjamin Peterson7295c6a2012-05-01 09:51:09 -0400482 if (argc < 1) {
483 PyErr_Format(PyExc_TypeError,
484 "descriptor '%V' of '%.100s' "
485 "object needs an argument",
486 descr_name((PyDescrObject *)descr), "?",
487 PyDescr_TYPE(descr)->tp_name);
488 return NULL;
489 }
Jeroen Demeyer3f345c32019-06-07 12:20:24 +0200490 PyObject *self = PyTuple_GET_ITEM(args, 0);
491 PyObject *bound = classmethod_get(descr, NULL, self);
492 if (bound == NULL) {
Benjamin Peterson7295c6a2012-05-01 09:51:09 -0400493 return NULL;
494 }
Petr Viktorinffd97532020-02-11 17:46:57 +0100495 PyObject *res = PyObject_VectorcallDict(bound, _PyTuple_ITEMS(args)+1,
Jeroen Demeyer3f345c32019-06-07 12:20:24 +0200496 argc-1, kwds);
497 Py_DECREF(bound);
498 return res;
Tim Petersbca1cbc2002-12-09 22:56:13 +0000499}
500
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300501Py_LOCAL_INLINE(PyObject *)
502wrapperdescr_raw_call(PyWrapperDescrObject *descr, PyObject *self,
503 PyObject *args, PyObject *kwds)
504{
505 wrapperfunc wrapper = descr->d_base->wrapper;
506
507 if (descr->d_base->flags & PyWrapperFlag_KEYWORDS) {
Serhiy Storchaka1c607152018-11-27 21:34:27 +0200508 wrapperfunc_kwds wk = (wrapperfunc_kwds)(void(*)(void))wrapper;
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300509 return (*wk)(self, args, descr->d_wrapped, kwds);
510 }
511
512 if (kwds != NULL && (!PyDict_Check(kwds) || PyDict_GET_SIZE(kwds) != 0)) {
513 PyErr_Format(PyExc_TypeError,
514 "wrapper %s() takes no keyword arguments",
515 descr->d_base->name);
516 return NULL;
517 }
518 return (*wrapper)(self, args, descr->d_wrapped);
519}
520
Tim Petersbca1cbc2002-12-09 22:56:13 +0000521static PyObject *
Tim Peters6d6c1a32001-08-02 04:15:00 +0000522wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
523{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000524 Py_ssize_t argc;
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300525 PyObject *self, *result;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000526
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000527 /* Make sure that the first argument is acceptable as 'self' */
528 assert(PyTuple_Check(args));
529 argc = PyTuple_GET_SIZE(args);
530 if (argc < 1) {
531 PyErr_Format(PyExc_TypeError,
532 "descriptor '%V' of '%.100s' "
533 "object needs an argument",
534 descr_name((PyDescrObject *)descr), "?",
535 PyDescr_TYPE(descr)->tp_name);
536 return NULL;
537 }
538 self = PyTuple_GET_ITEM(args, 0);
Victor Stinner3249dec2011-05-01 23:19:15 +0200539 if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
Victor Stinnerd9561312011-05-01 23:31:36 +0200540 (PyObject *)PyDescr_TYPE(descr))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000541 PyErr_Format(PyExc_TypeError,
542 "descriptor '%V' "
543 "requires a '%.100s' object "
544 "but received a '%.100s'",
545 descr_name((PyDescrObject *)descr), "?",
546 PyDescr_TYPE(descr)->tp_name,
Victor Stinner58ac7002020-02-07 03:04:21 +0100547 Py_TYPE(self)->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000548 return NULL;
549 }
Tim Peters6d6c1a32001-08-02 04:15:00 +0000550
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300551 args = PyTuple_GetSlice(args, 1, argc);
552 if (args == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000553 return NULL;
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300554 }
555 result = wrapperdescr_raw_call(descr, self, args, kwds);
556 Py_DECREF(args);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000557 return result;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000558}
559
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300560
Tim Peters6d6c1a32001-08-02 04:15:00 +0000561static PyObject *
Guido van Rossum6f799372001-09-20 20:46:19 +0000562method_get_doc(PyMethodDescrObject *descr, void *closure)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000563{
Larry Hastings2623c8c2014-02-08 22:15:29 -0800564 return _PyType_GetDocFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc);
Larry Hastings5c661892014-01-24 06:17:25 -0800565}
566
567static PyObject *
568method_get_text_signature(PyMethodDescrObject *descr, void *closure)
569{
Larry Hastings2623c8c2014-02-08 22:15:29 -0800570 return _PyType_GetTextSignatureFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000571}
572
Antoine Pitrou9d574812011-12-12 13:47:25 +0100573static PyObject *
574calculate_qualname(PyDescrObject *descr)
575{
576 PyObject *type_qualname, *res;
577 _Py_IDENTIFIER(__qualname__);
578
579 if (descr->d_name == NULL || !PyUnicode_Check(descr->d_name)) {
580 PyErr_SetString(PyExc_TypeError,
581 "<descriptor>.__name__ is not a unicode object");
582 return NULL;
583 }
584
585 type_qualname = _PyObject_GetAttrId((PyObject *)descr->d_type,
586 &PyId___qualname__);
587 if (type_qualname == NULL)
588 return NULL;
589
590 if (!PyUnicode_Check(type_qualname)) {
591 PyErr_SetString(PyExc_TypeError, "<descriptor>.__objclass__."
592 "__qualname__ is not a unicode object");
593 Py_XDECREF(type_qualname);
594 return NULL;
595 }
596
597 res = PyUnicode_FromFormat("%S.%S", type_qualname, descr->d_name);
598 Py_DECREF(type_qualname);
599 return res;
600}
601
602static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +0200603descr_get_qualname(PyDescrObject *descr, void *Py_UNUSED(ignored))
Antoine Pitrou9d574812011-12-12 13:47:25 +0100604{
605 if (descr->d_qualname == NULL)
606 descr->d_qualname = calculate_qualname(descr);
607 Py_XINCREF(descr->d_qualname);
608 return descr->d_qualname;
609}
610
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100611static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530612descr_reduce(PyDescrObject *descr, PyObject *Py_UNUSED(ignored))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100613{
Serhiy Storchakabb86bf42018-12-11 08:28:18 +0200614 return Py_BuildValue("N(OO)", _PyEval_GetBuiltinId(&PyId_getattr),
615 PyDescr_TYPE(descr), PyDescr_NAME(descr));
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100616}
617
618static PyMethodDef descr_methods[] = {
619 {"__reduce__", (PyCFunction)descr_reduce, METH_NOARGS, NULL},
620 {NULL, NULL}
621};
622
Guido van Rossum6f799372001-09-20 20:46:19 +0000623static PyMemberDef descr_members[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000624 {"__objclass__", T_OBJECT, offsetof(PyDescrObject, d_type), READONLY},
625 {"__name__", T_OBJECT, offsetof(PyDescrObject, d_name), READONLY},
626 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +0000627};
628
Guido van Rossum32d34c82001-09-20 21:45:26 +0000629static PyGetSetDef method_getset[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000630 {"__doc__", (getter)method_get_doc},
Antoine Pitrou9d574812011-12-12 13:47:25 +0100631 {"__qualname__", (getter)descr_get_qualname},
Larry Hastings5c661892014-01-24 06:17:25 -0800632 {"__text_signature__", (getter)method_get_text_signature},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000633 {0}
Guido van Rossum6f799372001-09-20 20:46:19 +0000634};
635
636static PyObject *
637member_get_doc(PyMemberDescrObject *descr, void *closure)
638{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000639 if (descr->d_member->doc == NULL) {
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200640 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000641 }
642 return PyUnicode_FromString(descr->d_member->doc);
Guido van Rossum6f799372001-09-20 20:46:19 +0000643}
644
Guido van Rossum32d34c82001-09-20 21:45:26 +0000645static PyGetSetDef member_getset[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000646 {"__doc__", (getter)member_get_doc},
Antoine Pitrou9d574812011-12-12 13:47:25 +0100647 {"__qualname__", (getter)descr_get_qualname},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000648 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +0000649};
650
651static PyObject *
Guido van Rossum32d34c82001-09-20 21:45:26 +0000652getset_get_doc(PyGetSetDescrObject *descr, void *closure)
653{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000654 if (descr->d_getset->doc == NULL) {
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200655 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000656 }
657 return PyUnicode_FromString(descr->d_getset->doc);
Guido van Rossum32d34c82001-09-20 21:45:26 +0000658}
659
660static PyGetSetDef getset_getset[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000661 {"__doc__", (getter)getset_get_doc},
Antoine Pitrou9d574812011-12-12 13:47:25 +0100662 {"__qualname__", (getter)descr_get_qualname},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000663 {0}
Guido van Rossum32d34c82001-09-20 21:45:26 +0000664};
665
666static PyObject *
Armin Rigoc6686b72005-11-07 08:38:00 +0000667wrapperdescr_get_doc(PyWrapperDescrObject *descr, void *closure)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000668{
Larry Hastings2623c8c2014-02-08 22:15:29 -0800669 return _PyType_GetDocFromInternalDoc(descr->d_base->name, descr->d_base->doc);
Larry Hastings5c661892014-01-24 06:17:25 -0800670}
671
672static PyObject *
673wrapperdescr_get_text_signature(PyWrapperDescrObject *descr, void *closure)
674{
Larry Hastings2623c8c2014-02-08 22:15:29 -0800675 return _PyType_GetTextSignatureFromInternalDoc(descr->d_base->name, descr->d_base->doc);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000676}
677
Armin Rigoc6686b72005-11-07 08:38:00 +0000678static PyGetSetDef wrapperdescr_getset[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000679 {"__doc__", (getter)wrapperdescr_get_doc},
Antoine Pitrou9d574812011-12-12 13:47:25 +0100680 {"__qualname__", (getter)descr_get_qualname},
Larry Hastings5c661892014-01-24 06:17:25 -0800681 {"__text_signature__", (getter)wrapperdescr_get_text_signature},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000682 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +0000683};
684
Guido van Rossum048eb752001-10-02 21:24:57 +0000685static int
686descr_traverse(PyObject *self, visitproc visit, void *arg)
687{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000688 PyDescrObject *descr = (PyDescrObject *)self;
689 Py_VISIT(descr->d_type);
690 return 0;
Guido van Rossum048eb752001-10-02 21:24:57 +0000691}
692
Christian Heimesa22e8bd2007-11-29 22:35:39 +0000693PyTypeObject PyMethodDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000694 PyVarObject_HEAD_INIT(&PyType_Type, 0)
695 "method_descriptor",
696 sizeof(PyMethodDescrObject),
697 0,
698 (destructor)descr_dealloc, /* tp_dealloc */
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200699 offsetof(PyMethodDescrObject, vectorcall), /* 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 */
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200708 PyVectorcall_Call, /* tp_call */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000709 0, /* tp_str */
710 PyObject_GenericGetAttr, /* tp_getattro */
711 0, /* tp_setattro */
712 0, /* tp_as_buffer */
Jeroen Demeyereb65e242019-05-28 14:42:53 +0200713 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Petr Viktorinffd97532020-02-11 17:46:57 +0100714 Py_TPFLAGS_HAVE_VECTORCALL |
Jeroen Demeyereb65e242019-05-28 14:42:53 +0200715 Py_TPFLAGS_METHOD_DESCRIPTOR, /* tp_flags */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000716 0, /* tp_doc */
717 descr_traverse, /* tp_traverse */
718 0, /* tp_clear */
719 0, /* tp_richcompare */
720 0, /* tp_weaklistoffset */
721 0, /* tp_iter */
722 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100723 descr_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000724 descr_members, /* tp_members */
725 method_getset, /* tp_getset */
726 0, /* tp_base */
727 0, /* tp_dict */
728 (descrgetfunc)method_get, /* tp_descr_get */
729 0, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000730};
731
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +0000732/* This is for METH_CLASS in C, not for "f = classmethod(f)" in Python! */
Christian Heimesa22e8bd2007-11-29 22:35:39 +0000733PyTypeObject PyClassMethodDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000734 PyVarObject_HEAD_INIT(&PyType_Type, 0)
735 "classmethod_descriptor",
736 sizeof(PyMethodDescrObject),
737 0,
738 (destructor)descr_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200739 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000740 0, /* tp_getattr */
741 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200742 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000743 (reprfunc)method_repr, /* tp_repr */
744 0, /* tp_as_number */
745 0, /* tp_as_sequence */
746 0, /* tp_as_mapping */
747 0, /* tp_hash */
748 (ternaryfunc)classmethoddescr_call, /* tp_call */
749 0, /* tp_str */
750 PyObject_GenericGetAttr, /* tp_getattro */
751 0, /* tp_setattro */
752 0, /* tp_as_buffer */
753 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
754 0, /* tp_doc */
755 descr_traverse, /* tp_traverse */
756 0, /* tp_clear */
757 0, /* tp_richcompare */
758 0, /* tp_weaklistoffset */
759 0, /* tp_iter */
760 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100761 descr_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000762 descr_members, /* tp_members */
763 method_getset, /* tp_getset */
764 0, /* tp_base */
765 0, /* tp_dict */
766 (descrgetfunc)classmethod_get, /* tp_descr_get */
767 0, /* tp_descr_set */
Tim Petersbca1cbc2002-12-09 22:56:13 +0000768};
769
Christian Heimesa22e8bd2007-11-29 22:35:39 +0000770PyTypeObject PyMemberDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000771 PyVarObject_HEAD_INIT(&PyType_Type, 0)
772 "member_descriptor",
773 sizeof(PyMemberDescrObject),
774 0,
775 (destructor)descr_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200776 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000777 0, /* tp_getattr */
778 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200779 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000780 (reprfunc)member_repr, /* tp_repr */
781 0, /* tp_as_number */
782 0, /* tp_as_sequence */
783 0, /* tp_as_mapping */
784 0, /* tp_hash */
785 0, /* tp_call */
786 0, /* tp_str */
787 PyObject_GenericGetAttr, /* tp_getattro */
788 0, /* tp_setattro */
789 0, /* tp_as_buffer */
790 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
791 0, /* tp_doc */
792 descr_traverse, /* tp_traverse */
793 0, /* tp_clear */
794 0, /* tp_richcompare */
795 0, /* tp_weaklistoffset */
796 0, /* tp_iter */
797 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100798 descr_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000799 descr_members, /* tp_members */
800 member_getset, /* tp_getset */
801 0, /* tp_base */
802 0, /* tp_dict */
803 (descrgetfunc)member_get, /* tp_descr_get */
804 (descrsetfunc)member_set, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000805};
806
Christian Heimesa22e8bd2007-11-29 22:35:39 +0000807PyTypeObject PyGetSetDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000808 PyVarObject_HEAD_INIT(&PyType_Type, 0)
809 "getset_descriptor",
810 sizeof(PyGetSetDescrObject),
811 0,
812 (destructor)descr_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200813 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000814 0, /* tp_getattr */
815 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200816 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000817 (reprfunc)getset_repr, /* tp_repr */
818 0, /* tp_as_number */
819 0, /* tp_as_sequence */
820 0, /* tp_as_mapping */
821 0, /* tp_hash */
822 0, /* tp_call */
823 0, /* tp_str */
824 PyObject_GenericGetAttr, /* tp_getattro */
825 0, /* tp_setattro */
826 0, /* tp_as_buffer */
827 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
828 0, /* tp_doc */
829 descr_traverse, /* tp_traverse */
830 0, /* tp_clear */
831 0, /* tp_richcompare */
832 0, /* tp_weaklistoffset */
833 0, /* tp_iter */
834 0, /* tp_iternext */
835 0, /* tp_methods */
836 descr_members, /* tp_members */
837 getset_getset, /* tp_getset */
838 0, /* tp_base */
839 0, /* tp_dict */
840 (descrgetfunc)getset_get, /* tp_descr_get */
841 (descrsetfunc)getset_set, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000842};
843
Guido van Rossumf4593e02001-10-03 12:09:30 +0000844PyTypeObject PyWrapperDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000845 PyVarObject_HEAD_INIT(&PyType_Type, 0)
846 "wrapper_descriptor",
847 sizeof(PyWrapperDescrObject),
848 0,
849 (destructor)descr_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200850 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000851 0, /* tp_getattr */
852 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200853 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000854 (reprfunc)wrapperdescr_repr, /* tp_repr */
855 0, /* tp_as_number */
856 0, /* tp_as_sequence */
857 0, /* tp_as_mapping */
858 0, /* tp_hash */
859 (ternaryfunc)wrapperdescr_call, /* tp_call */
860 0, /* tp_str */
861 PyObject_GenericGetAttr, /* tp_getattro */
862 0, /* tp_setattro */
863 0, /* tp_as_buffer */
Jeroen Demeyereb65e242019-05-28 14:42:53 +0200864 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
865 Py_TPFLAGS_METHOD_DESCRIPTOR, /* tp_flags */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000866 0, /* tp_doc */
867 descr_traverse, /* tp_traverse */
868 0, /* tp_clear */
869 0, /* tp_richcompare */
870 0, /* tp_weaklistoffset */
871 0, /* tp_iter */
872 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100873 descr_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000874 descr_members, /* tp_members */
875 wrapperdescr_getset, /* tp_getset */
876 0, /* tp_base */
877 0, /* tp_dict */
878 (descrgetfunc)wrapperdescr_get, /* tp_descr_get */
879 0, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000880};
881
882static PyDescrObject *
Jeremy Hyltonaf68c872005-12-10 18:50:16 +0000883descr_new(PyTypeObject *descrtype, PyTypeObject *type, const char *name)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000884{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000885 PyDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000886
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000887 descr = (PyDescrObject *)PyType_GenericAlloc(descrtype, 0);
888 if (descr != NULL) {
889 Py_XINCREF(type);
890 descr->d_type = type;
891 descr->d_name = PyUnicode_InternFromString(name);
892 if (descr->d_name == NULL) {
893 Py_DECREF(descr);
894 descr = NULL;
895 }
Benjamin Petersonf2fe7f02011-12-17 08:02:20 -0500896 else {
897 descr->d_qualname = NULL;
898 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000899 }
900 return descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000901}
902
903PyObject *
904PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method)
905{
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200906 /* Figure out correct vectorcall function to use */
907 vectorcallfunc vectorcall;
Petr Viktorine1becf42020-05-07 15:39:59 +0200908 switch (method->ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS |
909 METH_O | METH_KEYWORDS | METH_METHOD))
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200910 {
911 case METH_VARARGS:
912 vectorcall = method_vectorcall_VARARGS;
913 break;
914 case METH_VARARGS | METH_KEYWORDS:
915 vectorcall = method_vectorcall_VARARGS_KEYWORDS;
916 break;
917 case METH_FASTCALL:
918 vectorcall = method_vectorcall_FASTCALL;
919 break;
920 case METH_FASTCALL | METH_KEYWORDS:
921 vectorcall = method_vectorcall_FASTCALL_KEYWORDS;
922 break;
923 case METH_NOARGS:
924 vectorcall = method_vectorcall_NOARGS;
925 break;
926 case METH_O:
927 vectorcall = method_vectorcall_O;
928 break;
Petr Viktorine1becf42020-05-07 15:39:59 +0200929 case METH_METHOD | METH_FASTCALL | METH_KEYWORDS:
930 vectorcall = method_vectorcall_FASTCALL_KEYWORDS_METHOD;
931 break;
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200932 default:
Victor Stinnerc7d2d692020-03-12 08:38:11 +0100933 PyErr_Format(PyExc_SystemError,
934 "%s() method: bad call flags", method->ml_name);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200935 return NULL;
936 }
937
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000938 PyMethodDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000939
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000940 descr = (PyMethodDescrObject *)descr_new(&PyMethodDescr_Type,
941 type, method->ml_name);
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200942 if (descr != NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000943 descr->d_method = method;
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200944 descr->vectorcall = vectorcall;
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200945 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000946 return (PyObject *)descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000947}
948
949PyObject *
Tim Petersbca1cbc2002-12-09 22:56:13 +0000950PyDescr_NewClassMethod(PyTypeObject *type, PyMethodDef *method)
951{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000952 PyMethodDescrObject *descr;
Tim Petersbca1cbc2002-12-09 22:56:13 +0000953
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000954 descr = (PyMethodDescrObject *)descr_new(&PyClassMethodDescr_Type,
955 type, method->ml_name);
956 if (descr != NULL)
957 descr->d_method = method;
958 return (PyObject *)descr;
Tim Petersbca1cbc2002-12-09 22:56:13 +0000959}
960
961PyObject *
Guido van Rossum6f799372001-09-20 20:46:19 +0000962PyDescr_NewMember(PyTypeObject *type, PyMemberDef *member)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000963{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000964 PyMemberDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000965
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000966 descr = (PyMemberDescrObject *)descr_new(&PyMemberDescr_Type,
967 type, member->name);
968 if (descr != NULL)
969 descr->d_member = member;
970 return (PyObject *)descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000971}
972
973PyObject *
Guido van Rossum32d34c82001-09-20 21:45:26 +0000974PyDescr_NewGetSet(PyTypeObject *type, PyGetSetDef *getset)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000975{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000976 PyGetSetDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000977
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000978 descr = (PyGetSetDescrObject *)descr_new(&PyGetSetDescr_Type,
979 type, getset->name);
980 if (descr != NULL)
981 descr->d_getset = getset;
982 return (PyObject *)descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000983}
984
985PyObject *
986PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped)
987{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000988 PyWrapperDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000989
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000990 descr = (PyWrapperDescrObject *)descr_new(&PyWrapperDescr_Type,
991 type, base->name);
992 if (descr != NULL) {
993 descr->d_base = base;
994 descr->d_wrapped = wrapped;
995 }
996 return (PyObject *)descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000997}
998
Tim Peters6d6c1a32001-08-02 04:15:00 +0000999
Victor Stinner0db176f2012-04-16 00:16:30 +02001000/* --- mappingproxy: read-only proxy for mappings --- */
Tim Peters6d6c1a32001-08-02 04:15:00 +00001001
1002/* This has no reason to be in this file except that adding new files is a
1003 bit of a pain */
1004
1005typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001006 PyObject_HEAD
Victor Stinner0db176f2012-04-16 00:16:30 +02001007 PyObject *mapping;
1008} mappingproxyobject;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001009
Martin v. Löwis18e16552006-02-15 17:27:45 +00001010static Py_ssize_t
Victor Stinner0db176f2012-04-16 00:16:30 +02001011mappingproxy_len(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001012{
Victor Stinner0db176f2012-04-16 00:16:30 +02001013 return PyObject_Size(pp->mapping);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001014}
1015
1016static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001017mappingproxy_getitem(mappingproxyobject *pp, PyObject *key)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001018{
Victor Stinner0db176f2012-04-16 00:16:30 +02001019 return PyObject_GetItem(pp->mapping, key);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001020}
1021
Victor Stinner0db176f2012-04-16 00:16:30 +02001022static PyMappingMethods mappingproxy_as_mapping = {
1023 (lenfunc)mappingproxy_len, /* mp_length */
1024 (binaryfunc)mappingproxy_getitem, /* mp_subscript */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001025 0, /* mp_ass_subscript */
Tim Peters6d6c1a32001-08-02 04:15:00 +00001026};
1027
Brandt Bucher4663f662020-03-07 11:03:09 -08001028static PyObject *
1029mappingproxy_or(PyObject *left, PyObject *right)
1030{
1031 if (PyObject_TypeCheck(left, &PyDictProxy_Type)) {
1032 left = ((mappingproxyobject*)left)->mapping;
1033 }
1034 if (PyObject_TypeCheck(right, &PyDictProxy_Type)) {
1035 right = ((mappingproxyobject*)right)->mapping;
1036 }
1037 return PyNumber_Or(left, right);
1038}
1039
1040static PyObject *
1041mappingproxy_ior(PyObject *self, PyObject *Py_UNUSED(other))
1042{
1043 return PyErr_Format(PyExc_TypeError,
1044 "'|=' is not supported by %s; use '|' instead", Py_TYPE(self)->tp_name);
1045}
1046
1047static PyNumberMethods mappingproxy_as_number = {
1048 .nb_or = mappingproxy_or,
1049 .nb_inplace_or = mappingproxy_ior,
1050};
1051
Tim Peters6d6c1a32001-08-02 04:15:00 +00001052static int
Victor Stinner0db176f2012-04-16 00:16:30 +02001053mappingproxy_contains(mappingproxyobject *pp, PyObject *key)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001054{
Victor Stinner0db176f2012-04-16 00:16:30 +02001055 if (PyDict_CheckExact(pp->mapping))
1056 return PyDict_Contains(pp->mapping, key);
1057 else
1058 return PySequence_Contains(pp->mapping, key);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001059}
1060
Victor Stinner0db176f2012-04-16 00:16:30 +02001061static PySequenceMethods mappingproxy_as_sequence = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001062 0, /* sq_length */
1063 0, /* sq_concat */
1064 0, /* sq_repeat */
1065 0, /* sq_item */
1066 0, /* sq_slice */
1067 0, /* sq_ass_item */
1068 0, /* sq_ass_slice */
Victor Stinner0db176f2012-04-16 00:16:30 +02001069 (objobjproc)mappingproxy_contains, /* sq_contains */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001070 0, /* sq_inplace_concat */
1071 0, /* sq_inplace_repeat */
Tim Peters6d6c1a32001-08-02 04:15:00 +00001072};
1073
1074static PyObject *
Jeroen Demeyerb1263d52019-06-28 11:49:00 +02001075mappingproxy_get(mappingproxyobject *pp, PyObject *const *args, Py_ssize_t nargs)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001076{
Jeroen Demeyerb1263d52019-06-28 11:49:00 +02001077 /* newargs: mapping, key, default=None */
1078 PyObject *newargs[3];
1079 newargs[0] = pp->mapping;
1080 newargs[2] = Py_None;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001081
Jeroen Demeyerb1263d52019-06-28 11:49:00 +02001082 if (!_PyArg_UnpackStack(args, nargs, "get", 1, 2,
1083 &newargs[1], &newargs[2]))
1084 {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001085 return NULL;
Jeroen Demeyerb1263d52019-06-28 11:49:00 +02001086 }
1087 _Py_IDENTIFIER(get);
1088 return _PyObject_VectorcallMethodId(&PyId_get, newargs,
1089 3 | PY_VECTORCALL_ARGUMENTS_OFFSET,
1090 NULL);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001091}
1092
1093static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301094mappingproxy_keys(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001095{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001096 _Py_IDENTIFIER(keys);
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001097 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId_keys);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001098}
1099
1100static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301101mappingproxy_values(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001102{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001103 _Py_IDENTIFIER(values);
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001104 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId_values);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001105}
1106
1107static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301108mappingproxy_items(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001109{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001110 _Py_IDENTIFIER(items);
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001111 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId_items);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001112}
1113
1114static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301115mappingproxy_copy(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001116{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001117 _Py_IDENTIFIER(copy);
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001118 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId_copy);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001119}
1120
Zackery Spytz02fa0ea2020-05-07 23:25:50 -06001121static PyObject *
1122mappingproxy_reversed(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
1123{
1124 _Py_IDENTIFIER(__reversed__);
1125 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId___reversed__);
1126}
1127
Victor Stinner0db176f2012-04-16 00:16:30 +02001128/* WARNING: mappingproxy methods must not give access
1129 to the underlying mapping */
1130
1131static PyMethodDef mappingproxy_methods[] = {
Zackery Spytz43d564c2019-08-13 23:51:06 -06001132 {"get", (PyCFunction)(void(*)(void))mappingproxy_get, METH_FASTCALL,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001133 PyDoc_STR("D.get(k[,d]) -> D[k] if k in D, else d."
Victor Stinner0db176f2012-04-16 00:16:30 +02001134 " d defaults to None.")},
1135 {"keys", (PyCFunction)mappingproxy_keys, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001136 PyDoc_STR("D.keys() -> list of D's keys")},
Victor Stinner0db176f2012-04-16 00:16:30 +02001137 {"values", (PyCFunction)mappingproxy_values, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001138 PyDoc_STR("D.values() -> list of D's values")},
Victor Stinner0db176f2012-04-16 00:16:30 +02001139 {"items", (PyCFunction)mappingproxy_items, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001140 PyDoc_STR("D.items() -> list of D's (key, value) pairs, as 2-tuples")},
Victor Stinner0db176f2012-04-16 00:16:30 +02001141 {"copy", (PyCFunction)mappingproxy_copy, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001142 PyDoc_STR("D.copy() -> a shallow copy of D")},
Guido van Rossum48b069a2020-04-07 09:50:06 -07001143 {"__class_getitem__", (PyCFunction)Py_GenericAlias, METH_O|METH_CLASS,
1144 PyDoc_STR("See PEP 585")},
Zackery Spytz02fa0ea2020-05-07 23:25:50 -06001145 {"__reversed__", (PyCFunction)mappingproxy_reversed, METH_NOARGS,
1146 PyDoc_STR("D.__reversed__() -> reverse iterator")},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001147 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001148};
1149
1150static void
Victor Stinner0db176f2012-04-16 00:16:30 +02001151mappingproxy_dealloc(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001152{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001153 _PyObject_GC_UNTRACK(pp);
Victor Stinner0db176f2012-04-16 00:16:30 +02001154 Py_DECREF(pp->mapping);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001155 PyObject_GC_Del(pp);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001156}
1157
1158static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001159mappingproxy_getiter(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001160{
Victor Stinner0db176f2012-04-16 00:16:30 +02001161 return PyObject_GetIter(pp->mapping);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001162}
1163
Neil Schemenauer26775122001-10-21 22:26:43 +00001164static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001165mappingproxy_str(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001166{
Victor Stinner0db176f2012-04-16 00:16:30 +02001167 return PyObject_Str(pp->mapping);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001168}
1169
Ezio Melottiac53ab62010-12-18 14:59:43 +00001170static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001171mappingproxy_repr(mappingproxyobject *pp)
Ezio Melottiac53ab62010-12-18 14:59:43 +00001172{
Victor Stinner0db176f2012-04-16 00:16:30 +02001173 return PyUnicode_FromFormat("mappingproxy(%R)", pp->mapping);
Ezio Melottiac53ab62010-12-18 14:59:43 +00001174}
1175
Guido van Rossum048eb752001-10-02 21:24:57 +00001176static int
Victor Stinner0db176f2012-04-16 00:16:30 +02001177mappingproxy_traverse(PyObject *self, visitproc visit, void *arg)
Guido van Rossum048eb752001-10-02 21:24:57 +00001178{
Victor Stinner0db176f2012-04-16 00:16:30 +02001179 mappingproxyobject *pp = (mappingproxyobject *)self;
1180 Py_VISIT(pp->mapping);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001181 return 0;
Guido van Rossum048eb752001-10-02 21:24:57 +00001182}
1183
Raymond Hettinger29a6d442002-08-31 15:51:04 +00001184static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001185mappingproxy_richcompare(mappingproxyobject *v, PyObject *w, int op)
Raymond Hettinger29a6d442002-08-31 15:51:04 +00001186{
Victor Stinner0db176f2012-04-16 00:16:30 +02001187 return PyObject_RichCompare(v->mapping, w, op);
1188}
1189
1190static int
1191mappingproxy_check_mapping(PyObject *mapping)
1192{
1193 if (!PyMapping_Check(mapping)
1194 || PyList_Check(mapping)
1195 || PyTuple_Check(mapping)) {
1196 PyErr_Format(PyExc_TypeError,
1197 "mappingproxy() argument must be a mapping, not %s",
1198 Py_TYPE(mapping)->tp_name);
1199 return -1;
1200 }
1201 return 0;
1202}
1203
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001204/*[clinic input]
1205@classmethod
1206mappingproxy.__new__ as mappingproxy_new
Victor Stinner0db176f2012-04-16 00:16:30 +02001207
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001208 mapping: object
1209
1210[clinic start generated code]*/
1211
1212static PyObject *
1213mappingproxy_new_impl(PyTypeObject *type, PyObject *mapping)
1214/*[clinic end generated code: output=65f27f02d5b68fa7 input=d2d620d4f598d4f8]*/
1215{
1216 mappingproxyobject *mappingproxy;
Victor Stinner0db176f2012-04-16 00:16:30 +02001217
1218 if (mappingproxy_check_mapping(mapping) == -1)
1219 return NULL;
1220
1221 mappingproxy = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type);
1222 if (mappingproxy == NULL)
1223 return NULL;
1224 Py_INCREF(mapping);
1225 mappingproxy->mapping = mapping;
1226 _PyObject_GC_TRACK(mappingproxy);
1227 return (PyObject *)mappingproxy;
Raymond Hettinger29a6d442002-08-31 15:51:04 +00001228}
1229
Tim Peters6d6c1a32001-08-02 04:15:00 +00001230PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001231PyDictProxy_New(PyObject *mapping)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001232{
Victor Stinner0db176f2012-04-16 00:16:30 +02001233 mappingproxyobject *pp;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001234
Victor Stinner0db176f2012-04-16 00:16:30 +02001235 if (mappingproxy_check_mapping(mapping) == -1)
1236 return NULL;
1237
1238 pp = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001239 if (pp != NULL) {
Victor Stinner0db176f2012-04-16 00:16:30 +02001240 Py_INCREF(mapping);
1241 pp->mapping = mapping;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001242 _PyObject_GC_TRACK(pp);
1243 }
1244 return (PyObject *)pp;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001245}
1246
1247
1248/* --- Wrapper object for "slot" methods --- */
1249
1250/* This has no reason to be in this file except that adding new files is a
1251 bit of a pain */
1252
1253typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001254 PyObject_HEAD
1255 PyWrapperDescrObject *descr;
1256 PyObject *self;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001257} wrapperobject;
1258
Andy Lesterdffe4c02020-03-04 07:15:20 -06001259#define Wrapper_Check(v) Py_IS_TYPE(v, &_PyMethodWrapper_Type)
Mark Dickinson211c6252009-02-01 10:28:51 +00001260
Tim Peters6d6c1a32001-08-02 04:15:00 +00001261static void
1262wrapper_dealloc(wrapperobject *wp)
1263{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001264 PyObject_GC_UnTrack(wp);
Jeroen Demeyer351c6742019-05-10 19:21:11 +02001265 Py_TRASHCAN_BEGIN(wp, wrapper_dealloc)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001266 Py_XDECREF(wp->descr);
1267 Py_XDECREF(wp->self);
1268 PyObject_GC_Del(wp);
Jeroen Demeyer351c6742019-05-10 19:21:11 +02001269 Py_TRASHCAN_END
Tim Peters6d6c1a32001-08-02 04:15:00 +00001270}
1271
Mark Dickinson211c6252009-02-01 10:28:51 +00001272static PyObject *
1273wrapper_richcompare(PyObject *a, PyObject *b, int op)
Armin Rigoc6686b72005-11-07 08:38:00 +00001274{
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001275 wrapperobject *wa, *wb;
1276 int eq;
Mark Dickinson211c6252009-02-01 10:28:51 +00001277
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001278 assert(a != NULL && b != NULL);
Mark Dickinson211c6252009-02-01 10:28:51 +00001279
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001280 /* both arguments should be wrapperobjects */
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001281 if ((op != Py_EQ && op != Py_NE)
1282 || !Wrapper_Check(a) || !Wrapper_Check(b))
1283 {
stratakise8b19652017-11-02 11:32:54 +01001284 Py_RETURN_NOTIMPLEMENTED;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001285 }
Mark Dickinson211c6252009-02-01 10:28:51 +00001286
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001287 wa = (wrapperobject *)a;
1288 wb = (wrapperobject *)b;
1289 eq = (wa->descr == wb->descr && wa->self == wb->self);
1290 if (eq == (op == Py_EQ)) {
1291 Py_RETURN_TRUE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001292 }
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001293 else {
1294 Py_RETURN_FALSE;
1295 }
Armin Rigoc6686b72005-11-07 08:38:00 +00001296}
1297
Benjamin Peterson8f67d082010-10-17 20:54:53 +00001298static Py_hash_t
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001299wrapper_hash(wrapperobject *wp)
1300{
Benjamin Peterson8f67d082010-10-17 20:54:53 +00001301 Py_hash_t x, y;
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001302 x = _Py_HashPointer(wp->self);
1303 y = _Py_HashPointer(wp->descr);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001304 x = x ^ y;
1305 if (x == -1)
1306 x = -2;
1307 return x;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001308}
1309
Armin Rigoc6686b72005-11-07 08:38:00 +00001310static PyObject *
1311wrapper_repr(wrapperobject *wp)
1312{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001313 return PyUnicode_FromFormat("<method-wrapper '%s' of %s object at %p>",
1314 wp->descr->d_base->name,
Victor Stinner58ac7002020-02-07 03:04:21 +01001315 Py_TYPE(wp->self)->tp_name,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001316 wp->self);
Armin Rigoc6686b72005-11-07 08:38:00 +00001317}
1318
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001319static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301320wrapper_reduce(wrapperobject *wp, PyObject *Py_UNUSED(ignored))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001321{
Serhiy Storchakabb86bf42018-12-11 08:28:18 +02001322 return Py_BuildValue("N(OO)", _PyEval_GetBuiltinId(&PyId_getattr),
1323 wp->self, PyDescr_NAME(wp->descr));
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001324}
1325
1326static PyMethodDef wrapper_methods[] = {
1327 {"__reduce__", (PyCFunction)wrapper_reduce, METH_NOARGS, NULL},
1328 {NULL, NULL}
1329};
1330
Armin Rigoc6686b72005-11-07 08:38:00 +00001331static PyMemberDef wrapper_members[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001332 {"__self__", T_OBJECT, offsetof(wrapperobject, self), READONLY},
1333 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001334};
1335
1336static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001337wrapper_objclass(wrapperobject *wp, void *Py_UNUSED(ignored))
Armin Rigoc6686b72005-11-07 08:38:00 +00001338{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001339 PyObject *c = (PyObject *)PyDescr_TYPE(wp->descr);
Armin Rigoc6686b72005-11-07 08:38:00 +00001340
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001341 Py_INCREF(c);
1342 return c;
Armin Rigoc6686b72005-11-07 08:38:00 +00001343}
1344
1345static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001346wrapper_name(wrapperobject *wp, void *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001347{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001348 const char *s = wp->descr->d_base->name;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001349
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001350 return PyUnicode_FromString(s);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001351}
1352
1353static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001354wrapper_doc(wrapperobject *wp, void *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001355{
Larry Hastings2623c8c2014-02-08 22:15:29 -08001356 return _PyType_GetDocFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc);
Larry Hastings5c661892014-01-24 06:17:25 -08001357}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001358
Larry Hastings5c661892014-01-24 06:17:25 -08001359static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001360wrapper_text_signature(wrapperobject *wp, void *Py_UNUSED(ignored))
Larry Hastings5c661892014-01-24 06:17:25 -08001361{
Larry Hastings2623c8c2014-02-08 22:15:29 -08001362 return _PyType_GetTextSignatureFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001363}
1364
Antoine Pitrou9d574812011-12-12 13:47:25 +01001365static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001366wrapper_qualname(wrapperobject *wp, void *Py_UNUSED(ignored))
Antoine Pitrou9d574812011-12-12 13:47:25 +01001367{
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001368 return descr_get_qualname((PyDescrObject *)wp->descr, NULL);
Antoine Pitrou9d574812011-12-12 13:47:25 +01001369}
1370
Guido van Rossum32d34c82001-09-20 21:45:26 +00001371static PyGetSetDef wrapper_getsets[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001372 {"__objclass__", (getter)wrapper_objclass},
1373 {"__name__", (getter)wrapper_name},
Antoine Pitrou9d574812011-12-12 13:47:25 +01001374 {"__qualname__", (getter)wrapper_qualname},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001375 {"__doc__", (getter)wrapper_doc},
Larry Hastings5c661892014-01-24 06:17:25 -08001376 {"__text_signature__", (getter)wrapper_text_signature},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001377 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001378};
1379
1380static PyObject *
1381wrapper_call(wrapperobject *wp, PyObject *args, PyObject *kwds)
1382{
Serhiy Storchaka5e02c782017-09-21 14:25:36 +03001383 return wrapperdescr_raw_call(wp->descr, wp->self, args, kwds);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001384}
1385
Guido van Rossum048eb752001-10-02 21:24:57 +00001386static int
1387wrapper_traverse(PyObject *self, visitproc visit, void *arg)
1388{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001389 wrapperobject *wp = (wrapperobject *)self;
1390 Py_VISIT(wp->descr);
1391 Py_VISIT(wp->self);
1392 return 0;
Guido van Rossum048eb752001-10-02 21:24:57 +00001393}
1394
Benjamin Petersoneff61f62011-09-01 16:32:31 -04001395PyTypeObject _PyMethodWrapper_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001396 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1397 "method-wrapper", /* tp_name */
1398 sizeof(wrapperobject), /* tp_basicsize */
1399 0, /* tp_itemsize */
1400 /* methods */
1401 (destructor)wrapper_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001402 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001403 0, /* tp_getattr */
1404 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001405 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001406 (reprfunc)wrapper_repr, /* tp_repr */
1407 0, /* tp_as_number */
1408 0, /* tp_as_sequence */
1409 0, /* tp_as_mapping */
1410 (hashfunc)wrapper_hash, /* tp_hash */
1411 (ternaryfunc)wrapper_call, /* tp_call */
1412 0, /* tp_str */
1413 PyObject_GenericGetAttr, /* tp_getattro */
1414 0, /* tp_setattro */
1415 0, /* tp_as_buffer */
1416 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1417 0, /* tp_doc */
1418 wrapper_traverse, /* tp_traverse */
1419 0, /* tp_clear */
1420 wrapper_richcompare, /* tp_richcompare */
1421 0, /* tp_weaklistoffset */
1422 0, /* tp_iter */
1423 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001424 wrapper_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001425 wrapper_members, /* tp_members */
1426 wrapper_getsets, /* tp_getset */
1427 0, /* tp_base */
1428 0, /* tp_dict */
1429 0, /* tp_descr_get */
1430 0, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +00001431};
1432
1433PyObject *
1434PyWrapper_New(PyObject *d, PyObject *self)
1435{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001436 wrapperobject *wp;
1437 PyWrapperDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001438
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001439 assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type));
1440 descr = (PyWrapperDescrObject *)d;
Victor Stinner3249dec2011-05-01 23:19:15 +02001441 assert(_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
Victor Stinnerd9561312011-05-01 23:31:36 +02001442 (PyObject *)PyDescr_TYPE(descr)));
Tim Peters6d6c1a32001-08-02 04:15:00 +00001443
Benjamin Petersoneff61f62011-09-01 16:32:31 -04001444 wp = PyObject_GC_New(wrapperobject, &_PyMethodWrapper_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001445 if (wp != NULL) {
1446 Py_INCREF(descr);
1447 wp->descr = descr;
1448 Py_INCREF(self);
1449 wp->self = self;
1450 _PyObject_GC_TRACK(wp);
1451 }
1452 return (PyObject *)wp;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001453}
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001454
1455
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001456/* A built-in 'property' type */
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001457
1458/*
Serhiy Storchakad741a882015-06-11 00:06:39 +03001459class property(object):
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001460
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001461 def __init__(self, fget=None, fset=None, fdel=None, doc=None):
1462 if doc is None and fget is not None and hasattr(fget, "__doc__"):
Serhiy Storchakad741a882015-06-11 00:06:39 +03001463 doc = fget.__doc__
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001464 self.__get = fget
1465 self.__set = fset
1466 self.__del = fdel
1467 self.__doc__ = doc
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001468
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001469 def __get__(self, inst, type=None):
1470 if inst is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001471 return self
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001472 if self.__get is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001473 raise AttributeError, "unreadable attribute"
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001474 return self.__get(inst)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001475
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001476 def __set__(self, inst, value):
1477 if self.__set is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001478 raise AttributeError, "can't set attribute"
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001479 return self.__set(inst, value)
Guido van Rossumba2485f2001-12-10 18:03:34 +00001480
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001481 def __delete__(self, inst):
1482 if self.__del is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001483 raise AttributeError, "can't delete attribute"
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001484 return self.__del(inst)
Guido van Rossumba2485f2001-12-10 18:03:34 +00001485
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001486*/
1487
1488typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001489 PyObject_HEAD
1490 PyObject *prop_get;
1491 PyObject *prop_set;
1492 PyObject *prop_del;
1493 PyObject *prop_doc;
1494 int getter_doc;
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001495} propertyobject;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001496
Christian Heimes0449f632007-12-15 01:27:15 +00001497static PyObject * property_copy(PyObject *, PyObject *, PyObject *,
Benjamin Peterson93964832010-06-28 03:07:10 +00001498 PyObject *);
Christian Heimes0449f632007-12-15 01:27:15 +00001499
Tim Peters66c1a522001-09-24 21:17:50 +00001500static PyMemberDef property_members[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001501 {"fget", T_OBJECT, offsetof(propertyobject, prop_get), READONLY},
1502 {"fset", T_OBJECT, offsetof(propertyobject, prop_set), READONLY},
1503 {"fdel", T_OBJECT, offsetof(propertyobject, prop_del), READONLY},
Raymond Hettingereac503a2015-05-13 01:09:59 -07001504 {"__doc__", T_OBJECT, offsetof(propertyobject, prop_doc), 0},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001505 {0}
Tim Peters66c1a522001-09-24 21:17:50 +00001506};
1507
Christian Heimes0449f632007-12-15 01:27:15 +00001508
Guido van Rossum58da9312007-11-10 23:39:45 +00001509PyDoc_STRVAR(getter_doc,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001510 "Descriptor to change the getter on a property.");
Guido van Rossum58da9312007-11-10 23:39:45 +00001511
Neal Norwitz32dde222008-04-15 06:43:13 +00001512static PyObject *
Guido van Rossum58da9312007-11-10 23:39:45 +00001513property_getter(PyObject *self, PyObject *getter)
1514{
Benjamin Peterson93964832010-06-28 03:07:10 +00001515 return property_copy(self, getter, NULL, NULL);
Guido van Rossum58da9312007-11-10 23:39:45 +00001516}
1517
Christian Heimes0449f632007-12-15 01:27:15 +00001518
Guido van Rossum58da9312007-11-10 23:39:45 +00001519PyDoc_STRVAR(setter_doc,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001520 "Descriptor to change the setter on a property.");
Guido van Rossum58da9312007-11-10 23:39:45 +00001521
Neal Norwitz32dde222008-04-15 06:43:13 +00001522static PyObject *
Guido van Rossum58da9312007-11-10 23:39:45 +00001523property_setter(PyObject *self, PyObject *setter)
1524{
Benjamin Peterson93964832010-06-28 03:07:10 +00001525 return property_copy(self, NULL, setter, NULL);
Guido van Rossum58da9312007-11-10 23:39:45 +00001526}
1527
Christian Heimes0449f632007-12-15 01:27:15 +00001528
Guido van Rossum58da9312007-11-10 23:39:45 +00001529PyDoc_STRVAR(deleter_doc,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001530 "Descriptor to change the deleter on a property.");
Guido van Rossum58da9312007-11-10 23:39:45 +00001531
Neal Norwitz32dde222008-04-15 06:43:13 +00001532static PyObject *
Guido van Rossum58da9312007-11-10 23:39:45 +00001533property_deleter(PyObject *self, PyObject *deleter)
1534{
Benjamin Peterson93964832010-06-28 03:07:10 +00001535 return property_copy(self, NULL, NULL, deleter);
Guido van Rossum58da9312007-11-10 23:39:45 +00001536}
1537
1538
Guido van Rossum58da9312007-11-10 23:39:45 +00001539static PyMethodDef property_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001540 {"getter", property_getter, METH_O, getter_doc},
1541 {"setter", property_setter, METH_O, setter_doc},
1542 {"deleter", property_deleter, METH_O, deleter_doc},
1543 {0}
Guido van Rossum58da9312007-11-10 23:39:45 +00001544};
1545
Tim Peters66c1a522001-09-24 21:17:50 +00001546
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001547static void
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001548property_dealloc(PyObject *self)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001549{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001550 propertyobject *gs = (propertyobject *)self;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001551
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001552 _PyObject_GC_UNTRACK(self);
1553 Py_XDECREF(gs->prop_get);
1554 Py_XDECREF(gs->prop_set);
1555 Py_XDECREF(gs->prop_del);
1556 Py_XDECREF(gs->prop_doc);
Victor Stinner58ac7002020-02-07 03:04:21 +01001557 Py_TYPE(self)->tp_free(self);
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001558}
1559
1560static PyObject *
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001561property_descr_get(PyObject *self, PyObject *obj, PyObject *type)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001562{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001563 if (obj == NULL || obj == Py_None) {
1564 Py_INCREF(self);
1565 return self;
1566 }
Victor Stinnere972c132018-10-01 03:03:22 -07001567
1568 propertyobject *gs = (propertyobject *)self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001569 if (gs->prop_get == NULL) {
1570 PyErr_SetString(PyExc_AttributeError, "unreadable attribute");
1571 return NULL;
1572 }
Victor Stinnere972c132018-10-01 03:03:22 -07001573
Petr Viktorinffd97532020-02-11 17:46:57 +01001574 return PyObject_CallOneArg(gs->prop_get, obj);
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001575}
1576
1577static int
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001578property_descr_set(PyObject *self, PyObject *obj, PyObject *value)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001579{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001580 propertyobject *gs = (propertyobject *)self;
1581 PyObject *func, *res;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001582
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001583 if (value == NULL)
1584 func = gs->prop_del;
1585 else
1586 func = gs->prop_set;
1587 if (func == NULL) {
1588 PyErr_SetString(PyExc_AttributeError,
1589 value == NULL ?
1590 "can't delete attribute" :
1591 "can't set attribute");
1592 return -1;
1593 }
1594 if (value == NULL)
Petr Viktorinffd97532020-02-11 17:46:57 +01001595 res = PyObject_CallOneArg(func, obj);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001596 else
Benjamin Peterson9b955de2010-12-07 04:04:02 +00001597 res = PyObject_CallFunctionObjArgs(func, obj, value, NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001598 if (res == NULL)
1599 return -1;
1600 Py_DECREF(res);
1601 return 0;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001602}
1603
Christian Heimes0449f632007-12-15 01:27:15 +00001604static PyObject *
Benjamin Peterson93964832010-06-28 03:07:10 +00001605property_copy(PyObject *old, PyObject *get, PyObject *set, PyObject *del)
Christian Heimes0449f632007-12-15 01:27:15 +00001606{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001607 propertyobject *pold = (propertyobject *)old;
Benjamin Peterson93964832010-06-28 03:07:10 +00001608 PyObject *new, *type, *doc;
Christian Heimes0449f632007-12-15 01:27:15 +00001609
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001610 type = PyObject_Type(old);
1611 if (type == NULL)
1612 return NULL;
Christian Heimes0449f632007-12-15 01:27:15 +00001613
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001614 if (get == NULL || get == Py_None) {
1615 Py_XDECREF(get);
1616 get = pold->prop_get ? pold->prop_get : Py_None;
1617 }
1618 if (set == NULL || set == Py_None) {
1619 Py_XDECREF(set);
1620 set = pold->prop_set ? pold->prop_set : Py_None;
1621 }
1622 if (del == NULL || del == Py_None) {
1623 Py_XDECREF(del);
1624 del = pold->prop_del ? pold->prop_del : Py_None;
1625 }
Benjamin Peterson93964832010-06-28 03:07:10 +00001626 if (pold->getter_doc && get != Py_None) {
1627 /* make _init use __doc__ from getter */
1628 doc = Py_None;
1629 }
1630 else {
1631 doc = pold->prop_doc ? pold->prop_doc : Py_None;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001632 }
R. David Murrayb18500d2009-05-04 22:59:07 +00001633
Victor Stinner5abaa2b2016-12-09 16:22:32 +01001634 new = PyObject_CallFunctionObjArgs(type, get, set, del, doc, NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001635 Py_DECREF(type);
1636 if (new == NULL)
1637 return NULL;
1638 return new;
Christian Heimes0449f632007-12-15 01:27:15 +00001639}
1640
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001641/*[clinic input]
1642property.__init__ as property_init
1643
1644 fget: object(c_default="NULL") = None
1645 function to be used for getting an attribute value
1646 fset: object(c_default="NULL") = None
1647 function to be used for setting an attribute value
1648 fdel: object(c_default="NULL") = None
1649 function to be used for del'ing an attribute
1650 doc: object(c_default="NULL") = None
1651 docstring
1652
1653Property attribute.
1654
1655Typical use is to define a managed attribute x:
1656
1657class C(object):
1658 def getx(self): return self._x
1659 def setx(self, value): self._x = value
1660 def delx(self): del self._x
1661 x = property(getx, setx, delx, "I'm the 'x' property.")
1662
1663Decorators make defining new properties or modifying existing ones easy:
1664
1665class C(object):
1666 @property
1667 def x(self):
1668 "I am the 'x' property."
1669 return self._x
1670 @x.setter
1671 def x(self, value):
1672 self._x = value
1673 @x.deleter
1674 def x(self):
1675 del self._x
1676[clinic start generated code]*/
1677
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001678static int
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001679property_init_impl(propertyobject *self, PyObject *fget, PyObject *fset,
1680 PyObject *fdel, PyObject *doc)
1681/*[clinic end generated code: output=01a960742b692b57 input=dfb5dbbffc6932d5]*/
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001682{
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001683 if (fget == Py_None)
1684 fget = NULL;
1685 if (fset == Py_None)
1686 fset = NULL;
1687 if (fdel == Py_None)
1688 fdel = NULL;
Tim Peters66c1a522001-09-24 21:17:50 +00001689
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001690 Py_XINCREF(fget);
1691 Py_XINCREF(fset);
1692 Py_XINCREF(fdel);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001693 Py_XINCREF(doc);
Christian Heimes0449f632007-12-15 01:27:15 +00001694
Oren Milmand019bc82018-02-13 12:28:33 +02001695 Py_XSETREF(self->prop_get, fget);
1696 Py_XSETREF(self->prop_set, fset);
1697 Py_XSETREF(self->prop_del, fdel);
1698 Py_XSETREF(self->prop_doc, doc);
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001699 self->getter_doc = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001700
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001701 /* if no docstring given and the getter has one, use that one */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001702 if ((doc == NULL || doc == Py_None) && fget != NULL) {
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001703 _Py_IDENTIFIER(__doc__);
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001704 PyObject *get_doc;
1705 int rc = _PyObject_LookupAttrId(fget, &PyId___doc__, &get_doc);
1706 if (rc <= 0) {
1707 return rc;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001708 }
Andy Lesterdffe4c02020-03-04 07:15:20 -06001709 if (Py_IS_TYPE(self, &PyProperty_Type)) {
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001710 Py_XSETREF(self->prop_doc, get_doc);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001711 }
1712 else {
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001713 /* If this is a property subclass, put __doc__
1714 in dict of the subclass instance instead,
1715 otherwise it gets shadowed by __doc__ in the
1716 class's dict. */
1717 int err = _PyObject_SetAttrId((PyObject *)self, &PyId___doc__, get_doc);
1718 Py_DECREF(get_doc);
1719 if (err < 0)
1720 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001721 }
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001722 self->getter_doc = 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001723 }
1724
1725 return 0;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001726}
1727
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -05001728static PyObject *
1729property_get___isabstractmethod__(propertyobject *prop, void *closure)
1730{
1731 int res = _PyObject_IsAbstract(prop->prop_get);
1732 if (res == -1) {
1733 return NULL;
1734 }
1735 else if (res) {
1736 Py_RETURN_TRUE;
1737 }
1738
1739 res = _PyObject_IsAbstract(prop->prop_set);
1740 if (res == -1) {
1741 return NULL;
1742 }
1743 else if (res) {
1744 Py_RETURN_TRUE;
1745 }
1746
1747 res = _PyObject_IsAbstract(prop->prop_del);
1748 if (res == -1) {
1749 return NULL;
1750 }
1751 else if (res) {
1752 Py_RETURN_TRUE;
1753 }
1754 Py_RETURN_FALSE;
1755}
1756
1757static PyGetSetDef property_getsetlist[] = {
1758 {"__isabstractmethod__",
1759 (getter)property_get___isabstractmethod__, NULL,
1760 NULL,
1761 NULL},
1762 {NULL} /* Sentinel */
1763};
1764
Guido van Rossum048eb752001-10-02 21:24:57 +00001765static int
1766property_traverse(PyObject *self, visitproc visit, void *arg)
1767{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001768 propertyobject *pp = (propertyobject *)self;
1769 Py_VISIT(pp->prop_get);
1770 Py_VISIT(pp->prop_set);
1771 Py_VISIT(pp->prop_del);
1772 Py_VISIT(pp->prop_doc);
1773 return 0;
Guido van Rossum048eb752001-10-02 21:24:57 +00001774}
1775
Raymond Hettingerd4be6912015-05-13 11:12:33 -07001776static int
1777property_clear(PyObject *self)
1778{
1779 propertyobject *pp = (propertyobject *)self;
1780 Py_CLEAR(pp->prop_doc);
1781 return 0;
1782}
1783
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001784#include "clinic/descrobject.c.h"
1785
1786PyTypeObject PyDictProxy_Type = {
1787 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1788 "mappingproxy", /* tp_name */
1789 sizeof(mappingproxyobject), /* tp_basicsize */
1790 0, /* tp_itemsize */
1791 /* methods */
1792 (destructor)mappingproxy_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001793 0, /* tp_vectorcall_offset */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001794 0, /* tp_getattr */
1795 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001796 0, /* tp_as_async */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001797 (reprfunc)mappingproxy_repr, /* tp_repr */
Brandt Bucher4663f662020-03-07 11:03:09 -08001798 &mappingproxy_as_number, /* tp_as_number */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001799 &mappingproxy_as_sequence, /* tp_as_sequence */
1800 &mappingproxy_as_mapping, /* tp_as_mapping */
1801 0, /* tp_hash */
1802 0, /* tp_call */
1803 (reprfunc)mappingproxy_str, /* tp_str */
1804 PyObject_GenericGetAttr, /* tp_getattro */
1805 0, /* tp_setattro */
1806 0, /* tp_as_buffer */
1807 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1808 0, /* tp_doc */
1809 mappingproxy_traverse, /* tp_traverse */
1810 0, /* tp_clear */
1811 (richcmpfunc)mappingproxy_richcompare, /* tp_richcompare */
1812 0, /* tp_weaklistoffset */
1813 (getiterfunc)mappingproxy_getiter, /* tp_iter */
1814 0, /* tp_iternext */
1815 mappingproxy_methods, /* tp_methods */
1816 0, /* tp_members */
1817 0, /* tp_getset */
1818 0, /* tp_base */
1819 0, /* tp_dict */
1820 0, /* tp_descr_get */
1821 0, /* tp_descr_set */
1822 0, /* tp_dictoffset */
1823 0, /* tp_init */
1824 0, /* tp_alloc */
1825 mappingproxy_new, /* tp_new */
1826};
1827
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001828PyTypeObject PyProperty_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001829 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1830 "property", /* tp_name */
1831 sizeof(propertyobject), /* tp_basicsize */
1832 0, /* tp_itemsize */
1833 /* methods */
1834 property_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001835 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001836 0, /* tp_getattr */
1837 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001838 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001839 0, /* tp_repr */
1840 0, /* tp_as_number */
1841 0, /* tp_as_sequence */
1842 0, /* tp_as_mapping */
1843 0, /* tp_hash */
1844 0, /* tp_call */
1845 0, /* tp_str */
1846 PyObject_GenericGetAttr, /* tp_getattro */
1847 0, /* tp_setattro */
1848 0, /* tp_as_buffer */
1849 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1850 Py_TPFLAGS_BASETYPE, /* tp_flags */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001851 property_init__doc__, /* tp_doc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001852 property_traverse, /* tp_traverse */
Raymond Hettingerd4be6912015-05-13 11:12:33 -07001853 (inquiry)property_clear, /* tp_clear */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001854 0, /* tp_richcompare */
1855 0, /* tp_weaklistoffset */
1856 0, /* tp_iter */
1857 0, /* tp_iternext */
1858 property_methods, /* tp_methods */
1859 property_members, /* tp_members */
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -05001860 property_getsetlist, /* tp_getset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001861 0, /* tp_base */
1862 0, /* tp_dict */
1863 property_descr_get, /* tp_descr_get */
1864 property_descr_set, /* tp_descr_set */
1865 0, /* tp_dictoffset */
1866 property_init, /* tp_init */
1867 PyType_GenericAlloc, /* tp_alloc */
1868 PyType_GenericNew, /* tp_new */
1869 PyObject_GC_Del, /* tp_free */
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001870};