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