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