blob: 4ebbb74151a232478633cb87bbb3f4119ba6ba09 [file] [log] [blame]
Tim Peters6d6c1a32001-08-02 04:15:00 +00001/* Descriptors -- a new, flexible way to describe attributes */
2
3#include "Python.h"
Victor Stinnerbcda8f12018-11-21 22:27:47 +01004#include "pycore_object.h"
Victor Stinner621cebe2018-11-12 16:53:38 +01005#include "pycore_pystate.h"
Victor Stinnerec13b932018-11-25 23:56:17 +01006#include "pycore_tupleobject.h"
Tim Peters6d6c1a32001-08-02 04:15:00 +00007#include "structmember.h" /* Why is this not included in Python.h? */
8
Hai Shi46874c22020-01-30 17:20:25 -06009_Py_IDENTIFIER(getattr);
10
Serhiy Storchaka18b250f2017-03-19 08:51:07 +020011/*[clinic input]
12class mappingproxy "mappingproxyobject *" "&PyDictProxy_Type"
13class property "propertyobject *" "&PyProperty_Type"
14[clinic start generated code]*/
15/*[clinic end generated code: output=da39a3ee5e6b4b0d input=556352653fd4c02e]*/
16
Tim Peters6d6c1a32001-08-02 04:15:00 +000017static void
18descr_dealloc(PyDescrObject *descr)
19{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000020 _PyObject_GC_UNTRACK(descr);
21 Py_XDECREF(descr->d_type);
22 Py_XDECREF(descr->d_name);
Antoine Pitrou9d574812011-12-12 13:47:25 +010023 Py_XDECREF(descr->d_qualname);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000024 PyObject_GC_Del(descr);
Tim Peters6d6c1a32001-08-02 04:15:00 +000025}
26
Walter Dörwaldd7fb7642007-06-11 16:36:59 +000027static PyObject *
Tim Peters6d6c1a32001-08-02 04:15:00 +000028descr_name(PyDescrObject *descr)
29{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000030 if (descr->d_name != NULL && PyUnicode_Check(descr->d_name))
31 return descr->d_name;
32 return NULL;
Tim Peters6d6c1a32001-08-02 04:15:00 +000033}
34
35static PyObject *
Serhiy Storchakaef1585e2015-12-25 20:01:53 +020036descr_repr(PyDescrObject *descr, const char *format)
Tim Peters6d6c1a32001-08-02 04:15:00 +000037{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000038 PyObject *name = NULL;
39 if (descr->d_name != NULL && PyUnicode_Check(descr->d_name))
40 name = descr->d_name;
Walter Dörwaldd7fb7642007-06-11 16:36:59 +000041
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000042 return PyUnicode_FromFormat(format, name, "?", descr->d_type->tp_name);
Tim Peters6d6c1a32001-08-02 04:15:00 +000043}
44
45static PyObject *
46method_repr(PyMethodDescrObject *descr)
47{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000048 return descr_repr((PyDescrObject *)descr,
49 "<method '%V' of '%s' objects>");
Tim Peters6d6c1a32001-08-02 04:15:00 +000050}
51
52static PyObject *
53member_repr(PyMemberDescrObject *descr)
54{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000055 return descr_repr((PyDescrObject *)descr,
56 "<member '%V' of '%s' objects>");
Tim Peters6d6c1a32001-08-02 04:15:00 +000057}
58
59static PyObject *
60getset_repr(PyGetSetDescrObject *descr)
61{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000062 return descr_repr((PyDescrObject *)descr,
63 "<attribute '%V' of '%s' objects>");
Tim Peters6d6c1a32001-08-02 04:15:00 +000064}
65
66static PyObject *
Armin Rigoc6686b72005-11-07 08:38:00 +000067wrapperdescr_repr(PyWrapperDescrObject *descr)
Tim Peters6d6c1a32001-08-02 04:15:00 +000068{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000069 return descr_repr((PyDescrObject *)descr,
70 "<slot wrapper '%V' of '%s' objects>");
Tim Peters6d6c1a32001-08-02 04:15:00 +000071}
72
73static int
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +000074descr_check(PyDescrObject *descr, PyObject *obj, PyObject **pres)
Tim Peters6d6c1a32001-08-02 04:15:00 +000075{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000076 if (obj == NULL) {
77 Py_INCREF(descr);
78 *pres = (PyObject *)descr;
79 return 1;
80 }
81 if (!PyObject_TypeCheck(obj, descr->d_type)) {
82 PyErr_Format(PyExc_TypeError,
Inada Naoki62f95882019-04-01 17:56:11 +090083 "descriptor '%V' for '%.100s' objects "
84 "doesn't apply to a '%.100s' object",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000085 descr_name((PyDescrObject *)descr), "?",
86 descr->d_type->tp_name,
Victor Stinner58ac7002020-02-07 03:04:21 +010087 Py_TYPE(obj)->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000088 *pres = NULL;
89 return 1;
90 }
91 return 0;
Tim Peters6d6c1a32001-08-02 04:15:00 +000092}
93
94static PyObject *
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +000095classmethod_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type)
Tim Petersbca1cbc2002-12-09 22:56:13 +000096{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000097 /* Ensure a valid type. Class methods ignore obj. */
98 if (type == NULL) {
99 if (obj != NULL)
Victor Stinner58ac7002020-02-07 03:04:21 +0100100 type = (PyObject *)Py_TYPE(obj);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000101 else {
102 /* Wot - no type?! */
103 PyErr_Format(PyExc_TypeError,
Inada Naoki62f95882019-04-01 17:56:11 +0900104 "descriptor '%V' for type '%.100s' "
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000105 "needs either an object or a type",
106 descr_name((PyDescrObject *)descr), "?",
107 PyDescr_TYPE(descr)->tp_name);
108 return NULL;
109 }
110 }
111 if (!PyType_Check(type)) {
112 PyErr_Format(PyExc_TypeError,
Inada Naoki62f95882019-04-01 17:56:11 +0900113 "descriptor '%V' for type '%.100s' "
114 "needs a type, not a '%.100s' as arg 2",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000115 descr_name((PyDescrObject *)descr), "?",
116 PyDescr_TYPE(descr)->tp_name,
Victor Stinner58ac7002020-02-07 03:04:21 +0100117 Py_TYPE(type)->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000118 return NULL;
119 }
120 if (!PyType_IsSubtype((PyTypeObject *)type, PyDescr_TYPE(descr))) {
121 PyErr_Format(PyExc_TypeError,
Inada Naoki62f95882019-04-01 17:56:11 +0900122 "descriptor '%V' requires a subtype of '%.100s' "
123 "but received '%.100s'",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000124 descr_name((PyDescrObject *)descr), "?",
125 PyDescr_TYPE(descr)->tp_name,
126 ((PyTypeObject *)type)->tp_name);
127 return NULL;
128 }
Andrew Svetlov3ba3a3e2012-12-25 13:32:35 +0200129 return PyCFunction_NewEx(descr->d_method, type, NULL);
Tim Petersbca1cbc2002-12-09 22:56:13 +0000130}
131
132static PyObject *
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +0000133method_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000134{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000135 PyObject *res;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000136
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000137 if (descr_check((PyDescrObject *)descr, obj, &res))
138 return res;
Andrew Svetlov3ba3a3e2012-12-25 13:32:35 +0200139 return PyCFunction_NewEx(descr->d_method, obj, NULL);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000140}
141
142static PyObject *
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +0000143member_get(PyMemberDescrObject *descr, PyObject *obj, PyObject *type)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000144{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000145 PyObject *res;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000146
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000147 if (descr_check((PyDescrObject *)descr, obj, &res))
148 return res;
Steve Dowerb82e17e2019-05-23 08:45:22 -0700149
150 if (descr->d_member->flags & READ_RESTRICTED) {
151 if (PySys_Audit("object.__getattr__", "Os",
152 obj ? obj : Py_None, descr->d_member->name) < 0) {
153 return NULL;
154 }
155 }
156
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000157 return PyMember_GetOne((char *)obj, descr->d_member);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000158}
159
160static PyObject *
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +0000161getset_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *type)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000162{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000163 PyObject *res;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000164
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000165 if (descr_check((PyDescrObject *)descr, obj, &res))
166 return res;
167 if (descr->d_getset->get != NULL)
168 return descr->d_getset->get(obj, descr->d_getset->closure);
169 PyErr_Format(PyExc_AttributeError,
170 "attribute '%V' of '%.100s' objects is not readable",
171 descr_name((PyDescrObject *)descr), "?",
172 PyDescr_TYPE(descr)->tp_name);
173 return NULL;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000174}
175
176static PyObject *
Armin Rigoc6686b72005-11-07 08:38:00 +0000177wrapperdescr_get(PyWrapperDescrObject *descr, PyObject *obj, PyObject *type)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000178{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000179 PyObject *res;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000180
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000181 if (descr_check((PyDescrObject *)descr, obj, &res))
182 return res;
183 return PyWrapper_New((PyObject *)descr, obj);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000184}
185
186static int
187descr_setcheck(PyDescrObject *descr, PyObject *obj, PyObject *value,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000188 int *pres)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000189{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000190 assert(obj != NULL);
191 if (!PyObject_TypeCheck(obj, descr->d_type)) {
192 PyErr_Format(PyExc_TypeError,
193 "descriptor '%V' for '%.100s' objects "
Inada Naoki62f95882019-04-01 17:56:11 +0900194 "doesn't apply to a '%.100s' object",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000195 descr_name(descr), "?",
196 descr->d_type->tp_name,
Victor Stinner58ac7002020-02-07 03:04:21 +0100197 Py_TYPE(obj)->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000198 *pres = -1;
199 return 1;
200 }
201 return 0;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000202}
203
204static int
205member_set(PyMemberDescrObject *descr, PyObject *obj, PyObject *value)
206{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000207 int res;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000208
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000209 if (descr_setcheck((PyDescrObject *)descr, obj, value, &res))
210 return res;
211 return PyMember_SetOne((char *)obj, descr->d_member, value);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000212}
213
214static int
215getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value)
216{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000217 int res;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000218
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000219 if (descr_setcheck((PyDescrObject *)descr, obj, value, &res))
220 return res;
221 if (descr->d_getset->set != NULL)
222 return descr->d_getset->set(obj, value,
223 descr->d_getset->closure);
224 PyErr_Format(PyExc_AttributeError,
225 "attribute '%V' of '%.100s' objects is not writable",
226 descr_name((PyDescrObject *)descr), "?",
227 PyDescr_TYPE(descr)->tp_name);
228 return -1;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000229}
230
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200231
232/* Vectorcall functions for each of the PyMethodDescr calling conventions.
233 *
234 * First, common helpers
235 */
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200236static inline int
237method_check_args(PyObject *func, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
238{
239 assert(!PyErr_Occurred());
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200240 if (nargs < 1) {
Jeroen Demeyerbf17d412019-11-05 16:48:04 +0100241 PyObject *funcstr = _PyObject_FunctionStr(func);
242 if (funcstr != NULL) {
243 PyErr_Format(PyExc_TypeError,
244 "unbound method %U needs an argument", funcstr);
245 Py_DECREF(funcstr);
246 }
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200247 return -1;
248 }
249 PyObject *self = args[0];
Jeroen Demeyerbf17d412019-11-05 16:48:04 +0100250 PyObject *dummy;
251 if (descr_check((PyDescrObject *)func, self, &dummy)) {
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200252 return -1;
253 }
254 if (kwnames && PyTuple_GET_SIZE(kwnames)) {
Jeroen Demeyerbf17d412019-11-05 16:48:04 +0100255 PyObject *funcstr = _PyObject_FunctionStr(func);
256 if (funcstr != NULL) {
257 PyErr_Format(PyExc_TypeError,
258 "%U takes no keyword arguments", funcstr);
259 Py_DECREF(funcstr);
260 }
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200261 return -1;
262 }
263 return 0;
264}
265
Jeroen Demeyerbf17d412019-11-05 16:48:04 +0100266typedef void (*funcptr)(void);
267
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200268static inline funcptr
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100269method_enter_call(PyThreadState *tstate, PyObject *func)
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200270{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100271 if (_Py_EnterRecursiveCall(tstate, " while calling a Python object")) {
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200272 return NULL;
273 }
274 return (funcptr)((PyMethodDescrObject *)func)->d_method->ml_meth;
275}
276
277/* Now the actual vectorcall functions */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000278static PyObject *
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200279method_vectorcall_VARARGS(
280 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000281{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100282 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200283 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200284 if (method_check_args(func, args, nargs, kwnames)) {
INADA Naoki5566bbb2017-02-03 07:43:03 +0900285 return NULL;
286 }
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200287 PyObject *argstuple = _PyTuple_FromArray(args+1, nargs-1);
288 if (argstuple == NULL) {
INADA Naoki5566bbb2017-02-03 07:43:03 +0900289 return NULL;
290 }
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100291 PyCFunction meth = (PyCFunction)method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200292 if (meth == NULL) {
293 Py_DECREF(argstuple);
294 return NULL;
295 }
296 PyObject *result = meth(args[0], argstuple);
297 Py_DECREF(argstuple);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100298 _Py_LeaveRecursiveCall(tstate);
INADA Naoki5566bbb2017-02-03 07:43:03 +0900299 return result;
300}
301
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200302static PyObject *
303method_vectorcall_VARARGS_KEYWORDS(
304 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
305{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100306 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200307 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
308 if (method_check_args(func, args, nargs, NULL)) {
309 return NULL;
310 }
311 PyObject *argstuple = _PyTuple_FromArray(args+1, nargs-1);
312 if (argstuple == NULL) {
313 return NULL;
314 }
315 PyObject *result = NULL;
316 /* Create a temporary dict for keyword arguments */
317 PyObject *kwdict = NULL;
318 if (kwnames != NULL && PyTuple_GET_SIZE(kwnames) > 0) {
319 kwdict = _PyStack_AsDict(args + nargs, kwnames);
320 if (kwdict == NULL) {
321 goto exit;
322 }
323 }
324 PyCFunctionWithKeywords meth = (PyCFunctionWithKeywords)
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100325 method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200326 if (meth == NULL) {
327 goto exit;
328 }
329 result = meth(args[0], argstuple, kwdict);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100330 _Py_LeaveRecursiveCall(tstate);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200331exit:
332 Py_DECREF(argstuple);
333 Py_XDECREF(kwdict);
334 return result;
335}
336
337static PyObject *
338method_vectorcall_FASTCALL(
339 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
340{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100341 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200342 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
343 if (method_check_args(func, args, nargs, kwnames)) {
344 return NULL;
345 }
346 _PyCFunctionFast meth = (_PyCFunctionFast)
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100347 method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200348 if (meth == NULL) {
349 return NULL;
350 }
351 PyObject *result = meth(args[0], args+1, nargs-1);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100352 _Py_LeaveRecursiveCall(tstate);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200353 return result;
354}
355
356static PyObject *
357method_vectorcall_FASTCALL_KEYWORDS(
358 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
359{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100360 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200361 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
362 if (method_check_args(func, args, nargs, NULL)) {
363 return NULL;
364 }
365 _PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords)
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100366 method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200367 if (meth == NULL) {
368 return NULL;
369 }
370 PyObject *result = meth(args[0], args+1, nargs-1, kwnames);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100371 _Py_LeaveRecursiveCall(tstate);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200372 return result;
373}
374
375static PyObject *
376method_vectorcall_NOARGS(
377 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
378{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100379 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200380 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
381 if (method_check_args(func, args, nargs, kwnames)) {
382 return NULL;
383 }
384 if (nargs != 1) {
Jeroen Demeyerbf17d412019-11-05 16:48:04 +0100385 PyObject *funcstr = _PyObject_FunctionStr(func);
386 if (funcstr != NULL) {
387 PyErr_Format(PyExc_TypeError,
388 "%U takes no arguments (%zd given)", funcstr, nargs-1);
389 Py_DECREF(funcstr);
390 }
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200391 return NULL;
392 }
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100393 PyCFunction meth = (PyCFunction)method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200394 if (meth == NULL) {
395 return NULL;
396 }
397 PyObject *result = meth(args[0], NULL);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100398 _Py_LeaveRecursiveCall(tstate);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200399 return result;
400}
401
402static PyObject *
403method_vectorcall_O(
404 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
405{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100406 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200407 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
408 if (method_check_args(func, args, nargs, kwnames)) {
409 return NULL;
410 }
411 if (nargs != 2) {
Jeroen Demeyerbf17d412019-11-05 16:48:04 +0100412 PyObject *funcstr = _PyObject_FunctionStr(func);
413 if (funcstr != NULL) {
414 PyErr_Format(PyExc_TypeError,
415 "%U takes exactly one argument (%zd given)",
416 funcstr, nargs-1);
417 Py_DECREF(funcstr);
418 }
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200419 return NULL;
420 }
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100421 PyCFunction meth = (PyCFunction)method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200422 if (meth == NULL) {
423 return NULL;
424 }
425 PyObject *result = meth(args[0], args[1]);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100426 _Py_LeaveRecursiveCall(tstate);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200427 return result;
428}
429
430
Jeroen Demeyer3f345c32019-06-07 12:20:24 +0200431/* Instances of classmethod_descriptor are unlikely to be called directly.
432 For one, the analogous class "classmethod" (for Python classes) is not
433 callable. Second, users are not likely to access a classmethod_descriptor
434 directly, since it means pulling it from the class __dict__.
435
436 This is just an excuse to say that this doesn't need to be optimized:
437 we implement this simply by calling __get__ and then calling the result.
438*/
Tim Peters6d6c1a32001-08-02 04:15:00 +0000439static PyObject *
Tim Petersbca1cbc2002-12-09 22:56:13 +0000440classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000441 PyObject *kwds)
Tim Petersbca1cbc2002-12-09 22:56:13 +0000442{
Jeroen Demeyer3f345c32019-06-07 12:20:24 +0200443 Py_ssize_t argc = PyTuple_GET_SIZE(args);
Benjamin Peterson7295c6a2012-05-01 09:51:09 -0400444 if (argc < 1) {
445 PyErr_Format(PyExc_TypeError,
446 "descriptor '%V' of '%.100s' "
447 "object needs an argument",
448 descr_name((PyDescrObject *)descr), "?",
449 PyDescr_TYPE(descr)->tp_name);
450 return NULL;
451 }
Jeroen Demeyer3f345c32019-06-07 12:20:24 +0200452 PyObject *self = PyTuple_GET_ITEM(args, 0);
453 PyObject *bound = classmethod_get(descr, NULL, self);
454 if (bound == NULL) {
Benjamin Peterson7295c6a2012-05-01 09:51:09 -0400455 return NULL;
456 }
Petr Viktorinffd97532020-02-11 17:46:57 +0100457 PyObject *res = PyObject_VectorcallDict(bound, _PyTuple_ITEMS(args)+1,
Jeroen Demeyer3f345c32019-06-07 12:20:24 +0200458 argc-1, kwds);
459 Py_DECREF(bound);
460 return res;
Tim Petersbca1cbc2002-12-09 22:56:13 +0000461}
462
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300463Py_LOCAL_INLINE(PyObject *)
464wrapperdescr_raw_call(PyWrapperDescrObject *descr, PyObject *self,
465 PyObject *args, PyObject *kwds)
466{
467 wrapperfunc wrapper = descr->d_base->wrapper;
468
469 if (descr->d_base->flags & PyWrapperFlag_KEYWORDS) {
Serhiy Storchaka1c607152018-11-27 21:34:27 +0200470 wrapperfunc_kwds wk = (wrapperfunc_kwds)(void(*)(void))wrapper;
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300471 return (*wk)(self, args, descr->d_wrapped, kwds);
472 }
473
474 if (kwds != NULL && (!PyDict_Check(kwds) || PyDict_GET_SIZE(kwds) != 0)) {
475 PyErr_Format(PyExc_TypeError,
476 "wrapper %s() takes no keyword arguments",
477 descr->d_base->name);
478 return NULL;
479 }
480 return (*wrapper)(self, args, descr->d_wrapped);
481}
482
Tim Petersbca1cbc2002-12-09 22:56:13 +0000483static PyObject *
Tim Peters6d6c1a32001-08-02 04:15:00 +0000484wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
485{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000486 Py_ssize_t argc;
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300487 PyObject *self, *result;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000488
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000489 /* Make sure that the first argument is acceptable as 'self' */
490 assert(PyTuple_Check(args));
491 argc = PyTuple_GET_SIZE(args);
492 if (argc < 1) {
493 PyErr_Format(PyExc_TypeError,
494 "descriptor '%V' of '%.100s' "
495 "object needs an argument",
496 descr_name((PyDescrObject *)descr), "?",
497 PyDescr_TYPE(descr)->tp_name);
498 return NULL;
499 }
500 self = PyTuple_GET_ITEM(args, 0);
Victor Stinner3249dec2011-05-01 23:19:15 +0200501 if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
Victor Stinnerd9561312011-05-01 23:31:36 +0200502 (PyObject *)PyDescr_TYPE(descr))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000503 PyErr_Format(PyExc_TypeError,
504 "descriptor '%V' "
505 "requires a '%.100s' object "
506 "but received a '%.100s'",
507 descr_name((PyDescrObject *)descr), "?",
508 PyDescr_TYPE(descr)->tp_name,
Victor Stinner58ac7002020-02-07 03:04:21 +0100509 Py_TYPE(self)->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000510 return NULL;
511 }
Tim Peters6d6c1a32001-08-02 04:15:00 +0000512
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300513 args = PyTuple_GetSlice(args, 1, argc);
514 if (args == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000515 return NULL;
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300516 }
517 result = wrapperdescr_raw_call(descr, self, args, kwds);
518 Py_DECREF(args);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000519 return result;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000520}
521
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300522
Tim Peters6d6c1a32001-08-02 04:15:00 +0000523static PyObject *
Guido van Rossum6f799372001-09-20 20:46:19 +0000524method_get_doc(PyMethodDescrObject *descr, void *closure)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000525{
Larry Hastings2623c8c2014-02-08 22:15:29 -0800526 return _PyType_GetDocFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc);
Larry Hastings5c661892014-01-24 06:17:25 -0800527}
528
529static PyObject *
530method_get_text_signature(PyMethodDescrObject *descr, void *closure)
531{
Larry Hastings2623c8c2014-02-08 22:15:29 -0800532 return _PyType_GetTextSignatureFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000533}
534
Antoine Pitrou9d574812011-12-12 13:47:25 +0100535static PyObject *
536calculate_qualname(PyDescrObject *descr)
537{
538 PyObject *type_qualname, *res;
539 _Py_IDENTIFIER(__qualname__);
540
541 if (descr->d_name == NULL || !PyUnicode_Check(descr->d_name)) {
542 PyErr_SetString(PyExc_TypeError,
543 "<descriptor>.__name__ is not a unicode object");
544 return NULL;
545 }
546
547 type_qualname = _PyObject_GetAttrId((PyObject *)descr->d_type,
548 &PyId___qualname__);
549 if (type_qualname == NULL)
550 return NULL;
551
552 if (!PyUnicode_Check(type_qualname)) {
553 PyErr_SetString(PyExc_TypeError, "<descriptor>.__objclass__."
554 "__qualname__ is not a unicode object");
555 Py_XDECREF(type_qualname);
556 return NULL;
557 }
558
559 res = PyUnicode_FromFormat("%S.%S", type_qualname, descr->d_name);
560 Py_DECREF(type_qualname);
561 return res;
562}
563
564static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +0200565descr_get_qualname(PyDescrObject *descr, void *Py_UNUSED(ignored))
Antoine Pitrou9d574812011-12-12 13:47:25 +0100566{
567 if (descr->d_qualname == NULL)
568 descr->d_qualname = calculate_qualname(descr);
569 Py_XINCREF(descr->d_qualname);
570 return descr->d_qualname;
571}
572
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100573static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530574descr_reduce(PyDescrObject *descr, PyObject *Py_UNUSED(ignored))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100575{
Serhiy Storchakabb86bf42018-12-11 08:28:18 +0200576 return Py_BuildValue("N(OO)", _PyEval_GetBuiltinId(&PyId_getattr),
577 PyDescr_TYPE(descr), PyDescr_NAME(descr));
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100578}
579
580static PyMethodDef descr_methods[] = {
581 {"__reduce__", (PyCFunction)descr_reduce, METH_NOARGS, NULL},
582 {NULL, NULL}
583};
584
Guido van Rossum6f799372001-09-20 20:46:19 +0000585static PyMemberDef descr_members[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000586 {"__objclass__", T_OBJECT, offsetof(PyDescrObject, d_type), READONLY},
587 {"__name__", T_OBJECT, offsetof(PyDescrObject, d_name), READONLY},
588 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +0000589};
590
Guido van Rossum32d34c82001-09-20 21:45:26 +0000591static PyGetSetDef method_getset[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000592 {"__doc__", (getter)method_get_doc},
Antoine Pitrou9d574812011-12-12 13:47:25 +0100593 {"__qualname__", (getter)descr_get_qualname},
Larry Hastings5c661892014-01-24 06:17:25 -0800594 {"__text_signature__", (getter)method_get_text_signature},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000595 {0}
Guido van Rossum6f799372001-09-20 20:46:19 +0000596};
597
598static PyObject *
599member_get_doc(PyMemberDescrObject *descr, void *closure)
600{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000601 if (descr->d_member->doc == NULL) {
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200602 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000603 }
604 return PyUnicode_FromString(descr->d_member->doc);
Guido van Rossum6f799372001-09-20 20:46:19 +0000605}
606
Guido van Rossum32d34c82001-09-20 21:45:26 +0000607static PyGetSetDef member_getset[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000608 {"__doc__", (getter)member_get_doc},
Antoine Pitrou9d574812011-12-12 13:47:25 +0100609 {"__qualname__", (getter)descr_get_qualname},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000610 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +0000611};
612
613static PyObject *
Guido van Rossum32d34c82001-09-20 21:45:26 +0000614getset_get_doc(PyGetSetDescrObject *descr, void *closure)
615{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000616 if (descr->d_getset->doc == NULL) {
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200617 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000618 }
619 return PyUnicode_FromString(descr->d_getset->doc);
Guido van Rossum32d34c82001-09-20 21:45:26 +0000620}
621
622static PyGetSetDef getset_getset[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000623 {"__doc__", (getter)getset_get_doc},
Antoine Pitrou9d574812011-12-12 13:47:25 +0100624 {"__qualname__", (getter)descr_get_qualname},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000625 {0}
Guido van Rossum32d34c82001-09-20 21:45:26 +0000626};
627
628static PyObject *
Armin Rigoc6686b72005-11-07 08:38:00 +0000629wrapperdescr_get_doc(PyWrapperDescrObject *descr, void *closure)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000630{
Larry Hastings2623c8c2014-02-08 22:15:29 -0800631 return _PyType_GetDocFromInternalDoc(descr->d_base->name, descr->d_base->doc);
Larry Hastings5c661892014-01-24 06:17:25 -0800632}
633
634static PyObject *
635wrapperdescr_get_text_signature(PyWrapperDescrObject *descr, void *closure)
636{
Larry Hastings2623c8c2014-02-08 22:15:29 -0800637 return _PyType_GetTextSignatureFromInternalDoc(descr->d_base->name, descr->d_base->doc);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000638}
639
Armin Rigoc6686b72005-11-07 08:38:00 +0000640static PyGetSetDef wrapperdescr_getset[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000641 {"__doc__", (getter)wrapperdescr_get_doc},
Antoine Pitrou9d574812011-12-12 13:47:25 +0100642 {"__qualname__", (getter)descr_get_qualname},
Larry Hastings5c661892014-01-24 06:17:25 -0800643 {"__text_signature__", (getter)wrapperdescr_get_text_signature},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000644 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +0000645};
646
Guido van Rossum048eb752001-10-02 21:24:57 +0000647static int
648descr_traverse(PyObject *self, visitproc visit, void *arg)
649{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000650 PyDescrObject *descr = (PyDescrObject *)self;
651 Py_VISIT(descr->d_type);
652 return 0;
Guido van Rossum048eb752001-10-02 21:24:57 +0000653}
654
Christian Heimesa22e8bd2007-11-29 22:35:39 +0000655PyTypeObject PyMethodDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000656 PyVarObject_HEAD_INIT(&PyType_Type, 0)
657 "method_descriptor",
658 sizeof(PyMethodDescrObject),
659 0,
660 (destructor)descr_dealloc, /* tp_dealloc */
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200661 offsetof(PyMethodDescrObject, vectorcall), /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000662 0, /* tp_getattr */
663 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200664 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000665 (reprfunc)method_repr, /* tp_repr */
666 0, /* tp_as_number */
667 0, /* tp_as_sequence */
668 0, /* tp_as_mapping */
669 0, /* tp_hash */
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200670 PyVectorcall_Call, /* tp_call */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000671 0, /* tp_str */
672 PyObject_GenericGetAttr, /* tp_getattro */
673 0, /* tp_setattro */
674 0, /* tp_as_buffer */
Jeroen Demeyereb65e242019-05-28 14:42:53 +0200675 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Petr Viktorinffd97532020-02-11 17:46:57 +0100676 Py_TPFLAGS_HAVE_VECTORCALL |
Jeroen Demeyereb65e242019-05-28 14:42:53 +0200677 Py_TPFLAGS_METHOD_DESCRIPTOR, /* tp_flags */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000678 0, /* tp_doc */
679 descr_traverse, /* tp_traverse */
680 0, /* tp_clear */
681 0, /* tp_richcompare */
682 0, /* tp_weaklistoffset */
683 0, /* tp_iter */
684 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100685 descr_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000686 descr_members, /* tp_members */
687 method_getset, /* tp_getset */
688 0, /* tp_base */
689 0, /* tp_dict */
690 (descrgetfunc)method_get, /* tp_descr_get */
691 0, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000692};
693
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +0000694/* This is for METH_CLASS in C, not for "f = classmethod(f)" in Python! */
Christian Heimesa22e8bd2007-11-29 22:35:39 +0000695PyTypeObject PyClassMethodDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000696 PyVarObject_HEAD_INIT(&PyType_Type, 0)
697 "classmethod_descriptor",
698 sizeof(PyMethodDescrObject),
699 0,
700 (destructor)descr_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200701 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000702 0, /* tp_getattr */
703 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200704 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000705 (reprfunc)method_repr, /* tp_repr */
706 0, /* tp_as_number */
707 0, /* tp_as_sequence */
708 0, /* tp_as_mapping */
709 0, /* tp_hash */
710 (ternaryfunc)classmethoddescr_call, /* tp_call */
711 0, /* tp_str */
712 PyObject_GenericGetAttr, /* tp_getattro */
713 0, /* tp_setattro */
714 0, /* tp_as_buffer */
715 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
716 0, /* tp_doc */
717 descr_traverse, /* tp_traverse */
718 0, /* tp_clear */
719 0, /* tp_richcompare */
720 0, /* tp_weaklistoffset */
721 0, /* tp_iter */
722 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100723 descr_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000724 descr_members, /* tp_members */
725 method_getset, /* tp_getset */
726 0, /* tp_base */
727 0, /* tp_dict */
728 (descrgetfunc)classmethod_get, /* tp_descr_get */
729 0, /* tp_descr_set */
Tim Petersbca1cbc2002-12-09 22:56:13 +0000730};
731
Christian Heimesa22e8bd2007-11-29 22:35:39 +0000732PyTypeObject PyMemberDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000733 PyVarObject_HEAD_INIT(&PyType_Type, 0)
734 "member_descriptor",
735 sizeof(PyMemberDescrObject),
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)member_repr, /* tp_repr */
743 0, /* tp_as_number */
744 0, /* tp_as_sequence */
745 0, /* tp_as_mapping */
746 0, /* tp_hash */
747 0, /* 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 member_getset, /* tp_getset */
763 0, /* tp_base */
764 0, /* tp_dict */
765 (descrgetfunc)member_get, /* tp_descr_get */
766 (descrsetfunc)member_set, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000767};
768
Christian Heimesa22e8bd2007-11-29 22:35:39 +0000769PyTypeObject PyGetSetDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000770 PyVarObject_HEAD_INIT(&PyType_Type, 0)
771 "getset_descriptor",
772 sizeof(PyGetSetDescrObject),
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)getset_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 */
797 0, /* tp_methods */
798 descr_members, /* tp_members */
799 getset_getset, /* tp_getset */
800 0, /* tp_base */
801 0, /* tp_dict */
802 (descrgetfunc)getset_get, /* tp_descr_get */
803 (descrsetfunc)getset_set, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000804};
805
Guido van Rossumf4593e02001-10-03 12:09:30 +0000806PyTypeObject PyWrapperDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000807 PyVarObject_HEAD_INIT(&PyType_Type, 0)
808 "wrapper_descriptor",
809 sizeof(PyWrapperDescrObject),
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)wrapperdescr_repr, /* tp_repr */
817 0, /* tp_as_number */
818 0, /* tp_as_sequence */
819 0, /* tp_as_mapping */
820 0, /* tp_hash */
821 (ternaryfunc)wrapperdescr_call, /* tp_call */
822 0, /* tp_str */
823 PyObject_GenericGetAttr, /* tp_getattro */
824 0, /* tp_setattro */
825 0, /* tp_as_buffer */
Jeroen Demeyereb65e242019-05-28 14:42:53 +0200826 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
827 Py_TPFLAGS_METHOD_DESCRIPTOR, /* tp_flags */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000828 0, /* tp_doc */
829 descr_traverse, /* tp_traverse */
830 0, /* tp_clear */
831 0, /* tp_richcompare */
832 0, /* tp_weaklistoffset */
833 0, /* tp_iter */
834 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100835 descr_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000836 descr_members, /* tp_members */
837 wrapperdescr_getset, /* tp_getset */
838 0, /* tp_base */
839 0, /* tp_dict */
840 (descrgetfunc)wrapperdescr_get, /* tp_descr_get */
841 0, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000842};
843
844static PyDescrObject *
Jeremy Hyltonaf68c872005-12-10 18:50:16 +0000845descr_new(PyTypeObject *descrtype, PyTypeObject *type, const char *name)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000846{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000847 PyDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000848
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000849 descr = (PyDescrObject *)PyType_GenericAlloc(descrtype, 0);
850 if (descr != NULL) {
851 Py_XINCREF(type);
852 descr->d_type = type;
853 descr->d_name = PyUnicode_InternFromString(name);
854 if (descr->d_name == NULL) {
855 Py_DECREF(descr);
856 descr = NULL;
857 }
Benjamin Petersonf2fe7f02011-12-17 08:02:20 -0500858 else {
859 descr->d_qualname = NULL;
860 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000861 }
862 return descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000863}
864
865PyObject *
866PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method)
867{
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200868 /* Figure out correct vectorcall function to use */
869 vectorcallfunc vectorcall;
870 switch (method->ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O | METH_KEYWORDS))
871 {
872 case METH_VARARGS:
873 vectorcall = method_vectorcall_VARARGS;
874 break;
875 case METH_VARARGS | METH_KEYWORDS:
876 vectorcall = method_vectorcall_VARARGS_KEYWORDS;
877 break;
878 case METH_FASTCALL:
879 vectorcall = method_vectorcall_FASTCALL;
880 break;
881 case METH_FASTCALL | METH_KEYWORDS:
882 vectorcall = method_vectorcall_FASTCALL_KEYWORDS;
883 break;
884 case METH_NOARGS:
885 vectorcall = method_vectorcall_NOARGS;
886 break;
887 case METH_O:
888 vectorcall = method_vectorcall_O;
889 break;
890 default:
891 PyErr_SetString(PyExc_SystemError, "bad call flags");
892 return NULL;
893 }
894
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000895 PyMethodDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000896
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000897 descr = (PyMethodDescrObject *)descr_new(&PyMethodDescr_Type,
898 type, method->ml_name);
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200899 if (descr != NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000900 descr->d_method = method;
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200901 descr->vectorcall = vectorcall;
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200902 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000903 return (PyObject *)descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000904}
905
906PyObject *
Tim Petersbca1cbc2002-12-09 22:56:13 +0000907PyDescr_NewClassMethod(PyTypeObject *type, PyMethodDef *method)
908{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000909 PyMethodDescrObject *descr;
Tim Petersbca1cbc2002-12-09 22:56:13 +0000910
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000911 descr = (PyMethodDescrObject *)descr_new(&PyClassMethodDescr_Type,
912 type, method->ml_name);
913 if (descr != NULL)
914 descr->d_method = method;
915 return (PyObject *)descr;
Tim Petersbca1cbc2002-12-09 22:56:13 +0000916}
917
918PyObject *
Guido van Rossum6f799372001-09-20 20:46:19 +0000919PyDescr_NewMember(PyTypeObject *type, PyMemberDef *member)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000920{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000921 PyMemberDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000922
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000923 descr = (PyMemberDescrObject *)descr_new(&PyMemberDescr_Type,
924 type, member->name);
925 if (descr != NULL)
926 descr->d_member = member;
927 return (PyObject *)descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000928}
929
930PyObject *
Guido van Rossum32d34c82001-09-20 21:45:26 +0000931PyDescr_NewGetSet(PyTypeObject *type, PyGetSetDef *getset)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000932{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000933 PyGetSetDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000934
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000935 descr = (PyGetSetDescrObject *)descr_new(&PyGetSetDescr_Type,
936 type, getset->name);
937 if (descr != NULL)
938 descr->d_getset = getset;
939 return (PyObject *)descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000940}
941
942PyObject *
943PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped)
944{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000945 PyWrapperDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000946
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000947 descr = (PyWrapperDescrObject *)descr_new(&PyWrapperDescr_Type,
948 type, base->name);
949 if (descr != NULL) {
950 descr->d_base = base;
951 descr->d_wrapped = wrapped;
952 }
953 return (PyObject *)descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000954}
955
Tim Peters6d6c1a32001-08-02 04:15:00 +0000956
Victor Stinner0db176f2012-04-16 00:16:30 +0200957/* --- mappingproxy: read-only proxy for mappings --- */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000958
959/* This has no reason to be in this file except that adding new files is a
960 bit of a pain */
961
962typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000963 PyObject_HEAD
Victor Stinner0db176f2012-04-16 00:16:30 +0200964 PyObject *mapping;
965} mappingproxyobject;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000966
Martin v. Löwis18e16552006-02-15 17:27:45 +0000967static Py_ssize_t
Victor Stinner0db176f2012-04-16 00:16:30 +0200968mappingproxy_len(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000969{
Victor Stinner0db176f2012-04-16 00:16:30 +0200970 return PyObject_Size(pp->mapping);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000971}
972
973static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +0200974mappingproxy_getitem(mappingproxyobject *pp, PyObject *key)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000975{
Victor Stinner0db176f2012-04-16 00:16:30 +0200976 return PyObject_GetItem(pp->mapping, key);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000977}
978
Victor Stinner0db176f2012-04-16 00:16:30 +0200979static PyMappingMethods mappingproxy_as_mapping = {
980 (lenfunc)mappingproxy_len, /* mp_length */
981 (binaryfunc)mappingproxy_getitem, /* mp_subscript */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000982 0, /* mp_ass_subscript */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000983};
984
Brandt Bucher4663f662020-03-07 11:03:09 -0800985static PyObject *
986mappingproxy_or(PyObject *left, PyObject *right)
987{
988 if (PyObject_TypeCheck(left, &PyDictProxy_Type)) {
989 left = ((mappingproxyobject*)left)->mapping;
990 }
991 if (PyObject_TypeCheck(right, &PyDictProxy_Type)) {
992 right = ((mappingproxyobject*)right)->mapping;
993 }
994 return PyNumber_Or(left, right);
995}
996
997static PyObject *
998mappingproxy_ior(PyObject *self, PyObject *Py_UNUSED(other))
999{
1000 return PyErr_Format(PyExc_TypeError,
1001 "'|=' is not supported by %s; use '|' instead", Py_TYPE(self)->tp_name);
1002}
1003
1004static PyNumberMethods mappingproxy_as_number = {
1005 .nb_or = mappingproxy_or,
1006 .nb_inplace_or = mappingproxy_ior,
1007};
1008
Tim Peters6d6c1a32001-08-02 04:15:00 +00001009static int
Victor Stinner0db176f2012-04-16 00:16:30 +02001010mappingproxy_contains(mappingproxyobject *pp, PyObject *key)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001011{
Victor Stinner0db176f2012-04-16 00:16:30 +02001012 if (PyDict_CheckExact(pp->mapping))
1013 return PyDict_Contains(pp->mapping, key);
1014 else
1015 return PySequence_Contains(pp->mapping, key);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001016}
1017
Victor Stinner0db176f2012-04-16 00:16:30 +02001018static PySequenceMethods mappingproxy_as_sequence = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001019 0, /* sq_length */
1020 0, /* sq_concat */
1021 0, /* sq_repeat */
1022 0, /* sq_item */
1023 0, /* sq_slice */
1024 0, /* sq_ass_item */
1025 0, /* sq_ass_slice */
Victor Stinner0db176f2012-04-16 00:16:30 +02001026 (objobjproc)mappingproxy_contains, /* sq_contains */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001027 0, /* sq_inplace_concat */
1028 0, /* sq_inplace_repeat */
Tim Peters6d6c1a32001-08-02 04:15:00 +00001029};
1030
1031static PyObject *
Jeroen Demeyerb1263d52019-06-28 11:49:00 +02001032mappingproxy_get(mappingproxyobject *pp, PyObject *const *args, Py_ssize_t nargs)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001033{
Jeroen Demeyerb1263d52019-06-28 11:49:00 +02001034 /* newargs: mapping, key, default=None */
1035 PyObject *newargs[3];
1036 newargs[0] = pp->mapping;
1037 newargs[2] = Py_None;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001038
Jeroen Demeyerb1263d52019-06-28 11:49:00 +02001039 if (!_PyArg_UnpackStack(args, nargs, "get", 1, 2,
1040 &newargs[1], &newargs[2]))
1041 {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001042 return NULL;
Jeroen Demeyerb1263d52019-06-28 11:49:00 +02001043 }
1044 _Py_IDENTIFIER(get);
1045 return _PyObject_VectorcallMethodId(&PyId_get, newargs,
1046 3 | PY_VECTORCALL_ARGUMENTS_OFFSET,
1047 NULL);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001048}
1049
1050static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301051mappingproxy_keys(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001052{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001053 _Py_IDENTIFIER(keys);
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001054 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId_keys);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001055}
1056
1057static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301058mappingproxy_values(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001059{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001060 _Py_IDENTIFIER(values);
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001061 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId_values);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001062}
1063
1064static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301065mappingproxy_items(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001066{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001067 _Py_IDENTIFIER(items);
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001068 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId_items);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001069}
1070
1071static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301072mappingproxy_copy(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001073{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001074 _Py_IDENTIFIER(copy);
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001075 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId_copy);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001076}
1077
Victor Stinner0db176f2012-04-16 00:16:30 +02001078/* WARNING: mappingproxy methods must not give access
1079 to the underlying mapping */
1080
1081static PyMethodDef mappingproxy_methods[] = {
Zackery Spytz43d564c2019-08-13 23:51:06 -06001082 {"get", (PyCFunction)(void(*)(void))mappingproxy_get, METH_FASTCALL,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001083 PyDoc_STR("D.get(k[,d]) -> D[k] if k in D, else d."
Victor Stinner0db176f2012-04-16 00:16:30 +02001084 " d defaults to None.")},
1085 {"keys", (PyCFunction)mappingproxy_keys, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001086 PyDoc_STR("D.keys() -> list of D's keys")},
Victor Stinner0db176f2012-04-16 00:16:30 +02001087 {"values", (PyCFunction)mappingproxy_values, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001088 PyDoc_STR("D.values() -> list of D's values")},
Victor Stinner0db176f2012-04-16 00:16:30 +02001089 {"items", (PyCFunction)mappingproxy_items, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001090 PyDoc_STR("D.items() -> list of D's (key, value) pairs, as 2-tuples")},
Victor Stinner0db176f2012-04-16 00:16:30 +02001091 {"copy", (PyCFunction)mappingproxy_copy, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001092 PyDoc_STR("D.copy() -> a shallow copy of D")},
1093 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001094};
1095
1096static void
Victor Stinner0db176f2012-04-16 00:16:30 +02001097mappingproxy_dealloc(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001098{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001099 _PyObject_GC_UNTRACK(pp);
Victor Stinner0db176f2012-04-16 00:16:30 +02001100 Py_DECREF(pp->mapping);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001101 PyObject_GC_Del(pp);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001102}
1103
1104static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001105mappingproxy_getiter(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001106{
Victor Stinner0db176f2012-04-16 00:16:30 +02001107 return PyObject_GetIter(pp->mapping);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001108}
1109
Neil Schemenauer26775122001-10-21 22:26:43 +00001110static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001111mappingproxy_str(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001112{
Victor Stinner0db176f2012-04-16 00:16:30 +02001113 return PyObject_Str(pp->mapping);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001114}
1115
Ezio Melottiac53ab62010-12-18 14:59:43 +00001116static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001117mappingproxy_repr(mappingproxyobject *pp)
Ezio Melottiac53ab62010-12-18 14:59:43 +00001118{
Victor Stinner0db176f2012-04-16 00:16:30 +02001119 return PyUnicode_FromFormat("mappingproxy(%R)", pp->mapping);
Ezio Melottiac53ab62010-12-18 14:59:43 +00001120}
1121
Guido van Rossum048eb752001-10-02 21:24:57 +00001122static int
Victor Stinner0db176f2012-04-16 00:16:30 +02001123mappingproxy_traverse(PyObject *self, visitproc visit, void *arg)
Guido van Rossum048eb752001-10-02 21:24:57 +00001124{
Victor Stinner0db176f2012-04-16 00:16:30 +02001125 mappingproxyobject *pp = (mappingproxyobject *)self;
1126 Py_VISIT(pp->mapping);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001127 return 0;
Guido van Rossum048eb752001-10-02 21:24:57 +00001128}
1129
Raymond Hettinger29a6d442002-08-31 15:51:04 +00001130static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001131mappingproxy_richcompare(mappingproxyobject *v, PyObject *w, int op)
Raymond Hettinger29a6d442002-08-31 15:51:04 +00001132{
Victor Stinner0db176f2012-04-16 00:16:30 +02001133 return PyObject_RichCompare(v->mapping, w, op);
1134}
1135
1136static int
1137mappingproxy_check_mapping(PyObject *mapping)
1138{
1139 if (!PyMapping_Check(mapping)
1140 || PyList_Check(mapping)
1141 || PyTuple_Check(mapping)) {
1142 PyErr_Format(PyExc_TypeError,
1143 "mappingproxy() argument must be a mapping, not %s",
1144 Py_TYPE(mapping)->tp_name);
1145 return -1;
1146 }
1147 return 0;
1148}
1149
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001150/*[clinic input]
1151@classmethod
1152mappingproxy.__new__ as mappingproxy_new
Victor Stinner0db176f2012-04-16 00:16:30 +02001153
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001154 mapping: object
1155
1156[clinic start generated code]*/
1157
1158static PyObject *
1159mappingproxy_new_impl(PyTypeObject *type, PyObject *mapping)
1160/*[clinic end generated code: output=65f27f02d5b68fa7 input=d2d620d4f598d4f8]*/
1161{
1162 mappingproxyobject *mappingproxy;
Victor Stinner0db176f2012-04-16 00:16:30 +02001163
1164 if (mappingproxy_check_mapping(mapping) == -1)
1165 return NULL;
1166
1167 mappingproxy = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type);
1168 if (mappingproxy == NULL)
1169 return NULL;
1170 Py_INCREF(mapping);
1171 mappingproxy->mapping = mapping;
1172 _PyObject_GC_TRACK(mappingproxy);
1173 return (PyObject *)mappingproxy;
Raymond Hettinger29a6d442002-08-31 15:51:04 +00001174}
1175
Tim Peters6d6c1a32001-08-02 04:15:00 +00001176PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001177PyDictProxy_New(PyObject *mapping)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001178{
Victor Stinner0db176f2012-04-16 00:16:30 +02001179 mappingproxyobject *pp;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001180
Victor Stinner0db176f2012-04-16 00:16:30 +02001181 if (mappingproxy_check_mapping(mapping) == -1)
1182 return NULL;
1183
1184 pp = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001185 if (pp != NULL) {
Victor Stinner0db176f2012-04-16 00:16:30 +02001186 Py_INCREF(mapping);
1187 pp->mapping = mapping;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001188 _PyObject_GC_TRACK(pp);
1189 }
1190 return (PyObject *)pp;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001191}
1192
1193
1194/* --- Wrapper object for "slot" methods --- */
1195
1196/* This has no reason to be in this file except that adding new files is a
1197 bit of a pain */
1198
1199typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001200 PyObject_HEAD
1201 PyWrapperDescrObject *descr;
1202 PyObject *self;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001203} wrapperobject;
1204
Andy Lesterdffe4c02020-03-04 07:15:20 -06001205#define Wrapper_Check(v) Py_IS_TYPE(v, &_PyMethodWrapper_Type)
Mark Dickinson211c6252009-02-01 10:28:51 +00001206
Tim Peters6d6c1a32001-08-02 04:15:00 +00001207static void
1208wrapper_dealloc(wrapperobject *wp)
1209{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001210 PyObject_GC_UnTrack(wp);
Jeroen Demeyer351c6742019-05-10 19:21:11 +02001211 Py_TRASHCAN_BEGIN(wp, wrapper_dealloc)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001212 Py_XDECREF(wp->descr);
1213 Py_XDECREF(wp->self);
1214 PyObject_GC_Del(wp);
Jeroen Demeyer351c6742019-05-10 19:21:11 +02001215 Py_TRASHCAN_END
Tim Peters6d6c1a32001-08-02 04:15:00 +00001216}
1217
Mark Dickinson211c6252009-02-01 10:28:51 +00001218static PyObject *
1219wrapper_richcompare(PyObject *a, PyObject *b, int op)
Armin Rigoc6686b72005-11-07 08:38:00 +00001220{
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001221 wrapperobject *wa, *wb;
1222 int eq;
Mark Dickinson211c6252009-02-01 10:28:51 +00001223
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001224 assert(a != NULL && b != NULL);
Mark Dickinson211c6252009-02-01 10:28:51 +00001225
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001226 /* both arguments should be wrapperobjects */
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001227 if ((op != Py_EQ && op != Py_NE)
1228 || !Wrapper_Check(a) || !Wrapper_Check(b))
1229 {
stratakise8b19652017-11-02 11:32:54 +01001230 Py_RETURN_NOTIMPLEMENTED;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001231 }
Mark Dickinson211c6252009-02-01 10:28:51 +00001232
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001233 wa = (wrapperobject *)a;
1234 wb = (wrapperobject *)b;
1235 eq = (wa->descr == wb->descr && wa->self == wb->self);
1236 if (eq == (op == Py_EQ)) {
1237 Py_RETURN_TRUE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001238 }
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001239 else {
1240 Py_RETURN_FALSE;
1241 }
Armin Rigoc6686b72005-11-07 08:38:00 +00001242}
1243
Benjamin Peterson8f67d082010-10-17 20:54:53 +00001244static Py_hash_t
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001245wrapper_hash(wrapperobject *wp)
1246{
Benjamin Peterson8f67d082010-10-17 20:54:53 +00001247 Py_hash_t x, y;
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001248 x = _Py_HashPointer(wp->self);
1249 y = _Py_HashPointer(wp->descr);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001250 x = x ^ y;
1251 if (x == -1)
1252 x = -2;
1253 return x;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001254}
1255
Armin Rigoc6686b72005-11-07 08:38:00 +00001256static PyObject *
1257wrapper_repr(wrapperobject *wp)
1258{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001259 return PyUnicode_FromFormat("<method-wrapper '%s' of %s object at %p>",
1260 wp->descr->d_base->name,
Victor Stinner58ac7002020-02-07 03:04:21 +01001261 Py_TYPE(wp->self)->tp_name,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001262 wp->self);
Armin Rigoc6686b72005-11-07 08:38:00 +00001263}
1264
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001265static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301266wrapper_reduce(wrapperobject *wp, PyObject *Py_UNUSED(ignored))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001267{
Serhiy Storchakabb86bf42018-12-11 08:28:18 +02001268 return Py_BuildValue("N(OO)", _PyEval_GetBuiltinId(&PyId_getattr),
1269 wp->self, PyDescr_NAME(wp->descr));
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001270}
1271
1272static PyMethodDef wrapper_methods[] = {
1273 {"__reduce__", (PyCFunction)wrapper_reduce, METH_NOARGS, NULL},
1274 {NULL, NULL}
1275};
1276
Armin Rigoc6686b72005-11-07 08:38:00 +00001277static PyMemberDef wrapper_members[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001278 {"__self__", T_OBJECT, offsetof(wrapperobject, self), READONLY},
1279 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001280};
1281
1282static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001283wrapper_objclass(wrapperobject *wp, void *Py_UNUSED(ignored))
Armin Rigoc6686b72005-11-07 08:38:00 +00001284{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001285 PyObject *c = (PyObject *)PyDescr_TYPE(wp->descr);
Armin Rigoc6686b72005-11-07 08:38:00 +00001286
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001287 Py_INCREF(c);
1288 return c;
Armin Rigoc6686b72005-11-07 08:38:00 +00001289}
1290
1291static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001292wrapper_name(wrapperobject *wp, void *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001293{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001294 const char *s = wp->descr->d_base->name;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001295
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001296 return PyUnicode_FromString(s);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001297}
1298
1299static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001300wrapper_doc(wrapperobject *wp, void *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001301{
Larry Hastings2623c8c2014-02-08 22:15:29 -08001302 return _PyType_GetDocFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc);
Larry Hastings5c661892014-01-24 06:17:25 -08001303}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001304
Larry Hastings5c661892014-01-24 06:17:25 -08001305static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001306wrapper_text_signature(wrapperobject *wp, void *Py_UNUSED(ignored))
Larry Hastings5c661892014-01-24 06:17:25 -08001307{
Larry Hastings2623c8c2014-02-08 22:15:29 -08001308 return _PyType_GetTextSignatureFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001309}
1310
Antoine Pitrou9d574812011-12-12 13:47:25 +01001311static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001312wrapper_qualname(wrapperobject *wp, void *Py_UNUSED(ignored))
Antoine Pitrou9d574812011-12-12 13:47:25 +01001313{
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001314 return descr_get_qualname((PyDescrObject *)wp->descr, NULL);
Antoine Pitrou9d574812011-12-12 13:47:25 +01001315}
1316
Guido van Rossum32d34c82001-09-20 21:45:26 +00001317static PyGetSetDef wrapper_getsets[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001318 {"__objclass__", (getter)wrapper_objclass},
1319 {"__name__", (getter)wrapper_name},
Antoine Pitrou9d574812011-12-12 13:47:25 +01001320 {"__qualname__", (getter)wrapper_qualname},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001321 {"__doc__", (getter)wrapper_doc},
Larry Hastings5c661892014-01-24 06:17:25 -08001322 {"__text_signature__", (getter)wrapper_text_signature},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001323 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001324};
1325
1326static PyObject *
1327wrapper_call(wrapperobject *wp, PyObject *args, PyObject *kwds)
1328{
Serhiy Storchaka5e02c782017-09-21 14:25:36 +03001329 return wrapperdescr_raw_call(wp->descr, wp->self, args, kwds);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001330}
1331
Guido van Rossum048eb752001-10-02 21:24:57 +00001332static int
1333wrapper_traverse(PyObject *self, visitproc visit, void *arg)
1334{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001335 wrapperobject *wp = (wrapperobject *)self;
1336 Py_VISIT(wp->descr);
1337 Py_VISIT(wp->self);
1338 return 0;
Guido van Rossum048eb752001-10-02 21:24:57 +00001339}
1340
Benjamin Petersoneff61f62011-09-01 16:32:31 -04001341PyTypeObject _PyMethodWrapper_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001342 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1343 "method-wrapper", /* tp_name */
1344 sizeof(wrapperobject), /* tp_basicsize */
1345 0, /* tp_itemsize */
1346 /* methods */
1347 (destructor)wrapper_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001348 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001349 0, /* tp_getattr */
1350 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001351 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001352 (reprfunc)wrapper_repr, /* tp_repr */
1353 0, /* tp_as_number */
1354 0, /* tp_as_sequence */
1355 0, /* tp_as_mapping */
1356 (hashfunc)wrapper_hash, /* tp_hash */
1357 (ternaryfunc)wrapper_call, /* tp_call */
1358 0, /* tp_str */
1359 PyObject_GenericGetAttr, /* tp_getattro */
1360 0, /* tp_setattro */
1361 0, /* tp_as_buffer */
1362 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1363 0, /* tp_doc */
1364 wrapper_traverse, /* tp_traverse */
1365 0, /* tp_clear */
1366 wrapper_richcompare, /* tp_richcompare */
1367 0, /* tp_weaklistoffset */
1368 0, /* tp_iter */
1369 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001370 wrapper_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001371 wrapper_members, /* tp_members */
1372 wrapper_getsets, /* tp_getset */
1373 0, /* tp_base */
1374 0, /* tp_dict */
1375 0, /* tp_descr_get */
1376 0, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +00001377};
1378
1379PyObject *
1380PyWrapper_New(PyObject *d, PyObject *self)
1381{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001382 wrapperobject *wp;
1383 PyWrapperDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001384
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001385 assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type));
1386 descr = (PyWrapperDescrObject *)d;
Victor Stinner3249dec2011-05-01 23:19:15 +02001387 assert(_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
Victor Stinnerd9561312011-05-01 23:31:36 +02001388 (PyObject *)PyDescr_TYPE(descr)));
Tim Peters6d6c1a32001-08-02 04:15:00 +00001389
Benjamin Petersoneff61f62011-09-01 16:32:31 -04001390 wp = PyObject_GC_New(wrapperobject, &_PyMethodWrapper_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001391 if (wp != NULL) {
1392 Py_INCREF(descr);
1393 wp->descr = descr;
1394 Py_INCREF(self);
1395 wp->self = self;
1396 _PyObject_GC_TRACK(wp);
1397 }
1398 return (PyObject *)wp;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001399}
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001400
1401
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001402/* A built-in 'property' type */
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001403
1404/*
Serhiy Storchakad741a882015-06-11 00:06:39 +03001405class property(object):
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001406
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001407 def __init__(self, fget=None, fset=None, fdel=None, doc=None):
1408 if doc is None and fget is not None and hasattr(fget, "__doc__"):
Serhiy Storchakad741a882015-06-11 00:06:39 +03001409 doc = fget.__doc__
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001410 self.__get = fget
1411 self.__set = fset
1412 self.__del = fdel
1413 self.__doc__ = doc
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001414
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001415 def __get__(self, inst, type=None):
1416 if inst is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001417 return self
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001418 if self.__get is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001419 raise AttributeError, "unreadable attribute"
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001420 return self.__get(inst)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001421
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001422 def __set__(self, inst, value):
1423 if self.__set is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001424 raise AttributeError, "can't set attribute"
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001425 return self.__set(inst, value)
Guido van Rossumba2485f2001-12-10 18:03:34 +00001426
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001427 def __delete__(self, inst):
1428 if self.__del is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001429 raise AttributeError, "can't delete attribute"
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001430 return self.__del(inst)
Guido van Rossumba2485f2001-12-10 18:03:34 +00001431
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001432*/
1433
1434typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001435 PyObject_HEAD
1436 PyObject *prop_get;
1437 PyObject *prop_set;
1438 PyObject *prop_del;
1439 PyObject *prop_doc;
1440 int getter_doc;
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001441} propertyobject;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001442
Christian Heimes0449f632007-12-15 01:27:15 +00001443static PyObject * property_copy(PyObject *, PyObject *, PyObject *,
Benjamin Peterson93964832010-06-28 03:07:10 +00001444 PyObject *);
Christian Heimes0449f632007-12-15 01:27:15 +00001445
Tim Peters66c1a522001-09-24 21:17:50 +00001446static PyMemberDef property_members[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001447 {"fget", T_OBJECT, offsetof(propertyobject, prop_get), READONLY},
1448 {"fset", T_OBJECT, offsetof(propertyobject, prop_set), READONLY},
1449 {"fdel", T_OBJECT, offsetof(propertyobject, prop_del), READONLY},
Raymond Hettingereac503a2015-05-13 01:09:59 -07001450 {"__doc__", T_OBJECT, offsetof(propertyobject, prop_doc), 0},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001451 {0}
Tim Peters66c1a522001-09-24 21:17:50 +00001452};
1453
Christian Heimes0449f632007-12-15 01:27:15 +00001454
Guido van Rossum58da9312007-11-10 23:39:45 +00001455PyDoc_STRVAR(getter_doc,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001456 "Descriptor to change the getter on a property.");
Guido van Rossum58da9312007-11-10 23:39:45 +00001457
Neal Norwitz32dde222008-04-15 06:43:13 +00001458static PyObject *
Guido van Rossum58da9312007-11-10 23:39:45 +00001459property_getter(PyObject *self, PyObject *getter)
1460{
Benjamin Peterson93964832010-06-28 03:07:10 +00001461 return property_copy(self, getter, NULL, NULL);
Guido van Rossum58da9312007-11-10 23:39:45 +00001462}
1463
Christian Heimes0449f632007-12-15 01:27:15 +00001464
Guido van Rossum58da9312007-11-10 23:39:45 +00001465PyDoc_STRVAR(setter_doc,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001466 "Descriptor to change the setter on a property.");
Guido van Rossum58da9312007-11-10 23:39:45 +00001467
Neal Norwitz32dde222008-04-15 06:43:13 +00001468static PyObject *
Guido van Rossum58da9312007-11-10 23:39:45 +00001469property_setter(PyObject *self, PyObject *setter)
1470{
Benjamin Peterson93964832010-06-28 03:07:10 +00001471 return property_copy(self, NULL, setter, NULL);
Guido van Rossum58da9312007-11-10 23:39:45 +00001472}
1473
Christian Heimes0449f632007-12-15 01:27:15 +00001474
Guido van Rossum58da9312007-11-10 23:39:45 +00001475PyDoc_STRVAR(deleter_doc,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001476 "Descriptor to change the deleter on a property.");
Guido van Rossum58da9312007-11-10 23:39:45 +00001477
Neal Norwitz32dde222008-04-15 06:43:13 +00001478static PyObject *
Guido van Rossum58da9312007-11-10 23:39:45 +00001479property_deleter(PyObject *self, PyObject *deleter)
1480{
Benjamin Peterson93964832010-06-28 03:07:10 +00001481 return property_copy(self, NULL, NULL, deleter);
Guido van Rossum58da9312007-11-10 23:39:45 +00001482}
1483
1484
Guido van Rossum58da9312007-11-10 23:39:45 +00001485static PyMethodDef property_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001486 {"getter", property_getter, METH_O, getter_doc},
1487 {"setter", property_setter, METH_O, setter_doc},
1488 {"deleter", property_deleter, METH_O, deleter_doc},
1489 {0}
Guido van Rossum58da9312007-11-10 23:39:45 +00001490};
1491
Tim Peters66c1a522001-09-24 21:17:50 +00001492
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001493static void
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001494property_dealloc(PyObject *self)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001495{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001496 propertyobject *gs = (propertyobject *)self;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001497
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001498 _PyObject_GC_UNTRACK(self);
1499 Py_XDECREF(gs->prop_get);
1500 Py_XDECREF(gs->prop_set);
1501 Py_XDECREF(gs->prop_del);
1502 Py_XDECREF(gs->prop_doc);
Victor Stinner58ac7002020-02-07 03:04:21 +01001503 Py_TYPE(self)->tp_free(self);
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001504}
1505
1506static PyObject *
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001507property_descr_get(PyObject *self, PyObject *obj, PyObject *type)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001508{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001509 if (obj == NULL || obj == Py_None) {
1510 Py_INCREF(self);
1511 return self;
1512 }
Victor Stinnere972c132018-10-01 03:03:22 -07001513
1514 propertyobject *gs = (propertyobject *)self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001515 if (gs->prop_get == NULL) {
1516 PyErr_SetString(PyExc_AttributeError, "unreadable attribute");
1517 return NULL;
1518 }
Victor Stinnere972c132018-10-01 03:03:22 -07001519
Petr Viktorinffd97532020-02-11 17:46:57 +01001520 return PyObject_CallOneArg(gs->prop_get, obj);
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001521}
1522
1523static int
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001524property_descr_set(PyObject *self, PyObject *obj, PyObject *value)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001525{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001526 propertyobject *gs = (propertyobject *)self;
1527 PyObject *func, *res;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001528
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001529 if (value == NULL)
1530 func = gs->prop_del;
1531 else
1532 func = gs->prop_set;
1533 if (func == NULL) {
1534 PyErr_SetString(PyExc_AttributeError,
1535 value == NULL ?
1536 "can't delete attribute" :
1537 "can't set attribute");
1538 return -1;
1539 }
1540 if (value == NULL)
Petr Viktorinffd97532020-02-11 17:46:57 +01001541 res = PyObject_CallOneArg(func, obj);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001542 else
Benjamin Peterson9b955de2010-12-07 04:04:02 +00001543 res = PyObject_CallFunctionObjArgs(func, obj, value, NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001544 if (res == NULL)
1545 return -1;
1546 Py_DECREF(res);
1547 return 0;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001548}
1549
Christian Heimes0449f632007-12-15 01:27:15 +00001550static PyObject *
Benjamin Peterson93964832010-06-28 03:07:10 +00001551property_copy(PyObject *old, PyObject *get, PyObject *set, PyObject *del)
Christian Heimes0449f632007-12-15 01:27:15 +00001552{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001553 propertyobject *pold = (propertyobject *)old;
Benjamin Peterson93964832010-06-28 03:07:10 +00001554 PyObject *new, *type, *doc;
Christian Heimes0449f632007-12-15 01:27:15 +00001555
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001556 type = PyObject_Type(old);
1557 if (type == NULL)
1558 return NULL;
Christian Heimes0449f632007-12-15 01:27:15 +00001559
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001560 if (get == NULL || get == Py_None) {
1561 Py_XDECREF(get);
1562 get = pold->prop_get ? pold->prop_get : Py_None;
1563 }
1564 if (set == NULL || set == Py_None) {
1565 Py_XDECREF(set);
1566 set = pold->prop_set ? pold->prop_set : Py_None;
1567 }
1568 if (del == NULL || del == Py_None) {
1569 Py_XDECREF(del);
1570 del = pold->prop_del ? pold->prop_del : Py_None;
1571 }
Benjamin Peterson93964832010-06-28 03:07:10 +00001572 if (pold->getter_doc && get != Py_None) {
1573 /* make _init use __doc__ from getter */
1574 doc = Py_None;
1575 }
1576 else {
1577 doc = pold->prop_doc ? pold->prop_doc : Py_None;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001578 }
R. David Murrayb18500d2009-05-04 22:59:07 +00001579
Victor Stinner5abaa2b2016-12-09 16:22:32 +01001580 new = PyObject_CallFunctionObjArgs(type, get, set, del, doc, NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001581 Py_DECREF(type);
1582 if (new == NULL)
1583 return NULL;
1584 return new;
Christian Heimes0449f632007-12-15 01:27:15 +00001585}
1586
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001587/*[clinic input]
1588property.__init__ as property_init
1589
1590 fget: object(c_default="NULL") = None
1591 function to be used for getting an attribute value
1592 fset: object(c_default="NULL") = None
1593 function to be used for setting an attribute value
1594 fdel: object(c_default="NULL") = None
1595 function to be used for del'ing an attribute
1596 doc: object(c_default="NULL") = None
1597 docstring
1598
1599Property attribute.
1600
1601Typical use is to define a managed attribute x:
1602
1603class C(object):
1604 def getx(self): return self._x
1605 def setx(self, value): self._x = value
1606 def delx(self): del self._x
1607 x = property(getx, setx, delx, "I'm the 'x' property.")
1608
1609Decorators make defining new properties or modifying existing ones easy:
1610
1611class C(object):
1612 @property
1613 def x(self):
1614 "I am the 'x' property."
1615 return self._x
1616 @x.setter
1617 def x(self, value):
1618 self._x = value
1619 @x.deleter
1620 def x(self):
1621 del self._x
1622[clinic start generated code]*/
1623
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001624static int
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001625property_init_impl(propertyobject *self, PyObject *fget, PyObject *fset,
1626 PyObject *fdel, PyObject *doc)
1627/*[clinic end generated code: output=01a960742b692b57 input=dfb5dbbffc6932d5]*/
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001628{
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001629 if (fget == Py_None)
1630 fget = NULL;
1631 if (fset == Py_None)
1632 fset = NULL;
1633 if (fdel == Py_None)
1634 fdel = NULL;
Tim Peters66c1a522001-09-24 21:17:50 +00001635
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001636 Py_XINCREF(fget);
1637 Py_XINCREF(fset);
1638 Py_XINCREF(fdel);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001639 Py_XINCREF(doc);
Christian Heimes0449f632007-12-15 01:27:15 +00001640
Oren Milmand019bc82018-02-13 12:28:33 +02001641 Py_XSETREF(self->prop_get, fget);
1642 Py_XSETREF(self->prop_set, fset);
1643 Py_XSETREF(self->prop_del, fdel);
1644 Py_XSETREF(self->prop_doc, doc);
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001645 self->getter_doc = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001646
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001647 /* if no docstring given and the getter has one, use that one */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001648 if ((doc == NULL || doc == Py_None) && fget != NULL) {
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001649 _Py_IDENTIFIER(__doc__);
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001650 PyObject *get_doc;
1651 int rc = _PyObject_LookupAttrId(fget, &PyId___doc__, &get_doc);
1652 if (rc <= 0) {
1653 return rc;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001654 }
Andy Lesterdffe4c02020-03-04 07:15:20 -06001655 if (Py_IS_TYPE(self, &PyProperty_Type)) {
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001656 Py_XSETREF(self->prop_doc, get_doc);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001657 }
1658 else {
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001659 /* If this is a property subclass, put __doc__
1660 in dict of the subclass instance instead,
1661 otherwise it gets shadowed by __doc__ in the
1662 class's dict. */
1663 int err = _PyObject_SetAttrId((PyObject *)self, &PyId___doc__, get_doc);
1664 Py_DECREF(get_doc);
1665 if (err < 0)
1666 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001667 }
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001668 self->getter_doc = 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001669 }
1670
1671 return 0;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001672}
1673
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -05001674static PyObject *
1675property_get___isabstractmethod__(propertyobject *prop, void *closure)
1676{
1677 int res = _PyObject_IsAbstract(prop->prop_get);
1678 if (res == -1) {
1679 return NULL;
1680 }
1681 else if (res) {
1682 Py_RETURN_TRUE;
1683 }
1684
1685 res = _PyObject_IsAbstract(prop->prop_set);
1686 if (res == -1) {
1687 return NULL;
1688 }
1689 else if (res) {
1690 Py_RETURN_TRUE;
1691 }
1692
1693 res = _PyObject_IsAbstract(prop->prop_del);
1694 if (res == -1) {
1695 return NULL;
1696 }
1697 else if (res) {
1698 Py_RETURN_TRUE;
1699 }
1700 Py_RETURN_FALSE;
1701}
1702
1703static PyGetSetDef property_getsetlist[] = {
1704 {"__isabstractmethod__",
1705 (getter)property_get___isabstractmethod__, NULL,
1706 NULL,
1707 NULL},
1708 {NULL} /* Sentinel */
1709};
1710
Guido van Rossum048eb752001-10-02 21:24:57 +00001711static int
1712property_traverse(PyObject *self, visitproc visit, void *arg)
1713{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001714 propertyobject *pp = (propertyobject *)self;
1715 Py_VISIT(pp->prop_get);
1716 Py_VISIT(pp->prop_set);
1717 Py_VISIT(pp->prop_del);
1718 Py_VISIT(pp->prop_doc);
1719 return 0;
Guido van Rossum048eb752001-10-02 21:24:57 +00001720}
1721
Raymond Hettingerd4be6912015-05-13 11:12:33 -07001722static int
1723property_clear(PyObject *self)
1724{
1725 propertyobject *pp = (propertyobject *)self;
1726 Py_CLEAR(pp->prop_doc);
1727 return 0;
1728}
1729
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001730#include "clinic/descrobject.c.h"
1731
1732PyTypeObject PyDictProxy_Type = {
1733 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1734 "mappingproxy", /* tp_name */
1735 sizeof(mappingproxyobject), /* tp_basicsize */
1736 0, /* tp_itemsize */
1737 /* methods */
1738 (destructor)mappingproxy_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001739 0, /* tp_vectorcall_offset */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001740 0, /* tp_getattr */
1741 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001742 0, /* tp_as_async */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001743 (reprfunc)mappingproxy_repr, /* tp_repr */
Brandt Bucher4663f662020-03-07 11:03:09 -08001744 &mappingproxy_as_number, /* tp_as_number */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001745 &mappingproxy_as_sequence, /* tp_as_sequence */
1746 &mappingproxy_as_mapping, /* tp_as_mapping */
1747 0, /* tp_hash */
1748 0, /* tp_call */
1749 (reprfunc)mappingproxy_str, /* tp_str */
1750 PyObject_GenericGetAttr, /* tp_getattro */
1751 0, /* tp_setattro */
1752 0, /* tp_as_buffer */
1753 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1754 0, /* tp_doc */
1755 mappingproxy_traverse, /* tp_traverse */
1756 0, /* tp_clear */
1757 (richcmpfunc)mappingproxy_richcompare, /* tp_richcompare */
1758 0, /* tp_weaklistoffset */
1759 (getiterfunc)mappingproxy_getiter, /* tp_iter */
1760 0, /* tp_iternext */
1761 mappingproxy_methods, /* tp_methods */
1762 0, /* tp_members */
1763 0, /* tp_getset */
1764 0, /* tp_base */
1765 0, /* tp_dict */
1766 0, /* tp_descr_get */
1767 0, /* tp_descr_set */
1768 0, /* tp_dictoffset */
1769 0, /* tp_init */
1770 0, /* tp_alloc */
1771 mappingproxy_new, /* tp_new */
1772};
1773
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001774PyTypeObject PyProperty_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001775 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1776 "property", /* tp_name */
1777 sizeof(propertyobject), /* tp_basicsize */
1778 0, /* tp_itemsize */
1779 /* methods */
1780 property_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001781 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001782 0, /* tp_getattr */
1783 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001784 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001785 0, /* tp_repr */
1786 0, /* tp_as_number */
1787 0, /* tp_as_sequence */
1788 0, /* tp_as_mapping */
1789 0, /* tp_hash */
1790 0, /* tp_call */
1791 0, /* tp_str */
1792 PyObject_GenericGetAttr, /* tp_getattro */
1793 0, /* tp_setattro */
1794 0, /* tp_as_buffer */
1795 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1796 Py_TPFLAGS_BASETYPE, /* tp_flags */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001797 property_init__doc__, /* tp_doc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001798 property_traverse, /* tp_traverse */
Raymond Hettingerd4be6912015-05-13 11:12:33 -07001799 (inquiry)property_clear, /* tp_clear */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001800 0, /* tp_richcompare */
1801 0, /* tp_weaklistoffset */
1802 0, /* tp_iter */
1803 0, /* tp_iternext */
1804 property_methods, /* tp_methods */
1805 property_members, /* tp_members */
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -05001806 property_getsetlist, /* tp_getset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001807 0, /* tp_base */
1808 0, /* tp_dict */
1809 property_descr_get, /* tp_descr_get */
1810 property_descr_set, /* tp_descr_set */
1811 0, /* tp_dictoffset */
1812 property_init, /* tp_init */
1813 PyType_GenericAlloc, /* tp_alloc */
1814 PyType_GenericNew, /* tp_new */
1815 PyObject_GC_Del, /* tp_free */
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001816};