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