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 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include <structmember.h>
28 #include "dbus_bindings-internal.h"
29 #include "types-internal.h"
31 /* Array ============================================================ */
33 PyDoc_STRVAR(Array_tp_doc
,
34 "An array of similar items, implemented as a subtype of list.\n"
36 "As currently implemented, an Array behaves just like a list, but\n"
37 "with the addition of a ``signature`` property set by the constructor;\n"
38 "conversion of its items to D-Bus types is only done when it's sent in\n"
39 "a Message. This might change in future so validation is done earlier.\n"
43 " dbus.Array([iterable][, signature][, variant_level])\n"
45 "``variant_level`` must be non-negative; the default is 0.\n"
47 "``signature`` is the D-Bus signature string for a single element of the\n"
48 "array, or None. If not None it must represent a single complete type, the\n"
49 "type of a single array item; the signature of the whole Array may be\n"
50 "obtained by prepending ``a`` to the given signature.\n"
52 "If None (the default), when the Array is sent over\n"
53 "D-Bus, the item signature will be guessed from the first element.\n"
56 " `variant_level` : int\n"
57 " Indicates how many nested Variant containers this object\n"
58 " is contained in: if a message's wire format has a variant containing a\n"
59 " variant containing an array, this is represented in Python by an\n"
60 " Array with variant_level==2.\n"
63 static struct PyMemberDef Array_tp_members
[] = {
64 {"signature", T_OBJECT
, offsetof(DBusPyArray
, signature
), READONLY
,
65 "The D-Bus signature of each element of this Array (a Signature "
67 {"variant_level", T_LONG
, offsetof(DBusPyArray
, variant_level
),
69 "The number of nested variants wrapping the real data. "
70 "0 if not in a variant."},
75 Array_tp_dealloc (DBusPyArray
*self
)
77 Py_XDECREF(self
->signature
);
78 self
->signature
= NULL
;
79 (PyList_Type
.tp_dealloc
)((PyObject
*)self
);
83 Array_tp_repr(DBusPyArray
*self
)
85 PyObject
*parent_repr
= (PyList_Type
.tp_repr
)((PyObject
*)self
);
86 PyObject
*sig_repr
= PyObject_Repr(self
->signature
);
87 PyObject
*my_repr
= NULL
;
88 long variant_level
= self
->variant_level
;
90 if (!parent_repr
) goto finally
;
91 if (!sig_repr
) goto finally
;
92 if (variant_level
> 0) {
93 my_repr
= PyString_FromFormat("%s(%s, signature=%s, "
95 self
->super
.ob_type
->tp_name
,
96 PyString_AS_STRING(parent_repr
),
97 PyString_AS_STRING(sig_repr
),
101 my_repr
= PyString_FromFormat("%s(%s, signature=%s)",
102 self
->super
.ob_type
->tp_name
,
103 PyString_AS_STRING(parent_repr
),
104 PyString_AS_STRING(sig_repr
));
107 Py_XDECREF(parent_repr
);
108 Py_XDECREF(sig_repr
);
113 Array_tp_new (PyTypeObject
*cls
, PyObject
*args
, PyObject
*kwargs
)
115 PyObject
*variant_level
= NULL
;
116 DBusPyArray
*self
= (DBusPyArray
*)(PyList_Type
.tp_new
)(cls
, args
, kwargs
);
118 /* variant_level is immutable, so handle it in __new__ rather than
120 if (!self
) return NULL
;
122 self
->signature
= Py_None
;
123 self
->variant_level
= 0;
125 variant_level
= PyDict_GetItem(kwargs
, dbus_py_variant_level_const
);
128 self
->variant_level
= PyInt_AsLong(variant_level
);
129 if (PyErr_Occurred()) {
130 Py_DECREF((PyObject
*)self
);
134 return (PyObject
*)self
;
138 Array_tp_init (DBusPyArray
*self
, PyObject
*args
, PyObject
*kwargs
)
140 PyObject
*obj
= dbus_py_empty_tuple
;
141 PyObject
*signature
= NULL
;
143 PyObject
*variant_level
;
144 /* variant_level is accepted but ignored - it's immutable, so
145 * __new__ handles it */
146 static char *argnames
[] = {"iterable", "signature", "variant_level", NULL
};
148 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|OOO:__init__", argnames
,
149 &obj
, &signature
, &variant_level
)) {
153 /* convert signature from a borrowed ref of unknown type to an owned ref
154 of type Signature (or None) */
155 if (!signature
) signature
= Py_None
;
156 if (signature
== Py_None
157 || PyObject_IsInstance(signature
, (PyObject
*)&DBusPySignature_Type
)) {
158 Py_INCREF(signature
);
161 signature
= PyObject_CallFunction((PyObject
*)&DBusPySignature_Type
,
163 if (!signature
) return -1;
166 if (signature
!= Py_None
) {
167 const char *c_str
= PyString_AS_STRING(signature
);
169 if (!dbus_signature_validate_single(c_str
, NULL
)) {
170 Py_DECREF(signature
);
171 PyErr_SetString(PyExc_ValueError
,
172 "There must be exactly one complete type in "
173 "an Array's signature parameter");
178 tuple
= Py_BuildValue("(O)", obj
);
180 Py_DECREF(signature
);
183 if ((PyList_Type
.tp_init
)((PyObject
*)self
, tuple
, NULL
) < 0) {
185 Py_DECREF(signature
);
190 Py_XDECREF(self
->signature
);
191 self
->signature
= signature
;
195 PyTypeObject DBusPyArray_Type
= {
196 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type
))
201 (destructor
)Array_tp_dealloc
, /* tp_dealloc */
206 (reprfunc
)Array_tp_repr
, /* tp_repr */
207 0, /* tp_as_number */
208 0, /* tp_as_sequence */
209 0, /* tp_as_mapping */
215 0, /* tp_as_buffer */
216 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
, /* tp_flags */
217 Array_tp_doc
, /* tp_doc */
220 0, /* tp_richcompare */
221 0, /* tp_weaklistoffset */
225 Array_tp_members
, /* tp_members */
229 0, /* tp_descr_get */
230 0, /* tp_descr_set */
231 0, /* tp_dictoffset */
232 (initproc
)Array_tp_init
, /* tp_init */
234 Array_tp_new
, /* tp_new */
237 /* Dict ============================================================= */
239 PyDoc_STRVAR(Dict_tp_doc
,
240 "An mapping whose keys are similar and whose values are similar,\n"
241 "implemented as a subtype of dict.\n"
243 "As currently implemented, a Dictionary behaves just like a dict, but\n"
244 "with the addition of a ``signature`` property set by the constructor;\n"
245 "conversion of its items to D-Bus types is only done when it's sent in\n"
246 "a Message. This may change in future so validation is done earlier.\n"
250 " Dictionary(mapping_or_iterable=(), signature=None, variant_level=0)\n"
252 "``variant_level`` must be non-negative; the default is 0.\n"
254 "``signature`` is either a string or None. If a string, it must consist\n"
255 "of exactly two complete type signatures, representing the 'key' type\n"
256 "(which must be a primitive type, i.e. one of \"bd"
257 #ifdef WITH_DBUS_FLOAT32
261 "and the 'value' type. The signature of the whole Dictionary will be\n"
262 "``a{xx}`` where ``xx`` is replaced by the given signature.\n"
264 "If it is None (the default), when the Dictionary is sent over\n"
265 "D-Bus, the key and value signatures will be guessed from an arbitrary\n"
266 "element of the Dictionary.\n"
269 " `variant_level` : int\n"
270 " Indicates how many nested Variant containers this object\n"
271 " is contained in: if a message's wire format has a variant containing a\n"
272 " variant containing an array of DICT_ENTRY, this is represented in\n"
273 " Python by a Dictionary with variant_level==2.\n"
276 static struct PyMemberDef Dict_tp_members
[] = {
277 {"signature", T_OBJECT
, offsetof(DBusPyDict
, signature
), READONLY
,
278 "The D-Bus signature of each key in this Dictionary, followed by "
279 "that of each value in this Dictionary, as a Signature instance."},
280 {"variant_level", T_LONG
, offsetof(DBusPyDict
, variant_level
),
282 "The number of nested variants wrapping the real data. "
283 "0 if not in a variant."},
288 Dict_tp_dealloc (DBusPyDict
*self
)
290 Py_XDECREF(self
->signature
);
291 self
->signature
= NULL
;
292 (PyDict_Type
.tp_dealloc
)((PyObject
*)self
);
296 Dict_tp_repr(DBusPyDict
*self
)
298 PyObject
*parent_repr
= (PyDict_Type
.tp_repr
)((PyObject
*)self
);
299 PyObject
*sig_repr
= PyObject_Repr(self
->signature
);
300 PyObject
*my_repr
= NULL
;
301 long variant_level
= self
->variant_level
;
303 if (!parent_repr
) goto finally
;
304 if (!sig_repr
) goto finally
;
305 if (variant_level
> 0) {
306 my_repr
= PyString_FromFormat("%s(%s, signature=%s, "
307 "variant_level=%ld)",
308 self
->super
.ob_type
->tp_name
,
309 PyString_AS_STRING(parent_repr
),
310 PyString_AS_STRING(sig_repr
),
314 my_repr
= PyString_FromFormat("%s(%s, signature=%s)",
315 self
->super
.ob_type
->tp_name
,
316 PyString_AS_STRING(parent_repr
),
317 PyString_AS_STRING(sig_repr
));
320 Py_XDECREF(parent_repr
);
321 Py_XDECREF(sig_repr
);
326 Dict_tp_new(PyTypeObject
*cls
, PyObject
*args
, PyObject
*kwargs
)
328 DBusPyDict
*self
= (DBusPyDict
*)(PyDict_Type
.tp_new
)(cls
, args
, kwargs
);
329 PyObject
*variant_level
= NULL
;
331 /* variant_level is immutable, so handle it in __new__ rather than
333 if (!self
) return NULL
;
335 self
->signature
= Py_None
;
336 self
->variant_level
= 0;
338 variant_level
= PyDict_GetItem(kwargs
, dbus_py_variant_level_const
);
341 self
->variant_level
= PyInt_AsLong(variant_level
);
342 if (PyErr_Occurred()) {
343 Py_DECREF((PyObject
*)self
);
347 return (PyObject
*)self
;
351 Dict_tp_init(DBusPyDict
*self
, PyObject
*args
, PyObject
*kwargs
)
353 PyObject
*obj
= dbus_py_empty_tuple
;
354 PyObject
*signature
= NULL
;
356 PyObject
*variant_level
; /* ignored here - __new__ uses it */
357 static char *argnames
[] = {"mapping_or_iterable", "signature",
358 "variant_level", NULL
};
360 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|OOO:__init__", argnames
,
361 &obj
, &signature
, &variant_level
)) {
365 /* convert signature from a borrowed ref of unknown type to an owned ref
366 of type Signature (or None) */
367 if (!signature
) signature
= Py_None
;
368 if (signature
== Py_None
369 || PyObject_IsInstance(signature
, (PyObject
*)&DBusPySignature_Type
)) {
370 Py_INCREF(signature
);
373 signature
= PyObject_CallFunction((PyObject
*)&DBusPySignature_Type
,
375 if (!signature
) return -1;
378 if (signature
!= Py_None
) {
379 const char *c_str
= PyString_AS_STRING(signature
);
383 case DBUS_TYPE_BOOLEAN
:
384 case DBUS_TYPE_INT16
:
385 case DBUS_TYPE_UINT16
:
386 case DBUS_TYPE_INT32
:
387 case DBUS_TYPE_UINT32
:
388 case DBUS_TYPE_INT64
:
389 case DBUS_TYPE_UINT64
:
390 case DBUS_TYPE_DOUBLE
:
391 #ifdef WITH_DBUS_FLOAT32
392 case DBUS_TYPE_FLOAT
:
394 case DBUS_TYPE_STRING
:
395 case DBUS_TYPE_OBJECT_PATH
:
396 case DBUS_TYPE_SIGNATURE
:
399 Py_DECREF(signature
);
400 PyErr_SetString(PyExc_ValueError
,
401 "The key type in a Dictionary's signature "
402 "must be a primitive type");
406 if (!dbus_signature_validate_single(c_str
+ 1, NULL
)) {
407 Py_DECREF(signature
);
408 PyErr_SetString(PyExc_ValueError
,
409 "There must be exactly two complete types in "
410 "a Dictionary's signature parameter");
415 tuple
= Py_BuildValue("(O)", obj
);
417 Py_DECREF(signature
);
421 if ((PyDict_Type
.tp_init((PyObject
*)self
, tuple
, NULL
)) < 0) {
423 Py_DECREF(signature
);
428 Py_XDECREF(self
->signature
);
429 self
->signature
= signature
;
433 PyTypeObject DBusPyDict_Type
= {
434 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type
))
439 (destructor
)Dict_tp_dealloc
, /* tp_dealloc */
444 (reprfunc
)Dict_tp_repr
, /* tp_repr */
445 0, /* tp_as_number */
446 0, /* tp_as_sequence */
447 0, /* tp_as_mapping */
453 0, /* tp_as_buffer */
454 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
, /* tp_flags */
455 Dict_tp_doc
, /* tp_doc */
458 0, /* tp_richcompare */
459 0, /* tp_weaklistoffset */
463 Dict_tp_members
, /* tp_members */
467 0, /* tp_descr_get */
468 0, /* tp_descr_set */
469 0, /* tp_dictoffset */
470 (initproc
)Dict_tp_init
, /* tp_init */
472 Dict_tp_new
, /* tp_new */
475 /* Struct =========================================================== */
477 PyDoc_STRVAR(Struct_tp_doc
,
478 "An structure containing items of possibly distinct types.\n"
482 " dbus.Struct(iterable, signature=None, variant_level=0) -> Struct\n"
484 "D-Bus structs may not be empty, so the iterable argument is required and\n"
485 "may not be an empty iterable.\n"
487 "``signature`` is either None, or a string representing the contents of the\n"
488 "struct as one or more complete type signatures. The overall signature of\n"
489 "the struct will be the given signature enclosed in parentheses, ``()``.\n"
491 "If the signature is None (default) it will be guessed\n"
492 "from the types of the items during construction.\n"
494 "``variant_level`` must be non-negative; the default is 0.\n"
497 " `variant_level` : int\n"
498 " Indicates how many nested Variant containers this object\n"
499 " is contained in: if a message's wire format has a variant containing a\n"
500 " variant containing a struct, this is represented in Python by a\n"
501 " Struct with variant_level==2.\n"
505 Struct_tp_repr(PyObject
*self
)
507 PyObject
*parent_repr
= (PyTuple_Type
.tp_repr
)((PyObject
*)self
);
508 PyObject
*sig
= NULL
;
509 PyObject
*sig_repr
= NULL
;
510 PyObject
*vl_obj
= NULL
;
512 PyObject
*my_repr
= NULL
;
514 if (!parent_repr
) goto finally
;
515 sig
= PyObject_GetAttr(self
, dbus_py_signature_const
);
516 if (!sig
) goto finally
;
517 sig_repr
= PyObject_Repr(sig
);
518 if (!sig_repr
) goto finally
;
519 vl_obj
= PyObject_GetAttr(self
, dbus_py_variant_level_const
);
520 if (!vl_obj
) goto finally
;
521 variant_level
= PyInt_AsLong(vl_obj
);
522 if (variant_level
> 0) {
523 my_repr
= PyString_FromFormat("%s(%s, signature=%s, "
524 "variant_level=%ld)",
525 self
->ob_type
->tp_name
,
526 PyString_AS_STRING(parent_repr
),
527 PyString_AS_STRING(sig_repr
),
531 my_repr
= PyString_FromFormat("%s(%s, signature=%s)",
532 self
->ob_type
->tp_name
,
533 PyString_AS_STRING(parent_repr
),
534 PyString_AS_STRING(sig_repr
));
538 Py_XDECREF(parent_repr
);
540 Py_XDECREF(sig_repr
);
546 Struct_tp_new (PyTypeObject
*cls
, PyObject
*args
, PyObject
*kwargs
)
548 PyObject
*signature
= NULL
;
549 PyObject
*variantness
= NULL
;
551 static char *argnames
[] = {"signature", "variant_level", NULL
};
553 if (PyTuple_Size(args
) != 1) {
554 PyErr_SetString(PyExc_TypeError
,
555 "__new__ takes exactly one positional parameter");
558 if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple
, kwargs
,
559 "|OO!:__new__", argnames
,
560 &signature
, &PyInt_Type
,
565 variantness
= PyInt_FromLong(0);
568 self
= (PyTuple_Type
.tp_new
)(cls
, args
, NULL
);
571 if (PyTuple_Size(self
) < 1) {
572 PyErr_SetString(PyExc_ValueError
, "D-Bus structs may not be empty");
577 if (PyObject_GenericSetAttr(self
, dbus_py_variant_level_const
, variantness
) < 0) {
582 /* convert signature from a borrowed ref of unknown type to an owned ref
583 of type Signature (or None) */
584 if (!signature
) signature
= Py_None
;
585 if (signature
== Py_None
586 || PyObject_IsInstance(signature
, (PyObject
*)&DBusPySignature_Type
)) {
587 Py_INCREF(signature
);
590 signature
= PyObject_CallFunction((PyObject
*)&DBusPySignature_Type
,
598 if (PyObject_GenericSetAttr(self
, dbus_py_signature_const
, signature
) < 0) {
600 Py_DECREF(signature
);
603 Py_DECREF(signature
);
607 PyTypeObject DBusPyStruct_Type
= {
608 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type
))
611 INT_MAX
, /* placeholder */
618 (reprfunc
)Struct_tp_repr
, /* tp_repr */
619 0, /* tp_as_number */
620 0, /* tp_as_sequence */
621 0, /* tp_as_mapping */
625 PyObject_GenericGetAttr
, /* tp_getattro */
626 dbus_py_immutable_setattro
, /* tp_setattro */
627 0, /* tp_as_buffer */
628 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
, /* tp_flags */
629 Struct_tp_doc
, /* tp_doc */
632 0, /* tp_richcompare */
633 0, /* tp_weaklistoffset */
641 0, /* tp_descr_get */
642 0, /* tp_descr_set */
643 -sizeof(PyObject
*), /* tp_dictoffset */
646 Struct_tp_new
, /* tp_new */
650 dbus_py_init_container_types(void)
652 DBusPyArray_Type
.tp_base
= &PyList_Type
;
653 if (PyType_Ready(&DBusPyArray_Type
) < 0) return 0;
654 DBusPyArray_Type
.tp_print
= NULL
;
656 DBusPyDict_Type
.tp_base
= &PyDict_Type
;
657 if (PyType_Ready(&DBusPyDict_Type
) < 0) return 0;
658 DBusPyDict_Type
.tp_print
= NULL
;
660 DBusPyStruct_Type
.tp_basicsize
= PyTuple_Type
.tp_basicsize
661 + 2*sizeof(PyObject
*) - 1;
662 DBusPyStruct_Type
.tp_basicsize
/= sizeof(PyObject
*);
663 DBusPyStruct_Type
.tp_basicsize
*= sizeof(PyObject
*);
664 DBusPyStruct_Type
.tp_base
= &PyTuple_Type
;
665 if (PyType_Ready(&DBusPyStruct_Type
) < 0) return 0;
666 DBusPyStruct_Type
.tp_print
= NULL
;
672 dbus_py_insert_container_types(PyObject
*this_module
)
674 Py_INCREF(&DBusPyArray_Type
);
675 if (PyModule_AddObject(this_module
, "Array",
676 (PyObject
*)&DBusPyArray_Type
) < 0) return 0;
678 Py_INCREF(&DBusPyDict_Type
);
679 if (PyModule_AddObject(this_module
, "Dictionary",
680 (PyObject
*)&DBusPyDict_Type
) < 0) return 0;
682 Py_INCREF(&DBusPyStruct_Type
);
683 if (PyModule_AddObject(this_module
, "Struct",
684 (PyObject
*)&DBusPyStruct_Type
) < 0) return 0;
689 /* vim:set ft=c cino< sw=4 sts=4 et: */