1 /* D-Bus Message serialization. This contains all the logic to map from
2 * Python objects to D-Bus types.
4 * Copyright (C) 2006 Collabora Ltd.
6 * Licensed under the Academic Free License version 2.1
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #define DBG_IS_TOO_VERBOSE
25 #include "types-internal.h"
26 #include "message-internal.h"
28 /* Return the number of variants wrapping the given object. Return 0
29 * if the object is not a D-Bus type.
32 get_variant_level(PyObject
*obj
)
34 if (DBusPyIntBase_Check(obj
)) {
35 return ((DBusPyIntBase
*)obj
)->variant_level
;
37 else if (DBusPyFloatBase_Check(obj
)) {
38 return ((DBusPyFloatBase
*)obj
)->variant_level
;
40 else if (DBusPyArray_Check(obj
)) {
41 return ((DBusPyArray
*)obj
)->variant_level
;
43 else if (DBusPyDict_Check(obj
)) {
44 return ((DBusPyDict
*)obj
)->variant_level
;
46 else if (DBusPyLongBase_Check(obj
) ||
47 DBusPyStrBase_Check(obj
) ||
48 DBusPyString_Check(obj
) ||
49 DBusPyStruct_Check(obj
)) {
50 return PyInt_AsLong(PyObject_GetAttr(obj
, dbus_py_variant_level_const
));
57 char dbus_py_Message_append__doc__
[] = (
58 "set_args(*args[, **kwargs])\n\n"
59 "Set the message's arguments from the positional parameter, according to\n"
60 "the signature given by the ``signature`` keyword parameter.\n"
62 "The following type conversions are supported:\n\n"
63 "=============================== ===========================\n"
64 "D-Bus (in signature) Python\n"
65 "=============================== ===========================\n"
66 "boolean (b) any object (via bool())\n"
67 "byte (y) string of length 1\n"
69 "any integer type any integer\n"
70 "double (d) any float\n"
71 "object path anything with a __dbus_object_path__ attribute\n"
72 "string, signature, object path str (must be UTF-8) or unicode\n"
73 "dict (a{...}) any mapping\n"
74 "array (a...) any iterable over appropriate objects\n"
75 "struct ((...)) any iterable over appropriate objects\n"
76 "variant any object above (guess type as below)\n"
77 "=============================== ===========================\n"
79 "Here 'any integer' means anything on which int() or long()\n"
80 "(as appropriate) will work, except for basestring subclasses.\n"
81 "'Any float' means anything on which float() will work, except\n"
82 "for basestring subclasses.\n"
84 "If there is no signature, guess from the arguments using\n"
85 "the static method `Message.guess_signature`.\n"
88 char dbus_py_Message_guess_signature__doc__
[] = (
89 "guess_signature(*args) -> Signature [static method]\n\n"
90 "Guess a D-Bus signature which should be used to encode the given\n"
93 "The signature is constructed as follows:\n\n"
94 "+-------------------------------+---------------------------+\n"
96 "+===============================+===========================+\n"
97 "|D-Bus type, variant_level > 0 |variant (v) |\n"
98 "+-------------------------------+---------------------------+\n"
99 "|D-Bus type, variant_level == 0 |the corresponding type |\n"
100 "+-------------------------------+---------------------------+\n"
101 "|anything with a |object path |\n"
102 "|__dbus_object_path__ attribute | |\n"
103 "+-------------------------------+---------------------------+\n"
104 "|bool |boolean (y) |\n"
105 "+-------------------------------+---------------------------+\n"
106 "|any other int subclass |int32 (i) |\n"
107 "+-------------------------------+---------------------------+\n"
108 "|any other long subclass |int64 (x) |\n"
109 "+-------------------------------+---------------------------+\n"
110 "|any other float subclass |double (d) |\n"
111 "+-------------------------------+---------------------------+\n"
112 "|any other str subclass |string (s) |\n"
113 "+-------------------------------+---------------------------+\n"
114 "|any other unicode subclass |string (s) |\n"
115 "+-------------------------------+---------------------------+\n"
116 "|any other tuple subclass |struct ((...)) |\n"
117 "+-------------------------------+---------------------------+\n"
118 "|any other list subclass |array (a...), guess |\n"
119 "| |contents' type according to|\n"
120 "| |type of first item |\n"
121 "+-------------------------------+---------------------------+\n"
122 "|any other dict subclass |dict (a{...}), guess key, |\n"
123 "| |value type according to |\n"
124 "| |types for an arbitrary item|\n"
125 "+-------------------------------+---------------------------+\n"
126 "|anything else |raise TypeError |\n"
127 "+-------------------------------+---------------------------+\n"
130 /* return a new reference, possibly to None */
132 get_object_path(PyObject
*obj
)
134 PyObject
*magic_attr
= PyObject_GetAttr(obj
, dbus_py__dbus_object_path__const
);
137 if (PyString_Check(magic_attr
)) {
141 Py_DECREF(magic_attr
);
142 PyErr_SetString(PyExc_TypeError
, "__dbus_object_path__ must be "
148 /* Ignore exceptions, except for SystemExit and KeyboardInterrupt */
149 if (PyErr_ExceptionMatches(PyExc_SystemExit
) ||
150 PyErr_ExceptionMatches(PyExc_KeyboardInterrupt
))
157 /* Return a new reference. If the object is a variant and variant_level_ptr
158 * is not NULL, put the variant level in the variable pointed to, and
159 * return the contained type instead of "v". */
161 _signature_string_from_pyobject(PyObject
*obj
, long *variant_level_ptr
)
163 PyObject
*magic_attr
;
164 long variant_level
= get_variant_level(obj
);
165 if (variant_level_ptr
) {
166 *variant_level_ptr
= variant_level
;
168 else if (variant_level
> 0) {
169 return PyString_FromString(DBUS_TYPE_VARIANT_AS_STRING
);
172 if (obj
== Py_True
|| obj
== Py_False
) {
173 return PyString_FromString(DBUS_TYPE_BOOLEAN_AS_STRING
);
176 magic_attr
= get_object_path(obj
);
179 if (magic_attr
!= Py_None
) {
180 Py_DECREF(magic_attr
);
181 return PyString_FromString(DBUS_TYPE_OBJECT_PATH_AS_STRING
);
183 Py_DECREF(magic_attr
);
185 /* Ordering is important: some of these are subclasses of each other. */
186 if (PyInt_Check(obj
)) {
187 if (DBusPyInt16_Check(obj
))
188 return PyString_FromString(DBUS_TYPE_INT16_AS_STRING
);
189 else if (DBusPyInt32_Check(obj
))
190 return PyString_FromString(DBUS_TYPE_INT32_AS_STRING
);
191 else if (DBusPyByte_Check(obj
))
192 return PyString_FromString(DBUS_TYPE_BYTE_AS_STRING
);
193 else if (DBusPyUInt16_Check(obj
))
194 return PyString_FromString(DBUS_TYPE_UINT16_AS_STRING
);
195 else if (DBusPyBoolean_Check(obj
))
196 return PyString_FromString(DBUS_TYPE_BOOLEAN_AS_STRING
);
198 return PyString_FromString(DBUS_TYPE_INT32_AS_STRING
);
200 else if (PyLong_Check(obj
)) {
201 if (DBusPyInt64_Check(obj
))
202 return PyString_FromString(DBUS_TYPE_INT64_AS_STRING
);
203 else if (DBusPyUInt32_Check(obj
))
204 return PyString_FromString(DBUS_TYPE_UINT32_AS_STRING
);
205 else if (DBusPyUInt64_Check(obj
))
206 return PyString_FromString(DBUS_TYPE_UINT64_AS_STRING
);
208 return PyString_FromString(DBUS_TYPE_INT64_AS_STRING
);
210 else if (PyUnicode_Check(obj
))
211 return PyString_FromString(DBUS_TYPE_STRING_AS_STRING
);
212 else if (PyFloat_Check(obj
)) {
213 #ifdef WITH_DBUS_FLOAT32
214 if (DBusPyDouble_Check(obj
))
215 return PyString_FromString(DBUS_TYPE_DOUBLE_AS_STRING
);
216 else if (DBusPyFloat_Check(obj
))
217 return PyString_FromString(DBUS_TYPE_FLOAT_AS_STRING
);
220 return PyString_FromString(DBUS_TYPE_DOUBLE_AS_STRING
);
222 else if (PyString_Check(obj
)) {
223 if (DBusPyObjectPath_Check(obj
))
224 return PyString_FromString(DBUS_TYPE_OBJECT_PATH_AS_STRING
);
225 else if (DBusPySignature_Check(obj
))
226 return PyString_FromString(DBUS_TYPE_SIGNATURE_AS_STRING
);
227 else if (DBusPyByteArray_Check(obj
))
228 return PyString_FromString(DBUS_TYPE_ARRAY_AS_STRING
229 DBUS_TYPE_BYTE_AS_STRING
);
231 return PyString_FromString(DBUS_TYPE_STRING_AS_STRING
);
233 else if (PyTuple_Check(obj
)) {
234 Py_ssize_t len
= PyTuple_GET_SIZE(obj
);
235 PyObject
*list
= PyList_New(len
+ 2); /* new ref */
236 PyObject
*item
; /* temporary new ref */
237 PyObject
*empty_str
; /* temporary new ref */
241 if (!list
) return NULL
;
243 PyErr_SetString(PyExc_ValueError
, "D-Bus structs cannot be empty");
247 /* Set the first and last elements of list to be the parentheses */
248 item
= PyString_FromString(DBUS_STRUCT_BEGIN_CHAR_AS_STRING
);
249 if (PyList_SetItem(list
, 0, item
) < 0) {
253 item
= PyString_FromString(DBUS_STRUCT_END_CHAR_AS_STRING
);
254 if (PyList_SetItem(list
, len
+ 1, item
) < 0) {
258 if (!item
|| !PyList_GET_ITEM(list
, 0)) {
264 for (i
= 0; i
< len
; i
++) {
265 item
= PyTuple_GetItem(obj
, i
);
270 item
= _signature_string_from_pyobject(item
, NULL
);
275 if (PyList_SetItem(list
, i
+ 1, item
) < 0) {
281 empty_str
= PyString_FromString("");
283 /* really shouldn't happen */
287 ret
= PyObject_CallMethod(empty_str
, "join", "(O)", list
); /* new ref */
288 /* whether ret is NULL or not, */
289 Py_DECREF(empty_str
);
293 else if (PyList_Check(obj
)) {
295 PyObject
*ret
= PyString_FromString(DBUS_TYPE_ARRAY_AS_STRING
);
296 if (!ret
) return NULL
;
297 if (DBusPyArray_Check(obj
) && PyString_Check(((DBusPyArray
*)obj
)->signature
)) {
298 PyString_Concat(&ret
, ((DBusPyArray
*)obj
)->signature
);
301 if (PyList_GET_SIZE(obj
) == 0) {
302 /* No items, so fail. Or should we guess "av"? */
303 PyErr_SetString(PyExc_ValueError
, "Unable to guess signature "
304 "from an empty list");
307 tmp
= PyList_GetItem(obj
, 0);
308 tmp
= _signature_string_from_pyobject(tmp
, NULL
);
309 if (!tmp
) return NULL
;
310 PyString_ConcatAndDel(&ret
, tmp
);
313 else if (PyDict_Check(obj
)) {
314 PyObject
*key
, *value
, *keysig
, *valuesig
;
316 PyObject
*ret
= NULL
;
318 if (DBusPyDict_Check(obj
) && PyString_Check(((DBusPyDict
*)obj
)->signature
)) {
319 const char *sig
= PyString_AS_STRING(((DBusPyDict
*)obj
)->signature
);
321 return PyString_FromFormat((DBUS_TYPE_ARRAY_AS_STRING
322 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
324 DBUS_DICT_ENTRY_END_CHAR_AS_STRING
),
327 if (!PyDict_Next(obj
, &pos
, &key
, &value
)) {
328 /* No items, so fail. Or should we guess "a{vv}"? */
329 PyErr_SetString(PyExc_ValueError
, "Unable to guess signature "
330 "from an empty dict");
333 keysig
= _signature_string_from_pyobject(key
, NULL
);
334 valuesig
= _signature_string_from_pyobject(value
, NULL
);
335 if (keysig
&& valuesig
) {
336 ret
= PyString_FromFormat((DBUS_TYPE_ARRAY_AS_STRING
337 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
339 DBUS_DICT_ENTRY_END_CHAR_AS_STRING
),
340 PyString_AS_STRING(keysig
),
341 PyString_AS_STRING(valuesig
));
344 Py_XDECREF(valuesig
);
348 PyErr_Format(PyExc_TypeError
, "Don't know how which D-Bus type "
349 "to use to encode type \"%s\"",
350 obj
->ob_type
->tp_name
);
356 dbus_py_Message_guess_signature(PyObject
*unused UNUSED
, PyObject
*args
)
358 PyObject
*tmp
, *ret
= NULL
;
361 if (!PyErr_Occurred()) {
362 PyErr_BadInternalCall();
368 fprintf(stderr
, "DBG/%ld: called Message_guess_signature", (long)getpid());
369 PyObject_Print(args
, stderr
, 0);
370 fprintf(stderr
, "\n");
373 if (!PyTuple_Check(args
)) {
374 DBG("%s", "Message_guess_signature: args not a tuple");
375 PyErr_BadInternalCall();
379 /* if there were no args, easy */
380 if (PyTuple_GET_SIZE(args
) == 0) {
381 DBG("%s", "Message_guess_signature: no args, so return Signature('')");
382 return PyObject_CallFunction((PyObject
*)&DBusPySignature_Type
, "(s)", "");
385 /* if there were args, the signature we want is, by construction,
386 * exactly the signature we get for the tuple args, except that we don't
387 * want the parentheses. */
388 tmp
= _signature_string_from_pyobject(args
, NULL
);
390 DBG("%s", "Message_guess_signature: failed");
393 if (!PyString_Check(tmp
) || PyString_GET_SIZE(tmp
) < 2) {
394 PyErr_SetString(PyExc_RuntimeError
, "Internal error: "
395 "_signature_string_from_pyobject returned "
400 ret
= PyObject_CallFunction((PyObject
*)&DBusPySignature_Type
, "(s#)",
401 PyString_AS_STRING(tmp
) + 1,
402 PyString_GET_SIZE(tmp
) - 2);
403 DBG("Message_guess_signature: returning Signature at %p \"%s\"", ret
,
404 ret
? PyString_AS_STRING(ret
) : "(NULL)");
409 static int _message_iter_append_pyobject(DBusMessageIter
*appender
,
410 DBusSignatureIter
*sig_iter
,
413 static int _message_iter_append_variant(DBusMessageIter
*appender
,
417 _message_iter_append_string(DBusMessageIter
*appender
,
418 int sig_type
, PyObject
*obj
,
419 dbus_bool_t allow_object_path_attr
)
423 if (sig_type
== DBUS_TYPE_OBJECT_PATH
&& allow_object_path_attr
) {
424 PyObject
*object_path
= get_object_path (obj
);
426 if (object_path
== Py_None
) {
427 Py_DECREF(object_path
);
429 else if (!object_path
) {
433 int ret
= _message_iter_append_string(appender
, sig_type
,
435 Py_DECREF(object_path
);
440 if (PyString_Check(obj
)) {
443 /* Raise TypeError if the string has embedded NULs */
444 if (PyString_AsStringAndSize(obj
, &s
, NULL
) < 0) return -1;
445 /* Surely there's a faster stdlib way to validate UTF-8... */
446 unicode
= PyUnicode_DecodeUTF8(s
, PyString_GET_SIZE(obj
), NULL
);
448 PyErr_SetString(PyExc_UnicodeError
, "String parameters "
449 "to be sent over D-Bus must be valid UTF-8");
455 DBG("Performing actual append: string %s", s
);
456 if (!dbus_message_iter_append_basic(appender
, sig_type
,
462 else if (PyUnicode_Check(obj
)) {
463 PyObject
*utf8
= PyUnicode_AsUTF8String(obj
);
464 if (!utf8
) return -1;
465 /* Raise TypeError if the string has embedded NULs */
466 if (PyString_AsStringAndSize(utf8
, &s
, NULL
) < 0) return -1;
467 DBG("Performing actual append: string (from unicode) %s", s
);
468 if (!dbus_message_iter_append_basic(appender
, sig_type
, &s
)) {
475 PyErr_SetString(PyExc_TypeError
,
476 "Expected a string or unicode object");
483 _message_iter_append_byte(DBusMessageIter
*appender
, PyObject
*obj
)
487 if (PyString_Check(obj
)) {
488 if (PyString_GET_SIZE(obj
) != 1) {
489 PyErr_Format(PyExc_ValueError
, "Expected a string of "
490 "length 1 byte, but found %d bytes",
491 PyString_GET_SIZE(obj
));
494 y
= *(unsigned char *)PyString_AS_STRING(obj
);
497 long i
= PyInt_AsLong(obj
);
499 if (i
== -1 && PyErr_Occurred()) return -1;
500 if (i
< 0 || i
> 0xff) {
501 PyErr_Format(PyExc_ValueError
, "%d outside range for a "
502 "byte value", (int)i
);
507 DBG("Performing actual append: byte \\x%02x", (unsigned)y
);
508 if (!dbus_message_iter_append_basic(appender
, DBUS_TYPE_BYTE
, &y
)) {
516 _message_iter_append_dictentry(DBusMessageIter
*appender
,
517 DBusSignatureIter
*sig_iter
,
518 PyObject
*dict
, PyObject
*key
)
520 DBusSignatureIter sub_sig_iter
;
523 PyObject
*value
= PyObject_GetItem(dict
, key
);
526 if (!value
) return -1;
529 fprintf(stderr
, "Append dictentry: ");
530 PyObject_Print(key
, stderr
, 0);
531 fprintf(stderr
, " => ");
532 PyObject_Print(value
, stderr
, 0);
533 fprintf(stderr
, "\n");
536 DBG("Recursing signature iterator %p -> %p", sig_iter
, &sub_sig_iter
);
537 dbus_signature_iter_recurse(sig_iter
, &sub_sig_iter
);
541 s
= dbus_signature_iter_get_signature(sig_iter
);
542 DBG("Signature of parent iterator %p is %s", sig_iter
, s
);
544 s
= dbus_signature_iter_get_signature(&sub_sig_iter
);
545 DBG("Signature of sub-iterator %p is %s", &sub_sig_iter
, s
);
550 DBG("%s", "Opening DICT_ENTRY container");
551 if (!dbus_message_iter_open_container(appender
, DBUS_TYPE_DICT_ENTRY
,
556 ret
= _message_iter_append_pyobject(&sub
, &sub_sig_iter
, key
, &more
);
558 ret
= _message_iter_append_pyobject(&sub
, &sub_sig_iter
, value
, &more
);
560 DBG("%s", "Closing DICT_ENTRY container");
561 if (!dbus_message_iter_close_container(appender
, &sub
)) {
571 _message_iter_append_multi(DBusMessageIter
*appender
,
572 const DBusSignatureIter
*sig_iter
,
573 int mode
, PyObject
*obj
)
575 DBusMessageIter sub_appender
;
576 DBusSignatureIter sub_sig_iter
;
579 PyObject
*iterator
= PyObject_GetIter(obj
);
581 int container
= mode
;
582 dbus_bool_t is_byte_array
= DBusPyByteArray_Check(obj
);
587 fprintf(stderr
, "Appending multiple: ");
588 PyObject_Print(obj
, stderr
, 0);
589 fprintf(stderr
, "\n");
592 if (!iterator
) return -1;
593 if (mode
== DBUS_TYPE_DICT_ENTRY
) container
= DBUS_TYPE_ARRAY
;
595 DBG("Recursing signature iterator %p -> %p", sig_iter
, &sub_sig_iter
);
596 dbus_signature_iter_recurse(sig_iter
, &sub_sig_iter
);
600 s
= dbus_signature_iter_get_signature(sig_iter
);
601 DBG("Signature of parent iterator %p is %s", sig_iter
, s
);
603 s
= dbus_signature_iter_get_signature(&sub_sig_iter
);
604 DBG("Signature of sub-iterator %p is %s", &sub_sig_iter
, s
);
608 inner_type
= dbus_signature_iter_get_current_type(&sub_sig_iter
);
610 if (mode
== DBUS_TYPE_ARRAY
|| mode
== DBUS_TYPE_DICT_ENTRY
) {
611 sig
= dbus_signature_iter_get_signature(&sub_sig_iter
);
618 /* else leave sig set to NULL. */
620 DBG("Opening %c container", container
);
621 if (!dbus_message_iter_open_container(appender
, container
,
622 sig
, &sub_appender
)) {
628 while ((contents
= PyIter_Next(iterator
))) {
630 if (mode
== DBUS_TYPE_ARRAY
|| mode
== DBUS_TYPE_DICT_ENTRY
) {
631 DBG("Recursing signature iterator %p -> %p", sig_iter
, &sub_sig_iter
);
632 dbus_signature_iter_recurse(sig_iter
, &sub_sig_iter
);
636 s
= dbus_signature_iter_get_signature(sig_iter
);
637 DBG("Signature of parent iterator %p is %s", sig_iter
, s
);
639 s
= dbus_signature_iter_get_signature(&sub_sig_iter
);
640 DBG("Signature of sub-iterator %p is %s", &sub_sig_iter
, s
);
646 if (mode
== DBUS_TYPE_DICT_ENTRY
) {
647 ret
= _message_iter_append_dictentry(&sub_appender
, &sub_sig_iter
,
650 else if (mode
== DBUS_TYPE_ARRAY
&& is_byte_array
651 && inner_type
== DBUS_TYPE_VARIANT
) {
652 /* Subscripting a ByteArray gives a str of length 1, but if the
653 * container is a ByteArray and the parameter is an array of
654 * variants, we want to produce an array of variants containing
655 * bytes, not strings.
657 PyObject
*args
= Py_BuildValue("(O)", contents
);
662 byte
= PyObject_Call((PyObject
*)&DBusPyByte_Type
, args
, NULL
);
666 ret
= _message_iter_append_variant(&sub_appender
, byte
);
670 /* advances sub_sig_iter and sets more on success - for array
671 * this doesn't matter, for struct it's essential */
672 ret
= _message_iter_append_pyobject(&sub_appender
, &sub_sig_iter
,
682 if (PyErr_Occurred()) {
685 else if (mode
== DBUS_TYPE_STRUCT
&& more
) {
686 PyErr_Format(PyExc_TypeError
, "More items found in struct's D-Bus "
687 "signature than in Python arguments ");
691 /* This must be run as cleanup, even on failure. */
692 DBG("Closing %c container", container
);
693 if (!dbus_message_iter_close_container(appender
, &sub_appender
)) {
699 Py_XDECREF(iterator
);
705 _message_iter_append_string_as_byte_array(DBusMessageIter
*appender
,
708 /* a bit of a faster path for byte arrays that are strings */
709 Py_ssize_t len
= PyString_GET_SIZE(obj
);
714 s
= PyString_AS_STRING(obj
);
715 DBG("%s", "Opening ARRAY container");
716 if (!dbus_message_iter_open_container(appender
, DBUS_TYPE_ARRAY
,
717 DBUS_TYPE_BYTE_AS_STRING
, &sub
)) {
721 DBG("Appending fixed array of %d bytes", len
);
722 if (dbus_message_iter_append_fixed_array(&sub
, DBUS_TYPE_BYTE
, &s
, len
)) {
729 DBG("%s", "Closing ARRAY container");
730 if (!dbus_message_iter_close_container(appender
, &sub
)) {
737 /* Encode some Python object into a D-Bus variant slot. */
739 _message_iter_append_variant(DBusMessageIter
*appender
, PyObject
*obj
)
741 DBusSignatureIter obj_sig_iter
;
742 const char *obj_sig_str
;
748 /* Separate the object into the contained object, and the number of
749 * variants it's wrapped in. */
750 obj_sig
= _signature_string_from_pyobject(obj
, &variant_level
);
751 if (!obj_sig
) return -1;
753 obj_sig_str
= PyString_AsString(obj_sig
);
754 if (!obj_sig_str
) return -1;
756 if (variant_level
< 1) {
760 dbus_signature_iter_init(&obj_sig_iter
, obj_sig_str
);
762 { /* scope for variant_iters */
763 DBusMessageIter variant_iters
[variant_level
];
766 for (i
= 0; i
< variant_level
; i
++) {
767 DBusMessageIter
*child
= &variant_iters
[i
];
768 /* The first is a special case: its parent is the iter passed in
769 * to this function, instead of being the previous one in the
772 DBusMessageIter
*parent
= (i
== 0
774 : &(variant_iters
[i
-1]));
775 /* The last is also a special case: it contains the actual
776 * object, rather than another variant
778 const char *sig_str
= (i
== variant_level
-1
780 : DBUS_TYPE_VARIANT_AS_STRING
);
782 DBG("Opening VARIANT container %p inside %p containing '%s'",
783 child
, parent
, sig_str
);
784 if (!dbus_message_iter_open_container(parent
, DBUS_TYPE_VARIANT
,
792 /* Put the object itself into the innermost variant */
793 ret
= _message_iter_append_pyobject(&variant_iters
[variant_level
-1],
794 &obj_sig_iter
, obj
, &dummy
);
796 /* here we rely on i (and variant_level) being a signed long */
797 for (i
= variant_level
- 1; i
>= 0; i
--) {
798 DBusMessageIter
*child
= &variant_iters
[i
];
799 /* The first is a special case: its parent is the iter passed in
800 * to this function, instead of being the previous one in the
803 DBusMessageIter
*parent
= (i
== 0 ? appender
804 : &(variant_iters
[i
-1]));
806 DBG("Closing VARIANT container %p inside %p", child
, parent
);
807 if (!dbus_message_iter_close_container(parent
, child
)) {
821 /* On success, *more is set to whether there's more in the signature. */
823 _message_iter_append_pyobject(DBusMessageIter
*appender
,
824 DBusSignatureIter
*sig_iter
,
828 int sig_type
= dbus_signature_iter_get_current_type(sig_iter
);
832 dbus_uint16_t uint16
;
834 dbus_uint32_t uint32
;
836 #if defined(DBUS_HAVE_INT64) && defined(HAVE_LONG_LONG)
837 dbus_uint64_t uint64
;
844 fprintf(stderr
, "Appending object at %p: ", obj
);
845 PyObject_Print(obj
, stderr
, 0);
846 fprintf(stderr
, " into appender at %p, dbus wants type %c\n",
851 /* The numeric types are relatively simple to deal with, so are
854 case DBUS_TYPE_BOOLEAN
:
855 if (PyObject_IsTrue(obj
)) {
861 DBG("Performing actual append: bool(%ld)", (long)u
.b
);
862 if (!dbus_message_iter_append_basic(appender
, sig_type
, &u
.b
)) {
870 case DBUS_TYPE_DOUBLE
:
871 u
.d
= PyFloat_AsDouble(obj
);
872 if (PyErr_Occurred()) {
876 DBG("Performing actual append: double(%f)", u
.d
);
877 if (!dbus_message_iter_append_basic(appender
, sig_type
, &u
.d
)) {
885 #ifdef WITH_DBUS_FLOAT32
886 case DBUS_TYPE_FLOAT
:
887 u
.d
= PyFloat_AsDouble(obj
);
888 if (PyErr_Occurred()) {
893 DBG("Performing actual append: float(%f)", u
.f
);
894 if (!dbus_message_iter_append_basic(appender
, sig_type
, &u
.f
)) {
903 /* The integer types are all basically the same - we delegate to
904 intNN_range_check() */
905 #define PROCESS_INTEGER(size) \
906 u.size = dbus_py_##size##_range_check(obj);\
907 if (u.size == (dbus_##size##_t)(-1) && PyErr_Occurred()) {\
911 DBG("Performing actual append: " #size "(%lld)", (long long)u.size); \
912 if (!dbus_message_iter_append_basic(appender, sig_type, &u.size)) {\
919 case DBUS_TYPE_INT16
:
920 PROCESS_INTEGER(int16
)
922 case DBUS_TYPE_UINT16
:
923 PROCESS_INTEGER(uint16
)
925 case DBUS_TYPE_INT32
:
926 PROCESS_INTEGER(int32
)
928 case DBUS_TYPE_UINT32
:
929 PROCESS_INTEGER(uint32
)
931 #if defined(DBUS_HAVE_INT64) && defined(HAVE_LONG_LONG)
932 case DBUS_TYPE_INT64
:
933 PROCESS_INTEGER(int64
)
935 case DBUS_TYPE_UINT64
:
936 PROCESS_INTEGER(uint64
)
939 case DBUS_TYPE_INT64
:
940 case DBUS_TYPE_UINT64
:
941 PyErr_SetString(PyExc_NotImplementedError
, "64-bit integer "
942 "types are not supported on this platform");
946 #undef PROCESS_INTEGER
948 /* Now the more complicated cases, which are delegated to helper
949 * functions (although in practice, the compiler will hopefully
950 * inline them anyway). */
952 case DBUS_TYPE_STRING
:
953 case DBUS_TYPE_SIGNATURE
:
954 case DBUS_TYPE_OBJECT_PATH
:
955 ret
= _message_iter_append_string(appender
, sig_type
, obj
, TRUE
);
959 ret
= _message_iter_append_byte(appender
, obj
);
962 case DBUS_TYPE_ARRAY
:
963 /* 3 cases - it might actually be a dict, or it might be a byte array
964 * being copied from a string (for which we have a faster path),
965 * or it might be a generic array. */
967 sig_type
= dbus_signature_iter_get_element_type(sig_iter
);
968 if (sig_type
== DBUS_TYPE_DICT_ENTRY
)
969 ret
= _message_iter_append_multi(appender
, sig_iter
,
970 DBUS_TYPE_DICT_ENTRY
, obj
);
971 else if (sig_type
== DBUS_TYPE_BYTE
&& PyString_Check(obj
))
972 ret
= _message_iter_append_string_as_byte_array(appender
, obj
);
974 ret
= _message_iter_append_multi(appender
, sig_iter
,
975 DBUS_TYPE_ARRAY
, obj
);
976 DBG("_message_iter_append_multi(): %d", ret
);
979 case DBUS_TYPE_STRUCT
:
980 ret
= _message_iter_append_multi(appender
, sig_iter
, sig_type
, obj
);
983 case DBUS_TYPE_VARIANT
:
984 ret
= _message_iter_append_variant(appender
, obj
);
987 case DBUS_TYPE_INVALID
:
988 PyErr_SetString(PyExc_TypeError
, "Fewer items found in D-Bus "
989 "signature than in Python arguments");
994 PyErr_Format(PyExc_TypeError
, "Unknown type '\\x%x' in D-Bus "
995 "signature", sig_type
);
999 if (ret
< 0) return -1;
1001 DBG("Advancing signature iter at %p", sig_iter
);
1002 *more
= dbus_signature_iter_next(sig_iter
);
1004 DBG("- result: %ld, type %02x '%c'", (long)(*more
),
1005 (int)dbus_signature_iter_get_current_type(sig_iter
),
1006 (int)dbus_signature_iter_get_current_type(sig_iter
));
1013 dbus_py_Message_append(Message
*self
, PyObject
*args
, PyObject
*kwargs
)
1015 const char *signature
= NULL
;
1016 PyObject
*signature_obj
= NULL
;
1017 DBusSignatureIter sig_iter
;
1018 DBusMessageIter appender
;
1020 static char *argnames
[] = {"signature", NULL
};
1021 /* must start FALSE for the case where there's nothing there and we
1022 * never iterate at all */
1025 if (!self
->msg
) return DBusPy_RaiseUnusableMessage();
1028 fprintf(stderr
, "DBG/%ld: called Message_append(*", (long)getpid());
1029 PyObject_Print(args
, stderr
, 0);
1031 fprintf(stderr
, ", **");
1032 PyObject_Print(kwargs
, stderr
, 0);
1034 fprintf(stderr
, ")\n");
1037 /* only use kwargs for this step: deliberately ignore args for now */
1038 if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple
, kwargs
, "|z:append",
1039 argnames
, &signature
)) return NULL
;
1042 DBG("%s", "No signature for message, guessing...");
1043 signature_obj
= dbus_py_Message_guess_signature(NULL
, args
);
1044 if (!signature_obj
) return NULL
;
1045 signature
= PyString_AS_STRING(signature_obj
);
1047 /* from here onwards, you have to do a goto rather than returning NULL
1048 to make sure signature_obj gets freed */
1050 /* iterate over args and the signature, together */
1051 if (!dbus_signature_validate(signature
, NULL
)) {
1052 PyErr_SetString(PyExc_ValueError
, "Corrupt type signature");
1055 dbus_signature_iter_init(&sig_iter
, signature
);
1056 dbus_message_iter_init_append(self
->msg
, &appender
);
1057 more
= (signature
[0] != '\0');
1058 for (i
= 0; i
< PyTuple_GET_SIZE(args
); i
++) {
1059 if (_message_iter_append_pyobject(&appender
, &sig_iter
,
1060 PyTuple_GET_ITEM(args
, i
),
1066 PyErr_SetString(PyExc_TypeError
, "More items found in D-Bus "
1067 "signature than in Python arguments");
1072 Py_XDECREF(signature_obj
);
1076 /* "If appending any of the arguments fails due to lack of memory,
1077 * generally the message is hosed and you have to start over" -libdbus docs
1078 * Enforce this by throwing away the message structure.
1080 dbus_message_unref(self
->msg
);
1083 Py_XDECREF(signature_obj
);
1087 /* vim:set ft=c cino< sw=4 sts=4 et: */