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
26 #include <structmember.h>
30 #include "dbus_bindings-internal.h"
31 #include "types-internal.h"
33 /* Array ============================================================ */
35 PyDoc_STRVAR(Array_tp_doc
,
36 "An array of similar items, implemented as a subtype of list.\n"
38 "As currently implemented, an Array behaves just like a list, but\n"
39 "with the addition of a ``signature`` property set by the constructor;\n"
40 "conversion of its items to D-Bus types is only done when it's sent in\n"
41 "a Message. This might change in future so validation is done earlier.\n"
44 " ``from dbus import Array`` or ``from dbus.types import Array``\n"
47 " Array([iterable][, signature][, variant_level])\n"
49 " variant_level must be non-negative; the default is 0.\n"
51 " The signature may be None, in which case when the Array is sent over\n"
52 " D-Bus, the item signature will be guessed from the first element.\n"
55 " `variant_level` : int\n"
56 " Indicates how many nested Variant containers this object\n"
57 " is contained in: if a message's wire format has a variant containing a\n"
58 " variant containing an array, this is represented in Python by an\n"
59 " Array with variant_level==2.\n"
62 static struct PyMemberDef Array_tp_members
[] = {
63 {"signature", T_OBJECT
, offsetof(DBusPyArray
, signature
), READONLY
,
64 "The D-Bus signature of each element of this Array (a Signature "
66 {"variant_level", T_LONG
, offsetof(DBusPyArray
, variant_level
),
68 "The number of nested variants wrapping the real data. "
69 "0 if not in a variant."},
74 Array_tp_dealloc (DBusPyArray
*self
)
76 Py_XDECREF(self
->signature
);
77 self
->signature
= NULL
;
78 (PyList_Type
.tp_dealloc
)((PyObject
*)self
);
82 Array_tp_repr(DBusPyArray
*self
)
84 PyObject
*parent_repr
= (PyList_Type
.tp_repr
)((PyObject
*)self
);
85 PyObject
*sig_repr
= PyObject_Repr(self
->signature
);
86 PyObject
*my_repr
= NULL
;
87 long variant_level
= self
->variant_level
;
89 if (!parent_repr
) goto finally
;
90 if (!sig_repr
) goto finally
;
91 if (variant_level
> 0) {
92 my_repr
= PyString_FromFormat("%s(%s, signature=%s, "
94 self
->super
.ob_type
->tp_name
,
95 PyString_AS_STRING(parent_repr
),
96 PyString_AS_STRING(sig_repr
),
100 my_repr
= PyString_FromFormat("%s(%s, signature=%s)",
101 self
->super
.ob_type
->tp_name
,
102 PyString_AS_STRING(parent_repr
),
103 PyString_AS_STRING(sig_repr
));
106 Py_XDECREF(parent_repr
);
107 Py_XDECREF(sig_repr
);
112 Array_tp_new (PyTypeObject
*cls
, PyObject
*args
, PyObject
*kwargs
)
114 PyObject
*variant_level
= NULL
;
115 DBusPyArray
*self
= (DBusPyArray
*)(PyList_Type
.tp_new
)(cls
, args
, kwargs
);
117 /* variant_level is immutable, so handle it in __new__ rather than
119 if (!self
) return NULL
;
121 self
->signature
= Py_None
;
122 self
->variant_level
= 0;
124 variant_level
= PyDict_GetItem(kwargs
, dbus_py_variant_level_const
);
127 self
->variant_level
= PyInt_AsLong(variant_level
);
128 if (PyErr_Occurred()) {
129 Py_DECREF((PyObject
*)self
);
133 return (PyObject
*)self
;
137 Array_tp_init (DBusPyArray
*self
, PyObject
*args
, PyObject
*kwargs
)
139 PyObject
*obj
= dbus_py_empty_tuple
;
140 PyObject
*signature
= NULL
;
142 PyObject
*variant_level
;
143 /* variant_level is accepted but ignored - it's immutable, so
144 * __new__ handles it */
145 static char *argnames
[] = {"iterable", "signature", "variant_level", NULL
};
147 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|OOO:__init__", argnames
,
148 &obj
, &signature
, &variant_level
)) {
152 /* convert signature from a borrowed ref of unknown type to an owned ref
153 of type Signature (or None) */
154 if (!signature
) signature
= Py_None
;
155 if (signature
== Py_None
156 || PyObject_IsInstance(signature
, (PyObject
*)&DBusPySignature_Type
)) {
157 Py_INCREF(signature
);
160 signature
= PyObject_CallFunction((PyObject
*)&DBusPySignature_Type
,
162 if (!signature
) return -1;
165 tuple
= Py_BuildValue("(O)", obj
);
167 Py_DECREF(signature
);
170 if ((PyList_Type
.tp_init
)((PyObject
*)self
, tuple
, NULL
) < 0) {
172 Py_DECREF(signature
);
177 Py_XDECREF(self
->signature
);
178 self
->signature
= signature
;
182 PyTypeObject DBusPyArray_Type
= {
183 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type
))
188 (destructor
)Array_tp_dealloc
, /* tp_dealloc */
193 (reprfunc
)Array_tp_repr
, /* tp_repr */
194 0, /* tp_as_number */
195 0, /* tp_as_sequence */
196 0, /* tp_as_mapping */
202 0, /* tp_as_buffer */
203 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
, /* tp_flags */
204 Array_tp_doc
, /* tp_doc */
207 0, /* tp_richcompare */
208 0, /* tp_weaklistoffset */
212 Array_tp_members
, /* tp_members */
216 0, /* tp_descr_get */
217 0, /* tp_descr_set */
218 0, /* tp_dictoffset */
219 (initproc
)Array_tp_init
, /* tp_init */
221 Array_tp_new
, /* tp_new */
224 /* Dict ============================================================= */
226 PyDoc_STRVAR(Dict_tp_doc
,
227 "An mapping whose keys are similar and whose values are similar,\n"
228 "implemented as a subtype of dict.\n"
230 "As currently implemented, a Dictionary behaves just like a dict, but\n"
231 "with the addition of a ``signature`` property set by the constructor;\n"
232 "conversion of its items to D-Bus types is only done when it's sent in\n"
233 "a Message. This may change in future so validation is done earlier.\n"
236 " ``from dbus import Dictionary`` or ``from dbus.types import Dictionary``\n"
239 " Dictionary([mapping_or_iterable][, signature][, variant_level])\n"
241 " variant_level must be non-negative; the default is 0.\n"
243 " The signature may be None, in which case when the Dictionary is sent over\n"
244 " D-Bus, the key and value signatures will be guessed from some arbitrary.\n"
248 " `variant_level` : int\n"
249 " Indicates how many nested Variant containers this object\n"
250 " is contained in: if a message's wire format has a variant containing a\n"
251 " variant containing an array of DICT_ENTRY, this is represented in\n"
252 " Python by a Dictionary with variant_level==2.\n"
255 static struct PyMemberDef Dict_tp_members
[] = {
256 {"signature", T_OBJECT
, offsetof(DBusPyDict
, signature
), READONLY
,
257 "The D-Bus signature of each key in this Dictionary, followed by "
258 "that of each value in this Dictionary, as a Signature instance."},
259 {"variant_level", T_LONG
, offsetof(DBusPyDict
, variant_level
),
261 "The number of nested variants wrapping the real data. "
262 "0 if not in a variant."},
267 Dict_tp_dealloc (DBusPyDict
*self
)
269 Py_XDECREF(self
->signature
);
270 self
->signature
= NULL
;
271 (PyDict_Type
.tp_dealloc
)((PyObject
*)self
);
275 Dict_tp_repr(DBusPyDict
*self
)
277 PyObject
*parent_repr
= (PyDict_Type
.tp_repr
)((PyObject
*)self
);
278 PyObject
*sig_repr
= PyObject_Repr(self
->signature
);
279 PyObject
*my_repr
= NULL
;
280 long variant_level
= self
->variant_level
;
282 if (!parent_repr
) goto finally
;
283 if (!sig_repr
) goto finally
;
284 if (variant_level
> 0) {
285 my_repr
= PyString_FromFormat("%s(%s, signature=%s, "
286 "variant_level=%ld)",
287 self
->super
.ob_type
->tp_name
,
288 PyString_AS_STRING(parent_repr
),
289 PyString_AS_STRING(sig_repr
),
293 my_repr
= PyString_FromFormat("%s(%s, signature=%s)",
294 self
->super
.ob_type
->tp_name
,
295 PyString_AS_STRING(parent_repr
),
296 PyString_AS_STRING(sig_repr
));
299 Py_XDECREF(parent_repr
);
300 Py_XDECREF(sig_repr
);
305 Dict_tp_new(PyTypeObject
*cls
, PyObject
*args
, PyObject
*kwargs
)
307 DBusPyDict
*self
= (DBusPyDict
*)(PyDict_Type
.tp_new
)(cls
, args
, kwargs
);
308 PyObject
*variant_level
= NULL
;
310 /* variant_level is immutable, so handle it in __new__ rather than
312 if (!self
) return NULL
;
314 self
->signature
= Py_None
;
315 self
->variant_level
= 0;
317 variant_level
= PyDict_GetItem(kwargs
, dbus_py_variant_level_const
);
320 self
->variant_level
= PyInt_AsLong(variant_level
);
321 if (PyErr_Occurred()) {
322 Py_DECREF((PyObject
*)self
);
326 return (PyObject
*)self
;
330 Dict_tp_init(DBusPyDict
*self
, PyObject
*args
, PyObject
*kwargs
)
332 PyObject
*obj
= dbus_py_empty_tuple
;
333 PyObject
*signature
= NULL
;
335 PyObject
*variant_level
; /* ignored here - __new__ uses it */
336 static char *argnames
[] = {"mapping_or_iterable", "signature",
337 "variant_level", NULL
};
339 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|OOO:__init__", argnames
,
340 &obj
, &signature
, &variant_level
)) {
344 /* convert signature from a borrowed ref of unknown type to an owned ref
345 of type Signature (or None) */
346 if (!signature
) signature
= Py_None
;
347 if (signature
== Py_None
348 || PyObject_IsInstance(signature
, (PyObject
*)&DBusPySignature_Type
)) {
349 Py_INCREF(signature
);
352 signature
= PyObject_CallFunction((PyObject
*)&DBusPySignature_Type
,
354 if (!signature
) return -1;
357 tuple
= Py_BuildValue("(O)", obj
);
359 Py_DECREF(signature
);
363 if ((PyDict_Type
.tp_init((PyObject
*)self
, tuple
, NULL
)) < 0) {
365 Py_DECREF(signature
);
370 Py_XDECREF(self
->signature
);
371 self
->signature
= signature
;
375 PyTypeObject DBusPyDict_Type
= {
376 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type
))
381 (destructor
)Dict_tp_dealloc
, /* tp_dealloc */
386 (reprfunc
)Dict_tp_repr
, /* tp_repr */
387 0, /* tp_as_number */
388 0, /* tp_as_sequence */
389 0, /* tp_as_mapping */
395 0, /* tp_as_buffer */
396 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
, /* tp_flags */
397 Dict_tp_doc
, /* tp_doc */
400 0, /* tp_richcompare */
401 0, /* tp_weaklistoffset */
405 Dict_tp_members
, /* tp_members */
409 0, /* tp_descr_get */
410 0, /* tp_descr_set */
411 0, /* tp_dictoffset */
412 (initproc
)Dict_tp_init
, /* tp_init */
414 Dict_tp_new
, /* tp_new */
417 /* Struct =========================================================== */
419 PyDoc_STRVAR(Struct_tp_doc
,
420 "An structure containing items of possibly distinct types.\n"
423 " ``from dbus import Struct`` or ``from dbus.types import Struct``\n"
426 " ``Struct(iterable[, signature: str][, variant_level: int]) -> Struct``\n"
428 " D-Bus structs may not be empty, so the iterable argument is required.\n"
430 " The signature may be omitted or None, in which case it will be guessed\n"
431 " from the types of the items during construction.\n"
433 " variant_level must be non-negative; the default is 0.\n"
436 " `variant_level` : int\n"
437 " Indicates how many nested Variant containers this object\n"
438 " is contained in: if a message's wire format has a variant containing a\n"
439 " variant containing a struct, this is represented in Python by a\n"
440 " Struct with variant_level==2.\n"
444 Struct_tp_repr(PyObject
*self
)
446 PyObject
*parent_repr
= (PyTuple_Type
.tp_repr
)((PyObject
*)self
);
447 PyObject
*sig
, *sig_repr
= NULL
;
450 PyObject
*my_repr
= NULL
;
452 if (!parent_repr
) goto finally
;
453 sig
= PyObject_GetAttr(self
, dbus_py_signature_const
);
454 if (!sig
) goto finally
;
455 sig_repr
= PyObject_Repr(sig
);
456 if (!sig_repr
) goto finally
;
457 vl_obj
= PyObject_GetAttr(self
, dbus_py_variant_level_const
);
458 if (!vl_obj
) goto finally
;
459 variant_level
= PyInt_AsLong(vl_obj
);
460 if (variant_level
> 0) {
461 my_repr
= PyString_FromFormat("%s(%s, signature=%s, "
462 "variant_level=%ld)",
463 self
->ob_type
->tp_name
,
464 PyString_AS_STRING(parent_repr
),
465 PyString_AS_STRING(sig_repr
),
469 my_repr
= PyString_FromFormat("%s(%s, signature=%s)",
470 self
->ob_type
->tp_name
,
471 PyString_AS_STRING(parent_repr
),
472 PyString_AS_STRING(sig_repr
));
476 Py_XDECREF(parent_repr
);
477 Py_XDECREF(sig_repr
);
482 Struct_tp_new (PyTypeObject
*cls
, PyObject
*args
, PyObject
*kwargs
)
484 PyObject
*signature
= NULL
;
485 PyObject
*variantness
= NULL
;
487 static char *argnames
[] = {"signature", "variant_level", NULL
};
489 if (PyTuple_Size(args
) != 1) {
490 PyErr_SetString(PyExc_TypeError
,
491 "__new__ takes exactly one positional parameter");
494 if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple
, kwargs
,
495 "|OO!:__new__", argnames
,
496 &signature
, &PyInt_Type
,
501 variantness
= PyInt_FromLong(0);
504 self
= (PyTuple_Type
.tp_new
)(cls
, args
, NULL
);
507 if (PyTuple_Size(self
) < 1) {
508 PyErr_SetString(PyExc_ValueError
, "D-Bus structs may not be empty");
513 if (PyObject_GenericSetAttr(self
, dbus_py_variant_level_const
, variantness
) < 0) {
518 /* convert signature from a borrowed ref of unknown type to an owned ref
519 of type Signature (or None) */
520 if (!signature
) signature
= Py_None
;
521 if (signature
== Py_None
522 || PyObject_IsInstance(signature
, (PyObject
*)&DBusPySignature_Type
)) {
523 Py_INCREF(signature
);
526 signature
= PyObject_CallFunction((PyObject
*)&DBusPySignature_Type
,
534 if (PyObject_GenericSetAttr(self
, dbus_py_signature_const
, signature
) < 0) {
536 Py_DECREF(signature
);
539 Py_DECREF(signature
);
543 PyTypeObject DBusPyStruct_Type
= {
544 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type
))
547 INT_MAX
, /* placeholder */
554 (reprfunc
)Struct_tp_repr
, /* tp_repr */
555 0, /* tp_as_number */
556 0, /* tp_as_sequence */
557 0, /* tp_as_mapping */
561 PyObject_GenericGetAttr
, /* tp_getattro */
562 dbus_py_immutable_setattro
, /* tp_setattro */
563 0, /* tp_as_buffer */
564 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
, /* tp_flags */
565 Struct_tp_doc
, /* tp_doc */
568 0, /* tp_richcompare */
569 0, /* tp_weaklistoffset */
577 0, /* tp_descr_get */
578 0, /* tp_descr_set */
579 -sizeof(PyObject
*), /* tp_dictoffset */
582 Struct_tp_new
, /* tp_new */
586 dbus_py_init_container_types(void)
588 DBusPyArray_Type
.tp_base
= &PyList_Type
;
589 if (PyType_Ready(&DBusPyArray_Type
) < 0) return 0;
590 DBusPyArray_Type
.tp_print
= NULL
;
592 DBusPyDict_Type
.tp_base
= &PyDict_Type
;
593 if (PyType_Ready(&DBusPyDict_Type
) < 0) return 0;
594 DBusPyDict_Type
.tp_print
= NULL
;
596 DBusPyStruct_Type
.tp_basicsize
= PyTuple_Type
.tp_basicsize
597 + 2*sizeof(PyObject
*) - 1;
598 DBusPyStruct_Type
.tp_basicsize
/= sizeof(PyObject
*);
599 DBusPyStruct_Type
.tp_basicsize
*= sizeof(PyObject
*);
600 DBusPyStruct_Type
.tp_base
= &PyTuple_Type
;
601 if (PyType_Ready(&DBusPyStruct_Type
) < 0) return 0;
602 DBusPyStruct_Type
.tp_print
= NULL
;
608 dbus_py_insert_container_types(PyObject
*this_module
)
610 Py_INCREF(&DBusPyArray_Type
);
611 if (PyModule_AddObject(this_module
, "Array",
612 (PyObject
*)&DBusPyArray_Type
) < 0) return 0;
614 Py_INCREF(&DBusPyDict_Type
);
615 if (PyModule_AddObject(this_module
, "Dictionary",
616 (PyObject
*)&DBusPyDict_Type
) < 0) return 0;
618 Py_INCREF(&DBusPyStruct_Type
);
619 if (PyModule_AddObject(this_module
, "Struct",
620 (PyObject
*)&DBusPyStruct_Type
) < 0) return 0;
625 /* vim:set ft=c cino< sw=4 sts=4 et: */