blob: dd41620b9a9ee4cc5db4672ba63cbf362e3d4338 [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 Stinner384621c2020-06-22 17:27:35 +02004#include "pycore_ceval.h" // _Py_EnterRecursiveCall()
5#include "pycore_object.h" // _PyObject_GC_UNTRACK()
6#include "pycore_pystate.h" // _PyThreadState_GET()
7#include "pycore_tuple.h" // _PyTuple_ITEMS()
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
Steve Dower87655e22021-04-30 01:08:55 +0100167 if (descr->d_member->flags & PY_AUDIT_READ) {
Steve Dowerb82e17e2019-05-23 08:45:22 -0700168 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 }
Petr Viktorine1becf42020-05-07 15:39:59 +0200363 PyCMethod meth = (PyCMethod) method_enter_call(tstate, func);
364 if (meth == NULL) {
365 return NULL;
366 }
367 PyObject *result = meth(args[0],
368 ((PyMethodDescrObject *)func)->d_common.d_type,
369 args+1, nargs-1, kwnames);
370 Py_LeaveRecursiveCall();
371 return result;
372}
373
374static PyObject *
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200375method_vectorcall_FASTCALL(
376 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
377{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100378 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200379 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
380 if (method_check_args(func, args, nargs, kwnames)) {
381 return NULL;
382 }
383 _PyCFunctionFast meth = (_PyCFunctionFast)
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100384 method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200385 if (meth == NULL) {
386 return NULL;
387 }
388 PyObject *result = meth(args[0], args+1, nargs-1);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100389 _Py_LeaveRecursiveCall(tstate);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200390 return result;
391}
392
393static PyObject *
394method_vectorcall_FASTCALL_KEYWORDS(
395 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
396{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100397 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200398 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
399 if (method_check_args(func, args, nargs, NULL)) {
400 return NULL;
401 }
402 _PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords)
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100403 method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200404 if (meth == NULL) {
405 return NULL;
406 }
407 PyObject *result = meth(args[0], args+1, nargs-1, kwnames);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100408 _Py_LeaveRecursiveCall(tstate);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200409 return result;
410}
411
412static PyObject *
413method_vectorcall_NOARGS(
414 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
415{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100416 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200417 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
418 if (method_check_args(func, args, nargs, kwnames)) {
419 return NULL;
420 }
421 if (nargs != 1) {
Jeroen Demeyerbf17d412019-11-05 16:48:04 +0100422 PyObject *funcstr = _PyObject_FunctionStr(func);
423 if (funcstr != NULL) {
424 PyErr_Format(PyExc_TypeError,
425 "%U takes no arguments (%zd given)", funcstr, nargs-1);
426 Py_DECREF(funcstr);
427 }
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200428 return NULL;
429 }
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100430 PyCFunction meth = (PyCFunction)method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200431 if (meth == NULL) {
432 return NULL;
433 }
434 PyObject *result = meth(args[0], NULL);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100435 _Py_LeaveRecursiveCall(tstate);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200436 return result;
437}
438
439static PyObject *
440method_vectorcall_O(
441 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
442{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100443 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200444 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
445 if (method_check_args(func, args, nargs, kwnames)) {
446 return NULL;
447 }
448 if (nargs != 2) {
Jeroen Demeyerbf17d412019-11-05 16:48:04 +0100449 PyObject *funcstr = _PyObject_FunctionStr(func);
450 if (funcstr != NULL) {
451 PyErr_Format(PyExc_TypeError,
452 "%U takes exactly one argument (%zd given)",
453 funcstr, nargs-1);
454 Py_DECREF(funcstr);
455 }
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200456 return NULL;
457 }
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100458 PyCFunction meth = (PyCFunction)method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200459 if (meth == NULL) {
460 return NULL;
461 }
462 PyObject *result = meth(args[0], args[1]);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100463 _Py_LeaveRecursiveCall(tstate);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200464 return result;
465}
466
467
Jeroen Demeyer3f345c32019-06-07 12:20:24 +0200468/* Instances of classmethod_descriptor are unlikely to be called directly.
469 For one, the analogous class "classmethod" (for Python classes) is not
470 callable. Second, users are not likely to access a classmethod_descriptor
471 directly, since it means pulling it from the class __dict__.
472
473 This is just an excuse to say that this doesn't need to be optimized:
474 we implement this simply by calling __get__ and then calling the result.
475*/
Tim Peters6d6c1a32001-08-02 04:15:00 +0000476static PyObject *
Tim Petersbca1cbc2002-12-09 22:56:13 +0000477classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000478 PyObject *kwds)
Tim Petersbca1cbc2002-12-09 22:56:13 +0000479{
Jeroen Demeyer3f345c32019-06-07 12:20:24 +0200480 Py_ssize_t argc = PyTuple_GET_SIZE(args);
Benjamin Peterson7295c6a2012-05-01 09:51:09 -0400481 if (argc < 1) {
482 PyErr_Format(PyExc_TypeError,
483 "descriptor '%V' of '%.100s' "
484 "object needs an argument",
485 descr_name((PyDescrObject *)descr), "?",
486 PyDescr_TYPE(descr)->tp_name);
487 return NULL;
488 }
Jeroen Demeyer3f345c32019-06-07 12:20:24 +0200489 PyObject *self = PyTuple_GET_ITEM(args, 0);
490 PyObject *bound = classmethod_get(descr, NULL, self);
491 if (bound == NULL) {
Benjamin Peterson7295c6a2012-05-01 09:51:09 -0400492 return NULL;
493 }
Petr Viktorinffd97532020-02-11 17:46:57 +0100494 PyObject *res = PyObject_VectorcallDict(bound, _PyTuple_ITEMS(args)+1,
Jeroen Demeyer3f345c32019-06-07 12:20:24 +0200495 argc-1, kwds);
496 Py_DECREF(bound);
497 return res;
Tim Petersbca1cbc2002-12-09 22:56:13 +0000498}
499
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300500Py_LOCAL_INLINE(PyObject *)
501wrapperdescr_raw_call(PyWrapperDescrObject *descr, PyObject *self,
502 PyObject *args, PyObject *kwds)
503{
504 wrapperfunc wrapper = descr->d_base->wrapper;
505
506 if (descr->d_base->flags & PyWrapperFlag_KEYWORDS) {
Serhiy Storchaka1c607152018-11-27 21:34:27 +0200507 wrapperfunc_kwds wk = (wrapperfunc_kwds)(void(*)(void))wrapper;
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300508 return (*wk)(self, args, descr->d_wrapped, kwds);
509 }
510
511 if (kwds != NULL && (!PyDict_Check(kwds) || PyDict_GET_SIZE(kwds) != 0)) {
512 PyErr_Format(PyExc_TypeError,
513 "wrapper %s() takes no keyword arguments",
514 descr->d_base->name);
515 return NULL;
516 }
517 return (*wrapper)(self, args, descr->d_wrapped);
518}
519
Tim Petersbca1cbc2002-12-09 22:56:13 +0000520static PyObject *
Tim Peters6d6c1a32001-08-02 04:15:00 +0000521wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
522{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000523 Py_ssize_t argc;
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300524 PyObject *self, *result;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000525
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000526 /* Make sure that the first argument is acceptable as 'self' */
527 assert(PyTuple_Check(args));
528 argc = PyTuple_GET_SIZE(args);
529 if (argc < 1) {
530 PyErr_Format(PyExc_TypeError,
531 "descriptor '%V' of '%.100s' "
532 "object needs an argument",
533 descr_name((PyDescrObject *)descr), "?",
534 PyDescr_TYPE(descr)->tp_name);
535 return NULL;
536 }
537 self = PyTuple_GET_ITEM(args, 0);
Victor Stinner3249dec2011-05-01 23:19:15 +0200538 if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
Victor Stinnerd9561312011-05-01 23:31:36 +0200539 (PyObject *)PyDescr_TYPE(descr))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000540 PyErr_Format(PyExc_TypeError,
541 "descriptor '%V' "
542 "requires a '%.100s' object "
543 "but received a '%.100s'",
544 descr_name((PyDescrObject *)descr), "?",
545 PyDescr_TYPE(descr)->tp_name,
Victor Stinner58ac7002020-02-07 03:04:21 +0100546 Py_TYPE(self)->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000547 return NULL;
548 }
Tim Peters6d6c1a32001-08-02 04:15:00 +0000549
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300550 args = PyTuple_GetSlice(args, 1, argc);
551 if (args == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000552 return NULL;
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300553 }
554 result = wrapperdescr_raw_call(descr, self, args, kwds);
555 Py_DECREF(args);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000556 return result;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000557}
558
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300559
Tim Peters6d6c1a32001-08-02 04:15:00 +0000560static PyObject *
Guido van Rossum6f799372001-09-20 20:46:19 +0000561method_get_doc(PyMethodDescrObject *descr, void *closure)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000562{
Larry Hastings2623c8c2014-02-08 22:15:29 -0800563 return _PyType_GetDocFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc);
Larry Hastings5c661892014-01-24 06:17:25 -0800564}
565
566static PyObject *
567method_get_text_signature(PyMethodDescrObject *descr, void *closure)
568{
Larry Hastings2623c8c2014-02-08 22:15:29 -0800569 return _PyType_GetTextSignatureFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000570}
571
Antoine Pitrou9d574812011-12-12 13:47:25 +0100572static PyObject *
573calculate_qualname(PyDescrObject *descr)
574{
575 PyObject *type_qualname, *res;
576 _Py_IDENTIFIER(__qualname__);
577
578 if (descr->d_name == NULL || !PyUnicode_Check(descr->d_name)) {
579 PyErr_SetString(PyExc_TypeError,
580 "<descriptor>.__name__ is not a unicode object");
581 return NULL;
582 }
583
584 type_qualname = _PyObject_GetAttrId((PyObject *)descr->d_type,
585 &PyId___qualname__);
586 if (type_qualname == NULL)
587 return NULL;
588
589 if (!PyUnicode_Check(type_qualname)) {
590 PyErr_SetString(PyExc_TypeError, "<descriptor>.__objclass__."
591 "__qualname__ is not a unicode object");
592 Py_XDECREF(type_qualname);
593 return NULL;
594 }
595
596 res = PyUnicode_FromFormat("%S.%S", type_qualname, descr->d_name);
597 Py_DECREF(type_qualname);
598 return res;
599}
600
601static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +0200602descr_get_qualname(PyDescrObject *descr, void *Py_UNUSED(ignored))
Antoine Pitrou9d574812011-12-12 13:47:25 +0100603{
604 if (descr->d_qualname == NULL)
605 descr->d_qualname = calculate_qualname(descr);
606 Py_XINCREF(descr->d_qualname);
607 return descr->d_qualname;
608}
609
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100610static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530611descr_reduce(PyDescrObject *descr, PyObject *Py_UNUSED(ignored))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100612{
Serhiy Storchakabb86bf42018-12-11 08:28:18 +0200613 return Py_BuildValue("N(OO)", _PyEval_GetBuiltinId(&PyId_getattr),
614 PyDescr_TYPE(descr), PyDescr_NAME(descr));
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100615}
616
617static PyMethodDef descr_methods[] = {
618 {"__reduce__", (PyCFunction)descr_reduce, METH_NOARGS, NULL},
619 {NULL, NULL}
620};
621
Guido van Rossum6f799372001-09-20 20:46:19 +0000622static PyMemberDef descr_members[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000623 {"__objclass__", T_OBJECT, offsetof(PyDescrObject, d_type), READONLY},
624 {"__name__", T_OBJECT, offsetof(PyDescrObject, d_name), READONLY},
625 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +0000626};
627
Guido van Rossum32d34c82001-09-20 21:45:26 +0000628static PyGetSetDef method_getset[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000629 {"__doc__", (getter)method_get_doc},
Antoine Pitrou9d574812011-12-12 13:47:25 +0100630 {"__qualname__", (getter)descr_get_qualname},
Larry Hastings5c661892014-01-24 06:17:25 -0800631 {"__text_signature__", (getter)method_get_text_signature},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000632 {0}
Guido van Rossum6f799372001-09-20 20:46:19 +0000633};
634
635static PyObject *
636member_get_doc(PyMemberDescrObject *descr, void *closure)
637{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000638 if (descr->d_member->doc == NULL) {
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200639 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000640 }
641 return PyUnicode_FromString(descr->d_member->doc);
Guido van Rossum6f799372001-09-20 20:46:19 +0000642}
643
Guido van Rossum32d34c82001-09-20 21:45:26 +0000644static PyGetSetDef member_getset[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000645 {"__doc__", (getter)member_get_doc},
Antoine Pitrou9d574812011-12-12 13:47:25 +0100646 {"__qualname__", (getter)descr_get_qualname},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000647 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +0000648};
649
650static PyObject *
Guido van Rossum32d34c82001-09-20 21:45:26 +0000651getset_get_doc(PyGetSetDescrObject *descr, void *closure)
652{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000653 if (descr->d_getset->doc == NULL) {
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200654 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000655 }
656 return PyUnicode_FromString(descr->d_getset->doc);
Guido van Rossum32d34c82001-09-20 21:45:26 +0000657}
658
659static PyGetSetDef getset_getset[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000660 {"__doc__", (getter)getset_get_doc},
Antoine Pitrou9d574812011-12-12 13:47:25 +0100661 {"__qualname__", (getter)descr_get_qualname},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000662 {0}
Guido van Rossum32d34c82001-09-20 21:45:26 +0000663};
664
665static PyObject *
Armin Rigoc6686b72005-11-07 08:38:00 +0000666wrapperdescr_get_doc(PyWrapperDescrObject *descr, void *closure)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000667{
Larry Hastings2623c8c2014-02-08 22:15:29 -0800668 return _PyType_GetDocFromInternalDoc(descr->d_base->name, descr->d_base->doc);
Larry Hastings5c661892014-01-24 06:17:25 -0800669}
670
671static PyObject *
672wrapperdescr_get_text_signature(PyWrapperDescrObject *descr, void *closure)
673{
Larry Hastings2623c8c2014-02-08 22:15:29 -0800674 return _PyType_GetTextSignatureFromInternalDoc(descr->d_base->name, descr->d_base->doc);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000675}
676
Armin Rigoc6686b72005-11-07 08:38:00 +0000677static PyGetSetDef wrapperdescr_getset[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000678 {"__doc__", (getter)wrapperdescr_get_doc},
Antoine Pitrou9d574812011-12-12 13:47:25 +0100679 {"__qualname__", (getter)descr_get_qualname},
Larry Hastings5c661892014-01-24 06:17:25 -0800680 {"__text_signature__", (getter)wrapperdescr_get_text_signature},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000681 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +0000682};
683
Guido van Rossum048eb752001-10-02 21:24:57 +0000684static int
685descr_traverse(PyObject *self, visitproc visit, void *arg)
686{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000687 PyDescrObject *descr = (PyDescrObject *)self;
688 Py_VISIT(descr->d_type);
689 return 0;
Guido van Rossum048eb752001-10-02 21:24:57 +0000690}
691
Christian Heimesa22e8bd2007-11-29 22:35:39 +0000692PyTypeObject PyMethodDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000693 PyVarObject_HEAD_INIT(&PyType_Type, 0)
694 "method_descriptor",
695 sizeof(PyMethodDescrObject),
696 0,
697 (destructor)descr_dealloc, /* tp_dealloc */
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200698 offsetof(PyMethodDescrObject, vectorcall), /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000699 0, /* tp_getattr */
700 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200701 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000702 (reprfunc)method_repr, /* tp_repr */
703 0, /* tp_as_number */
704 0, /* tp_as_sequence */
705 0, /* tp_as_mapping */
706 0, /* tp_hash */
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200707 PyVectorcall_Call, /* tp_call */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000708 0, /* tp_str */
709 PyObject_GenericGetAttr, /* tp_getattro */
710 0, /* tp_setattro */
711 0, /* tp_as_buffer */
Jeroen Demeyereb65e242019-05-28 14:42:53 +0200712 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Petr Viktorinffd97532020-02-11 17:46:57 +0100713 Py_TPFLAGS_HAVE_VECTORCALL |
Jeroen Demeyereb65e242019-05-28 14:42:53 +0200714 Py_TPFLAGS_METHOD_DESCRIPTOR, /* tp_flags */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000715 0, /* tp_doc */
716 descr_traverse, /* tp_traverse */
717 0, /* tp_clear */
718 0, /* tp_richcompare */
719 0, /* tp_weaklistoffset */
720 0, /* tp_iter */
721 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100722 descr_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000723 descr_members, /* tp_members */
724 method_getset, /* tp_getset */
725 0, /* tp_base */
726 0, /* tp_dict */
727 (descrgetfunc)method_get, /* tp_descr_get */
728 0, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000729};
730
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +0000731/* This is for METH_CLASS in C, not for "f = classmethod(f)" in Python! */
Christian Heimesa22e8bd2007-11-29 22:35:39 +0000732PyTypeObject PyClassMethodDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000733 PyVarObject_HEAD_INIT(&PyType_Type, 0)
734 "classmethod_descriptor",
735 sizeof(PyMethodDescrObject),
736 0,
737 (destructor)descr_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200738 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000739 0, /* tp_getattr */
740 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200741 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000742 (reprfunc)method_repr, /* tp_repr */
743 0, /* tp_as_number */
744 0, /* tp_as_sequence */
745 0, /* tp_as_mapping */
746 0, /* tp_hash */
747 (ternaryfunc)classmethoddescr_call, /* tp_call */
748 0, /* tp_str */
749 PyObject_GenericGetAttr, /* tp_getattro */
750 0, /* tp_setattro */
751 0, /* tp_as_buffer */
752 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
753 0, /* tp_doc */
754 descr_traverse, /* tp_traverse */
755 0, /* tp_clear */
756 0, /* tp_richcompare */
757 0, /* tp_weaklistoffset */
758 0, /* tp_iter */
759 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100760 descr_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000761 descr_members, /* tp_members */
762 method_getset, /* tp_getset */
763 0, /* tp_base */
764 0, /* tp_dict */
765 (descrgetfunc)classmethod_get, /* tp_descr_get */
766 0, /* tp_descr_set */
Tim Petersbca1cbc2002-12-09 22:56:13 +0000767};
768
Christian Heimesa22e8bd2007-11-29 22:35:39 +0000769PyTypeObject PyMemberDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000770 PyVarObject_HEAD_INIT(&PyType_Type, 0)
771 "member_descriptor",
772 sizeof(PyMemberDescrObject),
773 0,
774 (destructor)descr_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200775 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000776 0, /* tp_getattr */
777 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200778 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000779 (reprfunc)member_repr, /* tp_repr */
780 0, /* tp_as_number */
781 0, /* tp_as_sequence */
782 0, /* tp_as_mapping */
783 0, /* tp_hash */
784 0, /* tp_call */
785 0, /* tp_str */
786 PyObject_GenericGetAttr, /* tp_getattro */
787 0, /* tp_setattro */
788 0, /* tp_as_buffer */
789 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
790 0, /* tp_doc */
791 descr_traverse, /* tp_traverse */
792 0, /* tp_clear */
793 0, /* tp_richcompare */
794 0, /* tp_weaklistoffset */
795 0, /* tp_iter */
796 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100797 descr_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000798 descr_members, /* tp_members */
799 member_getset, /* tp_getset */
800 0, /* tp_base */
801 0, /* tp_dict */
802 (descrgetfunc)member_get, /* tp_descr_get */
803 (descrsetfunc)member_set, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000804};
805
Christian Heimesa22e8bd2007-11-29 22:35:39 +0000806PyTypeObject PyGetSetDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000807 PyVarObject_HEAD_INIT(&PyType_Type, 0)
808 "getset_descriptor",
809 sizeof(PyGetSetDescrObject),
810 0,
811 (destructor)descr_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200812 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000813 0, /* tp_getattr */
814 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200815 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000816 (reprfunc)getset_repr, /* tp_repr */
817 0, /* tp_as_number */
818 0, /* tp_as_sequence */
819 0, /* tp_as_mapping */
820 0, /* tp_hash */
821 0, /* tp_call */
822 0, /* tp_str */
823 PyObject_GenericGetAttr, /* tp_getattro */
824 0, /* tp_setattro */
825 0, /* tp_as_buffer */
826 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
827 0, /* tp_doc */
828 descr_traverse, /* tp_traverse */
829 0, /* tp_clear */
830 0, /* tp_richcompare */
831 0, /* tp_weaklistoffset */
832 0, /* tp_iter */
833 0, /* tp_iternext */
834 0, /* tp_methods */
835 descr_members, /* tp_members */
836 getset_getset, /* tp_getset */
837 0, /* tp_base */
838 0, /* tp_dict */
839 (descrgetfunc)getset_get, /* tp_descr_get */
840 (descrsetfunc)getset_set, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000841};
842
Guido van Rossumf4593e02001-10-03 12:09:30 +0000843PyTypeObject PyWrapperDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000844 PyVarObject_HEAD_INIT(&PyType_Type, 0)
845 "wrapper_descriptor",
846 sizeof(PyWrapperDescrObject),
847 0,
848 (destructor)descr_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200849 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000850 0, /* tp_getattr */
851 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200852 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000853 (reprfunc)wrapperdescr_repr, /* tp_repr */
854 0, /* tp_as_number */
855 0, /* tp_as_sequence */
856 0, /* tp_as_mapping */
857 0, /* tp_hash */
858 (ternaryfunc)wrapperdescr_call, /* tp_call */
859 0, /* tp_str */
860 PyObject_GenericGetAttr, /* tp_getattro */
861 0, /* tp_setattro */
862 0, /* tp_as_buffer */
Jeroen Demeyereb65e242019-05-28 14:42:53 +0200863 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
864 Py_TPFLAGS_METHOD_DESCRIPTOR, /* tp_flags */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000865 0, /* tp_doc */
866 descr_traverse, /* tp_traverse */
867 0, /* tp_clear */
868 0, /* tp_richcompare */
869 0, /* tp_weaklistoffset */
870 0, /* tp_iter */
871 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100872 descr_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000873 descr_members, /* tp_members */
874 wrapperdescr_getset, /* tp_getset */
875 0, /* tp_base */
876 0, /* tp_dict */
877 (descrgetfunc)wrapperdescr_get, /* tp_descr_get */
878 0, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000879};
880
881static PyDescrObject *
Jeremy Hyltonaf68c872005-12-10 18:50:16 +0000882descr_new(PyTypeObject *descrtype, PyTypeObject *type, const char *name)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000883{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000884 PyDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000885
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000886 descr = (PyDescrObject *)PyType_GenericAlloc(descrtype, 0);
887 if (descr != NULL) {
888 Py_XINCREF(type);
889 descr->d_type = type;
890 descr->d_name = PyUnicode_InternFromString(name);
891 if (descr->d_name == NULL) {
892 Py_DECREF(descr);
893 descr = NULL;
894 }
Benjamin Petersonf2fe7f02011-12-17 08:02:20 -0500895 else {
896 descr->d_qualname = NULL;
897 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000898 }
899 return descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000900}
901
902PyObject *
903PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method)
904{
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200905 /* Figure out correct vectorcall function to use */
906 vectorcallfunc vectorcall;
Petr Viktorine1becf42020-05-07 15:39:59 +0200907 switch (method->ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS |
908 METH_O | METH_KEYWORDS | METH_METHOD))
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200909 {
910 case METH_VARARGS:
911 vectorcall = method_vectorcall_VARARGS;
912 break;
913 case METH_VARARGS | METH_KEYWORDS:
914 vectorcall = method_vectorcall_VARARGS_KEYWORDS;
915 break;
916 case METH_FASTCALL:
917 vectorcall = method_vectorcall_FASTCALL;
918 break;
919 case METH_FASTCALL | METH_KEYWORDS:
920 vectorcall = method_vectorcall_FASTCALL_KEYWORDS;
921 break;
922 case METH_NOARGS:
923 vectorcall = method_vectorcall_NOARGS;
924 break;
925 case METH_O:
926 vectorcall = method_vectorcall_O;
927 break;
Petr Viktorine1becf42020-05-07 15:39:59 +0200928 case METH_METHOD | METH_FASTCALL | METH_KEYWORDS:
929 vectorcall = method_vectorcall_FASTCALL_KEYWORDS_METHOD;
930 break;
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200931 default:
Victor Stinnerc7d2d692020-03-12 08:38:11 +0100932 PyErr_Format(PyExc_SystemError,
933 "%s() method: bad call flags", method->ml_name);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200934 return NULL;
935 }
936
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000937 PyMethodDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000938
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000939 descr = (PyMethodDescrObject *)descr_new(&PyMethodDescr_Type,
940 type, method->ml_name);
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200941 if (descr != NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000942 descr->d_method = method;
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200943 descr->vectorcall = vectorcall;
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200944 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000945 return (PyObject *)descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000946}
947
948PyObject *
Tim Petersbca1cbc2002-12-09 22:56:13 +0000949PyDescr_NewClassMethod(PyTypeObject *type, PyMethodDef *method)
950{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000951 PyMethodDescrObject *descr;
Tim Petersbca1cbc2002-12-09 22:56:13 +0000952
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000953 descr = (PyMethodDescrObject *)descr_new(&PyClassMethodDescr_Type,
954 type, method->ml_name);
955 if (descr != NULL)
956 descr->d_method = method;
957 return (PyObject *)descr;
Tim Petersbca1cbc2002-12-09 22:56:13 +0000958}
959
960PyObject *
Guido van Rossum6f799372001-09-20 20:46:19 +0000961PyDescr_NewMember(PyTypeObject *type, PyMemberDef *member)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000962{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000963 PyMemberDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000964
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000965 descr = (PyMemberDescrObject *)descr_new(&PyMemberDescr_Type,
966 type, member->name);
967 if (descr != NULL)
968 descr->d_member = member;
969 return (PyObject *)descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000970}
971
972PyObject *
Guido van Rossum32d34c82001-09-20 21:45:26 +0000973PyDescr_NewGetSet(PyTypeObject *type, PyGetSetDef *getset)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000974{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000975 PyGetSetDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000976
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000977 descr = (PyGetSetDescrObject *)descr_new(&PyGetSetDescr_Type,
978 type, getset->name);
979 if (descr != NULL)
980 descr->d_getset = getset;
981 return (PyObject *)descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000982}
983
984PyObject *
985PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped)
986{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000987 PyWrapperDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000988
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000989 descr = (PyWrapperDescrObject *)descr_new(&PyWrapperDescr_Type,
990 type, base->name);
991 if (descr != NULL) {
992 descr->d_base = base;
993 descr->d_wrapped = wrapped;
994 }
995 return (PyObject *)descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000996}
997
Erlend Egeberg Aasland871eb422021-02-16 08:50:00 +0100998int
999PyDescr_IsData(PyObject *ob)
1000{
1001 return Py_TYPE(ob)->tp_descr_set != NULL;
1002}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001003
Victor Stinner0db176f2012-04-16 00:16:30 +02001004/* --- mappingproxy: read-only proxy for mappings --- */
Tim Peters6d6c1a32001-08-02 04:15:00 +00001005
1006/* This has no reason to be in this file except that adding new files is a
1007 bit of a pain */
1008
1009typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001010 PyObject_HEAD
Victor Stinner0db176f2012-04-16 00:16:30 +02001011 PyObject *mapping;
1012} mappingproxyobject;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001013
Martin v. Löwis18e16552006-02-15 17:27:45 +00001014static Py_ssize_t
Victor Stinner0db176f2012-04-16 00:16:30 +02001015mappingproxy_len(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001016{
Victor Stinner0db176f2012-04-16 00:16:30 +02001017 return PyObject_Size(pp->mapping);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001018}
1019
1020static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001021mappingproxy_getitem(mappingproxyobject *pp, PyObject *key)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001022{
Victor Stinner0db176f2012-04-16 00:16:30 +02001023 return PyObject_GetItem(pp->mapping, key);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001024}
1025
Victor Stinner0db176f2012-04-16 00:16:30 +02001026static PyMappingMethods mappingproxy_as_mapping = {
1027 (lenfunc)mappingproxy_len, /* mp_length */
1028 (binaryfunc)mappingproxy_getitem, /* mp_subscript */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001029 0, /* mp_ass_subscript */
Tim Peters6d6c1a32001-08-02 04:15:00 +00001030};
1031
Brandt Bucher4663f662020-03-07 11:03:09 -08001032static PyObject *
1033mappingproxy_or(PyObject *left, PyObject *right)
1034{
1035 if (PyObject_TypeCheck(left, &PyDictProxy_Type)) {
1036 left = ((mappingproxyobject*)left)->mapping;
1037 }
1038 if (PyObject_TypeCheck(right, &PyDictProxy_Type)) {
1039 right = ((mappingproxyobject*)right)->mapping;
1040 }
1041 return PyNumber_Or(left, right);
1042}
1043
1044static PyObject *
1045mappingproxy_ior(PyObject *self, PyObject *Py_UNUSED(other))
1046{
1047 return PyErr_Format(PyExc_TypeError,
1048 "'|=' is not supported by %s; use '|' instead", Py_TYPE(self)->tp_name);
1049}
1050
1051static PyNumberMethods mappingproxy_as_number = {
1052 .nb_or = mappingproxy_or,
1053 .nb_inplace_or = mappingproxy_ior,
1054};
1055
Tim Peters6d6c1a32001-08-02 04:15:00 +00001056static int
Victor Stinner0db176f2012-04-16 00:16:30 +02001057mappingproxy_contains(mappingproxyobject *pp, PyObject *key)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001058{
Victor Stinner0db176f2012-04-16 00:16:30 +02001059 if (PyDict_CheckExact(pp->mapping))
1060 return PyDict_Contains(pp->mapping, key);
1061 else
1062 return PySequence_Contains(pp->mapping, key);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001063}
1064
Victor Stinner0db176f2012-04-16 00:16:30 +02001065static PySequenceMethods mappingproxy_as_sequence = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001066 0, /* sq_length */
1067 0, /* sq_concat */
1068 0, /* sq_repeat */
1069 0, /* sq_item */
1070 0, /* sq_slice */
1071 0, /* sq_ass_item */
1072 0, /* sq_ass_slice */
Victor Stinner0db176f2012-04-16 00:16:30 +02001073 (objobjproc)mappingproxy_contains, /* sq_contains */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001074 0, /* sq_inplace_concat */
1075 0, /* sq_inplace_repeat */
Tim Peters6d6c1a32001-08-02 04:15:00 +00001076};
1077
1078static PyObject *
Jeroen Demeyerb1263d52019-06-28 11:49:00 +02001079mappingproxy_get(mappingproxyobject *pp, PyObject *const *args, Py_ssize_t nargs)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001080{
Jeroen Demeyerb1263d52019-06-28 11:49:00 +02001081 /* newargs: mapping, key, default=None */
1082 PyObject *newargs[3];
1083 newargs[0] = pp->mapping;
1084 newargs[2] = Py_None;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001085
Jeroen Demeyerb1263d52019-06-28 11:49:00 +02001086 if (!_PyArg_UnpackStack(args, nargs, "get", 1, 2,
1087 &newargs[1], &newargs[2]))
1088 {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001089 return NULL;
Jeroen Demeyerb1263d52019-06-28 11:49:00 +02001090 }
1091 _Py_IDENTIFIER(get);
1092 return _PyObject_VectorcallMethodId(&PyId_get, newargs,
1093 3 | PY_VECTORCALL_ARGUMENTS_OFFSET,
1094 NULL);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001095}
1096
1097static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301098mappingproxy_keys(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001099{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001100 _Py_IDENTIFIER(keys);
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001101 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId_keys);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001102}
1103
1104static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301105mappingproxy_values(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001106{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001107 _Py_IDENTIFIER(values);
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001108 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId_values);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001109}
1110
1111static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301112mappingproxy_items(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001113{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001114 _Py_IDENTIFIER(items);
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001115 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId_items);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001116}
1117
1118static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301119mappingproxy_copy(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001120{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001121 _Py_IDENTIFIER(copy);
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001122 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId_copy);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001123}
1124
Zackery Spytz02fa0ea2020-05-07 23:25:50 -06001125static PyObject *
1126mappingproxy_reversed(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
1127{
1128 _Py_IDENTIFIER(__reversed__);
1129 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId___reversed__);
1130}
1131
Victor Stinner0db176f2012-04-16 00:16:30 +02001132/* WARNING: mappingproxy methods must not give access
1133 to the underlying mapping */
1134
1135static PyMethodDef mappingproxy_methods[] = {
Zackery Spytz43d564c2019-08-13 23:51:06 -06001136 {"get", (PyCFunction)(void(*)(void))mappingproxy_get, METH_FASTCALL,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001137 PyDoc_STR("D.get(k[,d]) -> D[k] if k in D, else d."
Victor Stinner0db176f2012-04-16 00:16:30 +02001138 " d defaults to None.")},
1139 {"keys", (PyCFunction)mappingproxy_keys, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001140 PyDoc_STR("D.keys() -> list of D's keys")},
Victor Stinner0db176f2012-04-16 00:16:30 +02001141 {"values", (PyCFunction)mappingproxy_values, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001142 PyDoc_STR("D.values() -> list of D's values")},
Victor Stinner0db176f2012-04-16 00:16:30 +02001143 {"items", (PyCFunction)mappingproxy_items, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001144 PyDoc_STR("D.items() -> list of D's (key, value) pairs, as 2-tuples")},
Victor Stinner0db176f2012-04-16 00:16:30 +02001145 {"copy", (PyCFunction)mappingproxy_copy, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001146 PyDoc_STR("D.copy() -> a shallow copy of D")},
Guido van Rossum48b069a2020-04-07 09:50:06 -07001147 {"__class_getitem__", (PyCFunction)Py_GenericAlias, METH_O|METH_CLASS,
1148 PyDoc_STR("See PEP 585")},
Zackery Spytz02fa0ea2020-05-07 23:25:50 -06001149 {"__reversed__", (PyCFunction)mappingproxy_reversed, METH_NOARGS,
1150 PyDoc_STR("D.__reversed__() -> reverse iterator")},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001151 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001152};
1153
1154static void
Victor Stinner0db176f2012-04-16 00:16:30 +02001155mappingproxy_dealloc(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001156{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001157 _PyObject_GC_UNTRACK(pp);
Victor Stinner0db176f2012-04-16 00:16:30 +02001158 Py_DECREF(pp->mapping);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001159 PyObject_GC_Del(pp);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001160}
1161
1162static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001163mappingproxy_getiter(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001164{
Victor Stinner0db176f2012-04-16 00:16:30 +02001165 return PyObject_GetIter(pp->mapping);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001166}
1167
Neil Schemenauer26775122001-10-21 22:26:43 +00001168static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001169mappingproxy_str(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001170{
Victor Stinner0db176f2012-04-16 00:16:30 +02001171 return PyObject_Str(pp->mapping);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001172}
1173
Ezio Melottiac53ab62010-12-18 14:59:43 +00001174static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001175mappingproxy_repr(mappingproxyobject *pp)
Ezio Melottiac53ab62010-12-18 14:59:43 +00001176{
Victor Stinner0db176f2012-04-16 00:16:30 +02001177 return PyUnicode_FromFormat("mappingproxy(%R)", pp->mapping);
Ezio Melottiac53ab62010-12-18 14:59:43 +00001178}
1179
Guido van Rossum048eb752001-10-02 21:24:57 +00001180static int
Victor Stinner0db176f2012-04-16 00:16:30 +02001181mappingproxy_traverse(PyObject *self, visitproc visit, void *arg)
Guido van Rossum048eb752001-10-02 21:24:57 +00001182{
Victor Stinner0db176f2012-04-16 00:16:30 +02001183 mappingproxyobject *pp = (mappingproxyobject *)self;
1184 Py_VISIT(pp->mapping);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001185 return 0;
Guido van Rossum048eb752001-10-02 21:24:57 +00001186}
1187
Raymond Hettinger29a6d442002-08-31 15:51:04 +00001188static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001189mappingproxy_richcompare(mappingproxyobject *v, PyObject *w, int op)
Raymond Hettinger29a6d442002-08-31 15:51:04 +00001190{
Victor Stinner0db176f2012-04-16 00:16:30 +02001191 return PyObject_RichCompare(v->mapping, w, op);
1192}
1193
1194static int
1195mappingproxy_check_mapping(PyObject *mapping)
1196{
1197 if (!PyMapping_Check(mapping)
1198 || PyList_Check(mapping)
1199 || PyTuple_Check(mapping)) {
1200 PyErr_Format(PyExc_TypeError,
1201 "mappingproxy() argument must be a mapping, not %s",
1202 Py_TYPE(mapping)->tp_name);
1203 return -1;
1204 }
1205 return 0;
1206}
1207
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001208/*[clinic input]
1209@classmethod
1210mappingproxy.__new__ as mappingproxy_new
Victor Stinner0db176f2012-04-16 00:16:30 +02001211
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001212 mapping: object
1213
1214[clinic start generated code]*/
1215
1216static PyObject *
1217mappingproxy_new_impl(PyTypeObject *type, PyObject *mapping)
1218/*[clinic end generated code: output=65f27f02d5b68fa7 input=d2d620d4f598d4f8]*/
1219{
1220 mappingproxyobject *mappingproxy;
Victor Stinner0db176f2012-04-16 00:16:30 +02001221
1222 if (mappingproxy_check_mapping(mapping) == -1)
1223 return NULL;
1224
1225 mappingproxy = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type);
1226 if (mappingproxy == NULL)
1227 return NULL;
1228 Py_INCREF(mapping);
1229 mappingproxy->mapping = mapping;
1230 _PyObject_GC_TRACK(mappingproxy);
1231 return (PyObject *)mappingproxy;
Raymond Hettinger29a6d442002-08-31 15:51:04 +00001232}
1233
Tim Peters6d6c1a32001-08-02 04:15:00 +00001234PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001235PyDictProxy_New(PyObject *mapping)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001236{
Victor Stinner0db176f2012-04-16 00:16:30 +02001237 mappingproxyobject *pp;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001238
Victor Stinner0db176f2012-04-16 00:16:30 +02001239 if (mappingproxy_check_mapping(mapping) == -1)
1240 return NULL;
1241
1242 pp = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001243 if (pp != NULL) {
Victor Stinner0db176f2012-04-16 00:16:30 +02001244 Py_INCREF(mapping);
1245 pp->mapping = mapping;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001246 _PyObject_GC_TRACK(pp);
1247 }
1248 return (PyObject *)pp;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001249}
1250
1251
1252/* --- Wrapper object for "slot" methods --- */
1253
1254/* This has no reason to be in this file except that adding new files is a
1255 bit of a pain */
1256
1257typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001258 PyObject_HEAD
1259 PyWrapperDescrObject *descr;
1260 PyObject *self;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001261} wrapperobject;
1262
Andy Lesterdffe4c02020-03-04 07:15:20 -06001263#define Wrapper_Check(v) Py_IS_TYPE(v, &_PyMethodWrapper_Type)
Mark Dickinson211c6252009-02-01 10:28:51 +00001264
Tim Peters6d6c1a32001-08-02 04:15:00 +00001265static void
1266wrapper_dealloc(wrapperobject *wp)
1267{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001268 PyObject_GC_UnTrack(wp);
Jeroen Demeyer351c6742019-05-10 19:21:11 +02001269 Py_TRASHCAN_BEGIN(wp, wrapper_dealloc)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001270 Py_XDECREF(wp->descr);
1271 Py_XDECREF(wp->self);
1272 PyObject_GC_Del(wp);
Jeroen Demeyer351c6742019-05-10 19:21:11 +02001273 Py_TRASHCAN_END
Tim Peters6d6c1a32001-08-02 04:15:00 +00001274}
1275
Mark Dickinson211c6252009-02-01 10:28:51 +00001276static PyObject *
1277wrapper_richcompare(PyObject *a, PyObject *b, int op)
Armin Rigoc6686b72005-11-07 08:38:00 +00001278{
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001279 wrapperobject *wa, *wb;
1280 int eq;
Mark Dickinson211c6252009-02-01 10:28:51 +00001281
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001282 assert(a != NULL && b != NULL);
Mark Dickinson211c6252009-02-01 10:28:51 +00001283
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001284 /* both arguments should be wrapperobjects */
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001285 if ((op != Py_EQ && op != Py_NE)
1286 || !Wrapper_Check(a) || !Wrapper_Check(b))
1287 {
stratakise8b19652017-11-02 11:32:54 +01001288 Py_RETURN_NOTIMPLEMENTED;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001289 }
Mark Dickinson211c6252009-02-01 10:28:51 +00001290
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001291 wa = (wrapperobject *)a;
1292 wb = (wrapperobject *)b;
1293 eq = (wa->descr == wb->descr && wa->self == wb->self);
1294 if (eq == (op == Py_EQ)) {
1295 Py_RETURN_TRUE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001296 }
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001297 else {
1298 Py_RETURN_FALSE;
1299 }
Armin Rigoc6686b72005-11-07 08:38:00 +00001300}
1301
Benjamin Peterson8f67d082010-10-17 20:54:53 +00001302static Py_hash_t
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001303wrapper_hash(wrapperobject *wp)
1304{
Benjamin Peterson8f67d082010-10-17 20:54:53 +00001305 Py_hash_t x, y;
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001306 x = _Py_HashPointer(wp->self);
1307 y = _Py_HashPointer(wp->descr);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001308 x = x ^ y;
1309 if (x == -1)
1310 x = -2;
1311 return x;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001312}
1313
Armin Rigoc6686b72005-11-07 08:38:00 +00001314static PyObject *
1315wrapper_repr(wrapperobject *wp)
1316{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001317 return PyUnicode_FromFormat("<method-wrapper '%s' of %s object at %p>",
1318 wp->descr->d_base->name,
Victor Stinner58ac7002020-02-07 03:04:21 +01001319 Py_TYPE(wp->self)->tp_name,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001320 wp->self);
Armin Rigoc6686b72005-11-07 08:38:00 +00001321}
1322
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001323static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301324wrapper_reduce(wrapperobject *wp, PyObject *Py_UNUSED(ignored))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001325{
Serhiy Storchakabb86bf42018-12-11 08:28:18 +02001326 return Py_BuildValue("N(OO)", _PyEval_GetBuiltinId(&PyId_getattr),
1327 wp->self, PyDescr_NAME(wp->descr));
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001328}
1329
1330static PyMethodDef wrapper_methods[] = {
1331 {"__reduce__", (PyCFunction)wrapper_reduce, METH_NOARGS, NULL},
1332 {NULL, NULL}
1333};
1334
Armin Rigoc6686b72005-11-07 08:38:00 +00001335static PyMemberDef wrapper_members[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001336 {"__self__", T_OBJECT, offsetof(wrapperobject, self), READONLY},
1337 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001338};
1339
1340static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001341wrapper_objclass(wrapperobject *wp, void *Py_UNUSED(ignored))
Armin Rigoc6686b72005-11-07 08:38:00 +00001342{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001343 PyObject *c = (PyObject *)PyDescr_TYPE(wp->descr);
Armin Rigoc6686b72005-11-07 08:38:00 +00001344
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001345 Py_INCREF(c);
1346 return c;
Armin Rigoc6686b72005-11-07 08:38:00 +00001347}
1348
1349static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001350wrapper_name(wrapperobject *wp, void *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001351{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001352 const char *s = wp->descr->d_base->name;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001353
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001354 return PyUnicode_FromString(s);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001355}
1356
1357static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001358wrapper_doc(wrapperobject *wp, void *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001359{
Larry Hastings2623c8c2014-02-08 22:15:29 -08001360 return _PyType_GetDocFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc);
Larry Hastings5c661892014-01-24 06:17:25 -08001361}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001362
Larry Hastings5c661892014-01-24 06:17:25 -08001363static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001364wrapper_text_signature(wrapperobject *wp, void *Py_UNUSED(ignored))
Larry Hastings5c661892014-01-24 06:17:25 -08001365{
Larry Hastings2623c8c2014-02-08 22:15:29 -08001366 return _PyType_GetTextSignatureFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001367}
1368
Antoine Pitrou9d574812011-12-12 13:47:25 +01001369static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001370wrapper_qualname(wrapperobject *wp, void *Py_UNUSED(ignored))
Antoine Pitrou9d574812011-12-12 13:47:25 +01001371{
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001372 return descr_get_qualname((PyDescrObject *)wp->descr, NULL);
Antoine Pitrou9d574812011-12-12 13:47:25 +01001373}
1374
Guido van Rossum32d34c82001-09-20 21:45:26 +00001375static PyGetSetDef wrapper_getsets[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001376 {"__objclass__", (getter)wrapper_objclass},
1377 {"__name__", (getter)wrapper_name},
Antoine Pitrou9d574812011-12-12 13:47:25 +01001378 {"__qualname__", (getter)wrapper_qualname},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001379 {"__doc__", (getter)wrapper_doc},
Larry Hastings5c661892014-01-24 06:17:25 -08001380 {"__text_signature__", (getter)wrapper_text_signature},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001381 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001382};
1383
1384static PyObject *
1385wrapper_call(wrapperobject *wp, PyObject *args, PyObject *kwds)
1386{
Serhiy Storchaka5e02c782017-09-21 14:25:36 +03001387 return wrapperdescr_raw_call(wp->descr, wp->self, args, kwds);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001388}
1389
Guido van Rossum048eb752001-10-02 21:24:57 +00001390static int
1391wrapper_traverse(PyObject *self, visitproc visit, void *arg)
1392{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001393 wrapperobject *wp = (wrapperobject *)self;
1394 Py_VISIT(wp->descr);
1395 Py_VISIT(wp->self);
1396 return 0;
Guido van Rossum048eb752001-10-02 21:24:57 +00001397}
1398
Benjamin Petersoneff61f62011-09-01 16:32:31 -04001399PyTypeObject _PyMethodWrapper_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001400 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1401 "method-wrapper", /* tp_name */
1402 sizeof(wrapperobject), /* tp_basicsize */
1403 0, /* tp_itemsize */
1404 /* methods */
1405 (destructor)wrapper_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001406 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001407 0, /* tp_getattr */
1408 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001409 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001410 (reprfunc)wrapper_repr, /* tp_repr */
1411 0, /* tp_as_number */
1412 0, /* tp_as_sequence */
1413 0, /* tp_as_mapping */
1414 (hashfunc)wrapper_hash, /* tp_hash */
1415 (ternaryfunc)wrapper_call, /* tp_call */
1416 0, /* tp_str */
1417 PyObject_GenericGetAttr, /* tp_getattro */
1418 0, /* tp_setattro */
1419 0, /* tp_as_buffer */
1420 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1421 0, /* tp_doc */
1422 wrapper_traverse, /* tp_traverse */
1423 0, /* tp_clear */
1424 wrapper_richcompare, /* tp_richcompare */
1425 0, /* tp_weaklistoffset */
1426 0, /* tp_iter */
1427 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001428 wrapper_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001429 wrapper_members, /* tp_members */
1430 wrapper_getsets, /* tp_getset */
1431 0, /* tp_base */
1432 0, /* tp_dict */
1433 0, /* tp_descr_get */
1434 0, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +00001435};
1436
1437PyObject *
1438PyWrapper_New(PyObject *d, PyObject *self)
1439{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001440 wrapperobject *wp;
1441 PyWrapperDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001442
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001443 assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type));
1444 descr = (PyWrapperDescrObject *)d;
Victor Stinner3249dec2011-05-01 23:19:15 +02001445 assert(_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
Victor Stinnerd9561312011-05-01 23:31:36 +02001446 (PyObject *)PyDescr_TYPE(descr)));
Tim Peters6d6c1a32001-08-02 04:15:00 +00001447
Benjamin Petersoneff61f62011-09-01 16:32:31 -04001448 wp = PyObject_GC_New(wrapperobject, &_PyMethodWrapper_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001449 if (wp != NULL) {
1450 Py_INCREF(descr);
1451 wp->descr = descr;
1452 Py_INCREF(self);
1453 wp->self = self;
1454 _PyObject_GC_TRACK(wp);
1455 }
1456 return (PyObject *)wp;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001457}
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001458
1459
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001460/* A built-in 'property' type */
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001461
1462/*
Serhiy Storchakad741a882015-06-11 00:06:39 +03001463class property(object):
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001464
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001465 def __init__(self, fget=None, fset=None, fdel=None, doc=None):
1466 if doc is None and fget is not None and hasattr(fget, "__doc__"):
Serhiy Storchakad741a882015-06-11 00:06:39 +03001467 doc = fget.__doc__
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001468 self.__get = fget
1469 self.__set = fset
1470 self.__del = fdel
1471 self.__doc__ = doc
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001472
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001473 def __get__(self, inst, type=None):
1474 if inst is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001475 return self
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001476 if self.__get is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001477 raise AttributeError, "unreadable attribute"
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001478 return self.__get(inst)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001479
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001480 def __set__(self, inst, value):
1481 if self.__set is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001482 raise AttributeError, "can't set attribute"
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001483 return self.__set(inst, value)
Guido van Rossumba2485f2001-12-10 18:03:34 +00001484
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001485 def __delete__(self, inst):
1486 if self.__del is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001487 raise AttributeError, "can't delete attribute"
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001488 return self.__del(inst)
Guido van Rossumba2485f2001-12-10 18:03:34 +00001489
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001490*/
1491
1492typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001493 PyObject_HEAD
1494 PyObject *prop_get;
1495 PyObject *prop_set;
1496 PyObject *prop_del;
1497 PyObject *prop_doc;
Yurii Karabasc56387f2020-12-30 11:51:24 +02001498 PyObject *prop_name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001499 int getter_doc;
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001500} propertyobject;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001501
Christian Heimes0449f632007-12-15 01:27:15 +00001502static PyObject * property_copy(PyObject *, PyObject *, PyObject *,
Benjamin Peterson93964832010-06-28 03:07:10 +00001503 PyObject *);
Christian Heimes0449f632007-12-15 01:27:15 +00001504
Tim Peters66c1a522001-09-24 21:17:50 +00001505static PyMemberDef property_members[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001506 {"fget", T_OBJECT, offsetof(propertyobject, prop_get), READONLY},
1507 {"fset", T_OBJECT, offsetof(propertyobject, prop_set), READONLY},
1508 {"fdel", T_OBJECT, offsetof(propertyobject, prop_del), READONLY},
Raymond Hettingereac503a2015-05-13 01:09:59 -07001509 {"__doc__", T_OBJECT, offsetof(propertyobject, prop_doc), 0},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001510 {0}
Tim Peters66c1a522001-09-24 21:17:50 +00001511};
1512
Christian Heimes0449f632007-12-15 01:27:15 +00001513
Guido van Rossum58da9312007-11-10 23:39:45 +00001514PyDoc_STRVAR(getter_doc,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001515 "Descriptor to change the getter on a property.");
Guido van Rossum58da9312007-11-10 23:39:45 +00001516
Neal Norwitz32dde222008-04-15 06:43:13 +00001517static PyObject *
Guido van Rossum58da9312007-11-10 23:39:45 +00001518property_getter(PyObject *self, PyObject *getter)
1519{
Benjamin Peterson93964832010-06-28 03:07:10 +00001520 return property_copy(self, getter, NULL, NULL);
Guido van Rossum58da9312007-11-10 23:39:45 +00001521}
1522
Christian Heimes0449f632007-12-15 01:27:15 +00001523
Guido van Rossum58da9312007-11-10 23:39:45 +00001524PyDoc_STRVAR(setter_doc,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001525 "Descriptor to change the setter on a property.");
Guido van Rossum58da9312007-11-10 23:39:45 +00001526
Neal Norwitz32dde222008-04-15 06:43:13 +00001527static PyObject *
Guido van Rossum58da9312007-11-10 23:39:45 +00001528property_setter(PyObject *self, PyObject *setter)
1529{
Benjamin Peterson93964832010-06-28 03:07:10 +00001530 return property_copy(self, NULL, setter, NULL);
Guido van Rossum58da9312007-11-10 23:39:45 +00001531}
1532
Christian Heimes0449f632007-12-15 01:27:15 +00001533
Guido van Rossum58da9312007-11-10 23:39:45 +00001534PyDoc_STRVAR(deleter_doc,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001535 "Descriptor to change the deleter on a property.");
Guido van Rossum58da9312007-11-10 23:39:45 +00001536
Neal Norwitz32dde222008-04-15 06:43:13 +00001537static PyObject *
Guido van Rossum58da9312007-11-10 23:39:45 +00001538property_deleter(PyObject *self, PyObject *deleter)
1539{
Benjamin Peterson93964832010-06-28 03:07:10 +00001540 return property_copy(self, NULL, NULL, deleter);
Guido van Rossum58da9312007-11-10 23:39:45 +00001541}
1542
1543
Yurii Karabasc56387f2020-12-30 11:51:24 +02001544PyDoc_STRVAR(set_name_doc,
1545 "Method to set name of a property.");
1546
1547static PyObject *
1548property_set_name(PyObject *self, PyObject *args) {
1549 if (PyTuple_GET_SIZE(args) != 2) {
1550 PyErr_Format(
1551 PyExc_TypeError,
1552 "__set_name__() takes 2 positional arguments but %d were given",
1553 PyTuple_GET_SIZE(args));
1554 return NULL;
1555 }
1556
1557 propertyobject *prop = (propertyobject *)self;
1558 PyObject *name = PyTuple_GET_ITEM(args, 1);
1559
1560 Py_XINCREF(name);
1561 Py_XSETREF(prop->prop_name, name);
1562
1563 Py_RETURN_NONE;
1564}
1565
Guido van Rossum58da9312007-11-10 23:39:45 +00001566static PyMethodDef property_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001567 {"getter", property_getter, METH_O, getter_doc},
1568 {"setter", property_setter, METH_O, setter_doc},
1569 {"deleter", property_deleter, METH_O, deleter_doc},
Yurii Karabasc56387f2020-12-30 11:51:24 +02001570 {"__set_name__", property_set_name, METH_VARARGS, set_name_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001571 {0}
Guido van Rossum58da9312007-11-10 23:39:45 +00001572};
1573
Tim Peters66c1a522001-09-24 21:17:50 +00001574
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001575static void
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001576property_dealloc(PyObject *self)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001577{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001578 propertyobject *gs = (propertyobject *)self;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001579
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001580 _PyObject_GC_UNTRACK(self);
1581 Py_XDECREF(gs->prop_get);
1582 Py_XDECREF(gs->prop_set);
1583 Py_XDECREF(gs->prop_del);
1584 Py_XDECREF(gs->prop_doc);
Yurii Karabasc56387f2020-12-30 11:51:24 +02001585 Py_XDECREF(gs->prop_name);
Victor Stinner58ac7002020-02-07 03:04:21 +01001586 Py_TYPE(self)->tp_free(self);
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001587}
1588
1589static PyObject *
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001590property_descr_get(PyObject *self, PyObject *obj, PyObject *type)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001591{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001592 if (obj == NULL || obj == Py_None) {
1593 Py_INCREF(self);
1594 return self;
1595 }
Victor Stinnere972c132018-10-01 03:03:22 -07001596
1597 propertyobject *gs = (propertyobject *)self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001598 if (gs->prop_get == NULL) {
Yurii Karabasc56387f2020-12-30 11:51:24 +02001599 if (gs->prop_name != NULL) {
1600 PyErr_Format(PyExc_AttributeError, "unreadable attribute %R", gs->prop_name);
1601 } else {
1602 PyErr_SetString(PyExc_AttributeError, "unreadable attribute");
1603 }
1604
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001605 return NULL;
1606 }
Victor Stinnere972c132018-10-01 03:03:22 -07001607
Petr Viktorinffd97532020-02-11 17:46:57 +01001608 return PyObject_CallOneArg(gs->prop_get, obj);
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001609}
1610
1611static int
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001612property_descr_set(PyObject *self, PyObject *obj, PyObject *value)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001613{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001614 propertyobject *gs = (propertyobject *)self;
1615 PyObject *func, *res;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001616
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001617 if (value == NULL)
1618 func = gs->prop_del;
1619 else
1620 func = gs->prop_set;
1621 if (func == NULL) {
Yurii Karabasc56387f2020-12-30 11:51:24 +02001622 if (gs->prop_name != NULL) {
1623 PyErr_Format(PyExc_AttributeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001624 value == NULL ?
Yurii Karabasc56387f2020-12-30 11:51:24 +02001625 "can't delete attribute %R" :
1626 "can't set attribute %R",
1627 gs->prop_name);
1628 } else {
1629 PyErr_SetString(PyExc_AttributeError,
1630 value == NULL ?
1631 "can't delete attribute" :
1632 "can't set attribute");
1633 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001634 return -1;
1635 }
1636 if (value == NULL)
Petr Viktorinffd97532020-02-11 17:46:57 +01001637 res = PyObject_CallOneArg(func, obj);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001638 else
Benjamin Peterson9b955de2010-12-07 04:04:02 +00001639 res = PyObject_CallFunctionObjArgs(func, obj, value, NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001640 if (res == NULL)
1641 return -1;
1642 Py_DECREF(res);
1643 return 0;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001644}
1645
Christian Heimes0449f632007-12-15 01:27:15 +00001646static PyObject *
Benjamin Peterson93964832010-06-28 03:07:10 +00001647property_copy(PyObject *old, PyObject *get, PyObject *set, PyObject *del)
Christian Heimes0449f632007-12-15 01:27:15 +00001648{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001649 propertyobject *pold = (propertyobject *)old;
Benjamin Peterson93964832010-06-28 03:07:10 +00001650 PyObject *new, *type, *doc;
Christian Heimes0449f632007-12-15 01:27:15 +00001651
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001652 type = PyObject_Type(old);
1653 if (type == NULL)
1654 return NULL;
Christian Heimes0449f632007-12-15 01:27:15 +00001655
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001656 if (get == NULL || get == Py_None) {
1657 Py_XDECREF(get);
1658 get = pold->prop_get ? pold->prop_get : Py_None;
1659 }
1660 if (set == NULL || set == Py_None) {
1661 Py_XDECREF(set);
1662 set = pold->prop_set ? pold->prop_set : Py_None;
1663 }
1664 if (del == NULL || del == Py_None) {
1665 Py_XDECREF(del);
1666 del = pold->prop_del ? pold->prop_del : Py_None;
1667 }
Benjamin Peterson93964832010-06-28 03:07:10 +00001668 if (pold->getter_doc && get != Py_None) {
1669 /* make _init use __doc__ from getter */
1670 doc = Py_None;
1671 }
1672 else {
1673 doc = pold->prop_doc ? pold->prop_doc : Py_None;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001674 }
R. David Murrayb18500d2009-05-04 22:59:07 +00001675
Victor Stinner5abaa2b2016-12-09 16:22:32 +01001676 new = PyObject_CallFunctionObjArgs(type, get, set, del, doc, NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001677 Py_DECREF(type);
1678 if (new == NULL)
1679 return NULL;
Yurii Karabasc56387f2020-12-30 11:51:24 +02001680
1681 Py_XINCREF(pold->prop_name);
1682 Py_XSETREF(((propertyobject *) new)->prop_name, pold->prop_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001683 return new;
Christian Heimes0449f632007-12-15 01:27:15 +00001684}
1685
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001686/*[clinic input]
1687property.__init__ as property_init
1688
1689 fget: object(c_default="NULL") = None
1690 function to be used for getting an attribute value
1691 fset: object(c_default="NULL") = None
1692 function to be used for setting an attribute value
1693 fdel: object(c_default="NULL") = None
1694 function to be used for del'ing an attribute
1695 doc: object(c_default="NULL") = None
1696 docstring
1697
1698Property attribute.
1699
1700Typical use is to define a managed attribute x:
1701
1702class C(object):
1703 def getx(self): return self._x
1704 def setx(self, value): self._x = value
1705 def delx(self): del self._x
1706 x = property(getx, setx, delx, "I'm the 'x' property.")
1707
1708Decorators make defining new properties or modifying existing ones easy:
1709
1710class C(object):
1711 @property
1712 def x(self):
1713 "I am the 'x' property."
1714 return self._x
1715 @x.setter
1716 def x(self, value):
1717 self._x = value
1718 @x.deleter
1719 def x(self):
1720 del self._x
1721[clinic start generated code]*/
1722
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001723static int
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001724property_init_impl(propertyobject *self, PyObject *fget, PyObject *fset,
1725 PyObject *fdel, PyObject *doc)
1726/*[clinic end generated code: output=01a960742b692b57 input=dfb5dbbffc6932d5]*/
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001727{
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001728 if (fget == Py_None)
1729 fget = NULL;
1730 if (fset == Py_None)
1731 fset = NULL;
1732 if (fdel == Py_None)
1733 fdel = NULL;
Tim Peters66c1a522001-09-24 21:17:50 +00001734
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001735 Py_XINCREF(fget);
1736 Py_XINCREF(fset);
1737 Py_XINCREF(fdel);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001738 Py_XINCREF(doc);
Christian Heimes0449f632007-12-15 01:27:15 +00001739
Oren Milmand019bc82018-02-13 12:28:33 +02001740 Py_XSETREF(self->prop_get, fget);
1741 Py_XSETREF(self->prop_set, fset);
1742 Py_XSETREF(self->prop_del, fdel);
1743 Py_XSETREF(self->prop_doc, doc);
Yurii Karabasc56387f2020-12-30 11:51:24 +02001744 Py_XSETREF(self->prop_name, NULL);
1745
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001746 self->getter_doc = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001747
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001748 /* if no docstring given and the getter has one, use that one */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001749 if ((doc == NULL || doc == Py_None) && fget != NULL) {
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001750 _Py_IDENTIFIER(__doc__);
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001751 PyObject *get_doc;
1752 int rc = _PyObject_LookupAttrId(fget, &PyId___doc__, &get_doc);
1753 if (rc <= 0) {
1754 return rc;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001755 }
Andy Lesterdffe4c02020-03-04 07:15:20 -06001756 if (Py_IS_TYPE(self, &PyProperty_Type)) {
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001757 Py_XSETREF(self->prop_doc, get_doc);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001758 }
1759 else {
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001760 /* If this is a property subclass, put __doc__
1761 in dict of the subclass instance instead,
1762 otherwise it gets shadowed by __doc__ in the
1763 class's dict. */
1764 int err = _PyObject_SetAttrId((PyObject *)self, &PyId___doc__, get_doc);
1765 Py_DECREF(get_doc);
1766 if (err < 0)
1767 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001768 }
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001769 self->getter_doc = 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001770 }
1771
1772 return 0;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001773}
1774
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -05001775static PyObject *
1776property_get___isabstractmethod__(propertyobject *prop, void *closure)
1777{
1778 int res = _PyObject_IsAbstract(prop->prop_get);
1779 if (res == -1) {
1780 return NULL;
1781 }
1782 else if (res) {
1783 Py_RETURN_TRUE;
1784 }
1785
1786 res = _PyObject_IsAbstract(prop->prop_set);
1787 if (res == -1) {
1788 return NULL;
1789 }
1790 else if (res) {
1791 Py_RETURN_TRUE;
1792 }
1793
1794 res = _PyObject_IsAbstract(prop->prop_del);
1795 if (res == -1) {
1796 return NULL;
1797 }
1798 else if (res) {
1799 Py_RETURN_TRUE;
1800 }
1801 Py_RETURN_FALSE;
1802}
1803
1804static PyGetSetDef property_getsetlist[] = {
1805 {"__isabstractmethod__",
1806 (getter)property_get___isabstractmethod__, NULL,
1807 NULL,
1808 NULL},
1809 {NULL} /* Sentinel */
1810};
1811
Guido van Rossum048eb752001-10-02 21:24:57 +00001812static int
1813property_traverse(PyObject *self, visitproc visit, void *arg)
1814{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001815 propertyobject *pp = (propertyobject *)self;
1816 Py_VISIT(pp->prop_get);
1817 Py_VISIT(pp->prop_set);
1818 Py_VISIT(pp->prop_del);
1819 Py_VISIT(pp->prop_doc);
Yurii Karabasc56387f2020-12-30 11:51:24 +02001820 Py_VISIT(pp->prop_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001821 return 0;
Guido van Rossum048eb752001-10-02 21:24:57 +00001822}
1823
Raymond Hettingerd4be6912015-05-13 11:12:33 -07001824static int
1825property_clear(PyObject *self)
1826{
1827 propertyobject *pp = (propertyobject *)self;
1828 Py_CLEAR(pp->prop_doc);
1829 return 0;
1830}
1831
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001832#include "clinic/descrobject.c.h"
1833
1834PyTypeObject PyDictProxy_Type = {
1835 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1836 "mappingproxy", /* tp_name */
1837 sizeof(mappingproxyobject), /* tp_basicsize */
1838 0, /* tp_itemsize */
1839 /* methods */
1840 (destructor)mappingproxy_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001841 0, /* tp_vectorcall_offset */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001842 0, /* tp_getattr */
1843 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001844 0, /* tp_as_async */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001845 (reprfunc)mappingproxy_repr, /* tp_repr */
Brandt Bucher4663f662020-03-07 11:03:09 -08001846 &mappingproxy_as_number, /* tp_as_number */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001847 &mappingproxy_as_sequence, /* tp_as_sequence */
1848 &mappingproxy_as_mapping, /* tp_as_mapping */
1849 0, /* tp_hash */
1850 0, /* tp_call */
1851 (reprfunc)mappingproxy_str, /* tp_str */
1852 PyObject_GenericGetAttr, /* tp_getattro */
1853 0, /* tp_setattro */
1854 0, /* tp_as_buffer */
1855 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1856 0, /* tp_doc */
1857 mappingproxy_traverse, /* tp_traverse */
1858 0, /* tp_clear */
1859 (richcmpfunc)mappingproxy_richcompare, /* tp_richcompare */
1860 0, /* tp_weaklistoffset */
1861 (getiterfunc)mappingproxy_getiter, /* tp_iter */
1862 0, /* tp_iternext */
1863 mappingproxy_methods, /* tp_methods */
1864 0, /* tp_members */
1865 0, /* tp_getset */
1866 0, /* tp_base */
1867 0, /* tp_dict */
1868 0, /* tp_descr_get */
1869 0, /* tp_descr_set */
1870 0, /* tp_dictoffset */
1871 0, /* tp_init */
1872 0, /* tp_alloc */
1873 mappingproxy_new, /* tp_new */
1874};
1875
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001876PyTypeObject PyProperty_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001877 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1878 "property", /* tp_name */
1879 sizeof(propertyobject), /* tp_basicsize */
1880 0, /* tp_itemsize */
1881 /* methods */
1882 property_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001883 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001884 0, /* tp_getattr */
1885 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001886 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001887 0, /* tp_repr */
1888 0, /* tp_as_number */
1889 0, /* tp_as_sequence */
1890 0, /* tp_as_mapping */
1891 0, /* tp_hash */
1892 0, /* tp_call */
1893 0, /* tp_str */
1894 PyObject_GenericGetAttr, /* tp_getattro */
1895 0, /* tp_setattro */
1896 0, /* tp_as_buffer */
1897 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1898 Py_TPFLAGS_BASETYPE, /* tp_flags */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001899 property_init__doc__, /* tp_doc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001900 property_traverse, /* tp_traverse */
Raymond Hettingerd4be6912015-05-13 11:12:33 -07001901 (inquiry)property_clear, /* tp_clear */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001902 0, /* tp_richcompare */
1903 0, /* tp_weaklistoffset */
1904 0, /* tp_iter */
1905 0, /* tp_iternext */
1906 property_methods, /* tp_methods */
1907 property_members, /* tp_members */
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -05001908 property_getsetlist, /* tp_getset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001909 0, /* tp_base */
1910 0, /* tp_dict */
1911 property_descr_get, /* tp_descr_get */
1912 property_descr_set, /* tp_descr_set */
1913 0, /* tp_dictoffset */
1914 property_init, /* tp_init */
1915 PyType_GenericAlloc, /* tp_alloc */
1916 PyType_GenericNew, /* tp_new */
1917 PyObject_GC_Del, /* tp_free */
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001918};