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 (DBusPyString_Check(obj
)) {
47 return ((DBusPyString
*)obj
)->variant_level
;
49 else if (DBusPyLongBase_Check(obj
) ||
50 DBusPyStrBase_Check(obj
) ||
51 DBusPyStruct_Check(obj
)) {
52 return dbus_py_variant_level_get(obj
);
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 Py_ssize_t 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
,
415 static int _message_iter_append_variant(DBusMessageIter
*appender
,
419 _message_iter_append_string(DBusMessageIter
*appender
,
420 int sig_type
, PyObject
*obj
,
421 dbus_bool_t allow_object_path_attr
)
425 if (sig_type
== DBUS_TYPE_OBJECT_PATH
&& allow_object_path_attr
) {
426 PyObject
*object_path
= get_object_path (obj
);
428 if (object_path
== Py_None
) {
429 Py_DECREF(object_path
);
431 else if (!object_path
) {
435 int ret
= _message_iter_append_string(appender
, sig_type
,
437 Py_DECREF(object_path
);
442 if (PyString_Check(obj
)) {
445 /* Raise TypeError if the string has embedded NULs */
446 if (PyString_AsStringAndSize(obj
, &s
, NULL
) < 0) return -1;
447 /* Surely there's a faster stdlib way to validate UTF-8... */
448 unicode
= PyUnicode_DecodeUTF8(s
, PyString_GET_SIZE(obj
), NULL
);
450 PyErr_SetString(PyExc_UnicodeError
, "String parameters "
451 "to be sent over D-Bus must be valid UTF-8");
457 DBG("Performing actual append: string %s", s
);
458 if (!dbus_message_iter_append_basic(appender
, sig_type
,
464 else if (PyUnicode_Check(obj
)) {
465 PyObject
*utf8
= PyUnicode_AsUTF8String(obj
);
466 if (!utf8
) return -1;
467 /* Raise TypeError if the string has embedded NULs */
468 if (PyString_AsStringAndSize(utf8
, &s
, NULL
) < 0) return -1;
469 DBG("Performing actual append: string (from unicode) %s", s
);
470 if (!dbus_message_iter_append_basic(appender
, sig_type
, &s
)) {
477 PyErr_SetString(PyExc_TypeError
,
478 "Expected a string or unicode object");
485 _message_iter_append_byte(DBusMessageIter
*appender
, PyObject
*obj
)
489 if (PyString_Check(obj
)) {
490 if (PyString_GET_SIZE(obj
) != 1) {
491 PyErr_Format(PyExc_ValueError
, "Expected a string of "
492 "length 1 byte, but found %d bytes",
493 PyString_GET_SIZE(obj
));
496 y
= *(unsigned char *)PyString_AS_STRING(obj
);
499 long i
= PyInt_AsLong(obj
);
501 if (i
== -1 && PyErr_Occurred()) return -1;
502 if (i
< 0 || i
> 0xff) {
503 PyErr_Format(PyExc_ValueError
, "%d outside range for a "
504 "byte value", (int)i
);
509 DBG("Performing actual append: byte \\x%02x", (unsigned)y
);
510 if (!dbus_message_iter_append_basic(appender
, DBUS_TYPE_BYTE
, &y
)) {
518 _message_iter_append_dictentry(DBusMessageIter
*appender
,
519 DBusSignatureIter
*sig_iter
,
520 PyObject
*dict
, PyObject
*key
)
522 DBusSignatureIter sub_sig_iter
;
525 PyObject
*value
= PyObject_GetItem(dict
, key
);
528 if (!value
) return -1;
531 fprintf(stderr
, "Append dictentry: ");
532 PyObject_Print(key
, stderr
, 0);
533 fprintf(stderr
, " => ");
534 PyObject_Print(value
, stderr
, 0);
535 fprintf(stderr
, "\n");
538 DBG("Recursing signature iterator %p -> %p", sig_iter
, &sub_sig_iter
);
539 dbus_signature_iter_recurse(sig_iter
, &sub_sig_iter
);
543 s
= dbus_signature_iter_get_signature(sig_iter
);
544 DBG("Signature of parent iterator %p is %s", sig_iter
, s
);
546 s
= dbus_signature_iter_get_signature(&sub_sig_iter
);
547 DBG("Signature of sub-iterator %p is %s", &sub_sig_iter
, s
);
552 DBG("%s", "Opening DICT_ENTRY container");
553 if (!dbus_message_iter_open_container(appender
, DBUS_TYPE_DICT_ENTRY
,
558 ret
= _message_iter_append_pyobject(&sub
, &sub_sig_iter
, key
, &more
);
560 ret
= _message_iter_append_pyobject(&sub
, &sub_sig_iter
, value
, &more
);
562 DBG("%s", "Closing DICT_ENTRY container");
563 if (!dbus_message_iter_close_container(appender
, &sub
)) {
573 _message_iter_append_multi(DBusMessageIter
*appender
,
574 const DBusSignatureIter
*sig_iter
,
575 int mode
, PyObject
*obj
)
577 DBusMessageIter sub_appender
;
578 DBusSignatureIter sub_sig_iter
;
581 PyObject
*iterator
= PyObject_GetIter(obj
);
583 int container
= mode
;
584 dbus_bool_t is_byte_array
= DBusPyByteArray_Check(obj
);
589 fprintf(stderr
, "Appending multiple: ");
590 PyObject_Print(obj
, stderr
, 0);
591 fprintf(stderr
, "\n");
594 if (!iterator
) return -1;
595 if (mode
== DBUS_TYPE_DICT_ENTRY
) container
= DBUS_TYPE_ARRAY
;
597 DBG("Recursing signature iterator %p -> %p", sig_iter
, &sub_sig_iter
);
598 dbus_signature_iter_recurse(sig_iter
, &sub_sig_iter
);
602 s
= dbus_signature_iter_get_signature(sig_iter
);
603 DBG("Signature of parent iterator %p is %s", sig_iter
, s
);
605 s
= dbus_signature_iter_get_signature(&sub_sig_iter
);
606 DBG("Signature of sub-iterator %p is %s", &sub_sig_iter
, s
);
610 inner_type
= dbus_signature_iter_get_current_type(&sub_sig_iter
);
612 if (mode
== DBUS_TYPE_ARRAY
|| mode
== DBUS_TYPE_DICT_ENTRY
) {
613 sig
= dbus_signature_iter_get_signature(&sub_sig_iter
);
620 /* else leave sig set to NULL. */
622 DBG("Opening %c container", container
);
623 if (!dbus_message_iter_open_container(appender
, container
,
624 sig
, &sub_appender
)) {
630 while ((contents
= PyIter_Next(iterator
))) {
632 if (mode
== DBUS_TYPE_ARRAY
|| mode
== DBUS_TYPE_DICT_ENTRY
) {
633 DBG("Recursing signature iterator %p -> %p", sig_iter
, &sub_sig_iter
);
634 dbus_signature_iter_recurse(sig_iter
, &sub_sig_iter
);
638 s
= dbus_signature_iter_get_signature(sig_iter
);
639 DBG("Signature of parent iterator %p is %s", sig_iter
, s
);
641 s
= dbus_signature_iter_get_signature(&sub_sig_iter
);
642 DBG("Signature of sub-iterator %p is %s", &sub_sig_iter
, s
);
648 if (mode
== DBUS_TYPE_DICT_ENTRY
) {
649 ret
= _message_iter_append_dictentry(&sub_appender
, &sub_sig_iter
,
652 else if (mode
== DBUS_TYPE_ARRAY
&& is_byte_array
653 && inner_type
== DBUS_TYPE_VARIANT
) {
654 /* Subscripting a ByteArray gives a str of length 1, but if the
655 * container is a ByteArray and the parameter is an array of
656 * variants, we want to produce an array of variants containing
657 * bytes, not strings.
659 PyObject
*args
= Py_BuildValue("(O)", contents
);
664 byte
= PyObject_Call((PyObject
*)&DBusPyByte_Type
, args
, NULL
);
668 ret
= _message_iter_append_variant(&sub_appender
, byte
);
672 /* advances sub_sig_iter and sets more on success - for array
673 * this doesn't matter, for struct it's essential */
674 ret
= _message_iter_append_pyobject(&sub_appender
, &sub_sig_iter
,
684 if (PyErr_Occurred()) {
687 else if (mode
== DBUS_TYPE_STRUCT
&& more
) {
688 PyErr_Format(PyExc_TypeError
, "More items found in struct's D-Bus "
689 "signature than in Python arguments ");
693 /* This must be run as cleanup, even on failure. */
694 DBG("Closing %c container", container
);
695 if (!dbus_message_iter_close_container(appender
, &sub_appender
)) {
701 Py_XDECREF(iterator
);
707 _message_iter_append_string_as_byte_array(DBusMessageIter
*appender
,
710 /* a bit of a faster path for byte arrays that are strings */
711 Py_ssize_t len
= PyString_GET_SIZE(obj
);
716 s
= PyString_AS_STRING(obj
);
717 DBG("%s", "Opening ARRAY container");
718 if (!dbus_message_iter_open_container(appender
, DBUS_TYPE_ARRAY
,
719 DBUS_TYPE_BYTE_AS_STRING
, &sub
)) {
723 DBG("Appending fixed array of %d bytes", len
);
724 if (dbus_message_iter_append_fixed_array(&sub
, DBUS_TYPE_BYTE
, &s
, len
)) {
731 DBG("%s", "Closing ARRAY container");
732 if (!dbus_message_iter_close_container(appender
, &sub
)) {
739 /* Encode some Python object into a D-Bus variant slot. */
741 _message_iter_append_variant(DBusMessageIter
*appender
, PyObject
*obj
)
743 DBusSignatureIter obj_sig_iter
;
744 const char *obj_sig_str
;
750 /* Separate the object into the contained object, and the number of
751 * variants it's wrapped in. */
752 obj_sig
= _signature_string_from_pyobject(obj
, &variant_level
);
753 if (!obj_sig
) return -1;
755 obj_sig_str
= PyString_AsString(obj_sig
);
756 if (!obj_sig_str
) return -1;
758 if (variant_level
< 1) {
762 dbus_signature_iter_init(&obj_sig_iter
, obj_sig_str
);
764 { /* scope for variant_iters */
765 DBusMessageIter variant_iters
[variant_level
];
768 for (i
= 0; i
< variant_level
; i
++) {
769 DBusMessageIter
*child
= &variant_iters
[i
];
770 /* The first is a special case: its parent is the iter passed in
771 * to this function, instead of being the previous one in the
774 DBusMessageIter
*parent
= (i
== 0
776 : &(variant_iters
[i
-1]));
777 /* The last is also a special case: it contains the actual
778 * object, rather than another variant
780 const char *sig_str
= (i
== variant_level
-1
782 : DBUS_TYPE_VARIANT_AS_STRING
);
784 DBG("Opening VARIANT container %p inside %p containing '%s'",
785 child
, parent
, sig_str
);
786 if (!dbus_message_iter_open_container(parent
, DBUS_TYPE_VARIANT
,
794 /* Put the object itself into the innermost variant */
795 ret
= _message_iter_append_pyobject(&variant_iters
[variant_level
-1],
796 &obj_sig_iter
, obj
, &dummy
);
798 /* here we rely on i (and variant_level) being a signed long */
799 for (i
= variant_level
- 1; i
>= 0; i
--) {
800 DBusMessageIter
*child
= &variant_iters
[i
];
801 /* The first is a special case: its parent is the iter passed in
802 * to this function, instead of being the previous one in the
805 DBusMessageIter
*parent
= (i
== 0 ? appender
806 : &(variant_iters
[i
-1]));
808 DBG("Closing VARIANT container %p inside %p", child
, parent
);
809 if (!dbus_message_iter_close_container(parent
, child
)) {
823 /* On success, *more is set to whether there's more in the signature. */
825 _message_iter_append_pyobject(DBusMessageIter
*appender
,
826 DBusSignatureIter
*sig_iter
,
830 int sig_type
= dbus_signature_iter_get_current_type(sig_iter
);
834 dbus_uint16_t uint16
;
836 dbus_uint32_t uint32
;
838 #if defined(DBUS_HAVE_INT64) && defined(HAVE_LONG_LONG)
839 dbus_uint64_t uint64
;
846 fprintf(stderr
, "Appending object at %p: ", obj
);
847 PyObject_Print(obj
, stderr
, 0);
848 fprintf(stderr
, " into appender at %p, dbus wants type %c\n",
853 /* The numeric types are relatively simple to deal with, so are
856 case DBUS_TYPE_BOOLEAN
:
857 if (PyObject_IsTrue(obj
)) {
863 DBG("Performing actual append: bool(%ld)", (long)u
.b
);
864 if (!dbus_message_iter_append_basic(appender
, sig_type
, &u
.b
)) {
872 case DBUS_TYPE_DOUBLE
:
873 u
.d
= PyFloat_AsDouble(obj
);
874 if (PyErr_Occurred()) {
878 DBG("Performing actual append: double(%f)", u
.d
);
879 if (!dbus_message_iter_append_basic(appender
, sig_type
, &u
.d
)) {
887 #ifdef WITH_DBUS_FLOAT32
888 case DBUS_TYPE_FLOAT
:
889 u
.d
= PyFloat_AsDouble(obj
);
890 if (PyErr_Occurred()) {
895 DBG("Performing actual append: float(%f)", u
.f
);
896 if (!dbus_message_iter_append_basic(appender
, sig_type
, &u
.f
)) {
905 /* The integer types are all basically the same - we delegate to
906 intNN_range_check() */
907 #define PROCESS_INTEGER(size) \
908 u.size = dbus_py_##size##_range_check(obj);\
909 if (u.size == (dbus_##size##_t)(-1) && PyErr_Occurred()) {\
913 DBG("Performing actual append: " #size "(%lld)", (long long)u.size); \
914 if (!dbus_message_iter_append_basic(appender, sig_type, &u.size)) {\
921 case DBUS_TYPE_INT16
:
922 PROCESS_INTEGER(int16
)
924 case DBUS_TYPE_UINT16
:
925 PROCESS_INTEGER(uint16
)
927 case DBUS_TYPE_INT32
:
928 PROCESS_INTEGER(int32
)
930 case DBUS_TYPE_UINT32
:
931 PROCESS_INTEGER(uint32
)
933 #if defined(DBUS_HAVE_INT64) && defined(HAVE_LONG_LONG)
934 case DBUS_TYPE_INT64
:
935 PROCESS_INTEGER(int64
)
937 case DBUS_TYPE_UINT64
:
938 PROCESS_INTEGER(uint64
)
941 case DBUS_TYPE_INT64
:
942 case DBUS_TYPE_UINT64
:
943 PyErr_SetString(PyExc_NotImplementedError
, "64-bit integer "
944 "types are not supported on this platform");
948 #undef PROCESS_INTEGER
950 /* Now the more complicated cases, which are delegated to helper
951 * functions (although in practice, the compiler will hopefully
952 * inline them anyway). */
954 case DBUS_TYPE_STRING
:
955 case DBUS_TYPE_SIGNATURE
:
956 case DBUS_TYPE_OBJECT_PATH
:
957 ret
= _message_iter_append_string(appender
, sig_type
, obj
, TRUE
);
961 ret
= _message_iter_append_byte(appender
, obj
);
964 case DBUS_TYPE_ARRAY
:
965 /* 3 cases - it might actually be a dict, or it might be a byte array
966 * being copied from a string (for which we have a faster path),
967 * or it might be a generic array. */
969 sig_type
= dbus_signature_iter_get_element_type(sig_iter
);
970 if (sig_type
== DBUS_TYPE_DICT_ENTRY
)
971 ret
= _message_iter_append_multi(appender
, sig_iter
,
972 DBUS_TYPE_DICT_ENTRY
, obj
);
973 else if (sig_type
== DBUS_TYPE_BYTE
&& PyString_Check(obj
))
974 ret
= _message_iter_append_string_as_byte_array(appender
, obj
);
976 ret
= _message_iter_append_multi(appender
, sig_iter
,
977 DBUS_TYPE_ARRAY
, obj
);
978 DBG("_message_iter_append_multi(): %d", ret
);
981 case DBUS_TYPE_STRUCT
:
982 ret
= _message_iter_append_multi(appender
, sig_iter
, sig_type
, obj
);
985 case DBUS_TYPE_VARIANT
:
986 ret
= _message_iter_append_variant(appender
, obj
);
989 case DBUS_TYPE_INVALID
:
990 PyErr_SetString(PyExc_TypeError
, "Fewer items found in D-Bus "
991 "signature than in Python arguments");
996 PyErr_Format(PyExc_TypeError
, "Unknown type '\\x%x' in D-Bus "
997 "signature", sig_type
);
1001 if (ret
< 0) return -1;
1003 DBG("Advancing signature iter at %p", sig_iter
);
1004 *more
= dbus_signature_iter_next(sig_iter
);
1006 DBG("- result: %ld, type %02x '%c'", (long)(*more
),
1007 (int)dbus_signature_iter_get_current_type(sig_iter
),
1008 (int)dbus_signature_iter_get_current_type(sig_iter
));
1015 dbus_py_Message_append(Message
*self
, PyObject
*args
, PyObject
*kwargs
)
1017 const char *signature
= NULL
;
1018 PyObject
*signature_obj
= NULL
;
1019 DBusSignatureIter sig_iter
;
1020 DBusMessageIter appender
;
1022 static char *argnames
[] = {"signature", NULL
};
1023 /* must start FALSE for the case where there's nothing there and we
1024 * never iterate at all */
1027 if (!self
->msg
) return DBusPy_RaiseUnusableMessage();
1030 fprintf(stderr
, "DBG/%ld: called Message_append(*", (long)getpid());
1031 PyObject_Print(args
, stderr
, 0);
1033 fprintf(stderr
, ", **");
1034 PyObject_Print(kwargs
, stderr
, 0);
1036 fprintf(stderr
, ")\n");
1039 /* only use kwargs for this step: deliberately ignore args for now */
1040 if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple
, kwargs
, "|z:append",
1041 argnames
, &signature
)) return NULL
;
1044 DBG("%s", "No signature for message, guessing...");
1045 signature_obj
= dbus_py_Message_guess_signature(NULL
, args
);
1046 if (!signature_obj
) return NULL
;
1047 signature
= PyString_AS_STRING(signature_obj
);
1049 /* from here onwards, you have to do a goto rather than returning NULL
1050 to make sure signature_obj gets freed */
1052 /* iterate over args and the signature, together */
1053 if (!dbus_signature_validate(signature
, NULL
)) {
1054 PyErr_SetString(PyExc_ValueError
, "Corrupt type signature");
1057 dbus_signature_iter_init(&sig_iter
, signature
);
1058 dbus_message_iter_init_append(self
->msg
, &appender
);
1059 more
= (signature
[0] != '\0');
1060 for (i
= 0; i
< PyTuple_GET_SIZE(args
); i
++) {
1061 if (_message_iter_append_pyobject(&appender
, &sig_iter
,
1062 PyTuple_GET_ITEM(args
, i
),
1068 PyErr_SetString(PyExc_TypeError
, "More items found in D-Bus "
1069 "signature than in Python arguments");
1074 Py_XDECREF(signature_obj
);
1078 /* "If appending any of the arguments fails due to lack of memory,
1079 * generally the message is hosed and you have to start over" -libdbus docs
1080 * Enforce this by throwing away the message structure.
1082 dbus_message_unref(self
->msg
);
1085 Py_XDECREF(signature_obj
);
1089 /* vim:set ft=c cino< sw=4 sts=4 et: */