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