blob: 97669bef368da8ad60eb04ae923435df82751f3d [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
Miss Islington (bot)35d48572021-10-07 00:48:00 -070075descr_check(PyDescrObject *descr, PyObject *obj)
Tim Peters6d6c1a32001-08-02 04:15:00 +000076{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000077 if (!PyObject_TypeCheck(obj, descr->d_type)) {
78 PyErr_Format(PyExc_TypeError,
Inada Naoki62f95882019-04-01 17:56:11 +090079 "descriptor '%V' for '%.100s' objects "
80 "doesn't apply to a '%.100s' object",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000081 descr_name((PyDescrObject *)descr), "?",
82 descr->d_type->tp_name,
Victor Stinner58ac7002020-02-07 03:04:21 +010083 Py_TYPE(obj)->tp_name);
Miss Islington (bot)35d48572021-10-07 00:48:00 -070084 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000085 }
86 return 0;
Tim Peters6d6c1a32001-08-02 04:15:00 +000087}
88
89static PyObject *
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +000090classmethod_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type)
Tim Petersbca1cbc2002-12-09 22:56:13 +000091{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000092 /* Ensure a valid type. Class methods ignore obj. */
93 if (type == NULL) {
94 if (obj != NULL)
Victor Stinner58ac7002020-02-07 03:04:21 +010095 type = (PyObject *)Py_TYPE(obj);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000096 else {
97 /* Wot - no type?! */
98 PyErr_Format(PyExc_TypeError,
Inada Naoki62f95882019-04-01 17:56:11 +090099 "descriptor '%V' for type '%.100s' "
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000100 "needs either an object or a type",
101 descr_name((PyDescrObject *)descr), "?",
102 PyDescr_TYPE(descr)->tp_name);
103 return NULL;
104 }
105 }
106 if (!PyType_Check(type)) {
107 PyErr_Format(PyExc_TypeError,
Inada Naoki62f95882019-04-01 17:56:11 +0900108 "descriptor '%V' for type '%.100s' "
109 "needs a type, not a '%.100s' as arg 2",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000110 descr_name((PyDescrObject *)descr), "?",
111 PyDescr_TYPE(descr)->tp_name,
Victor Stinner58ac7002020-02-07 03:04:21 +0100112 Py_TYPE(type)->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000113 return NULL;
114 }
115 if (!PyType_IsSubtype((PyTypeObject *)type, PyDescr_TYPE(descr))) {
116 PyErr_Format(PyExc_TypeError,
Inada Naoki62f95882019-04-01 17:56:11 +0900117 "descriptor '%V' requires a subtype of '%.100s' "
118 "but received '%.100s'",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000119 descr_name((PyDescrObject *)descr), "?",
120 PyDescr_TYPE(descr)->tp_name,
121 ((PyTypeObject *)type)->tp_name);
122 return NULL;
123 }
Petr Viktorine1becf42020-05-07 15:39:59 +0200124 PyTypeObject *cls = NULL;
125 if (descr->d_method->ml_flags & METH_METHOD) {
126 cls = descr->d_common.d_type;
127 }
128 return PyCMethod_New(descr->d_method, type, NULL, cls);
Tim Petersbca1cbc2002-12-09 22:56:13 +0000129}
130
131static PyObject *
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +0000132method_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000133{
Miss Islington (bot)35d48572021-10-07 00:48:00 -0700134 if (obj == NULL) {
135 return Py_NewRef(descr);
136 }
137 if (descr_check((PyDescrObject *)descr, obj) < 0) {
138 return NULL;
139 }
Petr Viktorine1becf42020-05-07 15:39:59 +0200140 if (descr->d_method->ml_flags & METH_METHOD) {
141 if (PyType_Check(type)) {
142 return PyCMethod_New(descr->d_method, obj, NULL, descr->d_common.d_type);
143 } else {
144 PyErr_Format(PyExc_TypeError,
145 "descriptor '%V' needs a type, not '%s', as arg 2",
146 descr_name((PyDescrObject *)descr),
147 Py_TYPE(type)->tp_name);
148 return NULL;
149 }
150 } else {
151 return PyCFunction_NewEx(descr->d_method, obj, NULL);
152 }
Tim Peters6d6c1a32001-08-02 04:15:00 +0000153}
154
155static PyObject *
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +0000156member_get(PyMemberDescrObject *descr, PyObject *obj, PyObject *type)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000157{
Miss Islington (bot)35d48572021-10-07 00:48:00 -0700158 if (obj == NULL) {
159 return Py_NewRef(descr);
160 }
161 if (descr_check((PyDescrObject *)descr, obj) < 0) {
162 return NULL;
163 }
Steve Dowerb82e17e2019-05-23 08:45:22 -0700164
Steve Dower87655e22021-04-30 01:08:55 +0100165 if (descr->d_member->flags & PY_AUDIT_READ) {
Steve Dowerb82e17e2019-05-23 08:45:22 -0700166 if (PySys_Audit("object.__getattr__", "Os",
167 obj ? obj : Py_None, descr->d_member->name) < 0) {
168 return NULL;
169 }
170 }
171
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000172 return PyMember_GetOne((char *)obj, descr->d_member);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000173}
174
175static PyObject *
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +0000176getset_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *type)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000177{
Miss Islington (bot)35d48572021-10-07 00:48:00 -0700178 if (obj == NULL) {
179 return Py_NewRef(descr);
180 }
181 if (descr_check((PyDescrObject *)descr, obj) < 0) {
182 return NULL;
183 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000184 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{
Miss Islington (bot)35d48572021-10-07 00:48:00 -0700196 if (obj == NULL) {
197 return Py_NewRef(descr);
198 }
199 if (descr_check((PyDescrObject *)descr, obj) < 0) {
200 return NULL;
201 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000202 return PyWrapper_New((PyObject *)descr, obj);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000203}
204
205static int
Miss Islington (bot)35d48572021-10-07 00:48:00 -0700206descr_setcheck(PyDescrObject *descr, PyObject *obj, PyObject *value)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000207{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000208 assert(obj != NULL);
209 if (!PyObject_TypeCheck(obj, descr->d_type)) {
210 PyErr_Format(PyExc_TypeError,
211 "descriptor '%V' for '%.100s' objects "
Inada Naoki62f95882019-04-01 17:56:11 +0900212 "doesn't apply to a '%.100s' object",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000213 descr_name(descr), "?",
214 descr->d_type->tp_name,
Victor Stinner58ac7002020-02-07 03:04:21 +0100215 Py_TYPE(obj)->tp_name);
Miss Islington (bot)35d48572021-10-07 00:48:00 -0700216 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000217 }
218 return 0;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000219}
220
221static int
222member_set(PyMemberDescrObject *descr, PyObject *obj, PyObject *value)
223{
Miss Islington (bot)35d48572021-10-07 00:48:00 -0700224 if (descr_setcheck((PyDescrObject *)descr, obj, value) < 0) {
225 return -1;
226 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000227 return PyMember_SetOne((char *)obj, descr->d_member, value);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000228}
229
230static int
231getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value)
232{
Miss Islington (bot)35d48572021-10-07 00:48:00 -0700233 if (descr_setcheck((PyDescrObject *)descr, obj, value) < 0) {
234 return -1;
235 }
236 if (descr->d_getset->set != NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000237 return descr->d_getset->set(obj, value,
238 descr->d_getset->closure);
Miss Islington (bot)35d48572021-10-07 00:48:00 -0700239 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000240 PyErr_Format(PyExc_AttributeError,
241 "attribute '%V' of '%.100s' objects is not writable",
242 descr_name((PyDescrObject *)descr), "?",
243 PyDescr_TYPE(descr)->tp_name);
244 return -1;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000245}
246
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200247
248/* Vectorcall functions for each of the PyMethodDescr calling conventions.
249 *
250 * First, common helpers
251 */
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200252static inline int
253method_check_args(PyObject *func, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
254{
255 assert(!PyErr_Occurred());
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200256 if (nargs < 1) {
Jeroen Demeyerbf17d412019-11-05 16:48:04 +0100257 PyObject *funcstr = _PyObject_FunctionStr(func);
258 if (funcstr != NULL) {
259 PyErr_Format(PyExc_TypeError,
260 "unbound method %U needs an argument", funcstr);
261 Py_DECREF(funcstr);
262 }
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200263 return -1;
264 }
265 PyObject *self = args[0];
Miss Islington (bot)35d48572021-10-07 00:48:00 -0700266 if (descr_check((PyDescrObject *)func, self) < 0) {
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200267 return -1;
268 }
269 if (kwnames && PyTuple_GET_SIZE(kwnames)) {
Jeroen Demeyerbf17d412019-11-05 16:48:04 +0100270 PyObject *funcstr = _PyObject_FunctionStr(func);
271 if (funcstr != NULL) {
272 PyErr_Format(PyExc_TypeError,
273 "%U takes no keyword arguments", funcstr);
274 Py_DECREF(funcstr);
275 }
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200276 return -1;
277 }
278 return 0;
279}
280
Jeroen Demeyerbf17d412019-11-05 16:48:04 +0100281typedef void (*funcptr)(void);
282
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200283static inline funcptr
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100284method_enter_call(PyThreadState *tstate, PyObject *func)
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200285{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100286 if (_Py_EnterRecursiveCall(tstate, " while calling a Python object")) {
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200287 return NULL;
288 }
289 return (funcptr)((PyMethodDescrObject *)func)->d_method->ml_meth;
290}
291
292/* Now the actual vectorcall functions */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000293static PyObject *
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200294method_vectorcall_VARARGS(
295 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000296{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100297 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200298 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200299 if (method_check_args(func, args, nargs, kwnames)) {
INADA Naoki5566bbb2017-02-03 07:43:03 +0900300 return NULL;
301 }
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200302 PyObject *argstuple = _PyTuple_FromArray(args+1, nargs-1);
303 if (argstuple == NULL) {
INADA Naoki5566bbb2017-02-03 07:43:03 +0900304 return NULL;
305 }
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100306 PyCFunction meth = (PyCFunction)method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200307 if (meth == NULL) {
308 Py_DECREF(argstuple);
309 return NULL;
310 }
311 PyObject *result = meth(args[0], argstuple);
312 Py_DECREF(argstuple);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100313 _Py_LeaveRecursiveCall(tstate);
INADA Naoki5566bbb2017-02-03 07:43:03 +0900314 return result;
315}
316
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200317static PyObject *
318method_vectorcall_VARARGS_KEYWORDS(
319 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
320{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100321 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200322 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
323 if (method_check_args(func, args, nargs, NULL)) {
324 return NULL;
325 }
326 PyObject *argstuple = _PyTuple_FromArray(args+1, nargs-1);
327 if (argstuple == NULL) {
328 return NULL;
329 }
330 PyObject *result = NULL;
331 /* Create a temporary dict for keyword arguments */
332 PyObject *kwdict = NULL;
333 if (kwnames != NULL && PyTuple_GET_SIZE(kwnames) > 0) {
334 kwdict = _PyStack_AsDict(args + nargs, kwnames);
335 if (kwdict == NULL) {
336 goto exit;
337 }
338 }
339 PyCFunctionWithKeywords meth = (PyCFunctionWithKeywords)
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100340 method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200341 if (meth == NULL) {
342 goto exit;
343 }
344 result = meth(args[0], argstuple, kwdict);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100345 _Py_LeaveRecursiveCall(tstate);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200346exit:
347 Py_DECREF(argstuple);
348 Py_XDECREF(kwdict);
349 return result;
350}
351
352static PyObject *
Petr Viktorine1becf42020-05-07 15:39:59 +0200353method_vectorcall_FASTCALL_KEYWORDS_METHOD(
354 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
355{
356 PyThreadState *tstate = _PyThreadState_GET();
357 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
358 if (method_check_args(func, args, nargs, NULL)) {
359 return NULL;
360 }
Petr Viktorine1becf42020-05-07 15:39:59 +0200361 PyCMethod meth = (PyCMethod) method_enter_call(tstate, func);
362 if (meth == NULL) {
363 return NULL;
364 }
365 PyObject *result = meth(args[0],
366 ((PyMethodDescrObject *)func)->d_common.d_type,
367 args+1, nargs-1, kwnames);
368 Py_LeaveRecursiveCall();
369 return result;
370}
371
372static PyObject *
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200373method_vectorcall_FASTCALL(
374 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
375{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100376 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200377 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
378 if (method_check_args(func, args, nargs, kwnames)) {
379 return NULL;
380 }
381 _PyCFunctionFast meth = (_PyCFunctionFast)
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100382 method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200383 if (meth == NULL) {
384 return NULL;
385 }
386 PyObject *result = meth(args[0], args+1, nargs-1);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100387 _Py_LeaveRecursiveCall(tstate);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200388 return result;
389}
390
391static PyObject *
392method_vectorcall_FASTCALL_KEYWORDS(
393 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
394{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100395 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200396 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
397 if (method_check_args(func, args, nargs, NULL)) {
398 return NULL;
399 }
400 _PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords)
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100401 method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200402 if (meth == NULL) {
403 return NULL;
404 }
405 PyObject *result = meth(args[0], args+1, nargs-1, kwnames);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100406 _Py_LeaveRecursiveCall(tstate);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200407 return result;
408}
409
410static PyObject *
411method_vectorcall_NOARGS(
412 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
413{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100414 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200415 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
416 if (method_check_args(func, args, nargs, kwnames)) {
417 return NULL;
418 }
419 if (nargs != 1) {
Jeroen Demeyerbf17d412019-11-05 16:48:04 +0100420 PyObject *funcstr = _PyObject_FunctionStr(func);
421 if (funcstr != NULL) {
422 PyErr_Format(PyExc_TypeError,
423 "%U takes no arguments (%zd given)", funcstr, nargs-1);
424 Py_DECREF(funcstr);
425 }
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200426 return NULL;
427 }
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100428 PyCFunction meth = (PyCFunction)method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200429 if (meth == NULL) {
430 return NULL;
431 }
432 PyObject *result = meth(args[0], NULL);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100433 _Py_LeaveRecursiveCall(tstate);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200434 return result;
435}
436
437static PyObject *
438method_vectorcall_O(
439 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
440{
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100441 PyThreadState *tstate = _PyThreadState_GET();
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200442 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
443 if (method_check_args(func, args, nargs, kwnames)) {
444 return NULL;
445 }
446 if (nargs != 2) {
Jeroen Demeyerbf17d412019-11-05 16:48:04 +0100447 PyObject *funcstr = _PyObject_FunctionStr(func);
448 if (funcstr != NULL) {
449 PyErr_Format(PyExc_TypeError,
450 "%U takes exactly one argument (%zd given)",
451 funcstr, nargs-1);
452 Py_DECREF(funcstr);
453 }
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200454 return NULL;
455 }
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100456 PyCFunction meth = (PyCFunction)method_enter_call(tstate, func);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200457 if (meth == NULL) {
458 return NULL;
459 }
460 PyObject *result = meth(args[0], args[1]);
Victor Stinnerbe434dc2019-11-05 00:51:22 +0100461 _Py_LeaveRecursiveCall(tstate);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200462 return result;
463}
464
465
Jeroen Demeyer3f345c32019-06-07 12:20:24 +0200466/* Instances of classmethod_descriptor are unlikely to be called directly.
467 For one, the analogous class "classmethod" (for Python classes) is not
468 callable. Second, users are not likely to access a classmethod_descriptor
469 directly, since it means pulling it from the class __dict__.
470
471 This is just an excuse to say that this doesn't need to be optimized:
472 we implement this simply by calling __get__ and then calling the result.
473*/
Tim Peters6d6c1a32001-08-02 04:15:00 +0000474static PyObject *
Tim Petersbca1cbc2002-12-09 22:56:13 +0000475classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000476 PyObject *kwds)
Tim Petersbca1cbc2002-12-09 22:56:13 +0000477{
Jeroen Demeyer3f345c32019-06-07 12:20:24 +0200478 Py_ssize_t argc = PyTuple_GET_SIZE(args);
Benjamin Peterson7295c6a2012-05-01 09:51:09 -0400479 if (argc < 1) {
480 PyErr_Format(PyExc_TypeError,
481 "descriptor '%V' of '%.100s' "
482 "object needs an argument",
483 descr_name((PyDescrObject *)descr), "?",
484 PyDescr_TYPE(descr)->tp_name);
485 return NULL;
486 }
Jeroen Demeyer3f345c32019-06-07 12:20:24 +0200487 PyObject *self = PyTuple_GET_ITEM(args, 0);
488 PyObject *bound = classmethod_get(descr, NULL, self);
489 if (bound == NULL) {
Benjamin Peterson7295c6a2012-05-01 09:51:09 -0400490 return NULL;
491 }
Petr Viktorinffd97532020-02-11 17:46:57 +0100492 PyObject *res = PyObject_VectorcallDict(bound, _PyTuple_ITEMS(args)+1,
Jeroen Demeyer3f345c32019-06-07 12:20:24 +0200493 argc-1, kwds);
494 Py_DECREF(bound);
495 return res;
Tim Petersbca1cbc2002-12-09 22:56:13 +0000496}
497
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300498Py_LOCAL_INLINE(PyObject *)
499wrapperdescr_raw_call(PyWrapperDescrObject *descr, PyObject *self,
500 PyObject *args, PyObject *kwds)
501{
502 wrapperfunc wrapper = descr->d_base->wrapper;
503
504 if (descr->d_base->flags & PyWrapperFlag_KEYWORDS) {
Serhiy Storchaka1c607152018-11-27 21:34:27 +0200505 wrapperfunc_kwds wk = (wrapperfunc_kwds)(void(*)(void))wrapper;
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300506 return (*wk)(self, args, descr->d_wrapped, kwds);
507 }
508
509 if (kwds != NULL && (!PyDict_Check(kwds) || PyDict_GET_SIZE(kwds) != 0)) {
510 PyErr_Format(PyExc_TypeError,
511 "wrapper %s() takes no keyword arguments",
512 descr->d_base->name);
513 return NULL;
514 }
515 return (*wrapper)(self, args, descr->d_wrapped);
516}
517
Tim Petersbca1cbc2002-12-09 22:56:13 +0000518static PyObject *
Tim Peters6d6c1a32001-08-02 04:15:00 +0000519wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
520{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000521 Py_ssize_t argc;
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300522 PyObject *self, *result;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000523
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000524 /* Make sure that the first argument is acceptable as 'self' */
525 assert(PyTuple_Check(args));
526 argc = PyTuple_GET_SIZE(args);
527 if (argc < 1) {
528 PyErr_Format(PyExc_TypeError,
529 "descriptor '%V' of '%.100s' "
530 "object needs an argument",
531 descr_name((PyDescrObject *)descr), "?",
532 PyDescr_TYPE(descr)->tp_name);
533 return NULL;
534 }
535 self = PyTuple_GET_ITEM(args, 0);
Victor Stinner3249dec2011-05-01 23:19:15 +0200536 if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
Victor Stinnerd9561312011-05-01 23:31:36 +0200537 (PyObject *)PyDescr_TYPE(descr))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000538 PyErr_Format(PyExc_TypeError,
539 "descriptor '%V' "
540 "requires a '%.100s' object "
541 "but received a '%.100s'",
542 descr_name((PyDescrObject *)descr), "?",
543 PyDescr_TYPE(descr)->tp_name,
Victor Stinner58ac7002020-02-07 03:04:21 +0100544 Py_TYPE(self)->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000545 return NULL;
546 }
Tim Peters6d6c1a32001-08-02 04:15:00 +0000547
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300548 args = PyTuple_GetSlice(args, 1, argc);
549 if (args == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000550 return NULL;
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300551 }
552 result = wrapperdescr_raw_call(descr, self, args, kwds);
553 Py_DECREF(args);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000554 return result;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000555}
556
Serhiy Storchaka5e02c782017-09-21 14:25:36 +0300557
Tim Peters6d6c1a32001-08-02 04:15:00 +0000558static PyObject *
Guido van Rossum6f799372001-09-20 20:46:19 +0000559method_get_doc(PyMethodDescrObject *descr, void *closure)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000560{
Larry Hastings2623c8c2014-02-08 22:15:29 -0800561 return _PyType_GetDocFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc);
Larry Hastings5c661892014-01-24 06:17:25 -0800562}
563
564static PyObject *
565method_get_text_signature(PyMethodDescrObject *descr, void *closure)
566{
Larry Hastings2623c8c2014-02-08 22:15:29 -0800567 return _PyType_GetTextSignatureFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000568}
569
Antoine Pitrou9d574812011-12-12 13:47:25 +0100570static PyObject *
571calculate_qualname(PyDescrObject *descr)
572{
573 PyObject *type_qualname, *res;
574 _Py_IDENTIFIER(__qualname__);
575
576 if (descr->d_name == NULL || !PyUnicode_Check(descr->d_name)) {
577 PyErr_SetString(PyExc_TypeError,
578 "<descriptor>.__name__ is not a unicode object");
579 return NULL;
580 }
581
582 type_qualname = _PyObject_GetAttrId((PyObject *)descr->d_type,
583 &PyId___qualname__);
584 if (type_qualname == NULL)
585 return NULL;
586
587 if (!PyUnicode_Check(type_qualname)) {
588 PyErr_SetString(PyExc_TypeError, "<descriptor>.__objclass__."
589 "__qualname__ is not a unicode object");
590 Py_XDECREF(type_qualname);
591 return NULL;
592 }
593
594 res = PyUnicode_FromFormat("%S.%S", type_qualname, descr->d_name);
595 Py_DECREF(type_qualname);
596 return res;
597}
598
599static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +0200600descr_get_qualname(PyDescrObject *descr, void *Py_UNUSED(ignored))
Antoine Pitrou9d574812011-12-12 13:47:25 +0100601{
602 if (descr->d_qualname == NULL)
603 descr->d_qualname = calculate_qualname(descr);
604 Py_XINCREF(descr->d_qualname);
605 return descr->d_qualname;
606}
607
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100608static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530609descr_reduce(PyDescrObject *descr, PyObject *Py_UNUSED(ignored))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100610{
Serhiy Storchakabb86bf42018-12-11 08:28:18 +0200611 return Py_BuildValue("N(OO)", _PyEval_GetBuiltinId(&PyId_getattr),
612 PyDescr_TYPE(descr), PyDescr_NAME(descr));
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100613}
614
615static PyMethodDef descr_methods[] = {
616 {"__reduce__", (PyCFunction)descr_reduce, METH_NOARGS, NULL},
617 {NULL, NULL}
618};
619
Guido van Rossum6f799372001-09-20 20:46:19 +0000620static PyMemberDef descr_members[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000621 {"__objclass__", T_OBJECT, offsetof(PyDescrObject, d_type), READONLY},
622 {"__name__", T_OBJECT, offsetof(PyDescrObject, d_name), READONLY},
623 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +0000624};
625
Guido van Rossum32d34c82001-09-20 21:45:26 +0000626static PyGetSetDef method_getset[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000627 {"__doc__", (getter)method_get_doc},
Antoine Pitrou9d574812011-12-12 13:47:25 +0100628 {"__qualname__", (getter)descr_get_qualname},
Larry Hastings5c661892014-01-24 06:17:25 -0800629 {"__text_signature__", (getter)method_get_text_signature},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000630 {0}
Guido van Rossum6f799372001-09-20 20:46:19 +0000631};
632
633static PyObject *
634member_get_doc(PyMemberDescrObject *descr, void *closure)
635{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000636 if (descr->d_member->doc == NULL) {
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200637 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000638 }
639 return PyUnicode_FromString(descr->d_member->doc);
Guido van Rossum6f799372001-09-20 20:46:19 +0000640}
641
Guido van Rossum32d34c82001-09-20 21:45:26 +0000642static PyGetSetDef member_getset[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000643 {"__doc__", (getter)member_get_doc},
Antoine Pitrou9d574812011-12-12 13:47:25 +0100644 {"__qualname__", (getter)descr_get_qualname},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000645 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +0000646};
647
648static PyObject *
Guido van Rossum32d34c82001-09-20 21:45:26 +0000649getset_get_doc(PyGetSetDescrObject *descr, void *closure)
650{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000651 if (descr->d_getset->doc == NULL) {
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200652 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000653 }
654 return PyUnicode_FromString(descr->d_getset->doc);
Guido van Rossum32d34c82001-09-20 21:45:26 +0000655}
656
657static PyGetSetDef getset_getset[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000658 {"__doc__", (getter)getset_get_doc},
Antoine Pitrou9d574812011-12-12 13:47:25 +0100659 {"__qualname__", (getter)descr_get_qualname},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000660 {0}
Guido van Rossum32d34c82001-09-20 21:45:26 +0000661};
662
663static PyObject *
Armin Rigoc6686b72005-11-07 08:38:00 +0000664wrapperdescr_get_doc(PyWrapperDescrObject *descr, void *closure)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000665{
Larry Hastings2623c8c2014-02-08 22:15:29 -0800666 return _PyType_GetDocFromInternalDoc(descr->d_base->name, descr->d_base->doc);
Larry Hastings5c661892014-01-24 06:17:25 -0800667}
668
669static PyObject *
670wrapperdescr_get_text_signature(PyWrapperDescrObject *descr, void *closure)
671{
Larry Hastings2623c8c2014-02-08 22:15:29 -0800672 return _PyType_GetTextSignatureFromInternalDoc(descr->d_base->name, descr->d_base->doc);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000673}
674
Armin Rigoc6686b72005-11-07 08:38:00 +0000675static PyGetSetDef wrapperdescr_getset[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000676 {"__doc__", (getter)wrapperdescr_get_doc},
Antoine Pitrou9d574812011-12-12 13:47:25 +0100677 {"__qualname__", (getter)descr_get_qualname},
Larry Hastings5c661892014-01-24 06:17:25 -0800678 {"__text_signature__", (getter)wrapperdescr_get_text_signature},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000679 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +0000680};
681
Guido van Rossum048eb752001-10-02 21:24:57 +0000682static int
683descr_traverse(PyObject *self, visitproc visit, void *arg)
684{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000685 PyDescrObject *descr = (PyDescrObject *)self;
686 Py_VISIT(descr->d_type);
687 return 0;
Guido van Rossum048eb752001-10-02 21:24:57 +0000688}
689
Christian Heimesa22e8bd2007-11-29 22:35:39 +0000690PyTypeObject PyMethodDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000691 PyVarObject_HEAD_INIT(&PyType_Type, 0)
692 "method_descriptor",
693 sizeof(PyMethodDescrObject),
694 0,
695 (destructor)descr_dealloc, /* tp_dealloc */
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200696 offsetof(PyMethodDescrObject, vectorcall), /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000697 0, /* tp_getattr */
698 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200699 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000700 (reprfunc)method_repr, /* tp_repr */
701 0, /* tp_as_number */
702 0, /* tp_as_sequence */
703 0, /* tp_as_mapping */
704 0, /* tp_hash */
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200705 PyVectorcall_Call, /* tp_call */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000706 0, /* tp_str */
707 PyObject_GenericGetAttr, /* tp_getattro */
708 0, /* tp_setattro */
709 0, /* tp_as_buffer */
Jeroen Demeyereb65e242019-05-28 14:42:53 +0200710 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Petr Viktorinffd97532020-02-11 17:46:57 +0100711 Py_TPFLAGS_HAVE_VECTORCALL |
Jeroen Demeyereb65e242019-05-28 14:42:53 +0200712 Py_TPFLAGS_METHOD_DESCRIPTOR, /* tp_flags */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000713 0, /* tp_doc */
714 descr_traverse, /* tp_traverse */
715 0, /* tp_clear */
716 0, /* tp_richcompare */
717 0, /* tp_weaklistoffset */
718 0, /* tp_iter */
719 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100720 descr_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000721 descr_members, /* tp_members */
722 method_getset, /* tp_getset */
723 0, /* tp_base */
724 0, /* tp_dict */
725 (descrgetfunc)method_get, /* tp_descr_get */
726 0, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000727};
728
Guido van Rossumb6e5a0c2003-02-11 18:44:42 +0000729/* This is for METH_CLASS in C, not for "f = classmethod(f)" in Python! */
Christian Heimesa22e8bd2007-11-29 22:35:39 +0000730PyTypeObject PyClassMethodDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000731 PyVarObject_HEAD_INIT(&PyType_Type, 0)
732 "classmethod_descriptor",
733 sizeof(PyMethodDescrObject),
734 0,
735 (destructor)descr_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200736 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000737 0, /* tp_getattr */
738 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200739 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000740 (reprfunc)method_repr, /* tp_repr */
741 0, /* tp_as_number */
742 0, /* tp_as_sequence */
743 0, /* tp_as_mapping */
744 0, /* tp_hash */
745 (ternaryfunc)classmethoddescr_call, /* tp_call */
746 0, /* tp_str */
747 PyObject_GenericGetAttr, /* tp_getattro */
748 0, /* tp_setattro */
749 0, /* tp_as_buffer */
750 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
751 0, /* tp_doc */
752 descr_traverse, /* tp_traverse */
753 0, /* tp_clear */
754 0, /* tp_richcompare */
755 0, /* tp_weaklistoffset */
756 0, /* tp_iter */
757 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100758 descr_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000759 descr_members, /* tp_members */
760 method_getset, /* tp_getset */
761 0, /* tp_base */
762 0, /* tp_dict */
763 (descrgetfunc)classmethod_get, /* tp_descr_get */
764 0, /* tp_descr_set */
Tim Petersbca1cbc2002-12-09 22:56:13 +0000765};
766
Christian Heimesa22e8bd2007-11-29 22:35:39 +0000767PyTypeObject PyMemberDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000768 PyVarObject_HEAD_INIT(&PyType_Type, 0)
769 "member_descriptor",
770 sizeof(PyMemberDescrObject),
771 0,
772 (destructor)descr_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200773 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000774 0, /* tp_getattr */
775 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200776 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000777 (reprfunc)member_repr, /* tp_repr */
778 0, /* tp_as_number */
779 0, /* tp_as_sequence */
780 0, /* tp_as_mapping */
781 0, /* tp_hash */
782 0, /* tp_call */
783 0, /* tp_str */
784 PyObject_GenericGetAttr, /* tp_getattro */
785 0, /* tp_setattro */
786 0, /* tp_as_buffer */
787 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
788 0, /* tp_doc */
789 descr_traverse, /* tp_traverse */
790 0, /* tp_clear */
791 0, /* tp_richcompare */
792 0, /* tp_weaklistoffset */
793 0, /* tp_iter */
794 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100795 descr_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000796 descr_members, /* tp_members */
797 member_getset, /* tp_getset */
798 0, /* tp_base */
799 0, /* tp_dict */
800 (descrgetfunc)member_get, /* tp_descr_get */
801 (descrsetfunc)member_set, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000802};
803
Christian Heimesa22e8bd2007-11-29 22:35:39 +0000804PyTypeObject PyGetSetDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000805 PyVarObject_HEAD_INIT(&PyType_Type, 0)
806 "getset_descriptor",
807 sizeof(PyGetSetDescrObject),
808 0,
809 (destructor)descr_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200810 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000811 0, /* tp_getattr */
812 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200813 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000814 (reprfunc)getset_repr, /* tp_repr */
815 0, /* tp_as_number */
816 0, /* tp_as_sequence */
817 0, /* tp_as_mapping */
818 0, /* tp_hash */
819 0, /* tp_call */
820 0, /* tp_str */
821 PyObject_GenericGetAttr, /* tp_getattro */
822 0, /* tp_setattro */
823 0, /* tp_as_buffer */
824 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
825 0, /* tp_doc */
826 descr_traverse, /* tp_traverse */
827 0, /* tp_clear */
828 0, /* tp_richcompare */
829 0, /* tp_weaklistoffset */
830 0, /* tp_iter */
831 0, /* tp_iternext */
832 0, /* tp_methods */
833 descr_members, /* tp_members */
834 getset_getset, /* tp_getset */
835 0, /* tp_base */
836 0, /* tp_dict */
837 (descrgetfunc)getset_get, /* tp_descr_get */
838 (descrsetfunc)getset_set, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000839};
840
Guido van Rossumf4593e02001-10-03 12:09:30 +0000841PyTypeObject PyWrapperDescr_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000842 PyVarObject_HEAD_INIT(&PyType_Type, 0)
843 "wrapper_descriptor",
844 sizeof(PyWrapperDescrObject),
845 0,
846 (destructor)descr_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200847 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000848 0, /* tp_getattr */
849 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200850 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000851 (reprfunc)wrapperdescr_repr, /* tp_repr */
852 0, /* tp_as_number */
853 0, /* tp_as_sequence */
854 0, /* tp_as_mapping */
855 0, /* tp_hash */
856 (ternaryfunc)wrapperdescr_call, /* tp_call */
857 0, /* tp_str */
858 PyObject_GenericGetAttr, /* tp_getattro */
859 0, /* tp_setattro */
860 0, /* tp_as_buffer */
Jeroen Demeyereb65e242019-05-28 14:42:53 +0200861 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
862 Py_TPFLAGS_METHOD_DESCRIPTOR, /* tp_flags */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000863 0, /* tp_doc */
864 descr_traverse, /* tp_traverse */
865 0, /* tp_clear */
866 0, /* tp_richcompare */
867 0, /* tp_weaklistoffset */
868 0, /* tp_iter */
869 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +0100870 descr_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000871 descr_members, /* tp_members */
872 wrapperdescr_getset, /* tp_getset */
873 0, /* tp_base */
874 0, /* tp_dict */
875 (descrgetfunc)wrapperdescr_get, /* tp_descr_get */
876 0, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000877};
878
879static PyDescrObject *
Jeremy Hyltonaf68c872005-12-10 18:50:16 +0000880descr_new(PyTypeObject *descrtype, PyTypeObject *type, const char *name)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000881{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000882 PyDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000883
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000884 descr = (PyDescrObject *)PyType_GenericAlloc(descrtype, 0);
885 if (descr != NULL) {
886 Py_XINCREF(type);
887 descr->d_type = type;
888 descr->d_name = PyUnicode_InternFromString(name);
889 if (descr->d_name == NULL) {
890 Py_DECREF(descr);
891 descr = NULL;
892 }
Benjamin Petersonf2fe7f02011-12-17 08:02:20 -0500893 else {
894 descr->d_qualname = NULL;
895 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000896 }
897 return descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000898}
899
900PyObject *
901PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method)
902{
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200903 /* Figure out correct vectorcall function to use */
904 vectorcallfunc vectorcall;
Petr Viktorine1becf42020-05-07 15:39:59 +0200905 switch (method->ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS |
906 METH_O | METH_KEYWORDS | METH_METHOD))
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200907 {
908 case METH_VARARGS:
909 vectorcall = method_vectorcall_VARARGS;
910 break;
911 case METH_VARARGS | METH_KEYWORDS:
912 vectorcall = method_vectorcall_VARARGS_KEYWORDS;
913 break;
914 case METH_FASTCALL:
915 vectorcall = method_vectorcall_FASTCALL;
916 break;
917 case METH_FASTCALL | METH_KEYWORDS:
918 vectorcall = method_vectorcall_FASTCALL_KEYWORDS;
919 break;
920 case METH_NOARGS:
921 vectorcall = method_vectorcall_NOARGS;
922 break;
923 case METH_O:
924 vectorcall = method_vectorcall_O;
925 break;
Petr Viktorine1becf42020-05-07 15:39:59 +0200926 case METH_METHOD | METH_FASTCALL | METH_KEYWORDS:
927 vectorcall = method_vectorcall_FASTCALL_KEYWORDS_METHOD;
928 break;
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200929 default:
Victor Stinnerc7d2d692020-03-12 08:38:11 +0100930 PyErr_Format(PyExc_SystemError,
931 "%s() method: bad call flags", method->ml_name);
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200932 return NULL;
933 }
934
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000935 PyMethodDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000936
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000937 descr = (PyMethodDescrObject *)descr_new(&PyMethodDescr_Type,
938 type, method->ml_name);
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200939 if (descr != NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000940 descr->d_method = method;
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200941 descr->vectorcall = vectorcall;
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200942 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000943 return (PyObject *)descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000944}
945
946PyObject *
Tim Petersbca1cbc2002-12-09 22:56:13 +0000947PyDescr_NewClassMethod(PyTypeObject *type, PyMethodDef *method)
948{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000949 PyMethodDescrObject *descr;
Tim Petersbca1cbc2002-12-09 22:56:13 +0000950
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000951 descr = (PyMethodDescrObject *)descr_new(&PyClassMethodDescr_Type,
952 type, method->ml_name);
953 if (descr != NULL)
954 descr->d_method = method;
955 return (PyObject *)descr;
Tim Petersbca1cbc2002-12-09 22:56:13 +0000956}
957
958PyObject *
Guido van Rossum6f799372001-09-20 20:46:19 +0000959PyDescr_NewMember(PyTypeObject *type, PyMemberDef *member)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000960{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000961 PyMemberDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000962
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000963 descr = (PyMemberDescrObject *)descr_new(&PyMemberDescr_Type,
964 type, member->name);
965 if (descr != NULL)
966 descr->d_member = member;
967 return (PyObject *)descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000968}
969
970PyObject *
Guido van Rossum32d34c82001-09-20 21:45:26 +0000971PyDescr_NewGetSet(PyTypeObject *type, PyGetSetDef *getset)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000972{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000973 PyGetSetDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000974
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000975 descr = (PyGetSetDescrObject *)descr_new(&PyGetSetDescr_Type,
976 type, getset->name);
977 if (descr != NULL)
978 descr->d_getset = getset;
979 return (PyObject *)descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000980}
981
982PyObject *
983PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped)
984{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000985 PyWrapperDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000986
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000987 descr = (PyWrapperDescrObject *)descr_new(&PyWrapperDescr_Type,
988 type, base->name);
989 if (descr != NULL) {
990 descr->d_base = base;
991 descr->d_wrapped = wrapped;
992 }
993 return (PyObject *)descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000994}
995
Erlend Egeberg Aasland871eb422021-02-16 08:50:00 +0100996int
997PyDescr_IsData(PyObject *ob)
998{
999 return Py_TYPE(ob)->tp_descr_set != NULL;
1000}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001001
Victor Stinner0db176f2012-04-16 00:16:30 +02001002/* --- mappingproxy: read-only proxy for mappings --- */
Tim Peters6d6c1a32001-08-02 04:15:00 +00001003
1004/* This has no reason to be in this file except that adding new files is a
1005 bit of a pain */
1006
1007typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001008 PyObject_HEAD
Victor Stinner0db176f2012-04-16 00:16:30 +02001009 PyObject *mapping;
1010} mappingproxyobject;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001011
Martin v. Löwis18e16552006-02-15 17:27:45 +00001012static Py_ssize_t
Victor Stinner0db176f2012-04-16 00:16:30 +02001013mappingproxy_len(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001014{
Victor Stinner0db176f2012-04-16 00:16:30 +02001015 return PyObject_Size(pp->mapping);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001016}
1017
1018static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001019mappingproxy_getitem(mappingproxyobject *pp, PyObject *key)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001020{
Victor Stinner0db176f2012-04-16 00:16:30 +02001021 return PyObject_GetItem(pp->mapping, key);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001022}
1023
Victor Stinner0db176f2012-04-16 00:16:30 +02001024static PyMappingMethods mappingproxy_as_mapping = {
1025 (lenfunc)mappingproxy_len, /* mp_length */
1026 (binaryfunc)mappingproxy_getitem, /* mp_subscript */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001027 0, /* mp_ass_subscript */
Tim Peters6d6c1a32001-08-02 04:15:00 +00001028};
1029
Brandt Bucher4663f662020-03-07 11:03:09 -08001030static PyObject *
1031mappingproxy_or(PyObject *left, PyObject *right)
1032{
1033 if (PyObject_TypeCheck(left, &PyDictProxy_Type)) {
1034 left = ((mappingproxyobject*)left)->mapping;
1035 }
1036 if (PyObject_TypeCheck(right, &PyDictProxy_Type)) {
1037 right = ((mappingproxyobject*)right)->mapping;
1038 }
1039 return PyNumber_Or(left, right);
1040}
1041
1042static PyObject *
1043mappingproxy_ior(PyObject *self, PyObject *Py_UNUSED(other))
1044{
1045 return PyErr_Format(PyExc_TypeError,
1046 "'|=' is not supported by %s; use '|' instead", Py_TYPE(self)->tp_name);
1047}
1048
1049static PyNumberMethods mappingproxy_as_number = {
1050 .nb_or = mappingproxy_or,
1051 .nb_inplace_or = mappingproxy_ior,
1052};
1053
Tim Peters6d6c1a32001-08-02 04:15:00 +00001054static int
Victor Stinner0db176f2012-04-16 00:16:30 +02001055mappingproxy_contains(mappingproxyobject *pp, PyObject *key)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001056{
Victor Stinner0db176f2012-04-16 00:16:30 +02001057 if (PyDict_CheckExact(pp->mapping))
1058 return PyDict_Contains(pp->mapping, key);
1059 else
1060 return PySequence_Contains(pp->mapping, key);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001061}
1062
Victor Stinner0db176f2012-04-16 00:16:30 +02001063static PySequenceMethods mappingproxy_as_sequence = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001064 0, /* sq_length */
1065 0, /* sq_concat */
1066 0, /* sq_repeat */
1067 0, /* sq_item */
1068 0, /* sq_slice */
1069 0, /* sq_ass_item */
1070 0, /* sq_ass_slice */
Victor Stinner0db176f2012-04-16 00:16:30 +02001071 (objobjproc)mappingproxy_contains, /* sq_contains */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001072 0, /* sq_inplace_concat */
1073 0, /* sq_inplace_repeat */
Tim Peters6d6c1a32001-08-02 04:15:00 +00001074};
1075
1076static PyObject *
Jeroen Demeyerb1263d52019-06-28 11:49:00 +02001077mappingproxy_get(mappingproxyobject *pp, PyObject *const *args, Py_ssize_t nargs)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001078{
Jeroen Demeyerb1263d52019-06-28 11:49:00 +02001079 /* newargs: mapping, key, default=None */
1080 PyObject *newargs[3];
1081 newargs[0] = pp->mapping;
1082 newargs[2] = Py_None;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001083
Jeroen Demeyerb1263d52019-06-28 11:49:00 +02001084 if (!_PyArg_UnpackStack(args, nargs, "get", 1, 2,
1085 &newargs[1], &newargs[2]))
1086 {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001087 return NULL;
Jeroen Demeyerb1263d52019-06-28 11:49:00 +02001088 }
1089 _Py_IDENTIFIER(get);
1090 return _PyObject_VectorcallMethodId(&PyId_get, newargs,
1091 3 | PY_VECTORCALL_ARGUMENTS_OFFSET,
1092 NULL);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001093}
1094
1095static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301096mappingproxy_keys(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001097{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001098 _Py_IDENTIFIER(keys);
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001099 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId_keys);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001100}
1101
1102static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301103mappingproxy_values(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001104{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001105 _Py_IDENTIFIER(values);
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001106 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId_values);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001107}
1108
1109static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301110mappingproxy_items(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001111{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001112 _Py_IDENTIFIER(items);
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001113 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId_items);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001114}
1115
1116static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301117mappingproxy_copy(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001118{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001119 _Py_IDENTIFIER(copy);
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001120 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId_copy);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001121}
1122
Zackery Spytz02fa0ea2020-05-07 23:25:50 -06001123static PyObject *
1124mappingproxy_reversed(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
1125{
1126 _Py_IDENTIFIER(__reversed__);
1127 return _PyObject_CallMethodIdNoArgs(pp->mapping, &PyId___reversed__);
1128}
1129
Victor Stinner0db176f2012-04-16 00:16:30 +02001130/* WARNING: mappingproxy methods must not give access
1131 to the underlying mapping */
1132
1133static PyMethodDef mappingproxy_methods[] = {
Zackery Spytz43d564c2019-08-13 23:51:06 -06001134 {"get", (PyCFunction)(void(*)(void))mappingproxy_get, METH_FASTCALL,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001135 PyDoc_STR("D.get(k[,d]) -> D[k] if k in D, else d."
Victor Stinner0db176f2012-04-16 00:16:30 +02001136 " d defaults to None.")},
1137 {"keys", (PyCFunction)mappingproxy_keys, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001138 PyDoc_STR("D.keys() -> list of D's keys")},
Victor Stinner0db176f2012-04-16 00:16:30 +02001139 {"values", (PyCFunction)mappingproxy_values, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001140 PyDoc_STR("D.values() -> list of D's values")},
Victor Stinner0db176f2012-04-16 00:16:30 +02001141 {"items", (PyCFunction)mappingproxy_items, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001142 PyDoc_STR("D.items() -> list of D's (key, value) pairs, as 2-tuples")},
Victor Stinner0db176f2012-04-16 00:16:30 +02001143 {"copy", (PyCFunction)mappingproxy_copy, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001144 PyDoc_STR("D.copy() -> a shallow copy of D")},
Guido van Rossum48b069a2020-04-07 09:50:06 -07001145 {"__class_getitem__", (PyCFunction)Py_GenericAlias, METH_O|METH_CLASS,
1146 PyDoc_STR("See PEP 585")},
Zackery Spytz02fa0ea2020-05-07 23:25:50 -06001147 {"__reversed__", (PyCFunction)mappingproxy_reversed, METH_NOARGS,
1148 PyDoc_STR("D.__reversed__() -> reverse iterator")},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001149 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001150};
1151
1152static void
Victor Stinner0db176f2012-04-16 00:16:30 +02001153mappingproxy_dealloc(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001154{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001155 _PyObject_GC_UNTRACK(pp);
Victor Stinner0db176f2012-04-16 00:16:30 +02001156 Py_DECREF(pp->mapping);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001157 PyObject_GC_Del(pp);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001158}
1159
1160static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001161mappingproxy_getiter(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001162{
Victor Stinner0db176f2012-04-16 00:16:30 +02001163 return PyObject_GetIter(pp->mapping);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001164}
1165
Neil Schemenauer26775122001-10-21 22:26:43 +00001166static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001167mappingproxy_str(mappingproxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001168{
Victor Stinner0db176f2012-04-16 00:16:30 +02001169 return PyObject_Str(pp->mapping);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001170}
1171
Ezio Melottiac53ab62010-12-18 14:59:43 +00001172static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001173mappingproxy_repr(mappingproxyobject *pp)
Ezio Melottiac53ab62010-12-18 14:59:43 +00001174{
Victor Stinner0db176f2012-04-16 00:16:30 +02001175 return PyUnicode_FromFormat("mappingproxy(%R)", pp->mapping);
Ezio Melottiac53ab62010-12-18 14:59:43 +00001176}
1177
Guido van Rossum048eb752001-10-02 21:24:57 +00001178static int
Victor Stinner0db176f2012-04-16 00:16:30 +02001179mappingproxy_traverse(PyObject *self, visitproc visit, void *arg)
Guido van Rossum048eb752001-10-02 21:24:57 +00001180{
Victor Stinner0db176f2012-04-16 00:16:30 +02001181 mappingproxyobject *pp = (mappingproxyobject *)self;
1182 Py_VISIT(pp->mapping);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001183 return 0;
Guido van Rossum048eb752001-10-02 21:24:57 +00001184}
1185
Raymond Hettinger29a6d442002-08-31 15:51:04 +00001186static PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001187mappingproxy_richcompare(mappingproxyobject *v, PyObject *w, int op)
Raymond Hettinger29a6d442002-08-31 15:51:04 +00001188{
Victor Stinner0db176f2012-04-16 00:16:30 +02001189 return PyObject_RichCompare(v->mapping, w, op);
1190}
1191
1192static int
1193mappingproxy_check_mapping(PyObject *mapping)
1194{
1195 if (!PyMapping_Check(mapping)
1196 || PyList_Check(mapping)
1197 || PyTuple_Check(mapping)) {
1198 PyErr_Format(PyExc_TypeError,
1199 "mappingproxy() argument must be a mapping, not %s",
1200 Py_TYPE(mapping)->tp_name);
1201 return -1;
1202 }
1203 return 0;
1204}
1205
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001206/*[clinic input]
1207@classmethod
1208mappingproxy.__new__ as mappingproxy_new
Victor Stinner0db176f2012-04-16 00:16:30 +02001209
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001210 mapping: object
1211
1212[clinic start generated code]*/
1213
1214static PyObject *
1215mappingproxy_new_impl(PyTypeObject *type, PyObject *mapping)
1216/*[clinic end generated code: output=65f27f02d5b68fa7 input=d2d620d4f598d4f8]*/
1217{
1218 mappingproxyobject *mappingproxy;
Victor Stinner0db176f2012-04-16 00:16:30 +02001219
1220 if (mappingproxy_check_mapping(mapping) == -1)
1221 return NULL;
1222
1223 mappingproxy = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type);
1224 if (mappingproxy == NULL)
1225 return NULL;
1226 Py_INCREF(mapping);
1227 mappingproxy->mapping = mapping;
1228 _PyObject_GC_TRACK(mappingproxy);
1229 return (PyObject *)mappingproxy;
Raymond Hettinger29a6d442002-08-31 15:51:04 +00001230}
1231
Tim Peters6d6c1a32001-08-02 04:15:00 +00001232PyObject *
Victor Stinner0db176f2012-04-16 00:16:30 +02001233PyDictProxy_New(PyObject *mapping)
Tim Peters6d6c1a32001-08-02 04:15:00 +00001234{
Victor Stinner0db176f2012-04-16 00:16:30 +02001235 mappingproxyobject *pp;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001236
Victor Stinner0db176f2012-04-16 00:16:30 +02001237 if (mappingproxy_check_mapping(mapping) == -1)
1238 return NULL;
1239
1240 pp = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001241 if (pp != NULL) {
Victor Stinner0db176f2012-04-16 00:16:30 +02001242 Py_INCREF(mapping);
1243 pp->mapping = mapping;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001244 _PyObject_GC_TRACK(pp);
1245 }
1246 return (PyObject *)pp;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001247}
1248
1249
1250/* --- Wrapper object for "slot" methods --- */
1251
1252/* This has no reason to be in this file except that adding new files is a
1253 bit of a pain */
1254
1255typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001256 PyObject_HEAD
1257 PyWrapperDescrObject *descr;
1258 PyObject *self;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001259} wrapperobject;
1260
Andy Lesterdffe4c02020-03-04 07:15:20 -06001261#define Wrapper_Check(v) Py_IS_TYPE(v, &_PyMethodWrapper_Type)
Mark Dickinson211c6252009-02-01 10:28:51 +00001262
Tim Peters6d6c1a32001-08-02 04:15:00 +00001263static void
1264wrapper_dealloc(wrapperobject *wp)
1265{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001266 PyObject_GC_UnTrack(wp);
Jeroen Demeyer351c6742019-05-10 19:21:11 +02001267 Py_TRASHCAN_BEGIN(wp, wrapper_dealloc)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001268 Py_XDECREF(wp->descr);
1269 Py_XDECREF(wp->self);
1270 PyObject_GC_Del(wp);
Jeroen Demeyer351c6742019-05-10 19:21:11 +02001271 Py_TRASHCAN_END
Tim Peters6d6c1a32001-08-02 04:15:00 +00001272}
1273
Mark Dickinson211c6252009-02-01 10:28:51 +00001274static PyObject *
1275wrapper_richcompare(PyObject *a, PyObject *b, int op)
Armin Rigoc6686b72005-11-07 08:38:00 +00001276{
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001277 wrapperobject *wa, *wb;
1278 int eq;
Mark Dickinson211c6252009-02-01 10:28:51 +00001279
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001280 assert(a != NULL && b != NULL);
Mark Dickinson211c6252009-02-01 10:28:51 +00001281
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001282 /* both arguments should be wrapperobjects */
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001283 if ((op != Py_EQ && op != Py_NE)
1284 || !Wrapper_Check(a) || !Wrapper_Check(b))
1285 {
stratakise8b19652017-11-02 11:32:54 +01001286 Py_RETURN_NOTIMPLEMENTED;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001287 }
Mark Dickinson211c6252009-02-01 10:28:51 +00001288
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001289 wa = (wrapperobject *)a;
1290 wb = (wrapperobject *)b;
1291 eq = (wa->descr == wb->descr && wa->self == wb->self);
1292 if (eq == (op == Py_EQ)) {
1293 Py_RETURN_TRUE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001294 }
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001295 else {
1296 Py_RETURN_FALSE;
1297 }
Armin Rigoc6686b72005-11-07 08:38:00 +00001298}
1299
Benjamin Peterson8f67d082010-10-17 20:54:53 +00001300static Py_hash_t
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001301wrapper_hash(wrapperobject *wp)
1302{
Benjamin Peterson8f67d082010-10-17 20:54:53 +00001303 Py_hash_t x, y;
Serhiy Storchakaac20e0f2018-07-31 09:18:24 +03001304 x = _Py_HashPointer(wp->self);
1305 y = _Py_HashPointer(wp->descr);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001306 x = x ^ y;
1307 if (x == -1)
1308 x = -2;
1309 return x;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001310}
1311
Armin Rigoc6686b72005-11-07 08:38:00 +00001312static PyObject *
1313wrapper_repr(wrapperobject *wp)
1314{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001315 return PyUnicode_FromFormat("<method-wrapper '%s' of %s object at %p>",
1316 wp->descr->d_base->name,
Victor Stinner58ac7002020-02-07 03:04:21 +01001317 Py_TYPE(wp->self)->tp_name,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001318 wp->self);
Armin Rigoc6686b72005-11-07 08:38:00 +00001319}
1320
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001321static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301322wrapper_reduce(wrapperobject *wp, PyObject *Py_UNUSED(ignored))
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001323{
Serhiy Storchakabb86bf42018-12-11 08:28:18 +02001324 return Py_BuildValue("N(OO)", _PyEval_GetBuiltinId(&PyId_getattr),
1325 wp->self, PyDescr_NAME(wp->descr));
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001326}
1327
1328static PyMethodDef wrapper_methods[] = {
1329 {"__reduce__", (PyCFunction)wrapper_reduce, METH_NOARGS, NULL},
1330 {NULL, NULL}
1331};
1332
Armin Rigoc6686b72005-11-07 08:38:00 +00001333static PyMemberDef wrapper_members[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001334 {"__self__", T_OBJECT, offsetof(wrapperobject, self), READONLY},
1335 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001336};
1337
1338static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001339wrapper_objclass(wrapperobject *wp, void *Py_UNUSED(ignored))
Armin Rigoc6686b72005-11-07 08:38:00 +00001340{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001341 PyObject *c = (PyObject *)PyDescr_TYPE(wp->descr);
Armin Rigoc6686b72005-11-07 08:38:00 +00001342
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001343 Py_INCREF(c);
1344 return c;
Armin Rigoc6686b72005-11-07 08:38:00 +00001345}
1346
1347static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001348wrapper_name(wrapperobject *wp, void *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001349{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001350 const char *s = wp->descr->d_base->name;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001351
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001352 return PyUnicode_FromString(s);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001353}
1354
1355static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001356wrapper_doc(wrapperobject *wp, void *Py_UNUSED(ignored))
Tim Peters6d6c1a32001-08-02 04:15:00 +00001357{
Larry Hastings2623c8c2014-02-08 22:15:29 -08001358 return _PyType_GetDocFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc);
Larry Hastings5c661892014-01-24 06:17:25 -08001359}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001360
Larry Hastings5c661892014-01-24 06:17:25 -08001361static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001362wrapper_text_signature(wrapperobject *wp, void *Py_UNUSED(ignored))
Larry Hastings5c661892014-01-24 06:17:25 -08001363{
Larry Hastings2623c8c2014-02-08 22:15:29 -08001364 return _PyType_GetTextSignatureFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001365}
1366
Antoine Pitrou9d574812011-12-12 13:47:25 +01001367static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001368wrapper_qualname(wrapperobject *wp, void *Py_UNUSED(ignored))
Antoine Pitrou9d574812011-12-12 13:47:25 +01001369{
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001370 return descr_get_qualname((PyDescrObject *)wp->descr, NULL);
Antoine Pitrou9d574812011-12-12 13:47:25 +01001371}
1372
Guido van Rossum32d34c82001-09-20 21:45:26 +00001373static PyGetSetDef wrapper_getsets[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001374 {"__objclass__", (getter)wrapper_objclass},
1375 {"__name__", (getter)wrapper_name},
Antoine Pitrou9d574812011-12-12 13:47:25 +01001376 {"__qualname__", (getter)wrapper_qualname},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001377 {"__doc__", (getter)wrapper_doc},
Larry Hastings5c661892014-01-24 06:17:25 -08001378 {"__text_signature__", (getter)wrapper_text_signature},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001379 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +00001380};
1381
1382static PyObject *
1383wrapper_call(wrapperobject *wp, PyObject *args, PyObject *kwds)
1384{
Serhiy Storchaka5e02c782017-09-21 14:25:36 +03001385 return wrapperdescr_raw_call(wp->descr, wp->self, args, kwds);
Tim Peters6d6c1a32001-08-02 04:15:00 +00001386}
1387
Guido van Rossum048eb752001-10-02 21:24:57 +00001388static int
1389wrapper_traverse(PyObject *self, visitproc visit, void *arg)
1390{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001391 wrapperobject *wp = (wrapperobject *)self;
1392 Py_VISIT(wp->descr);
1393 Py_VISIT(wp->self);
1394 return 0;
Guido van Rossum048eb752001-10-02 21:24:57 +00001395}
1396
Benjamin Petersoneff61f62011-09-01 16:32:31 -04001397PyTypeObject _PyMethodWrapper_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001398 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1399 "method-wrapper", /* tp_name */
1400 sizeof(wrapperobject), /* tp_basicsize */
1401 0, /* tp_itemsize */
1402 /* methods */
1403 (destructor)wrapper_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001404 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001405 0, /* tp_getattr */
1406 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001407 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001408 (reprfunc)wrapper_repr, /* tp_repr */
1409 0, /* tp_as_number */
1410 0, /* tp_as_sequence */
1411 0, /* tp_as_mapping */
1412 (hashfunc)wrapper_hash, /* tp_hash */
1413 (ternaryfunc)wrapper_call, /* tp_call */
1414 0, /* tp_str */
1415 PyObject_GenericGetAttr, /* tp_getattro */
1416 0, /* tp_setattro */
1417 0, /* tp_as_buffer */
1418 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1419 0, /* tp_doc */
1420 wrapper_traverse, /* tp_traverse */
1421 0, /* tp_clear */
1422 wrapper_richcompare, /* tp_richcompare */
1423 0, /* tp_weaklistoffset */
1424 0, /* tp_iter */
1425 0, /* tp_iternext */
Antoine Pitrouc9dc4a22013-11-23 18:59:12 +01001426 wrapper_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001427 wrapper_members, /* tp_members */
1428 wrapper_getsets, /* tp_getset */
1429 0, /* tp_base */
1430 0, /* tp_dict */
1431 0, /* tp_descr_get */
1432 0, /* tp_descr_set */
Tim Peters6d6c1a32001-08-02 04:15:00 +00001433};
1434
1435PyObject *
1436PyWrapper_New(PyObject *d, PyObject *self)
1437{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001438 wrapperobject *wp;
1439 PyWrapperDescrObject *descr;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001440
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001441 assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type));
1442 descr = (PyWrapperDescrObject *)d;
Victor Stinner3249dec2011-05-01 23:19:15 +02001443 assert(_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
Victor Stinnerd9561312011-05-01 23:31:36 +02001444 (PyObject *)PyDescr_TYPE(descr)));
Tim Peters6d6c1a32001-08-02 04:15:00 +00001445
Benjamin Petersoneff61f62011-09-01 16:32:31 -04001446 wp = PyObject_GC_New(wrapperobject, &_PyMethodWrapper_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001447 if (wp != NULL) {
1448 Py_INCREF(descr);
1449 wp->descr = descr;
1450 Py_INCREF(self);
1451 wp->self = self;
1452 _PyObject_GC_TRACK(wp);
1453 }
1454 return (PyObject *)wp;
Tim Peters6d6c1a32001-08-02 04:15:00 +00001455}
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001456
1457
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001458/* A built-in 'property' type */
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001459
1460/*
Serhiy Storchakad741a882015-06-11 00:06:39 +03001461class property(object):
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001462
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001463 def __init__(self, fget=None, fset=None, fdel=None, doc=None):
1464 if doc is None and fget is not None and hasattr(fget, "__doc__"):
Serhiy Storchakad741a882015-06-11 00:06:39 +03001465 doc = fget.__doc__
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001466 self.__get = fget
1467 self.__set = fset
1468 self.__del = fdel
1469 self.__doc__ = doc
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001470
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001471 def __get__(self, inst, type=None):
1472 if inst is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001473 return self
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001474 if self.__get is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001475 raise AttributeError, "unreadable attribute"
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001476 return self.__get(inst)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001477
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001478 def __set__(self, inst, value):
1479 if self.__set is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001480 raise AttributeError, "can't set attribute"
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001481 return self.__set(inst, value)
Guido van Rossumba2485f2001-12-10 18:03:34 +00001482
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001483 def __delete__(self, inst):
1484 if self.__del is None:
Serhiy Storchakad741a882015-06-11 00:06:39 +03001485 raise AttributeError, "can't delete attribute"
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001486 return self.__del(inst)
Guido van Rossumba2485f2001-12-10 18:03:34 +00001487
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001488*/
1489
1490typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001491 PyObject_HEAD
1492 PyObject *prop_get;
1493 PyObject *prop_set;
1494 PyObject *prop_del;
1495 PyObject *prop_doc;
Yurii Karabasc56387f2020-12-30 11:51:24 +02001496 PyObject *prop_name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001497 int getter_doc;
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001498} propertyobject;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001499
Christian Heimes0449f632007-12-15 01:27:15 +00001500static PyObject * property_copy(PyObject *, PyObject *, PyObject *,
Benjamin Peterson93964832010-06-28 03:07:10 +00001501 PyObject *);
Christian Heimes0449f632007-12-15 01:27:15 +00001502
Tim Peters66c1a522001-09-24 21:17:50 +00001503static PyMemberDef property_members[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001504 {"fget", T_OBJECT, offsetof(propertyobject, prop_get), READONLY},
1505 {"fset", T_OBJECT, offsetof(propertyobject, prop_set), READONLY},
1506 {"fdel", T_OBJECT, offsetof(propertyobject, prop_del), READONLY},
Raymond Hettingereac503a2015-05-13 01:09:59 -07001507 {"__doc__", T_OBJECT, offsetof(propertyobject, prop_doc), 0},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001508 {0}
Tim Peters66c1a522001-09-24 21:17:50 +00001509};
1510
Christian Heimes0449f632007-12-15 01:27:15 +00001511
Guido van Rossum58da9312007-11-10 23:39:45 +00001512PyDoc_STRVAR(getter_doc,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001513 "Descriptor to change the getter on a property.");
Guido van Rossum58da9312007-11-10 23:39:45 +00001514
Neal Norwitz32dde222008-04-15 06:43:13 +00001515static PyObject *
Guido van Rossum58da9312007-11-10 23:39:45 +00001516property_getter(PyObject *self, PyObject *getter)
1517{
Benjamin Peterson93964832010-06-28 03:07:10 +00001518 return property_copy(self, getter, NULL, NULL);
Guido van Rossum58da9312007-11-10 23:39:45 +00001519}
1520
Christian Heimes0449f632007-12-15 01:27:15 +00001521
Guido van Rossum58da9312007-11-10 23:39:45 +00001522PyDoc_STRVAR(setter_doc,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001523 "Descriptor to change the setter on a property.");
Guido van Rossum58da9312007-11-10 23:39:45 +00001524
Neal Norwitz32dde222008-04-15 06:43:13 +00001525static PyObject *
Guido van Rossum58da9312007-11-10 23:39:45 +00001526property_setter(PyObject *self, PyObject *setter)
1527{
Benjamin Peterson93964832010-06-28 03:07:10 +00001528 return property_copy(self, NULL, setter, NULL);
Guido van Rossum58da9312007-11-10 23:39:45 +00001529}
1530
Christian Heimes0449f632007-12-15 01:27:15 +00001531
Guido van Rossum58da9312007-11-10 23:39:45 +00001532PyDoc_STRVAR(deleter_doc,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001533 "Descriptor to change the deleter on a property.");
Guido van Rossum58da9312007-11-10 23:39:45 +00001534
Neal Norwitz32dde222008-04-15 06:43:13 +00001535static PyObject *
Guido van Rossum58da9312007-11-10 23:39:45 +00001536property_deleter(PyObject *self, PyObject *deleter)
1537{
Benjamin Peterson93964832010-06-28 03:07:10 +00001538 return property_copy(self, NULL, NULL, deleter);
Guido van Rossum58da9312007-11-10 23:39:45 +00001539}
1540
1541
Yurii Karabasc56387f2020-12-30 11:51:24 +02001542PyDoc_STRVAR(set_name_doc,
1543 "Method to set name of a property.");
1544
1545static PyObject *
1546property_set_name(PyObject *self, PyObject *args) {
1547 if (PyTuple_GET_SIZE(args) != 2) {
1548 PyErr_Format(
1549 PyExc_TypeError,
1550 "__set_name__() takes 2 positional arguments but %d were given",
1551 PyTuple_GET_SIZE(args));
1552 return NULL;
1553 }
1554
1555 propertyobject *prop = (propertyobject *)self;
1556 PyObject *name = PyTuple_GET_ITEM(args, 1);
1557
1558 Py_XINCREF(name);
1559 Py_XSETREF(prop->prop_name, name);
1560
1561 Py_RETURN_NONE;
1562}
1563
Guido van Rossum58da9312007-11-10 23:39:45 +00001564static PyMethodDef property_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001565 {"getter", property_getter, METH_O, getter_doc},
1566 {"setter", property_setter, METH_O, setter_doc},
1567 {"deleter", property_deleter, METH_O, deleter_doc},
Yurii Karabasc56387f2020-12-30 11:51:24 +02001568 {"__set_name__", property_set_name, METH_VARARGS, set_name_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001569 {0}
Guido van Rossum58da9312007-11-10 23:39:45 +00001570};
1571
Tim Peters66c1a522001-09-24 21:17:50 +00001572
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001573static void
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001574property_dealloc(PyObject *self)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001575{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001576 propertyobject *gs = (propertyobject *)self;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001577
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001578 _PyObject_GC_UNTRACK(self);
1579 Py_XDECREF(gs->prop_get);
1580 Py_XDECREF(gs->prop_set);
1581 Py_XDECREF(gs->prop_del);
1582 Py_XDECREF(gs->prop_doc);
Yurii Karabasc56387f2020-12-30 11:51:24 +02001583 Py_XDECREF(gs->prop_name);
Victor Stinner58ac7002020-02-07 03:04:21 +01001584 Py_TYPE(self)->tp_free(self);
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001585}
1586
1587static PyObject *
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001588property_descr_get(PyObject *self, PyObject *obj, PyObject *type)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001589{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001590 if (obj == NULL || obj == Py_None) {
1591 Py_INCREF(self);
1592 return self;
1593 }
Victor Stinnere972c132018-10-01 03:03:22 -07001594
1595 propertyobject *gs = (propertyobject *)self;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001596 if (gs->prop_get == NULL) {
Yurii Karabasc56387f2020-12-30 11:51:24 +02001597 if (gs->prop_name != NULL) {
1598 PyErr_Format(PyExc_AttributeError, "unreadable attribute %R", gs->prop_name);
1599 } else {
1600 PyErr_SetString(PyExc_AttributeError, "unreadable attribute");
1601 }
1602
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001603 return NULL;
1604 }
Victor Stinnere972c132018-10-01 03:03:22 -07001605
Petr Viktorinffd97532020-02-11 17:46:57 +01001606 return PyObject_CallOneArg(gs->prop_get, obj);
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001607}
1608
1609static int
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001610property_descr_set(PyObject *self, PyObject *obj, PyObject *value)
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001611{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001612 propertyobject *gs = (propertyobject *)self;
1613 PyObject *func, *res;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001614
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001615 if (value == NULL)
1616 func = gs->prop_del;
1617 else
1618 func = gs->prop_set;
1619 if (func == NULL) {
Yurii Karabasc56387f2020-12-30 11:51:24 +02001620 if (gs->prop_name != NULL) {
1621 PyErr_Format(PyExc_AttributeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001622 value == NULL ?
Yurii Karabasc56387f2020-12-30 11:51:24 +02001623 "can't delete attribute %R" :
1624 "can't set attribute %R",
1625 gs->prop_name);
1626 } else {
1627 PyErr_SetString(PyExc_AttributeError,
1628 value == NULL ?
1629 "can't delete attribute" :
1630 "can't set attribute");
1631 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001632 return -1;
1633 }
1634 if (value == NULL)
Petr Viktorinffd97532020-02-11 17:46:57 +01001635 res = PyObject_CallOneArg(func, obj);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001636 else
Benjamin Peterson9b955de2010-12-07 04:04:02 +00001637 res = PyObject_CallFunctionObjArgs(func, obj, value, NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001638 if (res == NULL)
1639 return -1;
1640 Py_DECREF(res);
1641 return 0;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001642}
1643
Christian Heimes0449f632007-12-15 01:27:15 +00001644static PyObject *
Benjamin Peterson93964832010-06-28 03:07:10 +00001645property_copy(PyObject *old, PyObject *get, PyObject *set, PyObject *del)
Christian Heimes0449f632007-12-15 01:27:15 +00001646{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001647 propertyobject *pold = (propertyobject *)old;
Benjamin Peterson93964832010-06-28 03:07:10 +00001648 PyObject *new, *type, *doc;
Christian Heimes0449f632007-12-15 01:27:15 +00001649
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001650 type = PyObject_Type(old);
1651 if (type == NULL)
1652 return NULL;
Christian Heimes0449f632007-12-15 01:27:15 +00001653
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001654 if (get == NULL || get == Py_None) {
1655 Py_XDECREF(get);
1656 get = pold->prop_get ? pold->prop_get : Py_None;
1657 }
1658 if (set == NULL || set == Py_None) {
1659 Py_XDECREF(set);
1660 set = pold->prop_set ? pold->prop_set : Py_None;
1661 }
1662 if (del == NULL || del == Py_None) {
1663 Py_XDECREF(del);
1664 del = pold->prop_del ? pold->prop_del : Py_None;
1665 }
Benjamin Peterson93964832010-06-28 03:07:10 +00001666 if (pold->getter_doc && get != Py_None) {
1667 /* make _init use __doc__ from getter */
1668 doc = Py_None;
1669 }
1670 else {
1671 doc = pold->prop_doc ? pold->prop_doc : Py_None;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001672 }
R. David Murrayb18500d2009-05-04 22:59:07 +00001673
Victor Stinner5abaa2b2016-12-09 16:22:32 +01001674 new = PyObject_CallFunctionObjArgs(type, get, set, del, doc, NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001675 Py_DECREF(type);
1676 if (new == NULL)
1677 return NULL;
Yurii Karabasc56387f2020-12-30 11:51:24 +02001678
1679 Py_XINCREF(pold->prop_name);
1680 Py_XSETREF(((propertyobject *) new)->prop_name, pold->prop_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001681 return new;
Christian Heimes0449f632007-12-15 01:27:15 +00001682}
1683
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001684/*[clinic input]
1685property.__init__ as property_init
1686
1687 fget: object(c_default="NULL") = None
1688 function to be used for getting an attribute value
1689 fset: object(c_default="NULL") = None
1690 function to be used for setting an attribute value
1691 fdel: object(c_default="NULL") = None
1692 function to be used for del'ing an attribute
1693 doc: object(c_default="NULL") = None
1694 docstring
1695
1696Property attribute.
1697
1698Typical use is to define a managed attribute x:
1699
1700class C(object):
1701 def getx(self): return self._x
1702 def setx(self, value): self._x = value
1703 def delx(self): del self._x
1704 x = property(getx, setx, delx, "I'm the 'x' property.")
1705
1706Decorators make defining new properties or modifying existing ones easy:
1707
1708class C(object):
1709 @property
1710 def x(self):
1711 "I am the 'x' property."
1712 return self._x
1713 @x.setter
1714 def x(self, value):
1715 self._x = value
1716 @x.deleter
1717 def x(self):
1718 del self._x
1719[clinic start generated code]*/
1720
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001721static int
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001722property_init_impl(propertyobject *self, PyObject *fget, PyObject *fset,
1723 PyObject *fdel, PyObject *doc)
1724/*[clinic end generated code: output=01a960742b692b57 input=dfb5dbbffc6932d5]*/
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001725{
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001726 if (fget == Py_None)
1727 fget = NULL;
1728 if (fset == Py_None)
1729 fset = NULL;
1730 if (fdel == Py_None)
1731 fdel = NULL;
Tim Peters66c1a522001-09-24 21:17:50 +00001732
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001733 Py_XINCREF(fget);
1734 Py_XINCREF(fset);
1735 Py_XINCREF(fdel);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001736 Py_XINCREF(doc);
Christian Heimes0449f632007-12-15 01:27:15 +00001737
Oren Milmand019bc82018-02-13 12:28:33 +02001738 Py_XSETREF(self->prop_get, fget);
1739 Py_XSETREF(self->prop_set, fset);
1740 Py_XSETREF(self->prop_del, fdel);
1741 Py_XSETREF(self->prop_doc, doc);
Yurii Karabasc56387f2020-12-30 11:51:24 +02001742 Py_XSETREF(self->prop_name, NULL);
1743
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001744 self->getter_doc = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001745
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001746 /* if no docstring given and the getter has one, use that one */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001747 if ((doc == NULL || doc == Py_None) && fget != NULL) {
Martin v. Löwisbd928fe2011-10-14 10:20:37 +02001748 _Py_IDENTIFIER(__doc__);
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001749 PyObject *get_doc;
1750 int rc = _PyObject_LookupAttrId(fget, &PyId___doc__, &get_doc);
1751 if (rc <= 0) {
1752 return rc;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001753 }
Andy Lesterdffe4c02020-03-04 07:15:20 -06001754 if (Py_IS_TYPE(self, &PyProperty_Type)) {
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001755 Py_XSETREF(self->prop_doc, get_doc);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001756 }
1757 else {
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001758 /* If this is a property subclass, put __doc__
1759 in dict of the subclass instance instead,
1760 otherwise it gets shadowed by __doc__ in the
1761 class's dict. */
1762 int err = _PyObject_SetAttrId((PyObject *)self, &PyId___doc__, get_doc);
1763 Py_DECREF(get_doc);
1764 if (err < 0)
1765 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001766 }
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001767 self->getter_doc = 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001768 }
1769
1770 return 0;
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001771}
1772
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -05001773static PyObject *
1774property_get___isabstractmethod__(propertyobject *prop, void *closure)
1775{
1776 int res = _PyObject_IsAbstract(prop->prop_get);
1777 if (res == -1) {
1778 return NULL;
1779 }
1780 else if (res) {
1781 Py_RETURN_TRUE;
1782 }
1783
1784 res = _PyObject_IsAbstract(prop->prop_set);
1785 if (res == -1) {
1786 return NULL;
1787 }
1788 else if (res) {
1789 Py_RETURN_TRUE;
1790 }
1791
1792 res = _PyObject_IsAbstract(prop->prop_del);
1793 if (res == -1) {
1794 return NULL;
1795 }
1796 else if (res) {
1797 Py_RETURN_TRUE;
1798 }
1799 Py_RETURN_FALSE;
1800}
1801
1802static PyGetSetDef property_getsetlist[] = {
1803 {"__isabstractmethod__",
1804 (getter)property_get___isabstractmethod__, NULL,
1805 NULL,
1806 NULL},
1807 {NULL} /* Sentinel */
1808};
1809
Guido van Rossum048eb752001-10-02 21:24:57 +00001810static int
1811property_traverse(PyObject *self, visitproc visit, void *arg)
1812{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001813 propertyobject *pp = (propertyobject *)self;
1814 Py_VISIT(pp->prop_get);
1815 Py_VISIT(pp->prop_set);
1816 Py_VISIT(pp->prop_del);
1817 Py_VISIT(pp->prop_doc);
Yurii Karabasc56387f2020-12-30 11:51:24 +02001818 Py_VISIT(pp->prop_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001819 return 0;
Guido van Rossum048eb752001-10-02 21:24:57 +00001820}
1821
Raymond Hettingerd4be6912015-05-13 11:12:33 -07001822static int
1823property_clear(PyObject *self)
1824{
1825 propertyobject *pp = (propertyobject *)self;
1826 Py_CLEAR(pp->prop_doc);
1827 return 0;
1828}
1829
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001830#include "clinic/descrobject.c.h"
1831
1832PyTypeObject PyDictProxy_Type = {
1833 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1834 "mappingproxy", /* tp_name */
1835 sizeof(mappingproxyobject), /* tp_basicsize */
1836 0, /* tp_itemsize */
1837 /* methods */
1838 (destructor)mappingproxy_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001839 0, /* tp_vectorcall_offset */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001840 0, /* tp_getattr */
1841 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001842 0, /* tp_as_async */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001843 (reprfunc)mappingproxy_repr, /* tp_repr */
Brandt Bucher4663f662020-03-07 11:03:09 -08001844 &mappingproxy_as_number, /* tp_as_number */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001845 &mappingproxy_as_sequence, /* tp_as_sequence */
1846 &mappingproxy_as_mapping, /* tp_as_mapping */
1847 0, /* tp_hash */
1848 0, /* tp_call */
1849 (reprfunc)mappingproxy_str, /* tp_str */
1850 PyObject_GenericGetAttr, /* tp_getattro */
1851 0, /* tp_setattro */
1852 0, /* tp_as_buffer */
Mark Shannon069e81a2021-04-30 09:50:28 +01001853 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1854 Py_TPFLAGS_MAPPING, /* tp_flags */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001855 0, /* tp_doc */
1856 mappingproxy_traverse, /* tp_traverse */
1857 0, /* tp_clear */
1858 (richcmpfunc)mappingproxy_richcompare, /* tp_richcompare */
1859 0, /* tp_weaklistoffset */
1860 (getiterfunc)mappingproxy_getiter, /* tp_iter */
1861 0, /* tp_iternext */
1862 mappingproxy_methods, /* tp_methods */
1863 0, /* tp_members */
1864 0, /* tp_getset */
1865 0, /* tp_base */
1866 0, /* tp_dict */
1867 0, /* tp_descr_get */
1868 0, /* tp_descr_set */
1869 0, /* tp_dictoffset */
1870 0, /* tp_init */
1871 0, /* tp_alloc */
1872 mappingproxy_new, /* tp_new */
1873};
1874
Guido van Rossum8bce4ac2001-09-06 21:56:42 +00001875PyTypeObject PyProperty_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001876 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1877 "property", /* tp_name */
1878 sizeof(propertyobject), /* tp_basicsize */
1879 0, /* tp_itemsize */
1880 /* methods */
1881 property_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001882 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001883 0, /* tp_getattr */
1884 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001885 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001886 0, /* tp_repr */
1887 0, /* tp_as_number */
1888 0, /* tp_as_sequence */
1889 0, /* tp_as_mapping */
1890 0, /* tp_hash */
1891 0, /* tp_call */
1892 0, /* tp_str */
1893 PyObject_GenericGetAttr, /* tp_getattro */
1894 0, /* tp_setattro */
1895 0, /* tp_as_buffer */
1896 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1897 Py_TPFLAGS_BASETYPE, /* tp_flags */
Serhiy Storchaka18b250f2017-03-19 08:51:07 +02001898 property_init__doc__, /* tp_doc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001899 property_traverse, /* tp_traverse */
Raymond Hettingerd4be6912015-05-13 11:12:33 -07001900 (inquiry)property_clear, /* tp_clear */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001901 0, /* tp_richcompare */
1902 0, /* tp_weaklistoffset */
1903 0, /* tp_iter */
1904 0, /* tp_iternext */
1905 property_methods, /* tp_methods */
1906 property_members, /* tp_members */
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -05001907 property_getsetlist, /* tp_getset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001908 0, /* tp_base */
1909 0, /* tp_dict */
1910 property_descr_get, /* tp_descr_get */
1911 property_descr_set, /* tp_descr_set */
1912 0, /* tp_dictoffset */
1913 property_init, /* tp_init */
1914 PyType_GenericAlloc, /* tp_alloc */
1915 PyType_GenericNew, /* tp_new */
1916 PyObject_GC_Del, /* tp_free */
Guido van Rossum29a62dd2001-08-23 21:40:38 +00001917};