blob: 2cb28b3a0f25346ba3fb2728574989a86297c651 [file] [log] [blame]
Tim Peters6d6c1a32001-08-02 04:15:00 +00001/* Descriptors -- a new, flexible way to describe attributes */
2
3#include "Python.h"
4#include "structmember.h" /* Why is this not included in Python.h? */
5
6/* Various kinds of descriptor objects */
7
8#define COMMON \
9 PyObject_HEAD \
10 PyTypeObject *d_type; \
11 PyObject *d_name
12
13typedef struct {
14 COMMON;
15} PyDescrObject;
16
17typedef struct {
18 COMMON;
19 PyMethodDef *d_method;
20} PyMethodDescrObject;
21
22typedef struct {
23 COMMON;
24 struct memberlist *d_member;
25} PyMemberDescrObject;
26
27typedef struct {
28 COMMON;
29 struct getsetlist *d_getset;
30} PyGetSetDescrObject;
31
32typedef struct {
33 COMMON;
34 struct wrapperbase *d_base;
35 void *d_wrapped; /* This can be any function pointer */
36} PyWrapperDescrObject;
37
38static void
39descr_dealloc(PyDescrObject *descr)
40{
41 Py_XDECREF(descr->d_type);
42 Py_XDECREF(descr->d_name);
43 PyObject_DEL(descr);
44}
45
46static char *
47descr_name(PyDescrObject *descr)
48{
49 if (descr->d_name != NULL && PyString_Check(descr->d_name))
50 return PyString_AS_STRING(descr->d_name);
51 else
52 return "?";
53}
54
55static PyObject *
56descr_repr(PyDescrObject *descr, char *format)
57{
58 char buffer[500];
59
60 sprintf(buffer, format, descr_name(descr), descr->d_type->tp_name);
61 return PyString_FromString(buffer);
62}
63
64static PyObject *
65method_repr(PyMethodDescrObject *descr)
66{
67 return descr_repr((PyDescrObject *)descr,
68 "<method '%.300s' of '%.100s' objects>");
69}
70
71static PyObject *
72member_repr(PyMemberDescrObject *descr)
73{
74 return descr_repr((PyDescrObject *)descr,
75 "<member '%.300s' of '%.100s' objects>");
76}
77
78static PyObject *
79getset_repr(PyGetSetDescrObject *descr)
80{
81 return descr_repr((PyDescrObject *)descr,
82 "<attribute '%.300s' of '%.100s' objects>");
83}
84
85static PyObject *
86wrapper_repr(PyWrapperDescrObject *descr)
87{
88 return descr_repr((PyDescrObject *)descr,
89 "<slot wrapper '%.300s' of '%.100s' objects>");
90}
91
92static int
93descr_check(PyDescrObject *descr, PyObject *obj, PyTypeObject *type,
Guido van Rossum8098ddb2001-08-16 08:27:33 +000094 PyObject **pres)
Tim Peters6d6c1a32001-08-02 04:15:00 +000095{
Guido van Rossum8098ddb2001-08-16 08:27:33 +000096 if (obj == NULL || (obj == Py_None && type != Py_None->ob_type)) {
Tim Peters6d6c1a32001-08-02 04:15:00 +000097 Py_INCREF(descr);
98 *pres = (PyObject *)descr;
99 return 1;
100 }
101 if (!PyObject_IsInstance(obj, (PyObject *)(descr->d_type))) {
102 PyErr_Format(PyExc_TypeError,
103 "descriptor '%.200s' for '%.100s' objects "
104 "doesn't apply to '%.100s' object",
105 descr_name((PyDescrObject *)descr),
106 descr->d_type->tp_name,
107 obj->ob_type->tp_name);
108 *pres = NULL;
109 return 1;
110 }
111 return 0;
112}
113
114static PyObject *
115method_get(PyMethodDescrObject *descr, PyObject *obj, PyTypeObject *type)
116{
117 PyObject *res;
118
119 if (descr_check((PyDescrObject *)descr, obj, type, &res))
120 return res;
121 return PyCFunction_New(descr->d_method, obj);
122}
123
124static PyObject *
125member_get(PyMemberDescrObject *descr, PyObject *obj, PyTypeObject *type)
126{
127 PyObject *res;
128
129 if (descr_check((PyDescrObject *)descr, obj, type, &res))
130 return res;
131 return PyMember_Get((char *)obj, descr->d_member,
132 descr->d_member->name);
133}
134
135static PyObject *
136getset_get(PyGetSetDescrObject *descr, PyObject *obj, PyTypeObject *type)
137{
138 PyObject *res;
139
140 if (descr_check((PyDescrObject *)descr, obj, type, &res))
141 return res;
142 if (descr->d_getset->get != NULL)
143 return descr->d_getset->get(obj, descr->d_getset->closure);
144 PyErr_Format(PyExc_TypeError,
145 "attribute '%300s' of '%.100s' objects is not readable",
146 descr_name((PyDescrObject *)descr),
147 descr->d_type->tp_name);
148 return NULL;
149}
150
151static PyObject *
152wrapper_get(PyWrapperDescrObject *descr, PyObject *obj, PyTypeObject *type)
153{
154 PyObject *res;
155
156 if (descr_check((PyDescrObject *)descr, obj, type, &res))
157 return res;
158 return PyWrapper_New((PyObject *)descr, obj);
159}
160
161static int
162descr_setcheck(PyDescrObject *descr, PyObject *obj, PyObject *value,
163 int *pres)
164{
165 assert(obj != NULL);
166 if (!PyObject_IsInstance(obj, (PyObject *)(descr->d_type))) {
167 PyErr_Format(PyExc_TypeError,
168 "descriptor '%.200s' for '%.100s' objects "
169 "doesn't apply to '%.100s' object",
170 descr_name(descr),
171 descr->d_type->tp_name,
172 obj->ob_type->tp_name);
173 *pres = -1;
174 return 1;
175 }
176 return 0;
177}
178
179static int
180member_set(PyMemberDescrObject *descr, PyObject *obj, PyObject *value)
181{
182 int res;
183
184 if (descr_setcheck((PyDescrObject *)descr, obj, value, &res))
185 return res;
186 return PyMember_Set((char *)obj, descr->d_member,
187 descr->d_member->name, value);
188}
189
190static int
191getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value)
192{
193 int res;
194
195 if (descr_setcheck((PyDescrObject *)descr, obj, value, &res))
196 return res;
197 if (descr->d_getset->set != NULL)
198 return descr->d_getset->set(obj, value,
199 descr->d_getset->closure);
200 PyErr_Format(PyExc_TypeError,
201 "attribute '%300s' of '%.100s' objects is not writable",
202 descr_name((PyDescrObject *)descr),
203 descr->d_type->tp_name);
204 return -1;
205}
206
207static PyObject *
208methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwds)
209{
210 int argc;
211 PyObject *self, *func, *result;
212
213 /* Make sure that the first argument is acceptable as 'self' */
214 assert(PyTuple_Check(args));
215 argc = PyTuple_GET_SIZE(args);
216 if (argc < 1) {
217 PyErr_Format(PyExc_TypeError,
218 "descriptor '%.300s' of '%.100s' "
219 "object needs an argument",
220 descr_name((PyDescrObject *)descr),
221 descr->d_type->tp_name);
222 return NULL;
223 }
224 self = PyTuple_GET_ITEM(args, 0);
225 if (!PyObject_IsInstance(self, (PyObject *)(descr->d_type))) {
226 PyErr_Format(PyExc_TypeError,
227 "descriptor '%.200s' "
228 "requires a '%.100s' object "
229 "but received a '%.100s'",
230 descr_name((PyDescrObject *)descr),
231 descr->d_type->tp_name,
232 self->ob_type->tp_name);
233 return NULL;
234 }
235
236 func = PyCFunction_New(descr->d_method, self);
237 if (func == NULL)
238 return NULL;
239 args = PyTuple_GetSlice(args, 1, argc);
240 if (args == NULL) {
241 Py_DECREF(func);
242 return NULL;
243 }
244 result = PyEval_CallObjectWithKeywords(func, args, kwds);
245 Py_DECREF(args);
246 Py_DECREF(func);
247 return result;
248}
249
250static PyObject *
251wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
252{
253 int argc;
254 PyObject *self, *func, *result;
255
256 /* Make sure that the first argument is acceptable as 'self' */
257 assert(PyTuple_Check(args));
258 argc = PyTuple_GET_SIZE(args);
259 if (argc < 1) {
260 PyErr_Format(PyExc_TypeError,
261 "descriptor '%.300s' of '%.100s' "
262 "object needs an argument",
263 descr_name((PyDescrObject *)descr),
264 descr->d_type->tp_name);
265 return NULL;
266 }
267 self = PyTuple_GET_ITEM(args, 0);
268 if (!PyObject_IsInstance(self, (PyObject *)(descr->d_type))) {
269 PyErr_Format(PyExc_TypeError,
270 "descriptor '%.200s' "
271 "requires a '%.100s' object "
272 "but received a '%.100s'",
273 descr_name((PyDescrObject *)descr),
274 descr->d_type->tp_name,
275 self->ob_type->tp_name);
276 return NULL;
277 }
278
279 func = PyWrapper_New((PyObject *)descr, self);
280 if (func == NULL)
281 return NULL;
282 args = PyTuple_GetSlice(args, 1, argc);
283 if (args == NULL) {
284 Py_DECREF(func);
285 return NULL;
286 }
287 result = PyEval_CallObjectWithKeywords(func, args, kwds);
288 Py_DECREF(args);
289 Py_DECREF(func);
290 return result;
291}
292
293static PyObject *
294member_get_doc(PyMethodDescrObject *descr, void *closure)
295{
296 if (descr->d_method->ml_doc == NULL) {
297 Py_INCREF(Py_None);
298 return Py_None;
299 }
300 return PyString_FromString(descr->d_method->ml_doc);
301}
302
303static struct memberlist descr_members[] = {
304 {"__objclass__", T_OBJECT, offsetof(PyDescrObject, d_type), READONLY},
305 {"__name__", T_OBJECT, offsetof(PyDescrObject, d_name), READONLY},
306 {0}
307};
308
309static struct getsetlist member_getset[] = {
310 {"__doc__", (getter)member_get_doc},
311 {0}
312};
313
314static PyObject *
315wrapper_get_doc(PyWrapperDescrObject *descr, void *closure)
316{
317 if (descr->d_base->doc == NULL) {
318 Py_INCREF(Py_None);
319 return Py_None;
320 }
321 return PyString_FromString(descr->d_base->doc);
322}
323
324static struct getsetlist wrapper_getset[] = {
325 {"__doc__", (getter)wrapper_get_doc},
326 {0}
327};
328
329static PyTypeObject PyMethodDescr_Type = {
330 PyObject_HEAD_INIT(&PyType_Type)
331 0,
332 "method_descriptor",
333 sizeof(PyMethodDescrObject),
334 0,
335 (destructor)descr_dealloc, /* tp_dealloc */
336 0, /* tp_print */
337 0, /* tp_getattr */
338 0, /* tp_setattr */
339 0, /* tp_compare */
340 (reprfunc)method_repr, /* tp_repr */
341 0, /* tp_as_number */
342 0, /* tp_as_sequence */
343 0, /* tp_as_mapping */
344 0, /* tp_hash */
345 (ternaryfunc)methoddescr_call, /* tp_call */
346 0, /* tp_str */
347 PyObject_GenericGetAttr, /* tp_getattro */
348 0, /* tp_setattro */
349 0, /* tp_as_buffer */
350 Py_TPFLAGS_DEFAULT, /* tp_flags */
351 0, /* tp_doc */
352 0, /* tp_traverse */
353 0, /* tp_clear */
354 0, /* tp_richcompare */
355 0, /* tp_weaklistoffset */
356 0, /* tp_iter */
357 0, /* tp_iternext */
358 0, /* tp_methods */
359 descr_members, /* tp_members */
360 member_getset, /* tp_getset */
361 0, /* tp_base */
362 0, /* tp_dict */
363 (descrgetfunc)method_get, /* tp_descr_get */
364 0, /* tp_descr_set */
365};
366
367static PyTypeObject PyMemberDescr_Type = {
368 PyObject_HEAD_INIT(&PyType_Type)
369 0,
370 "member_descriptor",
371 sizeof(PyMemberDescrObject),
372 0,
373 (destructor)descr_dealloc, /* tp_dealloc */
374 0, /* tp_print */
375 0, /* tp_getattr */
376 0, /* tp_setattr */
377 0, /* tp_compare */
378 (reprfunc)member_repr, /* tp_repr */
379 0, /* tp_as_number */
380 0, /* tp_as_sequence */
381 0, /* tp_as_mapping */
382 0, /* tp_hash */
383 (ternaryfunc)0, /* tp_call */
384 0, /* tp_str */
385 PyObject_GenericGetAttr, /* tp_getattro */
386 0, /* tp_setattro */
387 0, /* tp_as_buffer */
388 Py_TPFLAGS_DEFAULT, /* tp_flags */
389 0, /* tp_doc */
390 0, /* tp_traverse */
391 0, /* tp_clear */
392 0, /* tp_richcompare */
393 0, /* tp_weaklistoffset */
394 0, /* tp_iter */
395 0, /* tp_iternext */
396 0, /* tp_methods */
397 descr_members, /* tp_members */
398 0, /* tp_getset */
399 0, /* tp_base */
400 0, /* tp_dict */
401 (descrgetfunc)member_get, /* tp_descr_get */
402 (descrsetfunc)member_set, /* tp_descr_set */
403};
404
405static PyTypeObject PyGetSetDescr_Type = {
406 PyObject_HEAD_INIT(&PyType_Type)
407 0,
408 "getset_descriptor",
409 sizeof(PyGetSetDescrObject),
410 0,
411 (destructor)descr_dealloc, /* tp_dealloc */
412 0, /* tp_print */
413 0, /* tp_getattr */
414 0, /* tp_setattr */
415 0, /* tp_compare */
416 (reprfunc)getset_repr, /* tp_repr */
417 0, /* tp_as_number */
418 0, /* tp_as_sequence */
419 0, /* tp_as_mapping */
420 0, /* tp_hash */
421 (ternaryfunc)0, /* tp_call */
422 0, /* tp_str */
423 PyObject_GenericGetAttr, /* tp_getattro */
424 0, /* tp_setattro */
425 0, /* tp_as_buffer */
426 Py_TPFLAGS_DEFAULT, /* tp_flags */
427 0, /* tp_doc */
428 0, /* tp_traverse */
429 0, /* tp_clear */
430 0, /* tp_richcompare */
431 0, /* tp_weaklistoffset */
432 0, /* tp_iter */
433 0, /* tp_iternext */
434 0, /* tp_methods */
435 descr_members, /* tp_members */
436 0, /* tp_getset */
437 0, /* tp_base */
438 0, /* tp_dict */
439 (descrgetfunc)getset_get, /* tp_descr_get */
440 (descrsetfunc)getset_set, /* tp_descr_set */
441};
442
443static PyTypeObject PyWrapperDescr_Type = {
444 PyObject_HEAD_INIT(&PyType_Type)
445 0,
446 "wrapper_descriptor",
447 sizeof(PyWrapperDescrObject),
448 0,
449 (destructor)descr_dealloc, /* tp_dealloc */
450 0, /* tp_print */
451 0, /* tp_getattr */
452 0, /* tp_setattr */
453 0, /* tp_compare */
454 (reprfunc)wrapper_repr, /* tp_repr */
455 0, /* tp_as_number */
456 0, /* tp_as_sequence */
457 0, /* tp_as_mapping */
458 0, /* tp_hash */
459 (ternaryfunc)wrapperdescr_call, /* tp_call */
460 0, /* tp_str */
461 PyObject_GenericGetAttr, /* tp_getattro */
462 0, /* tp_setattro */
463 0, /* tp_as_buffer */
464 Py_TPFLAGS_DEFAULT, /* tp_flags */
465 0, /* tp_doc */
466 0, /* tp_traverse */
467 0, /* tp_clear */
468 0, /* tp_richcompare */
469 0, /* tp_weaklistoffset */
470 0, /* tp_iter */
471 0, /* tp_iternext */
472 0, /* tp_methods */
473 descr_members, /* tp_members */
474 wrapper_getset, /* tp_getset */
475 0, /* tp_base */
476 0, /* tp_dict */
477 (descrgetfunc)wrapper_get, /* tp_descr_get */
478 0, /* tp_descr_set */
479};
480
481static PyDescrObject *
482descr_new(PyTypeObject *descrtype, PyTypeObject *type, char *name)
483{
484 PyDescrObject *descr;
485
486 descr = (PyDescrObject *)PyType_GenericAlloc(descrtype, 0);
487 if (descr != NULL) {
488 Py_XINCREF(type);
489 descr->d_type = type;
490 descr->d_name = PyString_InternFromString(name);
491 if (descr->d_name == NULL) {
492 Py_DECREF(descr);
493 descr = NULL;
494 }
495 }
496 return descr;
497}
498
499PyObject *
500PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method)
501{
502 PyMethodDescrObject *descr;
503
504 descr = (PyMethodDescrObject *)descr_new(&PyMethodDescr_Type,
505 type, method->ml_name);
506 if (descr != NULL)
507 descr->d_method = method;
508 return (PyObject *)descr;
509}
510
511PyObject *
512PyDescr_NewMember(PyTypeObject *type, struct memberlist *member)
513{
514 PyMemberDescrObject *descr;
515
516 descr = (PyMemberDescrObject *)descr_new(&PyMemberDescr_Type,
517 type, member->name);
518 if (descr != NULL)
519 descr->d_member = member;
520 return (PyObject *)descr;
521}
522
523PyObject *
524PyDescr_NewGetSet(PyTypeObject *type, struct getsetlist *getset)
525{
526 PyGetSetDescrObject *descr;
527
528 descr = (PyGetSetDescrObject *)descr_new(&PyGetSetDescr_Type,
529 type, getset->name);
530 if (descr != NULL)
531 descr->d_getset = getset;
532 return (PyObject *)descr;
533}
534
535PyObject *
536PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped)
537{
538 PyWrapperDescrObject *descr;
539
540 descr = (PyWrapperDescrObject *)descr_new(&PyWrapperDescr_Type,
541 type, base->name);
542 if (descr != NULL) {
543 descr->d_base = base;
544 descr->d_wrapped = wrapped;
545 }
546 return (PyObject *)descr;
547}
548
549int
550PyDescr_IsData(PyObject *d)
551{
552 return d->ob_type->tp_descr_set != NULL;
553}
554
555
556/* --- Readonly proxy for dictionaries (actually any mapping) --- */
557
558/* This has no reason to be in this file except that adding new files is a
559 bit of a pain */
560
561typedef struct {
562 PyObject_HEAD
563 PyObject *dict;
564} proxyobject;
565
566static int
567proxy_len(proxyobject *pp)
568{
569 return PyObject_Size(pp->dict);
570}
571
572static PyObject *
573proxy_getitem(proxyobject *pp, PyObject *key)
574{
575 return PyObject_GetItem(pp->dict, key);
576}
577
578static PyMappingMethods proxy_as_mapping = {
579 (inquiry)proxy_len, /* mp_length */
580 (binaryfunc)proxy_getitem, /* mp_subscript */
581 0, /* mp_ass_subscript */
582};
583
584static int
585proxy_contains(proxyobject *pp, PyObject *key)
586{
587 return PySequence_Contains(pp->dict, key);
588}
589
590static PySequenceMethods proxy_as_sequence = {
591 0, /* sq_length */
592 0, /* sq_concat */
593 0, /* sq_repeat */
594 0, /* sq_item */
595 0, /* sq_slice */
596 0, /* sq_ass_item */
597 0, /* sq_ass_slice */
598 (objobjproc)proxy_contains, /* sq_contains */
599 0, /* sq_inplace_concat */
600 0, /* sq_inplace_repeat */
601};
602
603static PyObject *
Martin v. Löwise3eb1f22001-08-16 13:15:00 +0000604proxy_has_key(proxyobject *pp, PyObject *key)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000605{
Tim Peters6d6c1a32001-08-02 04:15:00 +0000606 return PyInt_FromLong(PySequence_Contains(pp->dict, key));
607}
608
609static PyObject *
610proxy_get(proxyobject *pp, PyObject *args)
611{
612 PyObject *key, *def = Py_None;
613
614 if (!PyArg_ParseTuple(args, "O|O:get", &key, &def))
615 return NULL;
616 return PyObject_CallMethod(pp->dict, "get", "(OO)", key, def);
617}
618
619static PyObject *
Martin v. Löwise3eb1f22001-08-16 13:15:00 +0000620proxy_keys(proxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000621{
Tim Peters6d6c1a32001-08-02 04:15:00 +0000622 return PyMapping_Keys(pp->dict);
623}
624
625static PyObject *
Martin v. Löwise3eb1f22001-08-16 13:15:00 +0000626proxy_values(proxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000627{
Tim Peters6d6c1a32001-08-02 04:15:00 +0000628 return PyMapping_Values(pp->dict);
629}
630
631static PyObject *
Martin v. Löwise3eb1f22001-08-16 13:15:00 +0000632proxy_items(proxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000633{
Tim Peters6d6c1a32001-08-02 04:15:00 +0000634 return PyMapping_Items(pp->dict);
635}
636
637static PyObject *
Martin v. Löwise3eb1f22001-08-16 13:15:00 +0000638proxy_copy(proxyobject *pp)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000639{
Tim Peters6d6c1a32001-08-02 04:15:00 +0000640 return PyObject_CallMethod(pp->dict, "copy", NULL);
641}
642
643static PyMethodDef proxy_methods[] = {
Martin v. Löwise3eb1f22001-08-16 13:15:00 +0000644 {"has_key", (PyCFunction)proxy_has_key, METH_O, "XXX"},
Tim Peters6d6c1a32001-08-02 04:15:00 +0000645 {"get", (PyCFunction)proxy_get, METH_VARARGS, "XXX"},
Martin v. Löwise3eb1f22001-08-16 13:15:00 +0000646 {"keys", (PyCFunction)proxy_keys, METH_NOARGS, "XXX"},
647 {"values", (PyCFunction)proxy_values, METH_NOARGS, "XXX"},
648 {"items", (PyCFunction)proxy_items, METH_NOARGS, "XXX"},
649 {"copy", (PyCFunction)proxy_copy, METH_NOARGS, "XXX"},
Tim Peters6d6c1a32001-08-02 04:15:00 +0000650 {0}
651};
652
653static void
654proxy_dealloc(proxyobject *pp)
655{
656 Py_DECREF(pp->dict);
657 PyObject_DEL(pp);
658}
659
660static PyObject *
661proxy_getiter(proxyobject *pp)
662{
663 return PyObject_GetIter(pp->dict);
664}
665
666PyObject *
667proxy_str(proxyobject *pp)
668{
669 return PyObject_Str(pp->dict);
670}
671
672PyTypeObject proxytype = {
673 PyObject_HEAD_INIT(&PyType_Type)
674 0, /* ob_size */
675 "dict-proxy", /* tp_name */
676 sizeof(proxyobject), /* tp_basicsize */
677 0, /* tp_itemsize */
678 /* methods */
679 (destructor)proxy_dealloc, /* tp_dealloc */
680 0, /* tp_print */
681 0, /* tp_getattr */
682 0, /* tp_setattr */
683 0, /* tp_compare */
684 0, /* tp_repr */
685 0, /* tp_as_number */
686 &proxy_as_sequence, /* tp_as_sequence */
687 &proxy_as_mapping, /* tp_as_mapping */
688 0, /* tp_hash */
689 0, /* tp_call */
690 (reprfunc)proxy_str, /* tp_str */
691 PyObject_GenericGetAttr, /* tp_getattro */
692 0, /* tp_setattro */
693 0, /* tp_as_buffer */
694 Py_TPFLAGS_DEFAULT, /* tp_flags */
695 0, /* tp_doc */
696 0, /* tp_traverse */
697 0, /* tp_clear */
698 0, /* tp_richcompare */
699 0, /* tp_weaklistoffset */
700 (getiterfunc)proxy_getiter, /* tp_iter */
701 0, /* tp_iternext */
702 proxy_methods, /* tp_methods */
703 0, /* tp_members */
704 0, /* tp_getset */
705 0, /* tp_base */
706 0, /* tp_dict */
707 0, /* tp_descr_get */
708 0, /* tp_descr_set */
709};
710
711PyObject *
712PyDictProxy_New(PyObject *dict)
713{
714 proxyobject *pp;
715
716 pp = PyObject_NEW(proxyobject, &proxytype);
717 if (pp != NULL) {
718 Py_INCREF(dict);
719 pp->dict = dict;
720 }
721 return (PyObject *)pp;
722}
723
724
725/* --- Wrapper object for "slot" methods --- */
726
727/* This has no reason to be in this file except that adding new files is a
728 bit of a pain */
729
730typedef struct {
731 PyObject_HEAD
732 PyWrapperDescrObject *descr;
733 PyObject *self;
734} wrapperobject;
735
736static void
737wrapper_dealloc(wrapperobject *wp)
738{
739 Py_XDECREF(wp->descr);
740 Py_XDECREF(wp->self);
741 PyObject_DEL(wp);
742}
743
744static PyMethodDef wrapper_methods[] = {
745 {0}
746};
747
748static PyObject *
749wrapper_name(wrapperobject *wp)
750{
751 char *s = wp->descr->d_base->name;
752
753 return PyString_FromString(s);
754}
755
756static PyObject *
757wrapper_doc(wrapperobject *wp)
758{
759 char *s = wp->descr->d_base->doc;
760
761 if (s == NULL) {
762 Py_INCREF(Py_None);
763 return Py_None;
764 }
765 else {
766 return PyString_FromString(s);
767 }
768}
769
770static struct getsetlist wrapper_getsets[] = {
771 {"__name__", (getter)wrapper_name},
772 {"__doc__", (getter)wrapper_doc},
773 {0}
774};
775
776static PyObject *
777wrapper_call(wrapperobject *wp, PyObject *args, PyObject *kwds)
778{
779 wrapperfunc wrapper = wp->descr->d_base->wrapper;
780 PyObject *self = wp->self;
781
782 return (*wrapper)(self, args, wp->descr->d_wrapped);
783}
784
785PyTypeObject wrappertype = {
786 PyObject_HEAD_INIT(&PyType_Type)
787 0, /* ob_size */
788 "method-wrapper", /* tp_name */
789 sizeof(wrapperobject), /* tp_basicsize */
790 0, /* tp_itemsize */
791 /* methods */
792 (destructor)wrapper_dealloc, /* tp_dealloc */
793 0, /* tp_print */
794 0, /* tp_getattr */
795 0, /* tp_setattr */
796 0, /* tp_compare */
797 0, /* tp_repr */
798 0, /* tp_as_number */
799 0, /* tp_as_sequence */
800 0, /* tp_as_mapping */
801 0, /* tp_hash */
802 (ternaryfunc)wrapper_call, /* tp_call */
803 0, /* tp_str */
804 PyObject_GenericGetAttr, /* tp_getattro */
805 0, /* tp_setattro */
806 0, /* tp_as_buffer */
807 Py_TPFLAGS_DEFAULT, /* tp_flags */
808 0, /* tp_doc */
809 0, /* tp_traverse */
810 0, /* tp_clear */
811 0, /* tp_richcompare */
812 0, /* tp_weaklistoffset */
813 0, /* tp_iter */
814 0, /* tp_iternext */
815 wrapper_methods, /* tp_methods */
816 0, /* tp_members */
817 wrapper_getsets, /* tp_getset */
818 0, /* tp_base */
819 0, /* tp_dict */
820 0, /* tp_descr_get */
821 0, /* tp_descr_set */
822};
823
824PyObject *
825PyWrapper_New(PyObject *d, PyObject *self)
826{
827 wrapperobject *wp;
828 PyWrapperDescrObject *descr;
829
830 assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type));
831 descr = (PyWrapperDescrObject *)d;
832 assert(PyObject_IsInstance(self, (PyObject *)(descr->d_type)));
833
834 wp = PyObject_NEW(wrapperobject, &wrappertype);
835 if (wp != NULL) {
836 Py_INCREF(descr);
837 wp->descr = descr;
838 Py_INCREF(self);
839 wp->self = self;
840 }
841 return (PyObject *)wp;
842}
Guido van Rossum29a62dd2001-08-23 21:40:38 +0000843
844
845/* A built-in 'getset' type */
846
847/*
848 class getset(object):
849
850 def __init__(self, get=None, set=None):
851 self.__get = get
852 self.__set = set
853
854 def __get__(self, inst, type=None):
855 if self.__get is None:
856 raise AttributeError, "unreadable attribute"
857 if inst is None:
858 return self
859 return self.__get(inst)
860
861 def __set__(self, inst, value):
862 if self.__set is None:
863 raise AttributeError, "unsettable attribute"
864 return self.__set(inst, value)
865*/
866
867typedef struct {
868 PyObject_HEAD
869 PyObject *get;
870 PyObject *set;
871} getsetobject;
872
873static void
874getset_dealloc(PyObject *self)
875{
876 getsetobject *gs = (getsetobject *)self;
877
878 Py_XDECREF(gs->get);
879 Py_XDECREF(gs->set);
880 self->ob_type->tp_free(self);
881}
882
883static PyObject *
884getset_descr_get(PyObject *self, PyObject *obj, PyObject *type)
885{
886 getsetobject *gs = (getsetobject *)self;
887
888 if (gs->get == NULL) {
889 PyErr_SetString(PyExc_AttributeError, "unreadable attribute");
890 return NULL;
891 }
892 if (obj == NULL || obj == Py_None) {
893 Py_INCREF(self);
894 return self;
895 }
896 return PyObject_CallFunction(gs->get, "(O)", obj);
897}
898
899static int
900getset_descr_set(PyObject *self, PyObject *obj, PyObject *value)
901{
902 getsetobject *gs = (getsetobject *)self;
903 PyObject *res;
904
905 if (gs->set == NULL) {
906 PyErr_SetString(PyExc_AttributeError, "unsettable attribute");
907 return -1;
908 }
909 res = PyObject_CallFunction(gs->set, "(OO)", obj, value);
910 if (res == NULL)
911 return -1;
912 Py_DECREF(res);
913 return 0;
914}
915
916static int
917getset_init(PyObject *self, PyObject *args, PyObject *kwds)
918{
919 PyObject *get, *set;
920 getsetobject *gs = (getsetobject *)self;
921
922 if (!PyArg_ParseTuple(args, "OO:getset.__init__", &get, &set))
923 return -1;
924 if (get == Py_None)
925 get = NULL;
926 if (set == Py_None)
927 set = NULL;
928 Py_XINCREF(get);
929 Py_XINCREF(set);
930 gs->get = get;
931 gs->set = set;
932 return 0;
933}
934
935PyTypeObject PyGetSet_Type = {
936 PyObject_HEAD_INIT(&PyType_Type)
937 0, /* ob_size */
938 "getset", /* tp_name */
939 sizeof(getsetobject), /* tp_basicsize */
940 0, /* tp_itemsize */
941 /* methods */
942 getset_dealloc, /* tp_dealloc */
943 0, /* tp_print */
944 0, /* tp_getattr */
945 0, /* tp_setattr */
946 0, /* tp_compare */
947 0, /* tp_repr */
948 0, /* tp_as_number */
949 0, /* tp_as_sequence */
950 0, /* tp_as_mapping */
951 0, /* tp_hash */
952 0, /* tp_call */
953 0, /* tp_str */
954 PyObject_GenericGetAttr, /* tp_getattro */
955 0, /* tp_setattro */
956 0, /* tp_as_buffer */
957 Py_TPFLAGS_DEFAULT, /* tp_flags */
958 0, /* tp_doc */
959 0, /* tp_traverse */
960 0, /* tp_clear */
961 0, /* tp_richcompare */
962 0, /* tp_weaklistoffset */
963 0, /* tp_iter */
964 0, /* tp_iternext */
965 0, /* tp_methods */
966 0, /* tp_members */
967 0, /* tp_getset */
968 0, /* tp_base */
969 0, /* tp_dict */
970 getset_descr_get, /* tp_descr_get */
971 getset_descr_set, /* tp_descr_set */
972 0, /* tp_dictoffset */
973 getset_init, /* tp_init */
974 PyType_GenericAlloc, /* tp_alloc */
975 PyType_GenericNew, /* tp_new */
976 _PyObject_Del, /* tp_free */
977};