1 /* Descriptors -- a new, flexible way to describe attributes */
4 #include "structmember.h" /* Why is this not included in Python.h? */
7 descr_dealloc(PyDescrObject
*descr
)
9 _PyObject_GC_UNTRACK(descr
);
10 Py_XDECREF(descr
->d_type
);
11 Py_XDECREF(descr
->d_name
);
12 PyObject_GC_Del(descr
);
16 descr_name(PyDescrObject
*descr
)
18 if (descr
->d_name
!= NULL
&& PyString_Check(descr
->d_name
))
19 return PyString_AS_STRING(descr
->d_name
);
25 descr_repr(PyDescrObject
*descr
, char *format
)
27 return PyString_FromFormat(format
, descr_name(descr
),
28 descr
->d_type
->tp_name
);
32 method_repr(PyMethodDescrObject
*descr
)
34 return descr_repr((PyDescrObject
*)descr
,
35 "<method '%s' of '%s' objects>");
39 member_repr(PyMemberDescrObject
*descr
)
41 return descr_repr((PyDescrObject
*)descr
,
42 "<member '%s' of '%s' objects>");
46 getset_repr(PyGetSetDescrObject
*descr
)
48 return descr_repr((PyDescrObject
*)descr
,
49 "<attribute '%s' of '%s' objects>");
53 wrapper_repr(PyWrapperDescrObject
*descr
)
55 return descr_repr((PyDescrObject
*)descr
,
56 "<slot wrapper '%s' of '%s' objects>");
60 descr_check(PyDescrObject
*descr
, PyObject
*obj
, PyTypeObject
*type
,
63 if (obj
== NULL
|| (obj
== Py_None
&& type
!= Py_None
->ob_type
)) {
65 *pres
= (PyObject
*)descr
;
68 if (!PyObject_IsInstance(obj
, (PyObject
*)(descr
->d_type
))) {
69 PyErr_Format(PyExc_TypeError
,
70 "descriptor '%s' for '%s' objects "
71 "doesn't apply to '%s' object",
72 descr_name((PyDescrObject
*)descr
),
73 descr
->d_type
->tp_name
,
74 obj
->ob_type
->tp_name
);
82 method_get(PyMethodDescrObject
*descr
, PyObject
*obj
, PyTypeObject
*type
)
86 if (descr_check((PyDescrObject
*)descr
, obj
, type
, &res
))
88 return PyCFunction_New(descr
->d_method
, obj
);
92 member_get(PyMemberDescrObject
*descr
, PyObject
*obj
, PyTypeObject
*type
)
96 if (descr_check((PyDescrObject
*)descr
, obj
, type
, &res
))
98 return PyMember_GetOne((char *)obj
, descr
->d_member
);
102 getset_get(PyGetSetDescrObject
*descr
, PyObject
*obj
, PyTypeObject
*type
)
106 if (descr_check((PyDescrObject
*)descr
, obj
, type
, &res
))
108 if (descr
->d_getset
->get
!= NULL
)
109 return descr
->d_getset
->get(obj
, descr
->d_getset
->closure
);
110 PyErr_Format(PyExc_TypeError
,
111 "attribute '%.300s' of '%.100s' objects is not readable",
112 descr_name((PyDescrObject
*)descr
),
113 descr
->d_type
->tp_name
);
118 wrapper_get(PyWrapperDescrObject
*descr
, PyObject
*obj
, PyTypeObject
*type
)
122 if (descr_check((PyDescrObject
*)descr
, obj
, type
, &res
))
124 return PyWrapper_New((PyObject
*)descr
, obj
);
128 descr_setcheck(PyDescrObject
*descr
, PyObject
*obj
, PyObject
*value
,
132 if (!PyObject_IsInstance(obj
, (PyObject
*)(descr
->d_type
))) {
133 PyErr_Format(PyExc_TypeError
,
134 "descriptor '%.200s' for '%.100s' objects "
135 "doesn't apply to '%.100s' object",
137 descr
->d_type
->tp_name
,
138 obj
->ob_type
->tp_name
);
146 member_set(PyMemberDescrObject
*descr
, PyObject
*obj
, PyObject
*value
)
150 if (descr_setcheck((PyDescrObject
*)descr
, obj
, value
, &res
))
152 return PyMember_SetOne((char *)obj
, descr
->d_member
, value
);
156 getset_set(PyGetSetDescrObject
*descr
, PyObject
*obj
, PyObject
*value
)
160 if (descr_setcheck((PyDescrObject
*)descr
, obj
, value
, &res
))
162 if (descr
->d_getset
->set
!= NULL
)
163 return descr
->d_getset
->set(obj
, value
,
164 descr
->d_getset
->closure
);
165 PyErr_Format(PyExc_TypeError
,
166 "attribute '%.300s' of '%.100s' objects is not writable",
167 descr_name((PyDescrObject
*)descr
),
168 descr
->d_type
->tp_name
);
173 methoddescr_call(PyMethodDescrObject
*descr
, PyObject
*args
, PyObject
*kwds
)
176 PyObject
*self
, *func
, *result
;
178 /* Make sure that the first argument is acceptable as 'self' */
179 assert(PyTuple_Check(args
));
180 argc
= PyTuple_GET_SIZE(args
);
182 PyErr_Format(PyExc_TypeError
,
183 "descriptor '%.300s' of '%.100s' "
184 "object needs an argument",
185 descr_name((PyDescrObject
*)descr
),
186 descr
->d_type
->tp_name
);
189 self
= PyTuple_GET_ITEM(args
, 0);
190 if (!PyObject_IsInstance(self
, (PyObject
*)(descr
->d_type
))) {
191 PyErr_Format(PyExc_TypeError
,
192 "descriptor '%.200s' "
193 "requires a '%.100s' object "
194 "but received a '%.100s'",
195 descr_name((PyDescrObject
*)descr
),
196 descr
->d_type
->tp_name
,
197 self
->ob_type
->tp_name
);
201 func
= PyCFunction_New(descr
->d_method
, self
);
204 args
= PyTuple_GetSlice(args
, 1, argc
);
209 result
= PyEval_CallObjectWithKeywords(func
, args
, kwds
);
216 wrapperdescr_call(PyWrapperDescrObject
*descr
, PyObject
*args
, PyObject
*kwds
)
219 PyObject
*self
, *func
, *result
;
221 /* Make sure that the first argument is acceptable as 'self' */
222 assert(PyTuple_Check(args
));
223 argc
= PyTuple_GET_SIZE(args
);
225 PyErr_Format(PyExc_TypeError
,
226 "descriptor '%.300s' of '%.100s' "
227 "object needs an argument",
228 descr_name((PyDescrObject
*)descr
),
229 descr
->d_type
->tp_name
);
232 self
= PyTuple_GET_ITEM(args
, 0);
233 if (!PyObject_IsInstance(self
, (PyObject
*)(descr
->d_type
))) {
234 PyErr_Format(PyExc_TypeError
,
235 "descriptor '%.200s' "
236 "requires a '%.100s' object "
237 "but received a '%.100s'",
238 descr_name((PyDescrObject
*)descr
),
239 descr
->d_type
->tp_name
,
240 self
->ob_type
->tp_name
);
244 func
= PyWrapper_New((PyObject
*)descr
, self
);
247 args
= PyTuple_GetSlice(args
, 1, argc
);
252 result
= PyEval_CallObjectWithKeywords(func
, args
, kwds
);
259 method_get_doc(PyMethodDescrObject
*descr
, void *closure
)
261 if (descr
->d_method
->ml_doc
== NULL
) {
265 return PyString_FromString(descr
->d_method
->ml_doc
);
268 static PyMemberDef descr_members
[] = {
269 {"__objclass__", T_OBJECT
, offsetof(PyDescrObject
, d_type
), READONLY
},
270 {"__name__", T_OBJECT
, offsetof(PyDescrObject
, d_name
), READONLY
},
274 static PyGetSetDef method_getset
[] = {
275 {"__doc__", (getter
)method_get_doc
},
280 member_get_doc(PyMemberDescrObject
*descr
, void *closure
)
282 if (descr
->d_member
->doc
== NULL
) {
286 return PyString_FromString(descr
->d_member
->doc
);
289 static PyGetSetDef member_getset
[] = {
290 {"__doc__", (getter
)member_get_doc
},
295 getset_get_doc(PyGetSetDescrObject
*descr
, void *closure
)
297 if (descr
->d_getset
->doc
== NULL
) {
301 return PyString_FromString(descr
->d_getset
->doc
);
304 static PyGetSetDef getset_getset
[] = {
305 {"__doc__", (getter
)getset_get_doc
},
310 wrapper_get_doc(PyWrapperDescrObject
*descr
, void *closure
)
312 if (descr
->d_base
->doc
== NULL
) {
316 return PyString_FromString(descr
->d_base
->doc
);
319 static PyGetSetDef wrapper_getset
[] = {
320 {"__doc__", (getter
)wrapper_get_doc
},
325 descr_traverse(PyObject
*self
, visitproc visit
, void *arg
)
327 PyDescrObject
*descr
= (PyDescrObject
*)self
;
331 err
= visit((PyObject
*)(descr
->d_type
), arg
);
338 static PyTypeObject PyMethodDescr_Type
= {
339 PyObject_HEAD_INIT(&PyType_Type
)
342 sizeof(PyMethodDescrObject
),
344 (destructor
)descr_dealloc
, /* tp_dealloc */
349 (reprfunc
)method_repr
, /* tp_repr */
350 0, /* tp_as_number */
351 0, /* tp_as_sequence */
352 0, /* tp_as_mapping */
354 (ternaryfunc
)methoddescr_call
, /* tp_call */
356 PyObject_GenericGetAttr
, /* tp_getattro */
358 0, /* tp_as_buffer */
359 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_GC
, /* tp_flags */
361 descr_traverse
, /* tp_traverse */
363 0, /* tp_richcompare */
364 0, /* tp_weaklistoffset */
368 descr_members
, /* tp_members */
369 method_getset
, /* tp_getset */
372 (descrgetfunc
)method_get
, /* tp_descr_get */
373 0, /* tp_descr_set */
376 static PyTypeObject PyMemberDescr_Type
= {
377 PyObject_HEAD_INIT(&PyType_Type
)
380 sizeof(PyMemberDescrObject
),
382 (destructor
)descr_dealloc
, /* tp_dealloc */
387 (reprfunc
)member_repr
, /* tp_repr */
388 0, /* tp_as_number */
389 0, /* tp_as_sequence */
390 0, /* tp_as_mapping */
392 (ternaryfunc
)0, /* tp_call */
394 PyObject_GenericGetAttr
, /* tp_getattro */
396 0, /* tp_as_buffer */
397 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_GC
, /* tp_flags */
399 descr_traverse
, /* tp_traverse */
401 0, /* tp_richcompare */
402 0, /* tp_weaklistoffset */
406 descr_members
, /* tp_members */
407 member_getset
, /* tp_getset */
410 (descrgetfunc
)member_get
, /* tp_descr_get */
411 (descrsetfunc
)member_set
, /* tp_descr_set */
414 static PyTypeObject PyGetSetDescr_Type
= {
415 PyObject_HEAD_INIT(&PyType_Type
)
418 sizeof(PyGetSetDescrObject
),
420 (destructor
)descr_dealloc
, /* tp_dealloc */
425 (reprfunc
)getset_repr
, /* tp_repr */
426 0, /* tp_as_number */
427 0, /* tp_as_sequence */
428 0, /* tp_as_mapping */
430 (ternaryfunc
)0, /* tp_call */
432 PyObject_GenericGetAttr
, /* tp_getattro */
434 0, /* tp_as_buffer */
435 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_GC
, /* tp_flags */
437 descr_traverse
, /* tp_traverse */
439 0, /* tp_richcompare */
440 0, /* tp_weaklistoffset */
444 descr_members
, /* tp_members */
445 getset_getset
, /* tp_getset */
448 (descrgetfunc
)getset_get
, /* tp_descr_get */
449 (descrsetfunc
)getset_set
, /* tp_descr_set */
452 PyTypeObject PyWrapperDescr_Type
= {
453 PyObject_HEAD_INIT(&PyType_Type
)
455 "wrapper_descriptor",
456 sizeof(PyWrapperDescrObject
),
458 (destructor
)descr_dealloc
, /* tp_dealloc */
463 (reprfunc
)wrapper_repr
, /* tp_repr */
464 0, /* tp_as_number */
465 0, /* tp_as_sequence */
466 0, /* tp_as_mapping */
468 (ternaryfunc
)wrapperdescr_call
, /* tp_call */
470 PyObject_GenericGetAttr
, /* tp_getattro */
472 0, /* tp_as_buffer */
473 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_GC
, /* tp_flags */
475 descr_traverse
, /* tp_traverse */
477 0, /* tp_richcompare */
478 0, /* tp_weaklistoffset */
482 descr_members
, /* tp_members */
483 wrapper_getset
, /* tp_getset */
486 (descrgetfunc
)wrapper_get
, /* tp_descr_get */
487 0, /* tp_descr_set */
490 static PyDescrObject
*
491 descr_new(PyTypeObject
*descrtype
, PyTypeObject
*type
, char *name
)
493 PyDescrObject
*descr
;
495 descr
= (PyDescrObject
*)PyType_GenericAlloc(descrtype
, 0);
498 descr
->d_type
= type
;
499 descr
->d_name
= PyString_InternFromString(name
);
500 if (descr
->d_name
== NULL
) {
509 PyDescr_NewMethod(PyTypeObject
*type
, PyMethodDef
*method
)
511 PyMethodDescrObject
*descr
;
513 descr
= (PyMethodDescrObject
*)descr_new(&PyMethodDescr_Type
,
514 type
, method
->ml_name
);
516 descr
->d_method
= method
;
517 return (PyObject
*)descr
;
521 PyDescr_NewMember(PyTypeObject
*type
, PyMemberDef
*member
)
523 PyMemberDescrObject
*descr
;
525 descr
= (PyMemberDescrObject
*)descr_new(&PyMemberDescr_Type
,
528 descr
->d_member
= member
;
529 return (PyObject
*)descr
;
533 PyDescr_NewGetSet(PyTypeObject
*type
, PyGetSetDef
*getset
)
535 PyGetSetDescrObject
*descr
;
537 descr
= (PyGetSetDescrObject
*)descr_new(&PyGetSetDescr_Type
,
540 descr
->d_getset
= getset
;
541 return (PyObject
*)descr
;
545 PyDescr_NewWrapper(PyTypeObject
*type
, struct wrapperbase
*base
, void *wrapped
)
547 PyWrapperDescrObject
*descr
;
549 descr
= (PyWrapperDescrObject
*)descr_new(&PyWrapperDescr_Type
,
552 descr
->d_base
= base
;
553 descr
->d_wrapped
= wrapped
;
555 return (PyObject
*)descr
;
559 PyDescr_IsData(PyObject
*d
)
561 return d
->ob_type
->tp_descr_set
!= NULL
;
565 /* --- Readonly proxy for dictionaries (actually any mapping) --- */
567 /* This has no reason to be in this file except that adding new files is a
576 proxy_len(proxyobject
*pp
)
578 return PyObject_Size(pp
->dict
);
582 proxy_getitem(proxyobject
*pp
, PyObject
*key
)
584 return PyObject_GetItem(pp
->dict
, key
);
587 static PyMappingMethods proxy_as_mapping
= {
588 (inquiry
)proxy_len
, /* mp_length */
589 (binaryfunc
)proxy_getitem
, /* mp_subscript */
590 0, /* mp_ass_subscript */
594 proxy_contains(proxyobject
*pp
, PyObject
*key
)
596 return PySequence_Contains(pp
->dict
, key
);
599 static PySequenceMethods proxy_as_sequence
= {
606 0, /* sq_ass_slice */
607 (objobjproc
)proxy_contains
, /* sq_contains */
608 0, /* sq_inplace_concat */
609 0, /* sq_inplace_repeat */
613 proxy_has_key(proxyobject
*pp
, PyObject
*key
)
615 return PyInt_FromLong(PySequence_Contains(pp
->dict
, key
));
619 proxy_get(proxyobject
*pp
, PyObject
*args
)
621 PyObject
*key
, *def
= Py_None
;
623 if (!PyArg_ParseTuple(args
, "O|O:get", &key
, &def
))
625 return PyObject_CallMethod(pp
->dict
, "get", "(OO)", key
, def
);
629 proxy_keys(proxyobject
*pp
)
631 return PyMapping_Keys(pp
->dict
);
635 proxy_values(proxyobject
*pp
)
637 return PyMapping_Values(pp
->dict
);
641 proxy_items(proxyobject
*pp
)
643 return PyMapping_Items(pp
->dict
);
647 proxy_copy(proxyobject
*pp
)
649 return PyObject_CallMethod(pp
->dict
, "copy", NULL
);
652 static PyMethodDef proxy_methods
[] = {
653 {"has_key", (PyCFunction
)proxy_has_key
, METH_O
, "XXX"},
654 {"get", (PyCFunction
)proxy_get
, METH_VARARGS
, "XXX"},
655 {"keys", (PyCFunction
)proxy_keys
, METH_NOARGS
, "XXX"},
656 {"values", (PyCFunction
)proxy_values
, METH_NOARGS
, "XXX"},
657 {"items", (PyCFunction
)proxy_items
, METH_NOARGS
, "XXX"},
658 {"copy", (PyCFunction
)proxy_copy
, METH_NOARGS
, "XXX"},
663 proxy_dealloc(proxyobject
*pp
)
665 _PyObject_GC_UNTRACK(pp
);
671 proxy_getiter(proxyobject
*pp
)
673 return PyObject_GetIter(pp
->dict
);
677 proxy_str(proxyobject
*pp
)
679 return PyObject_Str(pp
->dict
);
683 proxy_traverse(PyObject
*self
, visitproc visit
, void *arg
)
685 proxyobject
*pp
= (proxyobject
*)self
;
689 err
= visit(pp
->dict
, arg
);
696 static PyTypeObject proxytype
= {
697 PyObject_HEAD_INIT(&PyType_Type
)
699 "dict-proxy", /* tp_name */
700 sizeof(proxyobject
), /* tp_basicsize */
703 (destructor
)proxy_dealloc
, /* tp_dealloc */
709 0, /* tp_as_number */
710 &proxy_as_sequence
, /* tp_as_sequence */
711 &proxy_as_mapping
, /* tp_as_mapping */
714 (reprfunc
)proxy_str
, /* tp_str */
715 PyObject_GenericGetAttr
, /* tp_getattro */
717 0, /* tp_as_buffer */
718 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_GC
, /* tp_flags */
720 proxy_traverse
, /* tp_traverse */
722 0, /* tp_richcompare */
723 0, /* tp_weaklistoffset */
724 (getiterfunc
)proxy_getiter
, /* tp_iter */
726 proxy_methods
, /* tp_methods */
731 0, /* tp_descr_get */
732 0, /* tp_descr_set */
736 PyDictProxy_New(PyObject
*dict
)
740 pp
= PyObject_GC_New(proxyobject
, &proxytype
);
744 _PyObject_GC_TRACK(pp
);
746 return (PyObject
*)pp
;
750 /* --- Wrapper object for "slot" methods --- */
752 /* This has no reason to be in this file except that adding new files is a
757 PyWrapperDescrObject
*descr
;
762 wrapper_dealloc(wrapperobject
*wp
)
764 _PyObject_GC_UNTRACK(wp
);
765 Py_XDECREF(wp
->descr
);
766 Py_XDECREF(wp
->self
);
770 static PyMethodDef wrapper_methods
[] = {
775 wrapper_name(wrapperobject
*wp
)
777 char *s
= wp
->descr
->d_base
->name
;
779 return PyString_FromString(s
);
783 wrapper_doc(wrapperobject
*wp
)
785 char *s
= wp
->descr
->d_base
->doc
;
792 return PyString_FromString(s
);
796 static PyGetSetDef wrapper_getsets
[] = {
797 {"__name__", (getter
)wrapper_name
},
798 {"__doc__", (getter
)wrapper_doc
},
803 wrapper_call(wrapperobject
*wp
, PyObject
*args
, PyObject
*kwds
)
805 wrapperfunc wrapper
= wp
->descr
->d_base
->wrapper
;
806 PyObject
*self
= wp
->self
;
808 if (wp
->descr
->d_base
->flags
& PyWrapperFlag_KEYWORDS
) {
809 wrapperfunc_kwds wk
= (wrapperfunc_kwds
)wrapper
;
810 return (*wk
)(self
, args
, wp
->descr
->d_wrapped
, kwds
);
813 if (kwds
!= NULL
&& (!PyDict_Check(kwds
) || PyDict_Size(kwds
) != 0)) {
814 PyErr_Format(PyExc_TypeError
,
815 "wrapper %s doesn't take keyword arguments",
816 wp
->descr
->d_base
->name
);
819 return (*wrapper
)(self
, args
, wp
->descr
->d_wrapped
);
823 wrapper_traverse(PyObject
*self
, visitproc visit
, void *arg
)
825 wrapperobject
*wp
= (wrapperobject
*)self
;
829 err
= visit((PyObject
*)(wp
->descr
), arg
);
834 err
= visit(wp
->self
, arg
);
841 static PyTypeObject wrappertype
= {
842 PyObject_HEAD_INIT(&PyType_Type
)
844 "method-wrapper", /* tp_name */
845 sizeof(wrapperobject
), /* tp_basicsize */
848 (destructor
)wrapper_dealloc
, /* tp_dealloc */
854 0, /* tp_as_number */
855 0, /* tp_as_sequence */
856 0, /* tp_as_mapping */
858 (ternaryfunc
)wrapper_call
, /* tp_call */
860 PyObject_GenericGetAttr
, /* tp_getattro */
862 0, /* tp_as_buffer */
863 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_GC
, /* tp_flags */
865 wrapper_traverse
, /* tp_traverse */
867 0, /* tp_richcompare */
868 0, /* tp_weaklistoffset */
871 wrapper_methods
, /* tp_methods */
873 wrapper_getsets
, /* tp_getset */
876 0, /* tp_descr_get */
877 0, /* tp_descr_set */
881 PyWrapper_New(PyObject
*d
, PyObject
*self
)
884 PyWrapperDescrObject
*descr
;
886 assert(PyObject_TypeCheck(d
, &PyWrapperDescr_Type
));
887 descr
= (PyWrapperDescrObject
*)d
;
888 assert(PyObject_IsInstance(self
, (PyObject
*)(descr
->d_type
)));
890 wp
= PyObject_GC_New(wrapperobject
, &wrappertype
);
896 _PyObject_GC_TRACK(wp
);
898 return (PyObject
*)wp
;
902 /* A built-in 'property' type */
905 class property(object):
907 def __init__(self, fget=None, fset=None, fdel=None, doc=None):
913 def __get__(self, inst, type=None):
916 if self.__get is None:
917 raise AttributeError, "unreadable attribute"
918 return self.__get(inst)
920 def __set__(self, inst, value):
921 if self.__set is None:
922 raise AttributeError, "can't set attribute"
923 return self.__set(inst, value)
925 def __delete__(self, inst):
926 if self.__del is None:
927 raise AttributeError, "can't delete attribute"
928 return self.__del(inst)
940 static PyMemberDef property_members
[] = {
941 {"fget", T_OBJECT
, offsetof(propertyobject
, prop_get
), READONLY
},
942 {"fset", T_OBJECT
, offsetof(propertyobject
, prop_set
), READONLY
},
943 {"fdel", T_OBJECT
, offsetof(propertyobject
, prop_del
), READONLY
},
944 {"__doc__", T_OBJECT
, offsetof(propertyobject
, prop_doc
), READONLY
},
950 property_dealloc(PyObject
*self
)
952 propertyobject
*gs
= (propertyobject
*)self
;
954 _PyObject_GC_UNTRACK(self
);
955 Py_XDECREF(gs
->prop_get
);
956 Py_XDECREF(gs
->prop_set
);
957 Py_XDECREF(gs
->prop_del
);
958 Py_XDECREF(gs
->prop_doc
);
959 self
->ob_type
->tp_free(self
);
963 property_descr_get(PyObject
*self
, PyObject
*obj
, PyObject
*type
)
965 propertyobject
*gs
= (propertyobject
*)self
;
967 if (obj
== NULL
|| obj
== Py_None
) {
971 if (gs
->prop_get
== NULL
) {
972 PyErr_SetString(PyExc_AttributeError
, "unreadable attribute");
975 return PyObject_CallFunction(gs
->prop_get
, "(O)", obj
);
979 property_descr_set(PyObject
*self
, PyObject
*obj
, PyObject
*value
)
981 propertyobject
*gs
= (propertyobject
*)self
;
982 PyObject
*func
, *res
;
989 PyErr_SetString(PyExc_AttributeError
,
991 "can't delete attribute" :
992 "can't set attribute");
996 res
= PyObject_CallFunction(func
, "(O)", obj
);
998 res
= PyObject_CallFunction(func
, "(OO)", obj
, value
);
1006 property_init(PyObject
*self
, PyObject
*args
, PyObject
*kwds
)
1008 PyObject
*get
= NULL
, *set
= NULL
, *del
= NULL
, *doc
= NULL
;
1009 static char *kwlist
[] = {"fget", "fset", "fdel", "doc", 0};
1010 propertyobject
*gs
= (propertyobject
*)self
;
1012 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "|OOOO:property",
1013 kwlist
, &get
, &set
, &del
, &doc
))
1036 static char property_doc
[] =
1037 "property(fget=None, fset=None, fdel=None, doc=None) -> property attribute\n"
1039 "fget is a function to be used for getting an attribute value, and likewise\n"
1040 "fset is a function for setting, and fdel a function for del'ing, an\n"
1041 "attribute. Typical use is to define a managed attribute x:\n"
1042 "class C(object):\n"
1043 " def getx(self): return self.__x\n"
1044 " def setx(self, value): self.__x = value\n"
1045 " def delx(self): del self.__x\n"
1046 " x = property(getx, setx, delx, \"I'm the 'x' property.\")";
1049 property_traverse(PyObject
*self
, visitproc visit
, void *arg
)
1051 propertyobject
*pp
= (propertyobject
*)self
;
1054 #define VISIT(SLOT) \
1056 err = visit((PyObject *)(pp->SLOT), arg); \
1068 PyTypeObject PyProperty_Type
= {
1069 PyObject_HEAD_INIT(&PyType_Type
)
1071 "property", /* tp_name */
1072 sizeof(propertyobject
), /* tp_basicsize */
1073 0, /* tp_itemsize */
1075 property_dealloc
, /* tp_dealloc */
1081 0, /* tp_as_number */
1082 0, /* tp_as_sequence */
1083 0, /* tp_as_mapping */
1087 PyObject_GenericGetAttr
, /* tp_getattro */
1088 0, /* tp_setattro */
1089 0, /* tp_as_buffer */
1090 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_GC
|
1091 Py_TPFLAGS_BASETYPE
, /* tp_flags */
1092 property_doc
, /* tp_doc */
1093 property_traverse
, /* tp_traverse */
1095 0, /* tp_richcompare */
1096 0, /* tp_weaklistoffset */
1098 0, /* tp_iternext */
1100 property_members
, /* tp_members */
1104 property_descr_get
, /* tp_descr_get */
1105 property_descr_set
, /* tp_descr_set */
1106 0, /* tp_dictoffset */
1107 property_init
, /* tp_init */
1108 PyType_GenericAlloc
, /* tp_alloc */
1109 PyType_GenericNew
, /* tp_new */
1110 _PyObject_GC_Del
, /* tp_free */