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 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #define DBG_IS_TOO_VERBOSE
27 #include "types-internal.h"
28 #include "message-internal.h"
30 /* Return the number of variants wrapping the given object. Return 0
31 * if the object is not a D-Bus type.
34 get_variant_level(PyObject
*obj
)
36 if (DBusPyIntBase_Check(obj
)) {
37 return ((DBusPyIntBase
*)obj
)->variant_level
;
39 else if (DBusPyFloatBase_Check(obj
)) {
40 return ((DBusPyFloatBase
*)obj
)->variant_level
;
42 else if (DBusPyArray_Check(obj
)) {
43 return ((DBusPyArray
*)obj
)->variant_level
;
45 else if (DBusPyDict_Check(obj
)) {
46 return ((DBusPyDict
*)obj
)->variant_level
;
48 else if (DBusPyLongBase_Check(obj
) ||
49 DBusPyStrBase_Check(obj
) ||
50 DBusPyString_Check(obj
) ||
51 DBusPyStruct_Check(obj
)) {
52 return PyInt_AsLong(PyObject_GetAttr(obj
, dbus_py_variant_level_const
));
59 char dbus_py_Message_append__doc__
[] = (
60 "set_args(*args[, **kwargs])\n\n"
61 "Set the message's arguments from the positional parameter, according to\n"
62 "the signature given by the ``signature`` keyword parameter.\n"
64 "The following type conversions are supported:\n\n"
65 "=============================== ===========================\n"
66 "D-Bus (in signature) Python\n"
67 "=============================== ===========================\n"
68 "boolean (b) any object (via bool())\n"
69 "byte (y) string of length 1\n"
71 "any integer type any integer\n"
72 "double (d) any float\n"
73 "object path anything with a __dbus_object_path__ attribute\n"
74 "string, signature, object path str (must be UTF-8) or unicode\n"
75 "dict (a{...}) any mapping\n"
76 "array (a...) any iterable over appropriate objects\n"
77 "struct ((...)) any iterable over appropriate objects\n"
78 "variant any object above (guess type as below)\n"
79 "=============================== ===========================\n"
81 "Here 'any integer' means anything on which int() or long()\n"
82 "(as appropriate) will work, except for basestring subclasses.\n"
83 "'Any float' means anything on which float() will work, except\n"
84 "for basestring subclasses.\n"
86 "If there is no signature, guess from the arguments using\n"
87 "the static method `Message.guess_signature`.\n"
90 char dbus_py_Message_guess_signature__doc__
[] = (
91 "guess_signature(*args) -> Signature [static method]\n\n"
92 "Guess a D-Bus signature which should be used to encode the given\n"
95 "The signature is constructed as follows:\n\n"
96 "+-------------------------------+---------------------------+\n"
98 "+===============================+===========================+\n"
99 "|D-Bus type, variant_level > 0 |variant (v) |\n"
100 "+-------------------------------+---------------------------+\n"
101 "|D-Bus type, variant_level == 0 |the corresponding type |\n"
102 "+-------------------------------+---------------------------+\n"
103 "|anything with a |object path |\n"
104 "|__dbus_object_path__ attribute | |\n"
105 "+-------------------------------+---------------------------+\n"
106 "|bool |boolean (y) |\n"
107 "+-------------------------------+---------------------------+\n"
108 "|any other int subclass |int32 (i) |\n"
109 "+-------------------------------+---------------------------+\n"
110 "|any other long subclass |int64 (x) |\n"
111 "+-------------------------------+---------------------------+\n"
112 "|any other float subclass |double (d) |\n"
113 "+-------------------------------+---------------------------+\n"
114 "|any other str subclass |string (s) |\n"
115 "+-------------------------------+---------------------------+\n"
116 "|any other unicode subclass |string (s) |\n"
117 "+-------------------------------+---------------------------+\n"
118 "|any other tuple subclass |struct ((...)) |\n"
119 "+-------------------------------+---------------------------+\n"
120 "|any other list subclass |array (a...), guess |\n"
121 "| |contents' type according to|\n"
122 "| |type of first item |\n"
123 "+-------------------------------+---------------------------+\n"
124 "|any other dict subclass |dict (a{...}), guess key, |\n"
125 "| |value type according to |\n"
126 "| |types for an arbitrary item|\n"
127 "+-------------------------------+---------------------------+\n"
128 "|anything else |raise TypeError |\n"
129 "+-------------------------------+---------------------------+\n"
132 /* return a new reference, possibly to None */
134 get_object_path(PyObject
*obj
)
136 PyObject
*magic_attr
= PyObject_GetAttr(obj
, dbus_py__dbus_object_path__const
);
139 if (PyString_Check(magic_attr
)) {
143 Py_DECREF(magic_attr
);
144 PyErr_SetString(PyExc_TypeError
, "__dbus_object_path__ must be "
150 /* Ignore exceptions, except for SystemExit and KeyboardInterrupt */
151 if (PyErr_ExceptionMatches(PyExc_SystemExit
) ||
152 PyErr_ExceptionMatches(PyExc_KeyboardInterrupt
))
159 /* Return a new reference. If the object is a variant and variant_level_ptr
160 * is not NULL, put the variant level in the variable pointed to, and
161 * return the contained type instead of "v". */
163 _signature_string_from_pyobject(PyObject
*obj
, long *variant_level_ptr
)
165 PyObject
*magic_attr
;
166 long variant_level
= get_variant_level(obj
);
167 if (variant_level_ptr
) {
168 *variant_level_ptr
= variant_level
;
170 else if (variant_level
> 0) {
171 return PyString_FromString(DBUS_TYPE_VARIANT_AS_STRING
);
174 if (obj
== Py_True
|| obj
== Py_False
) {
175 return PyString_FromString(DBUS_TYPE_BOOLEAN_AS_STRING
);
178 magic_attr
= get_object_path(obj
);
181 if (magic_attr
!= Py_None
) {
182 Py_DECREF(magic_attr
);
183 return PyString_FromString(DBUS_TYPE_OBJECT_PATH_AS_STRING
);
185 Py_DECREF(magic_attr
);
187 /* Ordering is important: some of these are subclasses of each other. */
188 if (PyInt_Check(obj
)) {
189 if (DBusPyInt16_Check(obj
))
190 return PyString_FromString(DBUS_TYPE_INT16_AS_STRING
);
191 else if (DBusPyInt32_Check(obj
))
192 return PyString_FromString(DBUS_TYPE_INT32_AS_STRING
);
193 else if (DBusPyByte_Check(obj
))
194 return PyString_FromString(DBUS_TYPE_BYTE_AS_STRING
);
195 else if (DBusPyUInt16_Check(obj
))
196 return PyString_FromString(DBUS_TYPE_UINT16_AS_STRING
);
197 else if (DBusPyBoolean_Check(obj
))
198 return PyString_FromString(DBUS_TYPE_BOOLEAN_AS_STRING
);
200 return PyString_FromString(DBUS_TYPE_INT32_AS_STRING
);
202 else if (PyLong_Check(obj
)) {
203 if (DBusPyInt64_Check(obj
))
204 return PyString_FromString(DBUS_TYPE_INT64_AS_STRING
);
205 else if (DBusPyUInt32_Check(obj
))
206 return PyString_FromString(DBUS_TYPE_UINT32_AS_STRING
);
207 else if (DBusPyUInt64_Check(obj
))
208 return PyString_FromString(DBUS_TYPE_UINT64_AS_STRING
);
210 return PyString_FromString(DBUS_TYPE_INT64_AS_STRING
);
212 else if (PyUnicode_Check(obj
))
213 return PyString_FromString(DBUS_TYPE_STRING_AS_STRING
);
214 else if (PyFloat_Check(obj
)) {
215 #ifdef WITH_DBUS_FLOAT32
216 if (DBusPyDouble_Check(obj
))
217 return PyString_FromString(DBUS_TYPE_DOUBLE_AS_STRING
);
218 else if (DBusPyFloat_Check(obj
))
219 return PyString_FromString(DBUS_TYPE_FLOAT_AS_STRING
);
222 return PyString_FromString(DBUS_TYPE_DOUBLE_AS_STRING
);
224 else if (PyString_Check(obj
)) {
225 if (DBusPyObjectPath_Check(obj
))
226 return PyString_FromString(DBUS_TYPE_OBJECT_PATH_AS_STRING
);
227 else if (DBusPySignature_Check(obj
))
228 return PyString_FromString(DBUS_TYPE_SIGNATURE_AS_STRING
);
229 else if (DBusPyByteArray_Check(obj
))
230 return PyString_FromString(DBUS_TYPE_ARRAY_AS_STRING
231 DBUS_TYPE_BYTE_AS_STRING
);
233 return PyString_FromString(DBUS_TYPE_STRING_AS_STRING
);
235 else if (PyTuple_Check(obj
)) {
236 int len
= PyTuple_GET_SIZE(obj
);
237 PyObject
*list
= PyList_New(len
+ 2); /* new ref */
238 PyObject
*item
; /* temporary new ref */
239 PyObject
*empty_str
; /* temporary new ref */
243 if (!list
) return NULL
;
245 PyErr_SetString(PyExc_ValueError
, "D-Bus structs cannot be empty");
249 /* Set the first and last elements of list to be the parentheses */
250 item
= PyString_FromString(DBUS_STRUCT_BEGIN_CHAR_AS_STRING
);
251 if (PyList_SetItem(list
, 0, item
) < 0) {
255 item
= PyString_FromString(DBUS_STRUCT_END_CHAR_AS_STRING
);
256 if (PyList_SetItem(list
, len
+ 1, item
) < 0) {
260 if (!item
|| !PyList_GET_ITEM(list
, 0)) {
266 for (i
= 0; i
< len
; i
++) {
267 item
= PyTuple_GetItem(obj
, i
);
272 item
= _signature_string_from_pyobject(item
, NULL
);
277 if (PyList_SetItem(list
, i
+ 1, item
) < 0) {
283 empty_str
= PyString_FromString("");
285 /* really shouldn't happen */
289 ret
= PyObject_CallMethod(empty_str
, "join", "(O)", list
); /* new ref */
290 /* whether ret is NULL or not, */
291 Py_DECREF(empty_str
);
295 else if (PyList_Check(obj
)) {
297 PyObject
*ret
= PyString_FromString(DBUS_TYPE_ARRAY_AS_STRING
);
298 if (!ret
) return NULL
;
299 if (DBusPyArray_Check(obj
) && PyString_Check(((DBusPyArray
*)obj
)->signature
)) {
300 PyString_Concat(&ret
, ((DBusPyArray
*)obj
)->signature
);
303 if (PyList_GET_SIZE(obj
) == 0) {
304 /* No items, so fail. Or should we guess "av"? */
305 PyErr_SetString(PyExc_ValueError
, "Unable to guess signature "
306 "from an empty list");
309 tmp
= PyList_GetItem(obj
, 0);
310 tmp
= _signature_string_from_pyobject(tmp
, NULL
);
311 if (!tmp
) return NULL
;
312 PyString_ConcatAndDel(&ret
, tmp
);
315 else if (PyDict_Check(obj
)) {
316 PyObject
*key
, *value
, *keysig
, *valuesig
;
318 PyObject
*ret
= NULL
;
320 if (DBusPyDict_Check(obj
) && PyString_Check(((DBusPyDict
*)obj
)->signature
)) {
321 const char *sig
= PyString_AS_STRING(((DBusPyDict
*)obj
)->signature
);
323 return PyString_FromFormat((DBUS_TYPE_ARRAY_AS_STRING
324 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
326 DBUS_DICT_ENTRY_END_CHAR_AS_STRING
),
329 if (!PyDict_Next(obj
, &pos
, &key
, &value
)) {
330 /* No items, so fail. Or should we guess "a{vv}"? */
331 PyErr_SetString(PyExc_ValueError
, "Unable to guess signature "
332 "from an empty dict");
335 keysig
= _signature_string_from_pyobject(key
, NULL
);
336 valuesig
= _signature_string_from_pyobject(value
, NULL
);
337 if (keysig
&& valuesig
) {
338 ret
= PyString_FromFormat((DBUS_TYPE_ARRAY_AS_STRING
339 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
341 DBUS_DICT_ENTRY_END_CHAR_AS_STRING
),
342 PyString_AS_STRING(keysig
),
343 PyString_AS_STRING(valuesig
));
346 Py_XDECREF(valuesig
);
350 PyErr_Format(PyExc_TypeError
, "Don't know how which D-Bus type "
351 "to use to encode type \"%s\"",
352 obj
->ob_type
->tp_name
);
358 dbus_py_Message_guess_signature(PyObject
*unused UNUSED
, PyObject
*args
)
360 PyObject
*tmp
, *ret
= NULL
;
363 if (!PyErr_Occurred()) {
364 PyErr_BadInternalCall();
370 fprintf(stderr
, "DBG/%ld: called Message_guess_signature", (long)getpid());
371 PyObject_Print(args
, stderr
, 0);
372 fprintf(stderr
, "\n");
375 if (!PyTuple_Check(args
)) {
376 DBG("%s", "Message_guess_signature: args not a tuple");
377 PyErr_BadInternalCall();
381 /* if there were no args, easy */
382 if (PyTuple_GET_SIZE(args
) == 0) {
383 DBG("%s", "Message_guess_signature: no args, so return Signature('')");
384 return PyObject_CallFunction((PyObject
*)&DBusPySignature_Type
, "(s)", "");
387 /* if there were args, the signature we want is, by construction,
388 * exactly the signature we get for the tuple args, except that we don't
389 * want the parentheses. */
390 tmp
= _signature_string_from_pyobject(args
, NULL
);
392 DBG("%s", "Message_guess_signature: failed");
395 if (!PyString_Check(tmp
) || PyString_GET_SIZE(tmp
) < 2) {
396 PyErr_SetString(PyExc_RuntimeError
, "Internal error: "
397 "_signature_string_from_pyobject returned "
402 ret
= PyObject_CallFunction((PyObject
*)&DBusPySignature_Type
, "(s#)",
403 PyString_AS_STRING(tmp
) + 1,
404 PyString_GET_SIZE(tmp
) - 2);
405 DBG("Message_guess_signature: returning Signature at %p \"%s\"", ret
,
406 ret
? PyString_AS_STRING(ret
) : "(NULL)");
411 static int _message_iter_append_pyobject(DBusMessageIter
*appender
,
412 DBusSignatureIter
*sig_iter
,
414 static int _message_iter_append_variant(DBusMessageIter
*appender
,
418 _message_iter_append_string(DBusMessageIter
*appender
,
419 int sig_type
, PyObject
*obj
,
420 dbus_bool_t allow_object_path_attr
)
424 if (sig_type
== DBUS_TYPE_OBJECT_PATH
&& allow_object_path_attr
) {
425 PyObject
*object_path
= get_object_path (obj
);
427 if (object_path
== Py_None
) {
428 Py_DECREF(object_path
);
430 else if (!object_path
) {
434 int ret
= _message_iter_append_string(appender
, sig_type
,
436 Py_DECREF(object_path
);
441 if (PyString_Check(obj
)) {
444 /* Raise TypeError if the string has embedded NULs */
445 if (PyString_AsStringAndSize(obj
, &s
, NULL
) < 0) return -1;
446 /* Surely there's a faster stdlib way to validate UTF-8... */
447 unicode
= PyUnicode_DecodeUTF8(s
, PyString_GET_SIZE(obj
), NULL
);
449 PyErr_SetString(PyExc_UnicodeError
, "String parameters "
450 "to be sent over D-Bus must be valid UTF-8");
456 DBG("Performing actual append: string %s", s
);
457 if (!dbus_message_iter_append_basic(appender
, sig_type
,
463 else if (PyUnicode_Check(obj
)) {
464 PyObject
*utf8
= PyUnicode_AsUTF8String(obj
);
465 if (!utf8
) return -1;
466 /* Raise TypeError if the string has embedded NULs */
467 if (PyString_AsStringAndSize(utf8
, &s
, NULL
) < 0) return -1;
468 DBG("Performing actual append: string (from unicode) %s", s
);
469 if (!dbus_message_iter_append_basic(appender
, sig_type
, &s
)) {
476 PyErr_SetString(PyExc_TypeError
,
477 "Expected a string or unicode object");
484 _message_iter_append_byte(DBusMessageIter
*appender
, PyObject
*obj
)
488 if (PyString_Check(obj
)) {
489 if (PyString_GET_SIZE(obj
) != 1) {
490 PyErr_Format(PyExc_ValueError
, "Expected a string of "
491 "length 1 byte, but found %d bytes",
492 PyString_GET_SIZE(obj
));
495 y
= *(unsigned char *)PyString_AS_STRING(obj
);
498 long i
= PyInt_AsLong(obj
);
500 if (i
== -1 && PyErr_Occurred()) return -1;
501 if (i
< 0 || i
> 0xff) {
502 PyErr_Format(PyExc_ValueError
, "%d outside range for a "
503 "byte value", (int)i
);
508 DBG("Performing actual append: byte \\x%02x", (unsigned)y
);
509 if (!dbus_message_iter_append_basic(appender
, DBUS_TYPE_BYTE
, &y
)) {
517 _message_iter_append_dictentry(DBusMessageIter
*appender
,
518 DBusSignatureIter
*sig_iter
,
519 PyObject
*dict
, PyObject
*key
)
521 DBusSignatureIter sub_sig_iter
;
524 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
);
558 ret
= _message_iter_append_pyobject(&sub
, &sub_sig_iter
, value
);
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
);
586 fprintf(stderr
, "Appending multiple: ");
587 PyObject_Print(obj
, stderr
, 0);
588 fprintf(stderr
, "\n");
591 if (!iterator
) return -1;
592 if (mode
== DBUS_TYPE_DICT_ENTRY
) container
= DBUS_TYPE_ARRAY
;
594 DBG("Recursing signature iterator %p -> %p", sig_iter
, &sub_sig_iter
);
595 dbus_signature_iter_recurse(sig_iter
, &sub_sig_iter
);
599 s
= dbus_signature_iter_get_signature(sig_iter
);
600 DBG("Signature of parent iterator %p is %s", sig_iter
, s
);
602 s
= dbus_signature_iter_get_signature(&sub_sig_iter
);
603 DBG("Signature of sub-iterator %p is %s", &sub_sig_iter
, s
);
607 inner_type
= dbus_signature_iter_get_current_type(&sub_sig_iter
);
609 if (mode
== DBUS_TYPE_ARRAY
|| mode
== DBUS_TYPE_DICT_ENTRY
) {
610 sig
= dbus_signature_iter_get_signature(&sub_sig_iter
);
617 /* else leave sig set to NULL. */
619 DBG("Opening %c container", container
);
620 if (!dbus_message_iter_open_container(appender
, container
,
621 sig
, &sub_appender
)) {
627 while ((contents
= PyIter_Next(iterator
))) {
629 if (mode
== DBUS_TYPE_ARRAY
|| mode
== DBUS_TYPE_DICT_ENTRY
) {
630 DBG("Recursing signature iterator %p -> %p", sig_iter
, &sub_sig_iter
);
631 dbus_signature_iter_recurse(sig_iter
, &sub_sig_iter
);
635 s
= dbus_signature_iter_get_signature(sig_iter
);
636 DBG("Signature of parent iterator %p is %s", sig_iter
, s
);
638 s
= dbus_signature_iter_get_signature(&sub_sig_iter
);
639 DBG("Signature of sub-iterator %p is %s", &sub_sig_iter
, s
);
645 if (mode
== DBUS_TYPE_DICT_ENTRY
) {
646 ret
= _message_iter_append_dictentry(&sub_appender
, &sub_sig_iter
,
649 else if (mode
== DBUS_TYPE_ARRAY
&& is_byte_array
650 && inner_type
== DBUS_TYPE_VARIANT
) {
651 /* Subscripting a ByteArray gives a str of length 1, but if the
652 * container is a ByteArray and the parameter is an array of
653 * variants, we want to produce an array of variants containing
654 * bytes, not strings.
656 PyObject
*args
= Py_BuildValue("(O)", contents
);
661 byte
= PyObject_Call((PyObject
*)&DBusPyByte_Type
, args
, NULL
);
665 ret
= _message_iter_append_variant(&sub_appender
, byte
);
669 ret
= _message_iter_append_pyobject(&sub_appender
, &sub_sig_iter
,
677 if (PyErr_Occurred()) ret
= -1;
678 /* This must be run as cleanup, even on failure. */
679 DBG("Closing %c container", container
);
680 if (!dbus_message_iter_close_container(appender
, &sub_appender
)) {
686 Py_XDECREF(iterator
);
692 _message_iter_append_string_as_byte_array(DBusMessageIter
*appender
,
695 /* a bit of a faster path for byte arrays that are strings */
696 int len
= PyString_GET_SIZE(obj
);
701 s
= PyString_AS_STRING(obj
);
702 DBG("%s", "Opening ARRAY container");
703 if (!dbus_message_iter_open_container(appender
, DBUS_TYPE_ARRAY
,
704 DBUS_TYPE_BYTE_AS_STRING
, &sub
)) {
708 DBG("Appending fixed array of %d bytes", len
);
709 if (dbus_message_iter_append_fixed_array(&sub
, DBUS_TYPE_BYTE
, &s
, len
)) {
716 DBG("%s", "Closing ARRAY container");
717 if (!dbus_message_iter_close_container(appender
, &sub
)) {
724 /* Encode some Python object into a D-Bus variant slot. */
726 _message_iter_append_variant(DBusMessageIter
*appender
, PyObject
*obj
)
728 DBusSignatureIter obj_sig_iter
;
729 const char *obj_sig_str
;
734 /* Separate the object into the contained object, and the number of
735 * variants it's wrapped in. */
736 obj_sig
= _signature_string_from_pyobject(obj
, &variant_level
);
737 if (!obj_sig
) return -1;
739 obj_sig_str
= PyString_AsString(obj_sig
);
740 if (!obj_sig_str
) return -1;
742 if (variant_level
< 1) {
746 dbus_signature_iter_init(&obj_sig_iter
, obj_sig_str
);
748 { /* scope for variant_iters */
749 DBusMessageIter variant_iters
[variant_level
];
752 for (i
= 0; i
< variant_level
; i
++) {
753 DBusMessageIter
*child
= &variant_iters
[i
];
754 /* The first is a special case: its parent is the iter passed in
755 * to this function, instead of being the previous one in the
758 DBusMessageIter
*parent
= (i
== 0
760 : &(variant_iters
[i
-1]));
761 /* The last is also a special case: it contains the actual
762 * object, rather than another variant
764 const char *sig_str
= (i
== variant_level
-1
766 : DBUS_TYPE_VARIANT_AS_STRING
);
768 DBG("Opening VARIANT container %p inside %p containing '%s'",
769 child
, parent
, sig_str
);
770 if (!dbus_message_iter_open_container(parent
, DBUS_TYPE_VARIANT
,
778 /* Put the object itself into the innermost variant */
779 ret
= _message_iter_append_pyobject(&variant_iters
[variant_level
-1],
782 /* here we rely on i (and variant_level) being a signed long */
783 for (i
= variant_level
- 1; i
>= 0; i
--) {
784 DBusMessageIter
*child
= &variant_iters
[i
];
785 /* The first is a special case: its parent is the iter passed in
786 * to this function, instead of being the previous one in the
789 DBusMessageIter
*parent
= (i
== 0 ? appender
790 : &(variant_iters
[i
-1]));
792 DBG("Closing VARIANT container %p inside %p", child
, parent
);
793 if (!dbus_message_iter_close_container(parent
, child
)) {
808 _message_iter_append_pyobject(DBusMessageIter
*appender
,
809 DBusSignatureIter
*sig_iter
,
812 int sig_type
= dbus_signature_iter_get_current_type(sig_iter
);
816 dbus_uint16_t uint16
;
818 dbus_uint32_t uint32
;
820 #if defined(DBUS_HAVE_INT64) && defined(HAVE_LONG_LONG)
821 dbus_uint64_t uint64
;
828 fprintf(stderr
, "Appending object at %p: ", obj
);
829 PyObject_Print(obj
, stderr
, 0);
830 fprintf(stderr
, " into appender at %p, dbus wants type %c\n",
835 /* The numeric types are relatively simple to deal with, so are
838 case DBUS_TYPE_BOOLEAN
:
839 if (PyObject_IsTrue(obj
)) {
845 DBG("Performing actual append: bool(%ld)", (long)u
.b
);
846 if (!dbus_message_iter_append_basic(appender
, sig_type
, &u
.b
)) {
854 case DBUS_TYPE_DOUBLE
:
855 u
.d
= PyFloat_AsDouble(obj
);
856 if (PyErr_Occurred()) {
860 DBG("Performing actual append: double(%f)", u
.d
);
861 if (!dbus_message_iter_append_basic(appender
, sig_type
, &u
.d
)) {
869 #ifdef WITH_DBUS_FLOAT32
870 case DBUS_TYPE_FLOAT
:
871 u
.d
= PyFloat_AsDouble(obj
);
872 if (PyErr_Occurred()) {
877 DBG("Performing actual append: float(%f)", u
.f
);
878 if (!dbus_message_iter_append_basic(appender
, sig_type
, &u
.f
)) {
887 /* The integer types are all basically the same - we delegate to
888 intNN_range_check() */
889 #define PROCESS_INTEGER(size) \
890 u.size = dbus_py_##size##_range_check(obj);\
891 if (u.size == (dbus_##size##_t)(-1) && PyErr_Occurred()) {\
895 DBG("Performing actual append: " #size "(%lld)", (long long)u.size); \
896 if (!dbus_message_iter_append_basic(appender, sig_type, &u.size)) {\
903 case DBUS_TYPE_INT16
:
904 PROCESS_INTEGER(int16
)
906 case DBUS_TYPE_UINT16
:
907 PROCESS_INTEGER(uint16
)
909 case DBUS_TYPE_INT32
:
910 PROCESS_INTEGER(int32
)
912 case DBUS_TYPE_UINT32
:
913 PROCESS_INTEGER(uint32
)
915 #if defined(DBUS_HAVE_INT64) && defined(HAVE_LONG_LONG)
916 case DBUS_TYPE_INT64
:
917 PROCESS_INTEGER(int64
)
919 case DBUS_TYPE_UINT64
:
920 PROCESS_INTEGER(uint64
)
923 case DBUS_TYPE_INT64
:
924 case DBUS_TYPE_UINT64
:
925 PyErr_SetString(PyExc_NotImplementedError
, "64-bit integer "
926 "types are not supported on this platform");
930 #undef PROCESS_INTEGER
932 /* Now the more complicated cases, which are delegated to helper
933 * functions (although in practice, the compiler will hopefully
934 * inline them anyway). */
936 case DBUS_TYPE_STRING
:
937 case DBUS_TYPE_SIGNATURE
:
938 case DBUS_TYPE_OBJECT_PATH
:
939 ret
= _message_iter_append_string(appender
, sig_type
, obj
, TRUE
);
943 ret
= _message_iter_append_byte(appender
, obj
);
946 case DBUS_TYPE_ARRAY
:
947 /* 3 cases - it might actually be a dict, or it might be a byte array
948 * being copied from a string (for which we have a faster path),
949 * or it might be a generic array. */
951 sig_type
= dbus_signature_iter_get_element_type(sig_iter
);
952 if (sig_type
== DBUS_TYPE_DICT_ENTRY
)
953 ret
= _message_iter_append_multi(appender
, sig_iter
,
954 DBUS_TYPE_DICT_ENTRY
, obj
);
955 else if (sig_type
== DBUS_TYPE_BYTE
&& PyString_Check(obj
))
956 ret
= _message_iter_append_string_as_byte_array(appender
, obj
);
958 ret
= _message_iter_append_multi(appender
, sig_iter
,
959 DBUS_TYPE_ARRAY
, obj
);
960 DBG("_message_iter_append_multi(): %d", ret
);
963 case DBUS_TYPE_STRUCT
:
964 ret
= _message_iter_append_multi(appender
, sig_iter
, sig_type
, obj
);
967 case DBUS_TYPE_VARIANT
:
968 ret
= _message_iter_append_variant(appender
, obj
);
971 case DBUS_TYPE_INVALID
:
972 PyErr_SetString(PyExc_TypeError
, "Fewer items found in D-Bus "
973 "signature than in Python arguments");
978 PyErr_Format(PyExc_TypeError
, "Unknown type '\\x%x' in D-Bus "
979 "signature", sig_type
);
983 if (ret
< 0) return -1;
985 DBG("Advancing signature iter at %p", sig_iter
);
990 dbus_signature_iter_next(sig_iter
);
992 DBG("- result: %ld, type %02x '%c'", (long)b
,
993 (int)dbus_signature_iter_get_current_type(sig_iter
),
994 (int)dbus_signature_iter_get_current_type(sig_iter
));
1002 dbus_py_Message_append(Message
*self
, PyObject
*args
, PyObject
*kwargs
)
1004 const char *signature
= NULL
;
1005 PyObject
*signature_obj
= NULL
;
1006 DBusSignatureIter sig_iter
;
1007 DBusMessageIter appender
;
1009 static char *argnames
[] = {"signature", NULL
};
1011 if (!self
->msg
) return DBusPy_RaiseUnusableMessage();
1014 fprintf(stderr
, "DBG/%ld: called Message_append(*", (long)getpid());
1015 PyObject_Print(args
, stderr
, 0);
1017 fprintf(stderr
, ", **");
1018 PyObject_Print(kwargs
, stderr
, 0);
1020 fprintf(stderr
, ")\n");
1023 /* only use kwargs for this step: deliberately ignore args for now */
1024 if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple
, kwargs
, "|z:append",
1025 argnames
, &signature
)) return NULL
;
1028 DBG("%s", "No signature for message, guessing...");
1029 signature_obj
= dbus_py_Message_guess_signature(NULL
, args
);
1030 if (!signature_obj
) return NULL
;
1031 signature
= PyString_AS_STRING(signature_obj
);
1033 /* from here onwards, you have to do a goto rather than returning NULL
1034 to make sure signature_obj gets freed */
1036 /* iterate over args and the signature, together */
1037 if (!dbus_signature_validate(signature
, NULL
)) {
1038 PyErr_SetString(PyExc_ValueError
, "Corrupt type signature");
1041 dbus_signature_iter_init(&sig_iter
, signature
);
1042 dbus_message_iter_init_append(self
->msg
, &appender
);
1043 for (i
= 0; i
< PyTuple_GET_SIZE(args
); i
++) {
1044 if (_message_iter_append_pyobject(&appender
, &sig_iter
,
1045 PyTuple_GET_ITEM(args
, i
)) < 0) {
1049 if (dbus_signature_iter_get_current_type(&sig_iter
)
1050 != DBUS_TYPE_INVALID
) {
1051 PyErr_SetString(PyExc_TypeError
, "More items found in D-Bus "
1052 "signature than in Python arguments");
1057 Py_XDECREF(signature_obj
);
1061 /* "If appending any of the arguments fails due to lack of memory,
1062 * generally the message is hosed and you have to start over" -libdbus docs
1063 * Enforce this by throwing away the message structure.
1065 dbus_message_unref(self
->msg
);
1068 Py_XDECREF(signature_obj
);
1072 /* vim:set ft=c cino< sw=4 sts=4 et: */