Coverage Report

Created: 2022-07-08 09:39

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