Split out exceptions, pending call, message into separate .c files
[dbus-python-phuang.git] / _dbus_bindings / containers-impl.h
bloba7055dde240c5f4eabd2ee75bd3557534c2e7ae2
1 /* D-Bus container types: Array, Dict and Struct.
3 * Copyright (C) 2006 Collabora Ltd.
5 * Licensed under the Academic Free License version 2.1
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 /* Array ============================================================ */
27 PyDoc_STRVAR(Array_tp_doc,
28 "An array of similar items, implemented as a subtype of list.\n"
29 "\n"
30 "As currently implemented, an Array behaves just like a list, but\n"
31 "with the addition of a ``signature`` property set by the constructor;\n"
32 "conversion of its items to D-Bus types is only done when it's sent in\n"
33 "a Message. This might change in future so validation is done earlier.\n"
34 "\n"
35 ":SupportedUsage:\n"
36 " ``from dbus import Array`` or ``from dbus.types import Array``\n"
37 "\n"
38 ":Constructor:\n"
39 " Array([iterable][, signature][, variant_level])\n"
40 "\n"
41 " variant_level must be non-negative; the default is 0.\n"
42 "\n"
43 " The signature may be None, in which case when the Array is sent over\n"
44 " D-Bus, the item signature will be guessed from the first element.\n"
45 "\n"
46 ":IVariables:\n"
47 " `variant_level` : int\n"
48 " Indicates how many nested Variant containers this object\n"
49 " is contained in: if a message's wire format has a variant containing a\n"
50 " variant containing an array, this is represented in Python by an\n"
51 " Array with variant_level==2.\n"
54 static struct PyMemberDef Array_tp_members[] = {
55 {"signature", T_OBJECT, offsetof(DBusPyArray, signature), READONLY,
56 "The D-Bus signature of each element of this Array (a Signature "
57 "instance)"},
58 {"variant_level", T_LONG, offsetof(DBusPyArray, variant_level),
59 READONLY,
60 "The number of nested variants wrapping the real data. "
61 "0 if not in a variant."},
62 {NULL},
65 static void
66 Array_tp_dealloc (DBusPyArray *self)
68 Py_XDECREF(self->signature);
69 self->signature = NULL;
70 (PyList_Type.tp_dealloc)((PyObject *)self);
73 static PyObject *
74 Array_tp_repr(DBusPyArray *self)
76 PyObject *parent_repr = (PyList_Type.tp_repr)((PyObject *)self);
77 PyObject *sig_repr = PyObject_Repr(self->signature);
78 PyObject *my_repr = NULL;
79 long variant_level = self->variant_level;
81 if (!parent_repr) goto finally;
82 if (!sig_repr) goto finally;
83 if (variant_level > 0) {
84 my_repr = PyString_FromFormat("%s(%s, signature=%s, "
85 "variant_level=%ld)",
86 self->super.ob_type->tp_name,
87 PyString_AS_STRING(parent_repr),
88 PyString_AS_STRING(sig_repr),
89 variant_level);
91 else {
92 my_repr = PyString_FromFormat("%s(%s, signature=%s)",
93 self->super.ob_type->tp_name,
94 PyString_AS_STRING(parent_repr),
95 PyString_AS_STRING(sig_repr));
97 finally:
98 Py_XDECREF(parent_repr);
99 Py_XDECREF(sig_repr);
100 return my_repr;
103 static PyObject *
104 Array_tp_new (PyTypeObject *cls, PyObject *args, PyObject *kwargs)
106 PyObject *variant_level = NULL;
107 DBusPyArray *self = (DBusPyArray *)(PyList_Type.tp_new)(cls, args, kwargs);
109 /* variant_level is immutable, so handle it in __new__ rather than
110 __init__ */
111 if (!self) return NULL;
112 Py_INCREF(Py_None);
113 self->signature = Py_None;
114 self->variant_level = 0;
115 if (kwargs) {
116 variant_level = PyDict_GetItem(kwargs, dbus_py_variant_level_const);
118 if (variant_level) {
119 self->variant_level = PyInt_AsLong(variant_level);
120 if (PyErr_Occurred()) {
121 Py_DECREF((PyObject *)self);
122 return NULL;
125 return (PyObject *)self;
128 static int
129 Array_tp_init (DBusPyArray *self, PyObject *args, PyObject *kwargs)
131 PyObject *obj = dbus_py_empty_tuple;
132 PyObject *signature = NULL;
133 PyObject *tuple;
134 PyObject *variant_level;
135 /* variant_level is accepted but ignored - it's immutable, so
136 * __new__ handles it */
137 static char *argnames[] = {"iterable", "signature", "variant_level", NULL};
139 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOO:__init__", argnames,
140 &obj, &signature, &variant_level)) {
141 return -1;
144 /* convert signature from a borrowed ref of unknown type to an owned ref
145 of type Signature (or None) */
146 if (!signature) signature = Py_None;
147 if (signature == Py_None
148 || PyObject_IsInstance(signature, (PyObject *)&DBusPySignature_Type)) {
149 Py_INCREF(signature);
151 else {
152 signature = PyObject_CallFunction((PyObject *)&DBusPySignature_Type,
153 "(O)", signature);
154 if (!signature) return -1;
157 tuple = Py_BuildValue("(O)", obj);
158 if (!tuple) {
159 Py_DECREF(signature);
160 return -1;
162 if ((PyList_Type.tp_init)((PyObject *)self, tuple, NULL) < 0) {
163 Py_DECREF(tuple);
164 Py_DECREF(signature);
165 return -1;
167 Py_DECREF(tuple);
169 Py_XDECREF(self->signature);
170 self->signature = signature;
171 return 0;
174 PyTypeObject DBusPyArray_Type = {
175 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
177 "dbus.Array",
178 sizeof(DBusPyArray),
180 (destructor)Array_tp_dealloc, /* tp_dealloc */
181 0, /* tp_print */
182 0, /* tp_getattr */
183 0, /* tp_setattr */
184 0, /* tp_compare */
185 (reprfunc)Array_tp_repr, /* tp_repr */
186 0, /* tp_as_number */
187 0, /* tp_as_sequence */
188 0, /* tp_as_mapping */
189 0, /* tp_hash */
190 0, /* tp_call */
191 0, /* tp_str */
192 0, /* tp_getattro */
193 0, /* tp_setattro */
194 0, /* tp_as_buffer */
195 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
196 Array_tp_doc, /* tp_doc */
197 0, /* tp_traverse */
198 0, /* tp_clear */
199 0, /* tp_richcompare */
200 0, /* tp_weaklistoffset */
201 0, /* tp_iter */
202 0, /* tp_iternext */
203 0, /* tp_methods */
204 Array_tp_members, /* tp_members */
205 0, /* tp_getset */
206 0, /* tp_base */
207 0, /* tp_dict */
208 0, /* tp_descr_get */
209 0, /* tp_descr_set */
210 0, /* tp_dictoffset */
211 (initproc)Array_tp_init, /* tp_init */
212 0, /* tp_alloc */
213 Array_tp_new, /* tp_new */
216 /* Dict ============================================================= */
218 PyDoc_STRVAR(Dict_tp_doc,
219 "An mapping whose keys are similar and whose values are similar,\n"
220 "implemented as a subtype of dict.\n"
221 "\n"
222 "As currently implemented, a Dictionary behaves just like a dict, but\n"
223 "with the addition of a ``signature`` property set by the constructor;\n"
224 "conversion of its items to D-Bus types is only done when it's sent in\n"
225 "a Message. This may change in future so validation is done earlier.\n"
226 "\n"
227 ":SupportedUsage:\n"
228 " ``from dbus import Dictionary`` or ``from dbus.types import Dictionary``\n"
229 "\n"
230 ":Constructor:\n"
231 " Dictionary([mapping_or_iterable][, signature][, variant_level])\n"
232 "\n"
233 " variant_level must be non-negative; the default is 0.\n"
234 "\n"
235 " The signature may be None, in which case when the Dictionary is sent over\n"
236 " D-Bus, the key and value signatures will be guessed from some arbitrary.\n"
237 " element.\n"
238 "\n"
239 ":IVariables:\n"
240 " `variant_level` : int\n"
241 " Indicates how many nested Variant containers this object\n"
242 " is contained in: if a message's wire format has a variant containing a\n"
243 " variant containing an array of DICT_ENTRY, this is represented in\n"
244 " Python by a Dictionary with variant_level==2.\n"
247 static struct PyMemberDef Dict_tp_members[] = {
248 {"signature", T_OBJECT, offsetof(DBusPyDict, signature), READONLY,
249 "The D-Bus signature of each key in this Dictionary, followed by "
250 "that of each value in this Dictionary, as a Signature instance."},
251 {"variant_level", T_LONG, offsetof(DBusPyDict, variant_level),
252 READONLY,
253 "The number of nested variants wrapping the real data. "
254 "0 if not in a variant."},
255 {NULL},
258 static void
259 Dict_tp_dealloc (DBusPyDict *self)
261 Py_XDECREF(self->signature);
262 self->signature = NULL;
263 (PyDict_Type.tp_dealloc)((PyObject *)self);
266 static PyObject *
267 Dict_tp_repr(DBusPyDict *self)
269 PyObject *parent_repr = (PyDict_Type.tp_repr)((PyObject *)self);
270 PyObject *sig_repr = PyObject_Repr(self->signature);
271 PyObject *my_repr = NULL;
272 long variant_level = self->variant_level;
274 if (!parent_repr) goto finally;
275 if (!sig_repr) goto finally;
276 if (variant_level > 0) {
277 my_repr = PyString_FromFormat("%s(%s, signature=%s, "
278 "variant_level=%ld)",
279 self->super.ob_type->tp_name,
280 PyString_AS_STRING(parent_repr),
281 PyString_AS_STRING(sig_repr),
282 variant_level);
284 else {
285 my_repr = PyString_FromFormat("%s(%s, signature=%s)",
286 self->super.ob_type->tp_name,
287 PyString_AS_STRING(parent_repr),
288 PyString_AS_STRING(sig_repr));
290 finally:
291 Py_XDECREF(parent_repr);
292 Py_XDECREF(sig_repr);
293 return my_repr;
296 static PyObject *
297 Dict_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
299 DBusPyDict *self = (DBusPyDict *)(PyDict_Type.tp_new)(cls, args, kwargs);
300 PyObject *variant_level = NULL;
302 /* variant_level is immutable, so handle it in __new__ rather than
303 __init__ */
304 if (!self) return NULL;
305 Py_INCREF(Py_None);
306 self->signature = Py_None;
307 self->variant_level = 0;
308 if (kwargs) {
309 variant_level = PyDict_GetItem(kwargs, dbus_py_variant_level_const);
311 if (variant_level) {
312 self->variant_level = PyInt_AsLong(variant_level);
313 if (PyErr_Occurred()) {
314 Py_DECREF((PyObject *)self);
315 return NULL;
318 return (PyObject *)self;
321 static int
322 Dict_tp_init(DBusPyDict *self, PyObject *args, PyObject *kwargs)
324 PyObject *obj = dbus_py_empty_tuple;
325 PyObject *signature = NULL;
326 PyObject *tuple;
327 PyObject *variant_level; /* ignored here - __new__ uses it */
328 static char *argnames[] = {"mapping_or_iterable", "signature",
329 "variant_level", NULL};
331 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOO:__init__", argnames,
332 &obj, &signature, &variant_level)) {
333 return -1;
336 /* convert signature from a borrowed ref of unknown type to an owned ref
337 of type Signature (or None) */
338 if (!signature) signature = Py_None;
339 if (signature == Py_None
340 || PyObject_IsInstance(signature, (PyObject *)&DBusPySignature_Type)) {
341 Py_INCREF(signature);
343 else {
344 signature = PyObject_CallFunction((PyObject *)&DBusPySignature_Type,
345 "(O)", signature);
346 if (!signature) return -1;
349 tuple = Py_BuildValue("(O)", obj);
350 if (!tuple) {
351 Py_DECREF(signature);
352 return -1;
355 if ((PyDict_Type.tp_init((PyObject *)self, tuple, NULL)) < 0) {
356 Py_DECREF(tuple);
357 Py_DECREF(signature);
358 return -1;
360 Py_DECREF(tuple);
362 Py_XDECREF(self->signature);
363 self->signature = signature;
364 return 0;
367 PyTypeObject DBusPyDict_Type = {
368 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
370 "dbus.Dictionary",
371 sizeof(DBusPyDict),
373 (destructor)Dict_tp_dealloc, /* tp_dealloc */
374 0, /* tp_print */
375 0, /* tp_getattr */
376 0, /* tp_setattr */
377 0, /* tp_compare */
378 (reprfunc)Dict_tp_repr, /* tp_repr */
379 0, /* tp_as_number */
380 0, /* tp_as_sequence */
381 0, /* tp_as_mapping */
382 0, /* tp_hash */
383 0, /* tp_call */
384 0, /* tp_str */
385 0, /* tp_getattro */
386 0, /* tp_setattro */
387 0, /* tp_as_buffer */
388 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
389 Dict_tp_doc, /* 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 Dict_tp_members, /* tp_members */
398 0, /* tp_getset */
399 0, /* tp_base */
400 0, /* tp_dict */
401 0, /* tp_descr_get */
402 0, /* tp_descr_set */
403 0, /* tp_dictoffset */
404 (initproc)Dict_tp_init, /* tp_init */
405 0, /* tp_alloc */
406 Dict_tp_new, /* tp_new */
409 /* Struct =========================================================== */
411 PyDoc_STRVAR(Struct_tp_doc,
412 "An structure containing items of possibly distinct types.\n"
413 "\n"
414 ":SupportedUsage:\n"
415 " ``from dbus import Struct`` or ``from dbus.types import Struct``\n"
416 "\n"
417 ":Constructor:\n"
418 " ``Struct(iterable[, signature: str][, variant_level: int]) -> Struct``\n"
419 "\n"
420 " D-Bus structs may not be empty, so the iterable argument is required.\n"
421 "\n"
422 " The signature may be omitted or None, in which case it will be guessed\n"
423 " from the types of the items during construction.\n"
424 "\n"
425 " variant_level must be non-negative; the default is 0.\n"
426 "\n"
427 ":IVariables:\n"
428 " `variant_level` : int\n"
429 " Indicates how many nested Variant containers this object\n"
430 " is contained in: if a message's wire format has a variant containing a\n"
431 " variant containing a struct, this is represented in Python by a\n"
432 " Struct with variant_level==2.\n"
435 static PyObject *
436 Struct_tp_repr(PyObject *self)
438 PyObject *parent_repr = (PyTuple_Type.tp_repr)((PyObject *)self);
439 PyObject *sig, *sig_repr = NULL;
440 PyObject *vl_obj;
441 long variant_level;
442 PyObject *my_repr = NULL;
444 if (!parent_repr) goto finally;
445 sig = PyObject_GetAttr(self, dbus_py_signature_const);
446 if (!sig) goto finally;
447 sig_repr = PyObject_Repr(sig);
448 if (!sig_repr) goto finally;
449 vl_obj = PyObject_GetAttr(self, dbus_py_variant_level_const);
450 if (!vl_obj) goto finally;
451 variant_level = PyInt_AsLong(vl_obj);
452 if (variant_level > 0) {
453 my_repr = PyString_FromFormat("%s(%s, signature=%s, "
454 "variant_level=%ld)",
455 self->ob_type->tp_name,
456 PyString_AS_STRING(parent_repr),
457 PyString_AS_STRING(sig_repr),
458 variant_level);
460 else {
461 my_repr = PyString_FromFormat("%s(%s, signature=%s)",
462 self->ob_type->tp_name,
463 PyString_AS_STRING(parent_repr),
464 PyString_AS_STRING(sig_repr));
467 finally:
468 Py_XDECREF(parent_repr);
469 Py_XDECREF(sig_repr);
470 return my_repr;
473 static PyObject *
474 Struct_tp_new (PyTypeObject *cls, PyObject *args, PyObject *kwargs)
476 PyObject *signature = NULL;
477 PyObject *variantness = NULL;
478 PyObject *self;
479 static char *argnames[] = {"signature", "variant_level", NULL};
481 if (PyTuple_Size(args) != 1) {
482 PyErr_SetString(PyExc_TypeError,
483 "__new__ takes exactly one positional parameter");
484 return NULL;
486 if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple, kwargs,
487 "|OO!:__new__", argnames,
488 &signature, &PyInt_Type,
489 &variantness)) {
490 return NULL;
492 if (!variantness) {
493 variantness = PyInt_FromLong(0);
496 self = (PyTuple_Type.tp_new)(cls, args, NULL);
497 if (!self)
498 return NULL;
499 if (PyTuple_Size(self) < 1) {
500 PyErr_SetString(PyExc_ValueError, "D-Bus structs may not be empty");
501 Py_DECREF(self);
502 return NULL;
505 if (PyObject_GenericSetAttr(self, dbus_py_variant_level_const, variantness) < 0) {
506 Py_DECREF(self);
507 return NULL;
510 /* convert signature from a borrowed ref of unknown type to an owned ref
511 of type Signature (or None) */
512 if (!signature) signature = Py_None;
513 if (signature == Py_None
514 || PyObject_IsInstance(signature, (PyObject *)&DBusPySignature_Type)) {
515 Py_INCREF(signature);
517 else {
518 signature = PyObject_CallFunction((PyObject *)&DBusPySignature_Type,
519 "(O)", signature);
520 if (!signature) {
521 Py_DECREF(self);
522 return NULL;
526 if (PyObject_GenericSetAttr(self, dbus_py_signature_const, signature) < 0) {
527 Py_DECREF(self);
528 Py_DECREF(signature);
529 return NULL;
531 Py_DECREF(signature);
532 return self;
535 PyTypeObject DBusPyStruct_Type = {
536 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
538 "dbus.Struct",
539 INT_MAX, /* placeholder */
541 0, /* tp_dealloc */
542 0, /* tp_print */
543 0, /* tp_getattr */
544 0, /* tp_setattr */
545 0, /* tp_compare */
546 (reprfunc)Struct_tp_repr, /* tp_repr */
547 0, /* tp_as_number */
548 0, /* tp_as_sequence */
549 0, /* tp_as_mapping */
550 0, /* tp_hash */
551 0, /* tp_call */
552 0, /* tp_str */
553 PyObject_GenericGetAttr, /* tp_getattro */
554 Glue_immutable_setattro, /* tp_setattro */
555 0, /* tp_as_buffer */
556 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
557 Struct_tp_doc, /* tp_doc */
558 0, /* tp_traverse */
559 0, /* tp_clear */
560 0, /* tp_richcompare */
561 0, /* tp_weaklistoffset */
562 0, /* tp_iter */
563 0, /* tp_iternext */
564 0, /* tp_methods */
565 0, /* tp_members */
566 0, /* tp_getset */
567 0, /* tp_base */
568 0, /* tp_dict */
569 0, /* tp_descr_get */
570 0, /* tp_descr_set */
571 -sizeof(PyObject *), /* tp_dictoffset */
572 0, /* tp_init */
573 0, /* tp_alloc */
574 Struct_tp_new, /* tp_new */
577 static inline int
578 init_container_types(void)
580 DBusPyArray_Type.tp_base = &PyList_Type;
581 if (PyType_Ready(&DBusPyArray_Type) < 0) return 0;
582 DBusPyArray_Type.tp_print = NULL;
584 DBusPyDict_Type.tp_base = &PyDict_Type;
585 if (PyType_Ready(&DBusPyDict_Type) < 0) return 0;
586 DBusPyDict_Type.tp_print = NULL;
588 DBusPyStruct_Type.tp_basicsize = PyTuple_Type.tp_basicsize
589 + 2*sizeof(PyObject *) - 1;
590 DBusPyStruct_Type.tp_basicsize /= sizeof(PyObject *);
591 DBusPyStruct_Type.tp_basicsize *= sizeof(PyObject *);
592 DBusPyStruct_Type.tp_base = &PyTuple_Type;
593 if (PyType_Ready(&DBusPyStruct_Type) < 0) return 0;
594 DBusPyStruct_Type.tp_print = NULL;
596 return 1;
599 static inline int
600 insert_container_types(PyObject *this_module)
602 Py_INCREF(&DBusPyArray_Type);
603 if (PyModule_AddObject(this_module, "Array",
604 (PyObject *)&DBusPyArray_Type) < 0) return 0;
606 Py_INCREF(&DBusPyDict_Type);
607 if (PyModule_AddObject(this_module, "Dictionary",
608 (PyObject *)&DBusPyDict_Type) < 0) return 0;
610 Py_INCREF(&DBusPyStruct_Type);
611 if (PyModule_AddObject(this_module, "Struct",
612 (PyObject *)&DBusPyStruct_Type) < 0) return 0;
614 return 1;
617 /* vim:set ft=c cino< sw=4 sts=4 et: */