blob: 16c695a08f47d95cac669930ae480326000b8487 [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
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 }
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
Tim Peters6d6c1a32001-08-02 04:15:00 +0000998
Victor Stinner0db176f2012-04-16 00:16:30 +0200999/* --- mappingproxy: read-only proxy for mappings --- */
Tim Peters6d6c1a32001-08-02 04:15:00 +00001000
1001/* This has no reason to be in this file except that adding new files is a
1002 bit of a pain */
1003
1004typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001005 PyObject_HEAD
Victor Stinner0db176f2012-04-16 00:16:30 +02001006 PyObject *mapping;
1007} mappingproxyobject;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001008
Martin v. Löwis18e16552006-02-15 17:27:45 +00001009static Py_ssize_t
Victor Stinner0db176f2012-04-16 00:16:30 +02001010mappingproxy_len(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001011{
Victor Stinner0db176f2012-04-16 00:16:30 +02001012 return PyObject_Size(pp->mapping);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001013}
1014
1015static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001016mappingproxy_getitem(mappingproxyobject *pp, PyObject *key)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001017{
Victor Stinner0db176f2012-04-16 00:16:30 +02001018 return PyObject_GetItem(pp->mapping, key);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001019}
1020
Victor Stinner0db176f2012-04-16 00:16:30 +02001021static PyMappingMethods mappingproxy_as_mapping = {
1022 (lenfunc)mappingproxy_len, /* mp_length */
1023 (binaryfunc)mappingproxy_getitem, /* mp_subscript */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001024 0, /* mp_ass_subscript */
Tim Peters6d6c1a32001-08-02 04:15:00 +00001025};
1026
Brandt Bucher4663f662020-03-07 11:03:09 -08001027static PyObject *
1028mappingproxy_or(PyObject *left, PyObject *right)
1029{
1030 if (PyObject_TypeCheck(left, &PyDictProxy_Type)) {
1031 left = ((mappingproxyobject*)left)->mapping;
1032 }
1033 if (PyObject_TypeCheck(right, &PyDictProxy_Type)) {
1034 right = ((mappingproxyobject*)right)->mapping;
1035 }
1036 return PyNumber_Or(left, right);
1037}
1038
1039static PyObject *
1040mappingproxy_ior(PyObject *self, PyObject *Py_UNUSED(other))
1041{
1042 return PyErr_Format(PyExc_TypeError,
1043 "'|=' is not supported by %s; use '|' instead", Py_TYPE(self)->tp_name);
1044}
1045
1046static PyNumberMethods mappingproxy_as_number = {
1047 .nb_or = mappingproxy_or,
1048 .nb_inplace_or = mappingproxy_ior,
1049};
1050
Tim Peters6d6c1a32001-08-02 04:15:00 +00001051static int
Victor Stinner0db176f2012-04-16 00:16:30 +02001052mappingproxy_contains(mappingproxyobject *pp, PyObject *key)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001053{
Victor Stinner0db176f2012-04-16 00:16:30 +02001054 if (PyDict_CheckExact(pp->mapping))
1055 return PyDict_Contains(pp->mapping, key);
1056 else
1057 return PySequence_Contains(pp->mapping, key);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001058}
1059
Victor Stinner0db176f2012-04-16 00:16:30 +02001060static PySequenceMethods mappingproxy_as_sequence = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001061 0, /* sq_length */
1062 0, /* sq_concat */
1063 0, /* sq_repeat */
1064 0, /* sq_item */
1065 0, /* sq_slice */
1066 0, /* sq_ass_item */
1067 0, /* sq_ass_slice */
Victor Stinner0db176f2012-04-16 00:16:30 +02001068 (objobjproc)mappingproxy_contains, /* sq_contains */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001069 0, /* sq_inplace_concat */
1070 0, /* sq_inplace_repeat */
Tim Peters6d6c1a32001-08-02 04:15:00 +00001071};
1072
1073static PyObject *
Jeroen Demeyerb1263d52019-06-28 11:49:00 +02001074mappingproxy_get(mappingproxyobject *pp, PyObject *const *args, Py_ssize_t nargs)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001075{
Jeroen Demeyerb1263d52019-06-28 11:49:00 +02001076 /* newargs: mapping, key, default=None */
1077 PyObject *newargs[3];
1078 newargs[0] = pp->mapping;
1079 newargs[2] = Py_None;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001080
Jeroen Demeyerb1263d52019-06-28 11:49:00 +02001081 if (!_PyArg_UnpackStack(args, nargs, "get", 1, 2,
1082 &newargs[1], &newargs[2]))
1083 {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001084 return NULL;
Jeroen Demeyerb1263d52019-06-28 11:49:00 +02001085 }
1086 _Py_IDENTIFIER(get);
1087 return _PyObject_VectorcallMethodId(&PyId_get, newargs,
1088 3 | PY_VECTORCALL_ARGUMENTS_OFFSET,
1089 NULL);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001090}
1091
1092static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301093mappingproxy_keys(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001094{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001095 _Py_IDENTIFIER(keys);
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001096 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId_keys);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001097}
1098
1099static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301100mappingproxy_values(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001101{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001102 _Py_IDENTIFIER(values);
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001103 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId_values);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001104}
1105
1106static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301107mappingproxy_items(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001108{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001109 _Py_IDENTIFIER(items);
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001110 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId_items);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001111}
1112
1113static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301114mappingproxy_copy(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001115{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001116 _Py_IDENTIFIER(copy);
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001117 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId_copy);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001118}
1119
Zackery Spytz02fa0ea2020-05-07 23:25:50 -06001120static PyObject *
1121mappingproxy_reversed(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
1122{
1123 _Py_IDENTIFIER(__reversed__);
1124 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId___reversed__);
1125}
1126
Victor Stinner0db176f2012-04-16 00:16:30 +02001127/* WARNING: mappingproxy methods must not give access
1128 to the underlying mapping */
1129
1130static PyMethodDef mappingproxy_methods[] = {
Zackery Spytz43d564c2019-08-13 23:51:06 -06001131 {"get", (PyCFunction)(void(*)(void))mappingproxy_get, METH_FASTCALL,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001132 PyDoc_STR("D.get(k[,d]) -> D[k] if k in D, else d."
Victor Stinner0db176f2012-04-16 00:16:30 +02001133 " d defaults to None.")},
1134 {"keys", (PyCFunction)mappingproxy_keys, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001135 PyDoc_STR("D.keys() -> list of D's keys")},
Victor Stinner0db176f2012-04-16 00:16:30 +02001136 {"values", (PyCFunction)mappingproxy_values, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001137 PyDoc_STR("D.values() -> list of D's values")},
Victor Stinner0db176f2012-04-16 00:16:30 +02001138 {"items", (PyCFunction)mappingproxy_items, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001139 PyDoc_STR("D.items() -> list of D's (key, value) pairs, as 2-tuples")},
Victor Stinner0db176f2012-04-16 00:16:30 +02001140 {"copy", (PyCFunction)mappingproxy_copy, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001141 PyDoc_STR("D.copy() -> a shallow copy of D")},
Guido van Rossum48b069a2020-04-07 09:50:06 -07001142 {"__class_getitem__", (PyCFunction)Py_GenericAlias, METH_O|METH_CLASS,
1143 PyDoc_STR("See PEP 585")},
Zackery Spytz02fa0ea2020-05-07 23:25:50 -06001144 {"__reversed__", (PyCFunction)mappingproxy_reversed, METH_NOARGS,
1145 PyDoc_STR("D.__reversed__() -> reverse iterator")},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001146 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001147};
1148
1149static void
Victor Stinner0db176f2012-04-16 00:16:30 +02001150mappingproxy_dealloc(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001151{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001152 _PyObject_GC_UNTRACK(pp);
Victor Stinner0db176f2012-04-16 00:16:30 +02001153 Py_DECREF(pp->mapping);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001154 PyObject_GC_Del(pp);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001155}
1156
1157static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001158mappingproxy_getiter(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001159{
Victor Stinner0db176f2012-04-16 00:16:30 +02001160 return PyObject_GetIter(pp->mapping);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001161}
1162
Neil Schemenauer26775122001-10-21 22:26:43 +00001163static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001164mappingproxy_str(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001165{
Victor Stinner0db176f2012-04-16 00:16:30 +02001166 return PyObject_Str(pp->mapping);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001167}
1168
Ezio Melottiac53ab62010-12-18 14:59:43 +00001169static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001170mappingproxy_repr(mappingproxyobject *pp)
Ezio Melottiac53ab62010-12-18 14:59:43 +00001171{
Victor Stinner0db176f2012-04-16 00:16:30 +02001172 return PyUnicode_FromFormat("mappingproxy(%R)", pp->mapping);
Ezio Melottiac53ab62010-12-18 14:59:43 +00001173}
1174
Guido van Rossum048eb752001-10-02 21:24:57 +00001175static int
Victor Stinner0db176f2012-04-16 00:16:30 +02001176mappingproxy_traverse(PyObject *self, visitproc visit, void *arg)
Guido van Rossum048eb752001-10-02 21:24:57 +00001177{
Victor Stinner0db176f2012-04-16 00:16:30 +02001178 mappingproxyobject *pp = (mappingproxyobject *)self;
1179 Py_VISIT(pp->mapping);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001180 return 0;
Guido van Rossum048eb752001-10-02 21:24:57 +00001181}
1182
Raymond Hettinger29a6d442002-08-31 15:51:04 +00001183static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001184mappingproxy_richcompare(mappingproxyobject *v, PyObject *w, int op)
Raymond Hettinger29a6d442002-08-31 15:51:04 +00001185{
Victor Stinner0db176f2012-04-16 00:16:30 +02001186 return PyObject_RichCompare(v->mapping, w, op);
1187}
1188
1189static int
1190mappingproxy_check_mapping(PyObject *mapping)
1191{
1192 if (!PyMapping_Check(mapping)
1193 || PyList_Check(mapping)
1194 || PyTuple_Check(mapping)) {
1195 PyErr_Format(PyExc_TypeError,
1196 "mappingproxy() argument must be a mapping, not %s",
1197 Py_TYPE(mapping)->tp_name);
1198 return -1;
1199 }
1200 return 0;
1201}
1202
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001203/*[clinic input]
1204@classmethod
1205mappingproxy.__new__ as mappingproxy_new
Victor Stinner0db176f2012-04-16 00:16:30 +02001206
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001207 mapping: object
1208
1209[clinic start generated code]*/
1210
1211static PyObject *
1212mappingproxy_new_impl(PyTypeObject *type, PyObject *mapping)
1213/*[clinic end generated code: output=65f27f02d5b68fa7 input=d2d620d4f598d4f8]*/
1214{
1215 mappingproxyobject *mappingproxy;
Victor Stinner0db176f2012-04-16 00:16:30 +02001216
1217 if (mappingproxy_check_mapping(mapping) == -1)
1218 return NULL;
1219
1220 mappingproxy = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type);
1221 if (mappingproxy == NULL)
1222 return NULL;
1223 Py_INCREF(mapping);
1224 mappingproxy->mapping = mapping;
1225 _PyObject_GC_TRACK(mappingproxy);
1226 return (PyObject *)mappingproxy;
Raymond Hettinger29a6d442002-08-31 15:51:04 +00001227}
1228
Tim Peters6d6c1a32001-08-02 04:15:00 +00001229PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001230PyDictProxy_New(PyObject *mapping)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001231{
Victor Stinner0db176f2012-04-16 00:16:30 +02001232 mappingproxyobject *pp;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001233
Victor Stinner0db176f2012-04-16 00:16:30 +02001234 if (mappingproxy_check_mapping(mapping) == -1)
1235 return NULL;
1236
1237 pp = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001238 if (pp != NULL) {
Victor Stinner0db176f2012-04-16 00:16:30 +02001239 Py_INCREF(mapping);
1240 pp->mapping = mapping;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001241 _PyObject_GC_TRACK(pp);
1242 }
1243 return (PyObject *)pp;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001244}
1245
1246
1247/* --- Wrapper object for "slot" methods --- */
1248
1249/* This has no reason to be in this file except that adding new files is a
1250 bit of a pain */
1251
1252typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001253 PyObject_HEAD
1254 PyWrapperDescrObject *descr;
1255 PyObject *self;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001256} wrapperobject;
1257
Andy Lesterdffe4c02020-03-04 07:15:20 -06001258#define Wrapper_Check(v) Py_IS_TYPE(v, &_PyMethodWrapper_Type)
Mark Dickinson211c6252009-02-01 10:28:51 +00001259
Tim Peters6d6c1a32001-08-02 04:15:00 +00001260static void
1261wrapper_dealloc(wrapperobject *wp)
1262{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001263 PyObject_GC_UnTrack(wp);
Jeroen Demeyer351c6742019-05-10 19:21:11 +02001264 Py_TRASHCAN_BEGIN(wp, wrapper_dealloc)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001265 Py_XDECREF(wp->descr);
1266 Py_XDECREF(wp->self);
1267 PyObject_GC_Del(wp);
Jeroen Demeyer351c6742019-05-10 19:21:11 +02001268 Py_TRASHCAN_END
Tim Peters6d6c1a32001-08-02 04:15:00 +00001269}
1270
Mark Dickinson211c6252009-02-01 10:28:51 +00001271static PyObject *
1272wrapper_richcompare(PyObject *a, PyObject *b, int op)
Armin Rigoc6686b72005-11-07 08:38:00 +00001273{
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001274 wrapperobject *wa, *wb;
1275 int eq;
Mark Dickinson211c6252009-02-01 10:28:51 +00001276
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001277 assert(a != NULL && b != NULL);
Mark Dickinson211c6252009-02-01 10:28:51 +00001278
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001279 /* both arguments should be wrapperobjects */
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001280 if ((op != Py_EQ && op != Py_NE)
1281 || !Wrapper_Check(a) || !Wrapper_Check(b))
1282 {
stratakise8b19652017-11-02 11:32:54 +01001283 Py_RETURN_NOTIMPLEMENTED;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001284 }
Mark Dickinson211c6252009-02-01 10:28:51 +00001285
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001286 wa = (wrapperobject *)a;
1287 wb = (wrapperobject *)b;
1288 eq = (wa->descr == wb->descr && wa->self == wb->self);
1289 if (eq == (op == Py_EQ)) {
1290 Py_RETURN_TRUE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001291 }
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001292 else {
1293 Py_RETURN_FALSE;
1294 }
Armin Rigoc6686b72005-11-07 08:38:00 +00001295}
1296
Benjamin Peterson8f67d082010-10-17 20:54:53 +00001297static Py_hash_t
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001298wrapper_hash(wrapperobject *wp)
1299{
Benjamin Peterson8f67d082010-10-17 20:54:53 +00001300 Py_hash_t x, y;
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001301 x = _Py_HashPointer(wp->self);
1302 y = _Py_HashPointer(wp->descr);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001303 x = x ^ y;
1304 if (x == -1)
1305 x = -2;
1306 return x;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001307}
1308
Armin Rigoc6686b72005-11-07 08:38:00 +00001309static PyObject *
1310wrapper_repr(wrapperobject *wp)
1311{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001312 return PyUnicode_FromFormat("<method-wrapper '%s' of %s object at %p>",
1313 wp->descr->d_base->name,
Victor Stinner58ac7002020-02-07 03:04:21 +01001314 Py_TYPE(wp->self)->tp_name,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001315 wp->self);
Armin Rigoc6686b72005-11-07 08:38:00 +00001316}
1317
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001318static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301319wrapper_reduce(wrapperobject *wp, PyObject *Py_UNUSED(ignored))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001320{
Serhiy Storchakabb86bf42018-12-11 08:28:18 +02001321 return Py_BuildValue("N(OO)", _PyEval_GetBuiltinId(&PyId_getattr),
1322 wp->self, PyDescr_NAME(wp->descr));
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001323}
1324
1325static PyMethodDef wrapper_methods[] = {
1326 {"__reduce__", (PyCFunction)wrapper_reduce, METH_NOARGS, NULL},
1327 {NULL, NULL}
1328};
1329
Armin Rigoc6686b72005-11-07 08:38:00 +00001330static PyMemberDef wrapper_members[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001331 {"__self__", T_OBJECT, offsetof(wrapperobject, self), READONLY},
1332 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001333};
1334
1335static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001336wrapper_objclass(wrapperobject *wp, void *Py_UNUSED(ignored))
Armin Rigoc6686b72005-11-07 08:38:00 +00001337{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001338 PyObject *c = (PyObject *)PyDescr_TYPE(wp->descr);
Armin Rigoc6686b72005-11-07 08:38:00 +00001339
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001340 Py_INCREF(c);
1341 return c;
Armin Rigoc6686b72005-11-07 08:38:00 +00001342}
1343
1344static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001345wrapper_name(wrapperobject *wp, void *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001346{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001347 const char *s = wp->descr->d_base->name;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001348
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001349 return PyUnicode_FromString(s);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001350}
1351
1352static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001353wrapper_doc(wrapperobject *wp, void *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001354{
Larry Hastings2623c8c2014-02-08 22:15:29 -08001355 return _PyType_GetDocFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc);
Larry Hastings5c661892014-01-24 06:17:25 -08001356}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001357
Larry Hastings5c661892014-01-24 06:17:25 -08001358static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001359wrapper_text_signature(wrapperobject *wp, void *Py_UNUSED(ignored))
Larry Hastings5c661892014-01-24 06:17:25 -08001360{
Larry Hastings2623c8c2014-02-08 22:15:29 -08001361 return _PyType_GetTextSignatureFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001362}
1363
Antoine Pitrou9d574812011-12-12 13:47:25 +01001364static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001365wrapper_qualname(wrapperobject *wp, void *Py_UNUSED(ignored))
Antoine Pitrou9d574812011-12-12 13:47:25 +01001366{
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001367 return descr_get_qualname((PyDescrObject *)wp->descr, NULL);
Antoine Pitrou9d574812011-12-12 13:47:25 +01001368}
1369
Guido van Rossum32d34c82001-09-20 21:45:26 +00001370static PyGetSetDef wrapper_getsets[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001371 {"__objclass__", (getter)wrapper_objclass},
1372 {"__name__", (getter)wrapper_name},
Antoine Pitrou9d574812011-12-12 13:47:25 +01001373 {"__qualname__", (getter)wrapper_qualname},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001374 {"__doc__", (getter)wrapper_doc},
Larry Hastings5c661892014-01-24 06:17:25 -08001375 {"__text_signature__", (getter)wrapper_text_signature},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001376 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001377};
1378
1379static PyObject *
1380wrapper_call(wrapperobject *wp, PyObject *args, PyObject *kwds)
1381{
Serhiy Storchaka5e02c782017-09-21 14:25:36 +03001382 return wrapperdescr_raw_call(wp->descr, wp->self, args, kwds);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001383}
1384
Guido van Rossum048eb752001-10-02 21:24:57 +00001385static int
1386wrapper_traverse(PyObject *self, visitproc visit, void *arg)
1387{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001388 wrapperobject *wp = (wrapperobject *)self;
1389 Py_VISIT(wp->descr);
1390 Py_VISIT(wp->self);
1391 return 0;
Guido van Rossum048eb752001-10-02 21:24:57 +00001392}
1393
Benjamin Petersoneff61f62011-09-01 16:32:31 -04001394PyTypeObject _PyMethodWrapper_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001395 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1396 "method-wrapper", /* tp_name */
1397 sizeof(wrapperobject), /* tp_basicsize */
1398 0, /* tp_itemsize */
1399 /* methods */
1400 (destructor)wrapper_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001401 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001402 0, /* tp_getattr */
1403 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001404 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001405 (reprfunc)wrapper_repr, /* tp_repr */
1406 0, /* tp_as_number */
1407 0, /* tp_as_sequence */
1408 0, /* tp_as_mapping */
1409 (hashfunc)wrapper_hash, /* tp_hash */
1410 (ternaryfunc)wrapper_call, /* tp_call */
1411 0, /* tp_str */
1412 PyObject_GenericGetAttr, /* tp_getattro */
1413 0, /* tp_setattro */
1414 0, /* tp_as_buffer */
1415 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1416 0, /* tp_doc */
1417 wrapper_traverse, /* tp_traverse */
1418 0, /* tp_clear */
1419 wrapper_richcompare, /* tp_richcompare */
1420 0, /* tp_weaklistoffset */
1421 0, /* tp_iter */
1422 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001423 wrapper_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001424 wrapper_members, /* tp_members */
1425 wrapper_getsets, /* tp_getset */
1426 0, /* tp_base */
1427 0, /* tp_dict */
1428 0, /* tp_descr_get */
1429 0, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +00001430};
1431
1432PyObject *
1433PyWrapper_New(PyObject *d, PyObject *self)
1434{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001435 wrapperobject *wp;
1436 PyWrapperDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001437
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001438 assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type));
1439 descr = (PyWrapperDescrObject *)d;
Victor Stinner3249dec2011-05-01 23:19:15 +02001440 assert(_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
Victor Stinnerd9561312011-05-01 23:31:36 +02001441 (PyObject *)PyDescr_TYPE(descr)));
Tim Peters6d6c1a32001-08-02 04:15:00 +00001442
Benjamin Petersoneff61f62011-09-01 16:32:31 -04001443 wp = PyObject_GC_New(wrapperobject, &_PyMethodWrapper_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001444 if (wp != NULL) {
1445 Py_INCREF(descr);
1446 wp->descr = descr;
1447 Py_INCREF(self);
1448 wp->self = self;
1449 _PyObject_GC_TRACK(wp);
1450 }
1451 return (PyObject *)wp;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001452}
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001453
1454
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001455/* A built-in 'property' type */
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001456
1457/*
Serhiy Storchakad741a882015-06-11 00:06:39 +03001458class property(object):
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001459
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001460 def __init__(self, fget=None, fset=None, fdel=None, doc=None):
1461 if doc is None and fget is not None and hasattr(fget, "__doc__"):
Serhiy Storchakad741a882015-06-11 00:06:39 +03001462 doc = fget.__doc__
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001463 self.__get = fget
1464 self.__set = fset
1465 self.__del = fdel
1466 self.__doc__ = doc
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001467
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001468 def __get__(self, inst, type=None):
1469 if inst is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001470 return self
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001471 if self.__get is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001472 raise AttributeError, "unreadable attribute"
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001473 return self.__get(inst)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001474
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001475 def __set__(self, inst, value):
1476 if self.__set is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001477 raise AttributeError, "can't set attribute"
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001478 return self.__set(inst, value)
Guido van Rossumba2485f2001-12-10 18:03:34 +00001479
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001480 def __delete__(self, inst):
1481 if self.__del is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001482 raise AttributeError, "can't delete attribute"
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001483 return self.__del(inst)
Guido van Rossumba2485f2001-12-10 18:03:34 +00001484
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001485*/
1486
1487typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001488 PyObject_HEAD
1489 PyObject *prop_get;
1490 PyObject *prop_set;
1491 PyObject *prop_del;
1492 PyObject *prop_doc;
Yurii Karabasc56387f2020-12-30 11:51:24 +02001493 PyObject *prop_name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001494 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
Yurii Karabasc56387f2020-12-30 11:51:24 +02001539PyDoc_STRVAR(set_name_doc,
1540 "Method to set name of a property.");
1541
1542static PyObject *
1543property_set_name(PyObject *self, PyObject *args) {
1544 if (PyTuple_GET_SIZE(args) != 2) {
1545 PyErr_Format(
1546 PyExc_TypeError,
1547 "__set_name__() takes 2 positional arguments but %d were given",
1548 PyTuple_GET_SIZE(args));
1549 return NULL;
1550 }
1551
1552 propertyobject *prop = (propertyobject *)self;
1553 PyObject *name = PyTuple_GET_ITEM(args, 1);
1554
1555 Py_XINCREF(name);
1556 Py_XSETREF(prop->prop_name, name);
1557
1558 Py_RETURN_NONE;
1559}
1560
Guido van Rossum58da9312007-11-10 23:39:45 +00001561static PyMethodDef property_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001562 {"getter", property_getter, METH_O, getter_doc},
1563 {"setter", property_setter, METH_O, setter_doc},
1564 {"deleter", property_deleter, METH_O, deleter_doc},
Yurii Karabasc56387f2020-12-30 11:51:24 +02001565 {"__set_name__", property_set_name, METH_VARARGS, set_name_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001566 {0}
Guido van Rossum58da9312007-11-10 23:39:45 +00001567};
1568
Tim Peters66c1a522001-09-24 21:17:50 +00001569
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001570static void
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001571property_dealloc(PyObject *self)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001572{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001573 propertyobject *gs = (propertyobject *)self;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001574
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001575 _PyObject_GC_UNTRACK(self);
1576 Py_XDECREF(gs->prop_get);
1577 Py_XDECREF(gs->prop_set);
1578 Py_XDECREF(gs->prop_del);
1579 Py_XDECREF(gs->prop_doc);
Yurii Karabasc56387f2020-12-30 11:51:24 +02001580 Py_XDECREF(gs->prop_name);
Victor Stinner58ac7002020-02-07 03:04:21 +01001581 Py_TYPE(self)->tp_free(self);
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001582}
1583
1584static PyObject *
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001585property_descr_get(PyObject *self, PyObject *obj, PyObject *type)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001586{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001587 if (obj == NULL || obj == Py_None) {
1588 Py_INCREF(self);
1589 return self;
1590 }
Victor Stinnere972c132018-10-01 03:03:22 -07001591
1592 propertyobject *gs = (propertyobject *)self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001593 if (gs->prop_get == NULL) {
Yurii Karabasc56387f2020-12-30 11:51:24 +02001594 if (gs->prop_name != NULL) {
1595 PyErr_Format(PyExc_AttributeError, "unreadable attribute %R", gs->prop_name);
1596 } else {
1597 PyErr_SetString(PyExc_AttributeError, "unreadable attribute");
1598 }
1599
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001600 return NULL;
1601 }
Victor Stinnere972c132018-10-01 03:03:22 -07001602
Petr Viktorinffd97532020-02-11 17:46:57 +01001603 return PyObject_CallOneArg(gs->prop_get, obj);
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001604}
1605
1606static int
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001607property_descr_set(PyObject *self, PyObject *obj, PyObject *value)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001608{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001609 propertyobject *gs = (propertyobject *)self;
1610 PyObject *func, *res;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001611
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001612 if (value == NULL)
1613 func = gs->prop_del;
1614 else
1615 func = gs->prop_set;
1616 if (func == NULL) {
Yurii Karabasc56387f2020-12-30 11:51:24 +02001617 if (gs->prop_name != NULL) {
1618 PyErr_Format(PyExc_AttributeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001619 value == NULL ?
Yurii Karabasc56387f2020-12-30 11:51:24 +02001620 "can't delete attribute %R" :
1621 "can't set attribute %R",
1622 gs->prop_name);
1623 } else {
1624 PyErr_SetString(PyExc_AttributeError,
1625 value == NULL ?
1626 "can't delete attribute" :
1627 "can't set attribute");
1628 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001629 return -1;
1630 }
1631 if (value == NULL)
Petr Viktorinffd97532020-02-11 17:46:57 +01001632 res = PyObject_CallOneArg(func, obj);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001633 else
Benjamin Peterson9b955de2010-12-07 04:04:02 +00001634 res = PyObject_CallFunctionObjArgs(func, obj, value, NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001635 if (res == NULL)
1636 return -1;
1637 Py_DECREF(res);
1638 return 0;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001639}
1640
Christian Heimes0449f632007-12-15 01:27:15 +00001641static PyObject *
Benjamin Peterson93964832010-06-28 03:07:10 +00001642property_copy(PyObject *old, PyObject *get, PyObject *set, PyObject *del)
Christian Heimes0449f632007-12-15 01:27:15 +00001643{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001644 propertyobject *pold = (propertyobject *)old;
Benjamin Peterson93964832010-06-28 03:07:10 +00001645 PyObject *new, *type, *doc;
Christian Heimes0449f632007-12-15 01:27:15 +00001646
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001647 type = PyObject_Type(old);
1648 if (type == NULL)
1649 return NULL;
Christian Heimes0449f632007-12-15 01:27:15 +00001650
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001651 if (get == NULL || get == Py_None) {
1652 Py_XDECREF(get);
1653 get = pold->prop_get ? pold->prop_get : Py_None;
1654 }
1655 if (set == NULL || set == Py_None) {
1656 Py_XDECREF(set);
1657 set = pold->prop_set ? pold->prop_set : Py_None;
1658 }
1659 if (del == NULL || del == Py_None) {
1660 Py_XDECREF(del);
1661 del = pold->prop_del ? pold->prop_del : Py_None;
1662 }
Benjamin Peterson93964832010-06-28 03:07:10 +00001663 if (pold->getter_doc && get != Py_None) {
1664 /* make _init use __doc__ from getter */
1665 doc = Py_None;
1666 }
1667 else {
1668 doc = pold->prop_doc ? pold->prop_doc : Py_None;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001669 }
R. David Murrayb18500d2009-05-04 22:59:07 +00001670
Victor Stinner5abaa2b2016-12-09 16:22:32 +01001671 new = PyObject_CallFunctionObjArgs(type, get, set, del, doc, NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001672 Py_DECREF(type);
1673 if (new == NULL)
1674 return NULL;
Yurii Karabasc56387f2020-12-30 11:51:24 +02001675
1676 Py_XINCREF(pold->prop_name);
1677 Py_XSETREF(((propertyobject *) new)->prop_name, pold->prop_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001678 return new;
Christian Heimes0449f632007-12-15 01:27:15 +00001679}
1680
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001681/*[clinic input]
1682property.__init__ as property_init
1683
1684 fget: object(c_default="NULL") = None
1685 function to be used for getting an attribute value
1686 fset: object(c_default="NULL") = None
1687 function to be used for setting an attribute value
1688 fdel: object(c_default="NULL") = None
1689 function to be used for del'ing an attribute
1690 doc: object(c_default="NULL") = None
1691 docstring
1692
1693Property attribute.
1694
1695Typical use is to define a managed attribute x:
1696
1697class C(object):
1698 def getx(self): return self._x
1699 def setx(self, value): self._x = value
1700 def delx(self): del self._x
1701 x = property(getx, setx, delx, "I'm the 'x' property.")
1702
1703Decorators make defining new properties or modifying existing ones easy:
1704
1705class C(object):
1706 @property
1707 def x(self):
1708 "I am the 'x' property."
1709 return self._x
1710 @x.setter
1711 def x(self, value):
1712 self._x = value
1713 @x.deleter
1714 def x(self):
1715 del self._x
1716[clinic start generated code]*/
1717
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001718static int
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001719property_init_impl(propertyobject *self, PyObject *fget, PyObject *fset,
1720 PyObject *fdel, PyObject *doc)
1721/*[clinic end generated code: output=01a960742b692b57 input=dfb5dbbffc6932d5]*/
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001722{
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001723 if (fget == Py_None)
1724 fget = NULL;
1725 if (fset == Py_None)
1726 fset = NULL;
1727 if (fdel == Py_None)
1728 fdel = NULL;
Tim Peters66c1a522001-09-24 21:17:50 +00001729
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001730 Py_XINCREF(fget);
1731 Py_XINCREF(fset);
1732 Py_XINCREF(fdel);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001733 Py_XINCREF(doc);
Christian Heimes0449f632007-12-15 01:27:15 +00001734
Oren Milmand019bc82018-02-13 12:28:33 +02001735 Py_XSETREF(self->prop_get, fget);
1736 Py_XSETREF(self->prop_set, fset);
1737 Py_XSETREF(self->prop_del, fdel);
1738 Py_XSETREF(self->prop_doc, doc);
Yurii Karabasc56387f2020-12-30 11:51:24 +02001739 Py_XSETREF(self->prop_name, NULL);
1740
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001741 self->getter_doc = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001742
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001743 /* if no docstring given and the getter has one, use that one */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001744 if ((doc == NULL || doc == Py_None) && fget != NULL) {
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001745 _Py_IDENTIFIER(__doc__);
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001746 PyObject *get_doc;
1747 int rc = _PyObject_LookupAttrId(fget, &PyId___doc__, &get_doc);
1748 if (rc <= 0) {
1749 return rc;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001750 }
Andy Lesterdffe4c02020-03-04 07:15:20 -06001751 if (Py_IS_TYPE(self, &PyProperty_Type)) {
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001752 Py_XSETREF(self->prop_doc, get_doc);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001753 }
1754 else {
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001755 /* If this is a property subclass, put __doc__
1756 in dict of the subclass instance instead,
1757 otherwise it gets shadowed by __doc__ in the
1758 class's dict. */
1759 int err = _PyObject_SetAttrId((PyObject *)self, &PyId___doc__, get_doc);
1760 Py_DECREF(get_doc);
1761 if (err < 0)
1762 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001763 }
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001764 self->getter_doc = 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001765 }
1766
1767 return 0;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001768}
1769
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -05001770static PyObject *
1771property_get___isabstractmethod__(propertyobject *prop, void *closure)
1772{
1773 int res = _PyObject_IsAbstract(prop->prop_get);
1774 if (res == -1) {
1775 return NULL;
1776 }
1777 else if (res) {
1778 Py_RETURN_TRUE;
1779 }
1780
1781 res = _PyObject_IsAbstract(prop->prop_set);
1782 if (res == -1) {
1783 return NULL;
1784 }
1785 else if (res) {
1786 Py_RETURN_TRUE;
1787 }
1788
1789 res = _PyObject_IsAbstract(prop->prop_del);
1790 if (res == -1) {
1791 return NULL;
1792 }
1793 else if (res) {
1794 Py_RETURN_TRUE;
1795 }
1796 Py_RETURN_FALSE;
1797}
1798
1799static PyGetSetDef property_getsetlist[] = {
1800 {"__isabstractmethod__",
1801 (getter)property_get___isabstractmethod__, NULL,
1802 NULL,
1803 NULL},
1804 {NULL} /* Sentinel */
1805};
1806
Guido van Rossum048eb752001-10-02 21:24:57 +00001807static int
1808property_traverse(PyObject *self, visitproc visit, void *arg)
1809{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001810 propertyobject *pp = (propertyobject *)self;
1811 Py_VISIT(pp->prop_get);
1812 Py_VISIT(pp->prop_set);
1813 Py_VISIT(pp->prop_del);
1814 Py_VISIT(pp->prop_doc);
Yurii Karabasc56387f2020-12-30 11:51:24 +02001815 Py_VISIT(pp->prop_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001816 return 0;
Guido van Rossum048eb752001-10-02 21:24:57 +00001817}
1818
Raymond Hettingerd4be6912015-05-13 11:12:33 -07001819static int
1820property_clear(PyObject *self)
1821{
1822 propertyobject *pp = (propertyobject *)self;
1823 Py_CLEAR(pp->prop_doc);
1824 return 0;
1825}
1826
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001827#include "clinic/descrobject.c.h"
1828
1829PyTypeObject PyDictProxy_Type = {
1830 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1831 "mappingproxy", /* tp_name */
1832 sizeof(mappingproxyobject), /* tp_basicsize */
1833 0, /* tp_itemsize */
1834 /* methods */
1835 (destructor)mappingproxy_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001836 0, /* tp_vectorcall_offset */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001837 0, /* tp_getattr */
1838 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001839 0, /* tp_as_async */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001840 (reprfunc)mappingproxy_repr, /* tp_repr */
Brandt Bucher4663f662020-03-07 11:03:09 -08001841 &mappingproxy_as_number, /* tp_as_number */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001842 &mappingproxy_as_sequence, /* tp_as_sequence */
1843 &mappingproxy_as_mapping, /* tp_as_mapping */
1844 0, /* tp_hash */
1845 0, /* tp_call */
1846 (reprfunc)mappingproxy_str, /* tp_str */
1847 PyObject_GenericGetAttr, /* tp_getattro */
1848 0, /* tp_setattro */
1849 0, /* tp_as_buffer */
1850 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1851 0, /* tp_doc */
1852 mappingproxy_traverse, /* tp_traverse */
1853 0, /* tp_clear */
1854 (richcmpfunc)mappingproxy_richcompare, /* tp_richcompare */
1855 0, /* tp_weaklistoffset */
1856 (getiterfunc)mappingproxy_getiter, /* tp_iter */
1857 0, /* tp_iternext */
1858 mappingproxy_methods, /* tp_methods */
1859 0, /* tp_members */
1860 0, /* tp_getset */
1861 0, /* tp_base */
1862 0, /* tp_dict */
1863 0, /* tp_descr_get */
1864 0, /* tp_descr_set */
1865 0, /* tp_dictoffset */
1866 0, /* tp_init */
1867 0, /* tp_alloc */
1868 mappingproxy_new, /* tp_new */
1869};
1870
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001871PyTypeObject PyProperty_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001872 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1873 "property", /* tp_name */
1874 sizeof(propertyobject), /* tp_basicsize */
1875 0, /* tp_itemsize */
1876 /* methods */
1877 property_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001878 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001879 0, /* tp_getattr */
1880 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001881 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001882 0, /* tp_repr */
1883 0, /* tp_as_number */
1884 0, /* tp_as_sequence */
1885 0, /* tp_as_mapping */
1886 0, /* tp_hash */
1887 0, /* tp_call */
1888 0, /* tp_str */
1889 PyObject_GenericGetAttr, /* tp_getattro */
1890 0, /* tp_setattro */
1891 0, /* tp_as_buffer */
1892 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1893 Py_TPFLAGS_BASETYPE, /* tp_flags */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001894 property_init__doc__, /* tp_doc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001895 property_traverse, /* tp_traverse */
Raymond Hettingerd4be6912015-05-13 11:12:33 -07001896 (inquiry)property_clear, /* tp_clear */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001897 0, /* tp_richcompare */
1898 0, /* tp_weaklistoffset */
1899 0, /* tp_iter */
1900 0, /* tp_iternext */
1901 property_methods, /* tp_methods */
1902 property_members, /* tp_members */
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -05001903 property_getsetlist, /* tp_getset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001904 0, /* tp_base */
1905 0, /* tp_dict */
1906 property_descr_get, /* tp_descr_get */
1907 property_descr_set, /* tp_descr_set */
1908 0, /* tp_dictoffset */
1909 property_init, /* tp_init */
1910 PyType_GenericAlloc, /* tp_alloc */
1911 PyType_GenericNew, /* tp_new */
1912 PyObject_GC_Del, /* tp_free */
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001913};