1 /* Descriptors -- a new, flexible way to describe attributes */
2
3 #include "Python.h"
4 #include "pycore_object.h"
5 #include "pycore_pystate.h"
6 #include "pycore_tupleobject.h"
7 #include "structmember.h" /* Why is this not included in Python.h? */
8
9 /*[clinic input]
10 class mappingproxy "mappingproxyobject *" "&PyDictProxy_Type"
11 class property "propertyobject *" "&PyProperty_Type"
12 [clinic start generated code]*/
13 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=556352653fd4c02e]*/
14
15 static void
descr_dealloc(PyDescrObject * descr)16 descr_dealloc(PyDescrObject *descr)
17 {
18 _PyObject_GC_UNTRACK(descr);
19 Py_XDECREF(descr->d_type);
20 Py_XDECREF(descr->d_name);
21 Py_XDECREF(descr->d_qualname);
22 PyObject_GC_Del(descr);
23 }
24
25 static PyObject *
descr_name(PyDescrObject * descr)26 descr_name(PyDescrObject *descr)
27 {
28 if (descr->d_name != NULL && PyUnicode_Check(descr->d_name))
29 return descr->d_name;
30 return NULL;
31 }
32
33 static PyObject *
descr_repr(PyDescrObject * descr,const char * format)34 descr_repr(PyDescrObject *descr, const char *format)
35 {
36 PyObject *name = NULL;
37 if (descr->d_name != NULL && PyUnicode_Check(descr->d_name))
38 name = descr->d_name;
39
40 return PyUnicode_FromFormat(format, name, "?", descr->d_type->tp_name);
41 }
42
43 static PyObject *
method_repr(PyMethodDescrObject * descr)44 method_repr(PyMethodDescrObject *descr)
45 {
46 return descr_repr((PyDescrObject *)descr,
47 "<method '%V' of '%s' objects>");
48 }
49
50 static PyObject *
member_repr(PyMemberDescrObject * descr)51 member_repr(PyMemberDescrObject *descr)
52 {
53 return descr_repr((PyDescrObject *)descr,
54 "<member '%V' of '%s' objects>");
55 }
56
57 static PyObject *
getset_repr(PyGetSetDescrObject * descr)58 getset_repr(PyGetSetDescrObject *descr)
59 {
60 return descr_repr((PyDescrObject *)descr,
61 "<attribute '%V' of '%s' objects>");
62 }
63
64 static PyObject *
wrapperdescr_repr(PyWrapperDescrObject * descr)65 wrapperdescr_repr(PyWrapperDescrObject *descr)
66 {
67 return descr_repr((PyDescrObject *)descr,
68 "<slot wrapper '%V' of '%s' objects>");
69 }
70
71 static int
descr_check(PyDescrObject * descr,PyObject * obj,PyObject ** pres)72 descr_check(PyDescrObject *descr, PyObject *obj, PyObject **pres)
73 {
74 if (obj == NULL) {
75 Py_INCREF(descr);
76 *pres = (PyObject *)descr;
77 return 1;
78 }
79 if (!PyObject_TypeCheck(obj, descr->d_type)) {
80 PyErr_Format(PyExc_TypeError,
81 "descriptor '%V' for '%.100s' objects "
82 "doesn't apply to a '%.100s' object",
83 descr_name((PyDescrObject *)descr), "?",
84 descr->d_type->tp_name,
85 obj->ob_type->tp_name);
86 *pres = NULL;
87 return 1;
88 }
89 return 0;
90 }
91
92 static PyObject *
classmethod_get(PyMethodDescrObject * descr,PyObject * obj,PyObject * type)93 classmethod_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type)
94 {
95 /* Ensure a valid type. Class methods ignore obj. */
96 if (type == NULL) {
97 if (obj != NULL)
98 type = (PyObject *)obj->ob_type;
99 else {
100 /* Wot - no type?! */
101 PyErr_Format(PyExc_TypeError,
102 "descriptor '%V' for type '%.100s' "
103 "needs either an object or a type",
104 descr_name((PyDescrObject *)descr), "?",
105 PyDescr_TYPE(descr)->tp_name);
106 return NULL;
107 }
108 }
109 if (!PyType_Check(type)) {
110 PyErr_Format(PyExc_TypeError,
111 "descriptor '%V' for type '%.100s' "
112 "needs a type, not a '%.100s' as arg 2",
113 descr_name((PyDescrObject *)descr), "?",
114 PyDescr_TYPE(descr)->tp_name,
115 type->ob_type->tp_name);
116 return NULL;
117 }
118 if (!PyType_IsSubtype((PyTypeObject *)type, PyDescr_TYPE(descr))) {
119 PyErr_Format(PyExc_TypeError,
120 "descriptor '%V' requires a subtype of '%.100s' "
121 "but received '%.100s'",
122 descr_name((PyDescrObject *)descr), "?",
123 PyDescr_TYPE(descr)->tp_name,
124 ((PyTypeObject *)type)->tp_name);
125 return NULL;
126 }
127 return PyCFunction_NewEx(descr->d_method, type, NULL);
128 }
129
130 static PyObject *
method_get(PyMethodDescrObject * descr,PyObject * obj,PyObject * type)131 method_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type)
132 {
133 PyObject *res;
134
135 if (descr_check((PyDescrObject *)descr, obj, &res))
136 return res;
137 return PyCFunction_NewEx(descr->d_method, obj, NULL);
138 }
139
140 static PyObject *
member_get(PyMemberDescrObject * descr,PyObject * obj,PyObject * type)141 member_get(PyMemberDescrObject *descr, PyObject *obj, PyObject *type)
142 {
143 PyObject *res;
144
145 if (descr_check((PyDescrObject *)descr, obj, &res))
146 return res;
147
148 if (descr->d_member->flags & READ_RESTRICTED) {
149 if (PySys_Audit("object.__getattr__", "Os",
150 obj ? obj : Py_None, descr->d_member->name) < 0) {
151 return NULL;
152 }
153 }
154
155 return PyMember_GetOne((char *)obj, descr->d_member);
156 }
157
158 static PyObject *
getset_get(PyGetSetDescrObject * descr,PyObject * obj,PyObject * type)159 getset_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *type)
160 {
161 PyObject *res;
162
163 if (descr_check((PyDescrObject *)descr, obj, &res))
164 return res;
165 if (descr->d_getset->get != NULL)
166 return descr->d_getset->get(obj, descr->d_getset->closure);
167 PyErr_Format(PyExc_AttributeError,
168 "attribute '%V' of '%.100s' objects is not readable",
169 descr_name((PyDescrObject *)descr), "?",
170 PyDescr_TYPE(descr)->tp_name);
171 return NULL;
172 }
173
174 static PyObject *
wrapperdescr_get(PyWrapperDescrObject * descr,PyObject * obj,PyObject * type)175 wrapperdescr_get(PyWrapperDescrObject *descr, PyObject *obj, PyObject *type)
176 {
177 PyObject *res;
178
179 if (descr_check((PyDescrObject *)descr, obj, &res))
180 return res;
181 return PyWrapper_New((PyObject *)descr, obj);
182 }
183
184 static int
descr_setcheck(PyDescrObject * descr,PyObject * obj,PyObject * value,int * pres)185 descr_setcheck(PyDescrObject *descr, PyObject *obj, PyObject *value,
186 int *pres)
187 {
188 assert(obj != NULL);
189 if (!PyObject_TypeCheck(obj, descr->d_type)) {
190 PyErr_Format(PyExc_TypeError,
191 "descriptor '%V' for '%.100s' objects "
192 "doesn't apply to a '%.100s' object",
193 descr_name(descr), "?",
194 descr->d_type->tp_name,
195 obj->ob_type->tp_name);
196 *pres = -1;
197 return 1;
198 }
199 return 0;
200 }
201
202 static int
member_set(PyMemberDescrObject * descr,PyObject * obj,PyObject * value)203 member_set(PyMemberDescrObject *descr, PyObject *obj, PyObject *value)
204 {
205 int res;
206
207 if (descr_setcheck((PyDescrObject *)descr, obj, value, &res))
208 return res;
209 return PyMember_SetOne((char *)obj, descr->d_member, value);
210 }
211
212 static int
getset_set(PyGetSetDescrObject * descr,PyObject * obj,PyObject * value)213 getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value)
214 {
215 int res;
216
217 if (descr_setcheck((PyDescrObject *)descr, obj, value, &res))
218 return res;
219 if (descr->d_getset->set != NULL)
220 return descr->d_getset->set(obj, value,
221 descr->d_getset->closure);
222 PyErr_Format(PyExc_AttributeError,
223 "attribute '%V' of '%.100s' objects is not writable",
224 descr_name((PyDescrObject *)descr), "?",
225 PyDescr_TYPE(descr)->tp_name);
226 return -1;
227 }
228
229
230 /* Vectorcall functions for each of the PyMethodDescr calling conventions.
231 *
232 * First, common helpers
233 */
234 static const char *
get_name(PyObject * func)235 get_name(PyObject *func) {
236 assert(PyObject_TypeCheck(func, &PyMethodDescr_Type));
237 return ((PyMethodDescrObject *)func)->d_method->ml_name;
238 }
239
240 typedef void (*funcptr)(void);
241
242 static inline int
method_check_args(PyObject * func,PyObject * const * args,Py_ssize_t nargs,PyObject * kwnames)243 method_check_args(PyObject *func, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
244 {
245 assert(!PyErr_Occurred());
246 assert(PyObject_TypeCheck(func, &PyMethodDescr_Type));
247 if (nargs < 1) {
248 PyErr_Format(PyExc_TypeError,
249 "descriptor '%.200s' of '%.100s' "
250 "object needs an argument",
251 get_name(func), PyDescr_TYPE(func)->tp_name);
252 return -1;
253 }
254 PyObject *self = args[0];
255 if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
256 (PyObject *)PyDescr_TYPE(func)))
257 {
258 PyErr_Format(PyExc_TypeError,
259 "descriptor '%.200s' for '%.100s' objects "
260 "doesn't apply to a '%.100s' object",
261 get_name(func), PyDescr_TYPE(func)->tp_name,
262 Py_TYPE(self)->tp_name);
263 return -1;
264 }
265 if (kwnames && PyTuple_GET_SIZE(kwnames)) {
266 PyErr_Format(PyExc_TypeError,
267 "%.200s() takes no keyword arguments", get_name(func));
268 return -1;
269 }
270 return 0;
271 }
272
273 static inline funcptr
method_enter_call(PyObject * func)274 method_enter_call(PyObject *func)
275 {
276 if (Py_EnterRecursiveCall(" while calling a Python object")) {
277 return NULL;
278 }
279 return (funcptr)((PyMethodDescrObject *)func)->d_method->ml_meth;
280 }
281
282 /* Now the actual vectorcall functions */
283 static PyObject *
method_vectorcall_VARARGS(PyObject * func,PyObject * const * args,size_t nargsf,PyObject * kwnames)284 method_vectorcall_VARARGS(
285 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
286 {
287 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
288 if (method_check_args(func, args, nargs, kwnames)) {
289 return NULL;
290 }
291 PyObject *argstuple = _PyTuple_FromArray(args+1, nargs-1);
292 if (argstuple == NULL) {
293 return NULL;
294 }
295 PyCFunction meth = (PyCFunction)method_enter_call(func);
296 if (meth == NULL) {
297 Py_DECREF(argstuple);
298 return NULL;
299 }
300 PyObject *result = meth(args[0], argstuple);
301 Py_DECREF(argstuple);
302 Py_LeaveRecursiveCall();
303 return result;
304 }
305
306 static PyObject *
method_vectorcall_VARARGS_KEYWORDS(PyObject * func,PyObject * const * args,size_t nargsf,PyObject * kwnames)307 method_vectorcall_VARARGS_KEYWORDS(
308 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
309 {
310 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
311 if (method_check_args(func, args, nargs, NULL)) {
312 return NULL;
313 }
314 PyObject *argstuple = _PyTuple_FromArray(args+1, nargs-1);
315 if (argstuple == NULL) {
316 return NULL;
317 }
318 PyObject *result = NULL;
319 /* Create a temporary dict for keyword arguments */
320 PyObject *kwdict = NULL;
321 if (kwnames != NULL && PyTuple_GET_SIZE(kwnames) > 0) {
322 kwdict = _PyStack_AsDict(args + nargs, kwnames);
323 if (kwdict == NULL) {
324 goto exit;
325 }
326 }
327 PyCFunctionWithKeywords meth = (PyCFunctionWithKeywords)
328 method_enter_call(func);
329 if (meth == NULL) {
330 goto exit;
331 }
332 result = meth(args[0], argstuple, kwdict);
333 Py_LeaveRecursiveCall();
334 exit:
335 Py_DECREF(argstuple);
336 Py_XDECREF(kwdict);
337 return result;
338 }
339
340 static PyObject *
method_vectorcall_FASTCALL(PyObject * func,PyObject * const * args,size_t nargsf,PyObject * kwnames)341 method_vectorcall_FASTCALL(
342 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
343 {
344 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
345 if (method_check_args(func, args, nargs, kwnames)) {
346 return NULL;
347 }
348 _PyCFunctionFast meth = (_PyCFunctionFast)
349 method_enter_call(func);
350 if (meth == NULL) {
351 return NULL;
352 }
353 PyObject *result = meth(args[0], args+1, nargs-1);
354 Py_LeaveRecursiveCall();
355 return result;
356 }
357
358 static PyObject *
method_vectorcall_FASTCALL_KEYWORDS(PyObject * func,PyObject * const * args,size_t nargsf,PyObject * kwnames)359 method_vectorcall_FASTCALL_KEYWORDS(
360 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
361 {
362 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
363 if (method_check_args(func, args, nargs, NULL)) {
364 return NULL;
365 }
366 _PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords)
367 method_enter_call(func);
368 if (meth == NULL) {
369 return NULL;
370 }
371 PyObject *result = meth(args[0], args+1, nargs-1, kwnames);
372 Py_LeaveRecursiveCall();
373 return result;
374 }
375
376 static PyObject *
method_vectorcall_NOARGS(PyObject * func,PyObject * const * args,size_t nargsf,PyObject * kwnames)377 method_vectorcall_NOARGS(
378 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
379 {
380 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
381 if (method_check_args(func, args, nargs, kwnames)) {
382 return NULL;
383 }
384 if (nargs != 1) {
385 PyErr_Format(PyExc_TypeError,
386 "%.200s() takes no arguments (%zd given)", get_name(func), nargs-1);
387 return NULL;
388 }
389 PyCFunction meth = (PyCFunction)method_enter_call(func);
390 if (meth == NULL) {
391 return NULL;
392 }
393 PyObject *result = meth(args[0], NULL);
394 Py_LeaveRecursiveCall();
395 return result;
396 }
397
398 static PyObject *
method_vectorcall_O(PyObject * func,PyObject * const * args,size_t nargsf,PyObject * kwnames)399 method_vectorcall_O(
400 PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
401 {
402 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
403 if (method_check_args(func, args, nargs, kwnames)) {
404 return NULL;
405 }
406 if (nargs != 2) {
407 PyErr_Format(PyExc_TypeError,
408 "%.200s() takes exactly one argument (%zd given)",
409 get_name(func), nargs-1);
410 return NULL;
411 }
412 PyCFunction meth = (PyCFunction)method_enter_call(func);
413 if (meth == NULL) {
414 return NULL;
415 }
416 PyObject *result = meth(args[0], args[1]);
417 Py_LeaveRecursiveCall();
418 return result;
419 }
420
421
422 static PyObject *
classmethoddescr_call(PyMethodDescrObject * descr,PyObject * args,PyObject * kwds)423 classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
424 PyObject *kwds)
425 {
426 Py_ssize_t argc;
427 PyObject *self, *result;
428
429 /* Make sure that the first argument is acceptable as 'self' */
430 assert(PyTuple_Check(args));
431 argc = PyTuple_GET_SIZE(args);
432 if (argc < 1) {
433 PyErr_Format(PyExc_TypeError,
434 "descriptor '%V' of '%.100s' "
435 "object needs an argument",
436 descr_name((PyDescrObject *)descr), "?",
437 PyDescr_TYPE(descr)->tp_name);
438 return NULL;
439 }
440 self = PyTuple_GET_ITEM(args, 0);
441 if (!PyType_Check(self)) {
442 PyErr_Format(PyExc_TypeError,
443 "descriptor '%V' requires a type "
444 "but received a '%.100s' instance",
445 descr_name((PyDescrObject *)descr), "?",
446 self->ob_type->tp_name);
447 return NULL;
448 }
449 if (!PyType_IsSubtype((PyTypeObject *)self, PyDescr_TYPE(descr))) {
450 PyErr_Format(PyExc_TypeError,
451 "descriptor '%V' requires a subtype of '%.100s' "
452 "but received '%.100s'",
453 descr_name((PyDescrObject *)descr), "?",
454 PyDescr_TYPE(descr)->tp_name,
455 ((PyTypeObject*)self)->tp_name);
456 return NULL;
457 }
458
459 result = _PyMethodDef_RawFastCallDict(descr->d_method, self,
460 &_PyTuple_ITEMS(args)[1], argc - 1,
461 kwds);
462 result = _Py_CheckFunctionResult((PyObject *)descr, result, NULL);
463 return result;
464 }
465
466 Py_LOCAL_INLINE(PyObject *)
wrapperdescr_raw_call(PyWrapperDescrObject * descr,PyObject * self,PyObject * args,PyObject * kwds)467 wrapperdescr_raw_call(PyWrapperDescrObject *descr, PyObject *self,
468 PyObject *args, PyObject *kwds)
469 {
470 wrapperfunc wrapper = descr->d_base->wrapper;
471
472 if (descr->d_base->flags & PyWrapperFlag_KEYWORDS) {
473 wrapperfunc_kwds wk = (wrapperfunc_kwds)(void(*)(void))wrapper;
474 return (*wk)(self, args, descr->d_wrapped, kwds);
475 }
476
477 if (kwds != NULL && (!PyDict_Check(kwds) || PyDict_GET_SIZE(kwds) != 0)) {
478 PyErr_Format(PyExc_TypeError,
479 "wrapper %s() takes no keyword arguments",
480 descr->d_base->name);
481 return NULL;
482 }
483 return (*wrapper)(self, args, descr->d_wrapped);
484 }
485
486 static PyObject *
wrapperdescr_call(PyWrapperDescrObject * descr,PyObject * args,PyObject * kwds)487 wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
488 {
489 Py_ssize_t argc;
490 PyObject *self, *result;
491
492 /* Make sure that the first argument is acceptable as 'self' */
493 assert(PyTuple_Check(args));
494 argc = PyTuple_GET_SIZE(args);
495 if (argc < 1) {
496 PyErr_Format(PyExc_TypeError,
497 "descriptor '%V' of '%.100s' "
498 "object needs an argument",
499 descr_name((PyDescrObject *)descr), "?",
500 PyDescr_TYPE(descr)->tp_name);
501 return NULL;
502 }
503 self = PyTuple_GET_ITEM(args, 0);
504 if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
505 (PyObject *)PyDescr_TYPE(descr))) {
506 PyErr_Format(PyExc_TypeError,
507 "descriptor '%V' "
508 "requires a '%.100s' object "
509 "but received a '%.100s'",
510 descr_name((PyDescrObject *)descr), "?",
511 PyDescr_TYPE(descr)->tp_name,
512 self->ob_type->tp_name);
513 return NULL;
514 }
515
516 args = PyTuple_GetSlice(args, 1, argc);
517 if (args == NULL) {
518 return NULL;
519 }
520 result = wrapperdescr_raw_call(descr, self, args, kwds);
521 Py_DECREF(args);
522 return result;
523 }
524
525
526 static PyObject *
method_get_doc(PyMethodDescrObject * descr,void * closure)527 method_get_doc(PyMethodDescrObject *descr, void *closure)
528 {
529 return _PyType_GetDocFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc);
530 }
531
532 static PyObject *
method_get_text_signature(PyMethodDescrObject * descr,void * closure)533 method_get_text_signature(PyMethodDescrObject *descr, void *closure)
534 {
535 return _PyType_GetTextSignatureFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc);
536 }
537
538 static PyObject *
calculate_qualname(PyDescrObject * descr)539 calculate_qualname(PyDescrObject *descr)
540 {
541 PyObject *type_qualname, *res;
542 _Py_IDENTIFIER(__qualname__);
543
544 if (descr->d_name == NULL || !PyUnicode_Check(descr->d_name)) {
545 PyErr_SetString(PyExc_TypeError,
546 "<descriptor>.__name__ is not a unicode object");
547 return NULL;
548 }
549
550 type_qualname = _PyObject_GetAttrId((PyObject *)descr->d_type,
551 &PyId___qualname__);
552 if (type_qualname == NULL)
553 return NULL;
554
555 if (!PyUnicode_Check(type_qualname)) {
556 PyErr_SetString(PyExc_TypeError, "<descriptor>.__objclass__."
557 "__qualname__ is not a unicode object");
558 Py_XDECREF(type_qualname);
559 return NULL;
560 }
561
562 res = PyUnicode_FromFormat("%S.%S", type_qualname, descr->d_name);
563 Py_DECREF(type_qualname);
564 return res;
565 }
566
567 static PyObject *
descr_get_qualname(PyDescrObject * descr,void * Py_UNUSED (ignored))568 descr_get_qualname(PyDescrObject *descr, void *Py_UNUSED(ignored))
569 {
570 if (descr->d_qualname == NULL)
571 descr->d_qualname = calculate_qualname(descr);
572 Py_XINCREF(descr->d_qualname);
573 return descr->d_qualname;
574 }
575
576 static PyObject *
descr_reduce(PyDescrObject * descr,PyObject * Py_UNUSED (ignored))577 descr_reduce(PyDescrObject *descr, PyObject *Py_UNUSED(ignored))
578 {
579 _Py_IDENTIFIER(getattr);
580 return Py_BuildValue("N(OO)", _PyEval_GetBuiltinId(&PyId_getattr),
581 PyDescr_TYPE(descr), PyDescr_NAME(descr));
582 }
583
584 static PyMethodDef descr_methods[] = {
585 {"__reduce__", (PyCFunction)descr_reduce, METH_NOARGS, NULL},
586 {NULL, NULL}
587 };
588
589 static PyMemberDef descr_members[] = {
590 {"__objclass__", T_OBJECT, offsetof(PyDescrObject, d_type), READONLY},
591 {"__name__", T_OBJECT, offsetof(PyDescrObject, d_name), READONLY},
592 {0}
593 };
594
595 static PyGetSetDef method_getset[] = {
596 {"__doc__", (getter)method_get_doc},
597 {"__qualname__", (getter)descr_get_qualname},
598 {"__text_signature__", (getter)method_get_text_signature},
599 {0}
600 };
601
602 static PyObject *
member_get_doc(PyMemberDescrObject * descr,void * closure)603 member_get_doc(PyMemberDescrObject *descr, void *closure)
604 {
605 if (descr->d_member->doc == NULL) {
606 Py_RETURN_NONE;
607 }
608 return PyUnicode_FromString(descr->d_member->doc);
609 }
610
611 static PyGetSetDef member_getset[] = {
612 {"__doc__", (getter)member_get_doc},
613 {"__qualname__", (getter)descr_get_qualname},
614 {0}
615 };
616
617 static PyObject *
getset_get_doc(PyGetSetDescrObject * descr,void * closure)618 getset_get_doc(PyGetSetDescrObject *descr, void *closure)
619 {
620 if (descr->d_getset->doc == NULL) {
621 Py_RETURN_NONE;
622 }
623 return PyUnicode_FromString(descr->d_getset->doc);
624 }
625
626 static PyGetSetDef getset_getset[] = {
627 {"__doc__", (getter)getset_get_doc},
628 {"__qualname__", (getter)descr_get_qualname},
629 {0}
630 };
631
632 static PyObject *
wrapperdescr_get_doc(PyWrapperDescrObject * descr,void * closure)633 wrapperdescr_get_doc(PyWrapperDescrObject *descr, void *closure)
634 {
635 return _PyType_GetDocFromInternalDoc(descr->d_base->name, descr->d_base->doc);
636 }
637
638 static PyObject *
wrapperdescr_get_text_signature(PyWrapperDescrObject * descr,void * closure)639 wrapperdescr_get_text_signature(PyWrapperDescrObject *descr, void *closure)
640 {
641 return _PyType_GetTextSignatureFromInternalDoc(descr->d_base->name, descr->d_base->doc);
642 }
643
644 static PyGetSetDef wrapperdescr_getset[] = {
645 {"__doc__", (getter)wrapperdescr_get_doc},
646 {"__qualname__", (getter)descr_get_qualname},
647 {"__text_signature__", (getter)wrapperdescr_get_text_signature},
648 {0}
649 };
650
651 static int
descr_traverse(PyObject * self,visitproc visit,void * arg)652 descr_traverse(PyObject *self, visitproc visit, void *arg)
653 {
654 PyDescrObject *descr = (PyDescrObject *)self;
655 Py_VISIT(descr->d_type);
656 return 0;
657 }
658
659 PyTypeObject PyMethodDescr_Type = {
660 PyVarObject_HEAD_INIT(&PyType_Type, 0)
661 "method_descriptor",
662 sizeof(PyMethodDescrObject),
663 0,
664 (destructor)descr_dealloc, /* tp_dealloc */
665 offsetof(PyMethodDescrObject, vectorcall), /* tp_vectorcall_offset */
666 0, /* tp_getattr */
667 0, /* tp_setattr */
668 0, /* tp_as_async */
669 (reprfunc)method_repr, /* tp_repr */
670 0, /* tp_as_number */
671 0, /* tp_as_sequence */
672 0, /* tp_as_mapping */
673 0, /* tp_hash */
674 PyVectorcall_Call, /* tp_call */
675 0, /* tp_str */
676 PyObject_GenericGetAttr, /* tp_getattro */
677 0, /* tp_setattro */
678 0, /* tp_as_buffer */
679 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
680 _Py_TPFLAGS_HAVE_VECTORCALL |
681 Py_TPFLAGS_METHOD_DESCRIPTOR, /* tp_flags */
682 0, /* tp_doc */
683 descr_traverse, /* tp_traverse */
684 0, /* tp_clear */
685 0, /* tp_richcompare */
686 0, /* tp_weaklistoffset */
687 0, /* tp_iter */
688 0, /* tp_iternext */
689 descr_methods, /* tp_methods */
690 descr_members, /* tp_members */
691 method_getset, /* tp_getset */
692 0, /* tp_base */
693 0, /* tp_dict */
694 (descrgetfunc)method_get, /* tp_descr_get */
695 0, /* tp_descr_set */
696 };
697
698 /* This is for METH_CLASS in C, not for "f = classmethod(f)" in Python! */
699 PyTypeObject PyClassMethodDescr_Type = {
700 PyVarObject_HEAD_INIT(&PyType_Type, 0)
701 "classmethod_descriptor",
702 sizeof(PyMethodDescrObject),
703 0,
704 (destructor)descr_dealloc, /* tp_dealloc */
705 0, /* tp_vectorcall_offset */
706 0, /* tp_getattr */
707 0, /* tp_setattr */
708 0, /* tp_as_async */
709 (reprfunc)method_repr, /* tp_repr */
710 0, /* tp_as_number */
711 0, /* tp_as_sequence */
712 0, /* tp_as_mapping */
713 0, /* tp_hash */
714 (ternaryfunc)classmethoddescr_call, /* tp_call */
715 0, /* tp_str */
716 PyObject_GenericGetAttr, /* tp_getattro */
717 0, /* tp_setattro */
718 0, /* tp_as_buffer */
719 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
720 0, /* tp_doc */
721 descr_traverse, /* tp_traverse */
722 0, /* tp_clear */
723 0, /* tp_richcompare */
724 0, /* tp_weaklistoffset */
725 0, /* tp_iter */
726 0, /* tp_iternext */
727 descr_methods, /* tp_methods */
728 descr_members, /* tp_members */
729 method_getset, /* tp_getset */
730 0, /* tp_base */
731 0, /* tp_dict */
732 (descrgetfunc)classmethod_get, /* tp_descr_get */
733 0, /* tp_descr_set */
734 };
735
736 PyTypeObject PyMemberDescr_Type = {
737 PyVarObject_HEAD_INIT(&PyType_Type, 0)
738 "member_descriptor",
739 sizeof(PyMemberDescrObject),
740 0,
741 (destructor)descr_dealloc, /* tp_dealloc */
742 0, /* tp_vectorcall_offset */
743 0, /* tp_getattr */
744 0, /* tp_setattr */
745 0, /* tp_as_async */
746 (reprfunc)member_repr, /* tp_repr */
747 0, /* tp_as_number */
748 0, /* tp_as_sequence */
749 0, /* tp_as_mapping */
750 0, /* tp_hash */
751 0, /* tp_call */
752 0, /* tp_str */
753 PyObject_GenericGetAttr, /* tp_getattro */
754 0, /* tp_setattro */
755 0, /* tp_as_buffer */
756 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
757 0, /* tp_doc */
758 descr_traverse, /* tp_traverse */
759 0, /* tp_clear */
760 0, /* tp_richcompare */
761 0, /* tp_weaklistoffset */
762 0, /* tp_iter */
763 0, /* tp_iternext */
764 descr_methods, /* tp_methods */
765 descr_members, /* tp_members */
766 member_getset, /* tp_getset */
767 0, /* tp_base */
768 0, /* tp_dict */
769 (descrgetfunc)member_get, /* tp_descr_get */
770 (descrsetfunc)member_set, /* tp_descr_set */
771 };
772
773 PyTypeObject PyGetSetDescr_Type = {
774 PyVarObject_HEAD_INIT(&PyType_Type, 0)
775 "getset_descriptor",
776 sizeof(PyGetSetDescrObject),
777 0,
778 (destructor)descr_dealloc, /* tp_dealloc */
779 0, /* tp_vectorcall_offset */
780 0, /* tp_getattr */
781 0, /* tp_setattr */
782 0, /* tp_as_async */
783 (reprfunc)getset_repr, /* tp_repr */
784 0, /* tp_as_number */
785 0, /* tp_as_sequence */
786 0, /* tp_as_mapping */
787 0, /* tp_hash */
788 0, /* tp_call */
789 0, /* tp_str */
790 PyObject_GenericGetAttr, /* tp_getattro */
791 0, /* tp_setattro */
792 0, /* tp_as_buffer */
793 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
794 0, /* tp_doc */
795 descr_traverse, /* tp_traverse */
796 0, /* tp_clear */
797 0, /* tp_richcompare */
798 0, /* tp_weaklistoffset */
799 0, /* tp_iter */
800 0, /* tp_iternext */
801 0, /* tp_methods */
802 descr_members, /* tp_members */
803 getset_getset, /* tp_getset */
804 0, /* tp_base */
805 0, /* tp_dict */
806 (descrgetfunc)getset_get, /* tp_descr_get */
807 (descrsetfunc)getset_set, /* tp_descr_set */
808 };
809
810 PyTypeObject PyWrapperDescr_Type = {
811 PyVarObject_HEAD_INIT(&PyType_Type, 0)
812 "wrapper_descriptor",
813 sizeof(PyWrapperDescrObject),
814 0,
815 (destructor)descr_dealloc, /* tp_dealloc */
816 0, /* tp_vectorcall_offset */
817 0, /* tp_getattr */
818 0, /* tp_setattr */
819 0, /* tp_as_async */
820 (reprfunc)wrapperdescr_repr, /* tp_repr */
821 0, /* tp_as_number */
822 0, /* tp_as_sequence */
823 0, /* tp_as_mapping */
824 0, /* tp_hash */
825 (ternaryfunc)wrapperdescr_call, /* tp_call */
826 0, /* tp_str */
827 PyObject_GenericGetAttr, /* tp_getattro */
828 0, /* tp_setattro */
829 0, /* tp_as_buffer */
830 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
831 Py_TPFLAGS_METHOD_DESCRIPTOR, /* tp_flags */
832 0, /* tp_doc */
833 descr_traverse, /* tp_traverse */
834 0, /* tp_clear */
835 0, /* tp_richcompare */
836 0, /* tp_weaklistoffset */
837 0, /* tp_iter */
838 0, /* tp_iternext */
839 descr_methods, /* tp_methods */
840 descr_members, /* tp_members */
841 wrapperdescr_getset, /* tp_getset */
842 0, /* tp_base */
843 0, /* tp_dict */
844 (descrgetfunc)wrapperdescr_get, /* tp_descr_get */
845 0, /* tp_descr_set */
846 };
847
848 static PyDescrObject *
descr_new(PyTypeObject * descrtype,PyTypeObject * type,const char * name)849 descr_new(PyTypeObject *descrtype, PyTypeObject *type, const char *name)
850 {
851 PyDescrObject *descr;
852
853 descr = (PyDescrObject *)PyType_GenericAlloc(descrtype, 0);
854 if (descr != NULL) {
855 Py_XINCREF(type);
856 descr->d_type = type;
857 descr->d_name = PyUnicode_InternFromString(name);
858 if (descr->d_name == NULL) {
859 Py_DECREF(descr);
860 descr = NULL;
861 }
862 else {
863 descr->d_qualname = NULL;
864 }
865 }
866 return descr;
867 }
868
869 PyObject *
PyDescr_NewMethod(PyTypeObject * type,PyMethodDef * method)870 PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method)
871 {
872 /* Figure out correct vectorcall function to use */
873 vectorcallfunc vectorcall;
874 switch (method->ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O | METH_KEYWORDS))
875 {
876 case METH_VARARGS:
877 vectorcall = method_vectorcall_VARARGS;
878 break;
879 case METH_VARARGS | METH_KEYWORDS:
880 vectorcall = method_vectorcall_VARARGS_KEYWORDS;
881 break;
882 case METH_FASTCALL:
883 vectorcall = method_vectorcall_FASTCALL;
884 break;
885 case METH_FASTCALL | METH_KEYWORDS:
886 vectorcall = method_vectorcall_FASTCALL_KEYWORDS;
887 break;
888 case METH_NOARGS:
889 vectorcall = method_vectorcall_NOARGS;
890 break;
891 case METH_O:
892 vectorcall = method_vectorcall_O;
893 break;
894 default:
895 PyErr_Format(PyExc_SystemError,
896 "%s() method: bad call flags", method->ml_name);
897 return NULL;
898 }
899
900 PyMethodDescrObject *descr;
901
902 descr = (PyMethodDescrObject *)descr_new(&PyMethodDescr_Type,
903 type, method->ml_name);
904 if (descr != NULL) {
905 descr->d_method = method;
906 descr->vectorcall = vectorcall;
907 }
908 return (PyObject *)descr;
909 }
910
911 PyObject *
PyDescr_NewClassMethod(PyTypeObject * type,PyMethodDef * method)912 PyDescr_NewClassMethod(PyTypeObject *type, PyMethodDef *method)
913 {
914 PyMethodDescrObject *descr;
915
916 descr = (PyMethodDescrObject *)descr_new(&PyClassMethodDescr_Type,
917 type, method->ml_name);
918 if (descr != NULL)
919 descr->d_method = method;
920 return (PyObject *)descr;
921 }
922
923 PyObject *
PyDescr_NewMember(PyTypeObject * type,PyMemberDef * member)924 PyDescr_NewMember(PyTypeObject *type, PyMemberDef *member)
925 {
926 PyMemberDescrObject *descr;
927
928 descr = (PyMemberDescrObject *)descr_new(&PyMemberDescr_Type,
929 type, member->name);
930 if (descr != NULL)
931 descr->d_member = member;
932 return (PyObject *)descr;
933 }
934
935 PyObject *
PyDescr_NewGetSet(PyTypeObject * type,PyGetSetDef * getset)936 PyDescr_NewGetSet(PyTypeObject *type, PyGetSetDef *getset)
937 {
938 PyGetSetDescrObject *descr;
939
940 descr = (PyGetSetDescrObject *)descr_new(&PyGetSetDescr_Type,
941 type, getset->name);
942 if (descr != NULL)
943 descr->d_getset = getset;
944 return (PyObject *)descr;
945 }
946
947 PyObject *
PyDescr_NewWrapper(PyTypeObject * type,struct wrapperbase * base,void * wrapped)948 PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped)
949 {
950 PyWrapperDescrObject *descr;
951
952 descr = (PyWrapperDescrObject *)descr_new(&PyWrapperDescr_Type,
953 type, base->name);
954 if (descr != NULL) {
955 descr->d_base = base;
956 descr->d_wrapped = wrapped;
957 }
958 return (PyObject *)descr;
959 }
960
961
962 /* --- mappingproxy: read-only proxy for mappings --- */
963
964 /* This has no reason to be in this file except that adding new files is a
965 bit of a pain */
966
967 typedef struct {
968 PyObject_HEAD
969 PyObject *mapping;
970 } mappingproxyobject;
971
972 static Py_ssize_t
mappingproxy_len(mappingproxyobject * pp)973 mappingproxy_len(mappingproxyobject *pp)
974 {
975 return PyObject_Size(pp->mapping);
976 }
977
978 static PyObject *
mappingproxy_getitem(mappingproxyobject * pp,PyObject * key)979 mappingproxy_getitem(mappingproxyobject *pp, PyObject *key)
980 {
981 return PyObject_GetItem(pp->mapping, key);
982 }
983
984 static PyMappingMethods mappingproxy_as_mapping = {
985 (lenfunc)mappingproxy_len, /* mp_length */
986 (binaryfunc)mappingproxy_getitem, /* mp_subscript */
987 0, /* mp_ass_subscript */
988 };
989
990 static int
mappingproxy_contains(mappingproxyobject * pp,PyObject * key)991 mappingproxy_contains(mappingproxyobject *pp, PyObject *key)
992 {
993 if (PyDict_CheckExact(pp->mapping))
994 return PyDict_Contains(pp->mapping, key);
995 else
996 return PySequence_Contains(pp->mapping, key);
997 }
998
999 static PySequenceMethods mappingproxy_as_sequence = {
1000 0, /* sq_length */
1001 0, /* sq_concat */
1002 0, /* sq_repeat */
1003 0, /* sq_item */
1004 0, /* sq_slice */
1005 0, /* sq_ass_item */
1006 0, /* sq_ass_slice */
1007 (objobjproc)mappingproxy_contains, /* sq_contains */
1008 0, /* sq_inplace_concat */
1009 0, /* sq_inplace_repeat */
1010 };
1011
1012 static PyObject *
mappingproxy_get(mappingproxyobject * pp,PyObject * args)1013 mappingproxy_get(mappingproxyobject *pp, PyObject *args)
1014 {
1015 PyObject *key, *def = Py_None;
1016 _Py_IDENTIFIER(get);
1017
1018 if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &def))
1019 return NULL;
1020 return _PyObject_CallMethodIdObjArgs(pp->mapping, &PyId_get,
1021 key, def, NULL);
1022 }
1023
1024 static PyObject *
mappingproxy_keys(mappingproxyobject * pp,PyObject * Py_UNUSED (ignored))1025 mappingproxy_keys(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
1026 {
1027 _Py_IDENTIFIER(keys);
1028 return _PyObject_CallMethodId(pp->mapping, &PyId_keys, NULL);
1029 }
1030
1031 static PyObject *
mappingproxy_values(mappingproxyobject * pp,PyObject * Py_UNUSED (ignored))1032 mappingproxy_values(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
1033 {
1034 _Py_IDENTIFIER(values);
1035 return _PyObject_CallMethodId(pp->mapping, &PyId_values, NULL);
1036 }
1037
1038 static PyObject *
mappingproxy_items(mappingproxyobject * pp,PyObject * Py_UNUSED (ignored))1039 mappingproxy_items(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
1040 {
1041 _Py_IDENTIFIER(items);
1042 return _PyObject_CallMethodId(pp->mapping, &PyId_items, NULL);
1043 }
1044
1045 static PyObject *
mappingproxy_copy(mappingproxyobject * pp,PyObject * Py_UNUSED (ignored))1046 mappingproxy_copy(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
1047 {
1048 _Py_IDENTIFIER(copy);
1049 return _PyObject_CallMethodId(pp->mapping, &PyId_copy, NULL);
1050 }
1051
1052 /* WARNING: mappingproxy methods must not give access
1053 to the underlying mapping */
1054
1055 static PyMethodDef mappingproxy_methods[] = {
1056 {"get", (PyCFunction)mappingproxy_get, METH_VARARGS,
1057 PyDoc_STR("D.get(k[,d]) -> D[k] if k in D, else d."
1058 " d defaults to None.")},
1059 {"keys", (PyCFunction)mappingproxy_keys, METH_NOARGS,
1060 PyDoc_STR("D.keys() -> list of D's keys")},
1061 {"values", (PyCFunction)mappingproxy_values, METH_NOARGS,
1062 PyDoc_STR("D.values() -> list of D's values")},
1063 {"items", (PyCFunction)mappingproxy_items, METH_NOARGS,
1064 PyDoc_STR("D.items() -> list of D's (key, value) pairs, as 2-tuples")},
1065 {"copy", (PyCFunction)mappingproxy_copy, METH_NOARGS,
1066 PyDoc_STR("D.copy() -> a shallow copy of D")},
1067 {0}
1068 };
1069
1070 static void
mappingproxy_dealloc(mappingproxyobject * pp)1071 mappingproxy_dealloc(mappingproxyobject *pp)
1072 {
1073 _PyObject_GC_UNTRACK(pp);
1074 Py_DECREF(pp->mapping);
1075 PyObject_GC_Del(pp);
1076 }
1077
1078 static PyObject *
mappingproxy_getiter(mappingproxyobject * pp)1079 mappingproxy_getiter(mappingproxyobject *pp)
1080 {
1081 return PyObject_GetIter(pp->mapping);
1082 }
1083
1084 static PyObject *
mappingproxy_str(mappingproxyobject * pp)1085 mappingproxy_str(mappingproxyobject *pp)
1086 {
1087 return PyObject_Str(pp->mapping);
1088 }
1089
1090 static PyObject *
mappingproxy_repr(mappingproxyobject * pp)1091 mappingproxy_repr(mappingproxyobject *pp)
1092 {
1093 return PyUnicode_FromFormat("mappingproxy(%R)", pp->mapping);
1094 }
1095
1096 static int
mappingproxy_traverse(PyObject * self,visitproc visit,void * arg)1097 mappingproxy_traverse(PyObject *self, visitproc visit, void *arg)
1098 {
1099 mappingproxyobject *pp = (mappingproxyobject *)self;
1100 Py_VISIT(pp->mapping);
1101 return 0;
1102 }
1103
1104 static PyObject *
mappingproxy_richcompare(mappingproxyobject * v,PyObject * w,int op)1105 mappingproxy_richcompare(mappingproxyobject *v, PyObject *w, int op)
1106 {
1107 return PyObject_RichCompare(v->mapping, w, op);
1108 }
1109
1110 static int
mappingproxy_check_mapping(PyObject * mapping)1111 mappingproxy_check_mapping(PyObject *mapping)
1112 {
1113 if (!PyMapping_Check(mapping)
1114 || PyList_Check(mapping)
1115 || PyTuple_Check(mapping)) {
1116 PyErr_Format(PyExc_TypeError,
1117 "mappingproxy() argument must be a mapping, not %s",
1118 Py_TYPE(mapping)->tp_name);
1119 return -1;
1120 }
1121 return 0;
1122 }
1123
1124 /*[clinic input]
1125 @classmethod
1126 mappingproxy.__new__ as mappingproxy_new
1127
1128 mapping: object
1129
1130 [clinic start generated code]*/
1131
1132 static PyObject *
mappingproxy_new_impl(PyTypeObject * type,PyObject * mapping)1133 mappingproxy_new_impl(PyTypeObject *type, PyObject *mapping)
1134 /*[clinic end generated code: output=65f27f02d5b68fa7 input=d2d620d4f598d4f8]*/
1135 {
1136 mappingproxyobject *mappingproxy;
1137
1138 if (mappingproxy_check_mapping(mapping) == -1)
1139 return NULL;
1140
1141 mappingproxy = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type);
1142 if (mappingproxy == NULL)
1143 return NULL;
1144 Py_INCREF(mapping);
1145 mappingproxy->mapping = mapping;
1146 _PyObject_GC_TRACK(mappingproxy);
1147 return (PyObject *)mappingproxy;
1148 }
1149
1150 PyObject *
PyDictProxy_New(PyObject * mapping)1151 PyDictProxy_New(PyObject *mapping)
1152 {
1153 mappingproxyobject *pp;
1154
1155 if (mappingproxy_check_mapping(mapping) == -1)
1156 return NULL;
1157
1158 pp = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type);
1159 if (pp != NULL) {
1160 Py_INCREF(mapping);
1161 pp->mapping = mapping;
1162 _PyObject_GC_TRACK(pp);
1163 }
1164 return (PyObject *)pp;
1165 }
1166
1167
1168 /* --- Wrapper object for "slot" methods --- */
1169
1170 /* This has no reason to be in this file except that adding new files is a
1171 bit of a pain */
1172
1173 typedef struct {
1174 PyObject_HEAD
1175 PyWrapperDescrObject *descr;
1176 PyObject *self;
1177 } wrapperobject;
1178
1179 #define Wrapper_Check(v) (Py_TYPE(v) == &_PyMethodWrapper_Type)
1180
1181 static void
wrapper_dealloc(wrapperobject * wp)1182 wrapper_dealloc(wrapperobject *wp)
1183 {
1184 PyObject_GC_UnTrack(wp);
1185 Py_TRASHCAN_BEGIN(wp, wrapper_dealloc)
1186 Py_XDECREF(wp->descr);
1187 Py_XDECREF(wp->self);
1188 PyObject_GC_Del(wp);
1189 Py_TRASHCAN_END
1190 }
1191
1192 static PyObject *
wrapper_richcompare(PyObject * a,PyObject * b,int op)1193 wrapper_richcompare(PyObject *a, PyObject *b, int op)
1194 {
1195 wrapperobject *wa, *wb;
1196 int eq;
1197
1198 assert(a != NULL && b != NULL);
1199
1200 /* both arguments should be wrapperobjects */
1201 if ((op != Py_EQ && op != Py_NE)
1202 || !Wrapper_Check(a) || !Wrapper_Check(b))
1203 {
1204 Py_RETURN_NOTIMPLEMENTED;
1205 }
1206
1207 wa = (wrapperobject *)a;
1208 wb = (wrapperobject *)b;
1209 eq = (wa->descr == wb->descr && wa->self == wb->self);
1210 if (eq == (op == Py_EQ)) {
1211 Py_RETURN_TRUE;
1212 }
1213 else {
1214 Py_RETURN_FALSE;
1215 }
1216 }
1217
1218 static Py_hash_t
wrapper_hash(wrapperobject * wp)1219 wrapper_hash(wrapperobject *wp)
1220 {
1221 Py_hash_t x, y;
1222 x = _Py_HashPointer(wp->self);
1223 y = _Py_HashPointer(wp->descr);
1224 x = x ^ y;
1225 if (x == -1)
1226 x = -2;
1227 return x;
1228 }
1229
1230 static PyObject *
wrapper_repr(wrapperobject * wp)1231 wrapper_repr(wrapperobject *wp)
1232 {
1233 return PyUnicode_FromFormat("<method-wrapper '%s' of %s object at %p>",
1234 wp->descr->d_base->name,
1235 wp->self->ob_type->tp_name,
1236 wp->self);
1237 }
1238
1239 static PyObject *
wrapper_reduce(wrapperobject * wp,PyObject * Py_UNUSED (ignored))1240 wrapper_reduce(wrapperobject *wp, PyObject *Py_UNUSED(ignored))
1241 {
1242 _Py_IDENTIFIER(getattr);
1243 return Py_BuildValue("N(OO)", _PyEval_GetBuiltinId(&PyId_getattr),
1244 wp->self, PyDescr_NAME(wp->descr));
1245 }
1246
1247 static PyMethodDef wrapper_methods[] = {
1248 {"__reduce__", (PyCFunction)wrapper_reduce, METH_NOARGS, NULL},
1249 {NULL, NULL}
1250 };
1251
1252 static PyMemberDef wrapper_members[] = {
1253 {"__self__", T_OBJECT, offsetof(wrapperobject, self), READONLY},
1254 {0}
1255 };
1256
1257 static PyObject *
wrapper_objclass(wrapperobject * wp,void * Py_UNUSED (ignored))1258 wrapper_objclass(wrapperobject *wp, void *Py_UNUSED(ignored))
1259 {
1260 PyObject *c = (PyObject *)PyDescr_TYPE(wp->descr);
1261
1262 Py_INCREF(c);
1263 return c;
1264 }
1265
1266 static PyObject *
wrapper_name(wrapperobject * wp,void * Py_UNUSED (ignored))1267 wrapper_name(wrapperobject *wp, void *Py_UNUSED(ignored))
1268 {
1269 const char *s = wp->descr->d_base->name;
1270
1271 return PyUnicode_FromString(s);
1272 }
1273
1274 static PyObject *
wrapper_doc(wrapperobject * wp,void * Py_UNUSED (ignored))1275 wrapper_doc(wrapperobject *wp, void *Py_UNUSED(ignored))
1276 {
1277 return _PyType_GetDocFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc);
1278 }
1279
1280 static PyObject *
wrapper_text_signature(wrapperobject * wp,void * Py_UNUSED (ignored))1281 wrapper_text_signature(wrapperobject *wp, void *Py_UNUSED(ignored))
1282 {
1283 return _PyType_GetTextSignatureFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc);
1284 }
1285
1286 static PyObject *
wrapper_qualname(wrapperobject * wp,void * Py_UNUSED (ignored))1287 wrapper_qualname(wrapperobject *wp, void *Py_UNUSED(ignored))
1288 {
1289 return descr_get_qualname((PyDescrObject *)wp->descr, NULL);
1290 }
1291
1292 static PyGetSetDef wrapper_getsets[] = {
1293 {"__objclass__", (getter)wrapper_objclass},
1294 {"__name__", (getter)wrapper_name},
1295 {"__qualname__", (getter)wrapper_qualname},
1296 {"__doc__", (getter)wrapper_doc},
1297 {"__text_signature__", (getter)wrapper_text_signature},
1298 {0}
1299 };
1300
1301 static PyObject *
wrapper_call(wrapperobject * wp,PyObject * args,PyObject * kwds)1302 wrapper_call(wrapperobject *wp, PyObject *args, PyObject *kwds)
1303 {
1304 return wrapperdescr_raw_call(wp->descr, wp->self, args, kwds);
1305 }
1306
1307 static int
wrapper_traverse(PyObject * self,visitproc visit,void * arg)1308 wrapper_traverse(PyObject *self, visitproc visit, void *arg)
1309 {
1310 wrapperobject *wp = (wrapperobject *)self;
1311 Py_VISIT(wp->descr);
1312 Py_VISIT(wp->self);
1313 return 0;
1314 }
1315
1316 PyTypeObject _PyMethodWrapper_Type = {
1317 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1318 "method-wrapper", /* tp_name */
1319 sizeof(wrapperobject), /* tp_basicsize */
1320 0, /* tp_itemsize */
1321 /* methods */
1322 (destructor)wrapper_dealloc, /* tp_dealloc */
1323 0, /* tp_vectorcall_offset */
1324 0, /* tp_getattr */
1325 0, /* tp_setattr */
1326 0, /* tp_as_async */
1327 (reprfunc)wrapper_repr, /* tp_repr */
1328 0, /* tp_as_number */
1329 0, /* tp_as_sequence */
1330 0, /* tp_as_mapping */
1331 (hashfunc)wrapper_hash, /* tp_hash */
1332 (ternaryfunc)wrapper_call, /* tp_call */
1333 0, /* tp_str */
1334 PyObject_GenericGetAttr, /* tp_getattro */
1335 0, /* tp_setattro */
1336 0, /* tp_as_buffer */
1337 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1338 0, /* tp_doc */
1339 wrapper_traverse, /* tp_traverse */
1340 0, /* tp_clear */
1341 wrapper_richcompare, /* tp_richcompare */
1342 0, /* tp_weaklistoffset */
1343 0, /* tp_iter */
1344 0, /* tp_iternext */
1345 wrapper_methods, /* tp_methods */
1346 wrapper_members, /* tp_members */
1347 wrapper_getsets, /* tp_getset */
1348 0, /* tp_base */
1349 0, /* tp_dict */
1350 0, /* tp_descr_get */
1351 0, /* tp_descr_set */
1352 };
1353
1354 PyObject *
PyWrapper_New(PyObject * d,PyObject * self)1355 PyWrapper_New(PyObject *d, PyObject *self)
1356 {
1357 wrapperobject *wp;
1358 PyWrapperDescrObject *descr;
1359
1360 assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type));
1361 descr = (PyWrapperDescrObject *)d;
1362 assert(_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
1363 (PyObject *)PyDescr_TYPE(descr)));
1364
1365 wp = PyObject_GC_New(wrapperobject, &_PyMethodWrapper_Type);
1366 if (wp != NULL) {
1367 Py_INCREF(descr);
1368 wp->descr = descr;
1369 Py_INCREF(self);
1370 wp->self = self;
1371 _PyObject_GC_TRACK(wp);
1372 }
1373 return (PyObject *)wp;
1374 }
1375
1376
1377 /* A built-in 'property' type */
1378
1379 /*
1380 class property(object):
1381
1382 def __init__(self, fget=None, fset=None, fdel=None, doc=None):
1383 if doc is None and fget is not None and hasattr(fget, "__doc__"):
1384 doc = fget.__doc__
1385 self.__get = fget
1386 self.__set = fset
1387 self.__del = fdel
1388 self.__doc__ = doc
1389
1390 def __get__(self, inst, type=None):
1391 if inst is None:
1392 return self
1393 if self.__get is None:
1394 raise AttributeError, "unreadable attribute"
1395 return self.__get(inst)
1396
1397 def __set__(self, inst, value):
1398 if self.__set is None:
1399 raise AttributeError, "can't set attribute"
1400 return self.__set(inst, value)
1401
1402 def __delete__(self, inst):
1403 if self.__del is None:
1404 raise AttributeError, "can't delete attribute"
1405 return self.__del(inst)
1406
1407 */
1408
1409 typedef struct {
1410 PyObject_HEAD
1411 PyObject *prop_get;
1412 PyObject *prop_set;
1413 PyObject *prop_del;
1414 PyObject *prop_doc;
1415 int getter_doc;
1416 } propertyobject;
1417
1418 static PyObject * property_copy(PyObject *, PyObject *, PyObject *,
1419 PyObject *);
1420
1421 static PyMemberDef property_members[] = {
1422 {"fget", T_OBJECT, offsetof(propertyobject, prop_get), READONLY},
1423 {"fset", T_OBJECT, offsetof(propertyobject, prop_set), READONLY},
1424 {"fdel", T_OBJECT, offsetof(propertyobject, prop_del), READONLY},
1425 {"__doc__", T_OBJECT, offsetof(propertyobject, prop_doc), 0},
1426 {0}
1427 };
1428
1429
1430 PyDoc_STRVAR(getter_doc,
1431 "Descriptor to change the getter on a property.");
1432
1433 static PyObject *
property_getter(PyObject * self,PyObject * getter)1434 property_getter(PyObject *self, PyObject *getter)
1435 {
1436 return property_copy(self, getter, NULL, NULL);
1437 }
1438
1439
1440 PyDoc_STRVAR(setter_doc,
1441 "Descriptor to change the setter on a property.");
1442
1443 static PyObject *
property_setter(PyObject * self,PyObject * setter)1444 property_setter(PyObject *self, PyObject *setter)
1445 {
1446 return property_copy(self, NULL, setter, NULL);
1447 }
1448
1449
1450 PyDoc_STRVAR(deleter_doc,
1451 "Descriptor to change the deleter on a property.");
1452
1453 static PyObject *
property_deleter(PyObject * self,PyObject * deleter)1454 property_deleter(PyObject *self, PyObject *deleter)
1455 {
1456 return property_copy(self, NULL, NULL, deleter);
1457 }
1458
1459
1460 static PyMethodDef property_methods[] = {
1461 {"getter", property_getter, METH_O, getter_doc},
1462 {"setter", property_setter, METH_O, setter_doc},
1463 {"deleter", property_deleter, METH_O, deleter_doc},
1464 {0}
1465 };
1466
1467
1468 static void
property_dealloc(PyObject * self)1469 property_dealloc(PyObject *self)
1470 {
1471 propertyobject *gs = (propertyobject *)self;
1472
1473 _PyObject_GC_UNTRACK(self);
1474 Py_XDECREF(gs->prop_get);
1475 Py_XDECREF(gs->prop_set);
1476 Py_XDECREF(gs->prop_del);
1477 Py_XDECREF(gs->prop_doc);
1478 self->ob_type->tp_free(self);
1479 }
1480
1481 static PyObject *
property_descr_get(PyObject * self,PyObject * obj,PyObject * type)1482 property_descr_get(PyObject *self, PyObject *obj, PyObject *type)
1483 {
1484 if (obj == NULL || obj == Py_None) {
1485 Py_INCREF(self);
1486 return self;
1487 }
1488
1489 propertyobject *gs = (propertyobject *)self;
1490 if (gs->prop_get == NULL) {
1491 PyErr_SetString(PyExc_AttributeError, "unreadable attribute");
1492 return NULL;
1493 }
1494
1495 PyObject *args[1] = {obj};
1496 return _PyObject_FastCall(gs->prop_get, args, 1);
1497 }
1498
1499 static int
property_descr_set(PyObject * self,PyObject * obj,PyObject * value)1500 property_descr_set(PyObject *self, PyObject *obj, PyObject *value)
1501 {
1502 propertyobject *gs = (propertyobject *)self;
1503 PyObject *func, *res;
1504
1505 if (value == NULL)
1506 func = gs->prop_del;
1507 else
1508 func = gs->prop_set;
1509 if (func == NULL) {
1510 PyErr_SetString(PyExc_AttributeError,
1511 value == NULL ?
1512 "can't delete attribute" :
1513 "can't set attribute");
1514 return -1;
1515 }
1516 if (value == NULL)
1517 res = PyObject_CallFunctionObjArgs(func, obj, NULL);
1518 else
1519 res = PyObject_CallFunctionObjArgs(func, obj, value, NULL);
1520 if (res == NULL)
1521 return -1;
1522 Py_DECREF(res);
1523 return 0;
1524 }
1525
1526 static PyObject *
property_copy(PyObject * old,PyObject * get,PyObject * set,PyObject * del)1527 property_copy(PyObject *old, PyObject *get, PyObject *set, PyObject *del)
1528 {
1529 propertyobject *pold = (propertyobject *)old;
1530 PyObject *new, *type, *doc;
1531
1532 type = PyObject_Type(old);
1533 if (type == NULL)
1534 return NULL;
1535
1536 if (get == NULL || get == Py_None) {
1537 Py_XDECREF(get);
1538 get = pold->prop_get ? pold->prop_get : Py_None;
1539 }
1540 if (set == NULL || set == Py_None) {
1541 Py_XDECREF(set);
1542 set = pold->prop_set ? pold->prop_set : Py_None;
1543 }
1544 if (del == NULL || del == Py_None) {
1545 Py_XDECREF(del);
1546 del = pold->prop_del ? pold->prop_del : Py_None;
1547 }
1548 if (pold->getter_doc && get != Py_None) {
1549 /* make _init use __doc__ from getter */
1550 doc = Py_None;
1551 }
1552 else {
1553 doc = pold->prop_doc ? pold->prop_doc : Py_None;
1554 }
1555
1556 new = PyObject_CallFunctionObjArgs(type, get, set, del, doc, NULL);
1557 Py_DECREF(type);
1558 if (new == NULL)
1559 return NULL;
1560 return new;
1561 }
1562
1563 /*[clinic input]
1564 property.__init__ as property_init
1565
1566 fget: object(c_default="NULL") = None
1567 function to be used for getting an attribute value
1568 fset: object(c_default="NULL") = None
1569 function to be used for setting an attribute value
1570 fdel: object(c_default="NULL") = None
1571 function to be used for del'ing an attribute
1572 doc: object(c_default="NULL") = None
1573 docstring
1574
1575 Property attribute.
1576
1577 Typical use is to define a managed attribute x:
1578
1579 class C(object):
1580 def getx(self): return self._x
1581 def setx(self, value): self._x = value
1582 def delx(self): del self._x
1583 x = property(getx, setx, delx, "I'm the 'x' property.")
1584
1585 Decorators make defining new properties or modifying existing ones easy:
1586
1587 class C(object):
1588 @property
1589 def x(self):
1590 "I am the 'x' property."
1591 return self._x
1592 @x.setter
1593 def x(self, value):
1594 self._x = value
1595 @x.deleter
1596 def x(self):
1597 del self._x
1598 [clinic start generated code]*/
1599
1600 static int
property_init_impl(propertyobject * self,PyObject * fget,PyObject * fset,PyObject * fdel,PyObject * doc)1601 property_init_impl(propertyobject *self, PyObject *fget, PyObject *fset,
1602 PyObject *fdel, PyObject *doc)
1603 /*[clinic end generated code: output=01a960742b692b57 input=dfb5dbbffc6932d5]*/
1604 {
1605 if (fget == Py_None)
1606 fget = NULL;
1607 if (fset == Py_None)
1608 fset = NULL;
1609 if (fdel == Py_None)
1610 fdel = NULL;
1611
1612 Py_XINCREF(fget);
1613 Py_XINCREF(fset);
1614 Py_XINCREF(fdel);
1615 Py_XINCREF(doc);
1616
1617 Py_XSETREF(self->prop_get, fget);
1618 Py_XSETREF(self->prop_set, fset);
1619 Py_XSETREF(self->prop_del, fdel);
1620 Py_XSETREF(self->prop_doc, doc);
1621 self->getter_doc = 0;
1622
1623 /* if no docstring given and the getter has one, use that one */
1624 if ((doc == NULL || doc == Py_None) && fget != NULL) {
1625 _Py_IDENTIFIER(__doc__);
1626 PyObject *get_doc;
1627 int rc = _PyObject_LookupAttrId(fget, &PyId___doc__, &get_doc);
1628 if (rc <= 0) {
1629 return rc;
1630 }
1631 if (Py_TYPE(self) == &PyProperty_Type) {
1632 Py_XSETREF(self->prop_doc, get_doc);
1633 }
1634 else {
1635 /* If this is a property subclass, put __doc__
1636 in dict of the subclass instance instead,
1637 otherwise it gets shadowed by __doc__ in the
1638 class's dict. */
1639 int err = _PyObject_SetAttrId((PyObject *)self, &PyId___doc__, get_doc);
1640 Py_DECREF(get_doc);
1641 if (err < 0)
1642 return -1;
1643 }
1644 self->getter_doc = 1;
1645 }
1646
1647 return 0;
1648 }
1649
1650 static PyObject *
property_get___isabstractmethod__(propertyobject * prop,void * closure)1651 property_get___isabstractmethod__(propertyobject *prop, void *closure)
1652 {
1653 int res = _PyObject_IsAbstract(prop->prop_get);
1654 if (res == -1) {
1655 return NULL;
1656 }
1657 else if (res) {
1658 Py_RETURN_TRUE;
1659 }
1660
1661 res = _PyObject_IsAbstract(prop->prop_set);
1662 if (res == -1) {
1663 return NULL;
1664 }
1665 else if (res) {
1666 Py_RETURN_TRUE;
1667 }
1668
1669 res = _PyObject_IsAbstract(prop->prop_del);
1670 if (res == -1) {
1671 return NULL;
1672 }
1673 else if (res) {
1674 Py_RETURN_TRUE;
1675 }
1676 Py_RETURN_FALSE;
1677 }
1678
1679 static PyGetSetDef property_getsetlist[] = {
1680 {"__isabstractmethod__",
1681 (getter)property_get___isabstractmethod__, NULL,
1682 NULL,
1683 NULL},
1684 {NULL} /* Sentinel */
1685 };
1686
1687 static int
property_traverse(PyObject * self,visitproc visit,void * arg)1688 property_traverse(PyObject *self, visitproc visit, void *arg)
1689 {
1690 propertyobject *pp = (propertyobject *)self;
1691 Py_VISIT(pp->prop_get);
1692 Py_VISIT(pp->prop_set);
1693 Py_VISIT(pp->prop_del);
1694 Py_VISIT(pp->prop_doc);
1695 return 0;
1696 }
1697
1698 static int
property_clear(PyObject * self)1699 property_clear(PyObject *self)
1700 {
1701 propertyobject *pp = (propertyobject *)self;
1702 Py_CLEAR(pp->prop_doc);
1703 return 0;
1704 }
1705
1706 #include "clinic/descrobject.c.h"
1707
1708 PyTypeObject PyDictProxy_Type = {
1709 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1710 "mappingproxy", /* tp_name */
1711 sizeof(mappingproxyobject), /* tp_basicsize */
1712 0, /* tp_itemsize */
1713 /* methods */
1714 (destructor)mappingproxy_dealloc, /* tp_dealloc */
1715 0, /* tp_vectorcall_offset */
1716 0, /* tp_getattr */
1717 0, /* tp_setattr */
1718 0, /* tp_as_async */
1719 (reprfunc)mappingproxy_repr, /* tp_repr */
1720 0, /* tp_as_number */
1721 &mappingproxy_as_sequence, /* tp_as_sequence */
1722 &mappingproxy_as_mapping, /* tp_as_mapping */
1723 0, /* tp_hash */
1724 0, /* tp_call */
1725 (reprfunc)mappingproxy_str, /* tp_str */
1726 PyObject_GenericGetAttr, /* tp_getattro */
1727 0, /* tp_setattro */
1728 0, /* tp_as_buffer */
1729 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1730 0, /* tp_doc */
1731 mappingproxy_traverse, /* tp_traverse */
1732 0, /* tp_clear */
1733 (richcmpfunc)mappingproxy_richcompare, /* tp_richcompare */
1734 0, /* tp_weaklistoffset */
1735 (getiterfunc)mappingproxy_getiter, /* tp_iter */
1736 0, /* tp_iternext */
1737 mappingproxy_methods, /* tp_methods */
1738 0, /* tp_members */
1739 0, /* tp_getset */
1740 0, /* tp_base */
1741 0, /* tp_dict */
1742 0, /* tp_descr_get */
1743 0, /* tp_descr_set */
1744 0, /* tp_dictoffset */
1745 0, /* tp_init */
1746 0, /* tp_alloc */
1747 mappingproxy_new, /* tp_new */
1748 };
1749
1750 PyTypeObject PyProperty_Type = {
1751 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1752 "property", /* tp_name */
1753 sizeof(propertyobject), /* tp_basicsize */
1754 0, /* tp_itemsize */
1755 /* methods */
1756 property_dealloc, /* tp_dealloc */
1757 0, /* tp_vectorcall_offset */
1758 0, /* tp_getattr */
1759 0, /* tp_setattr */
1760 0, /* tp_as_async */
1761 0, /* tp_repr */
1762 0, /* tp_as_number */
1763 0, /* tp_as_sequence */
1764 0, /* tp_as_mapping */
1765 0, /* tp_hash */
1766 0, /* tp_call */
1767 0, /* tp_str */
1768 PyObject_GenericGetAttr, /* tp_getattro */
1769 0, /* tp_setattro */
1770 0, /* tp_as_buffer */
1771 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1772 Py_TPFLAGS_BASETYPE, /* tp_flags */
1773 property_init__doc__, /* tp_doc */
1774 property_traverse, /* tp_traverse */
1775 (inquiry)property_clear, /* tp_clear */
1776 0, /* tp_richcompare */
1777 0, /* tp_weaklistoffset */
1778 0, /* tp_iter */
1779 0, /* tp_iternext */
1780 property_methods, /* tp_methods */
1781 property_members, /* tp_members */
1782 property_getsetlist, /* tp_getset */
1783 0, /* tp_base */
1784 0, /* tp_dict */
1785 property_descr_get, /* tp_descr_get */
1786 property_descr_set, /* tp_descr_set */
1787 0, /* tp_dictoffset */
1788 property_init, /* tp_init */
1789 PyType_GenericAlloc, /* tp_alloc */
1790 PyType_GenericNew, /* tp_new */
1791 PyObject_GC_Del, /* tp_free */
1792 };
1793