ยปCore Development>Code coverage>Objects/descrobject.c

Python code coverage for Objects/descrobject.c

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