Remove old libxml2-based introspection parser
[dbus-python-phuang.git] / _dbus_bindings / containers.c
blobc9aaeeee6c2e1ac3a3a7d40de4810a96526e59a3
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
25 #include <Python.h>
26 #include <structmember.h>
28 #include <stdint.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"
37 "\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"
42 "\n"
43 ":SupportedUsage:\n"
44 " ``from dbus import Array`` or ``from dbus.types import Array``\n"
45 "\n"
46 ":Constructor:\n"
47 " Array([iterable][, signature][, variant_level])\n"
48 "\n"
49 " variant_level must be non-negative; the default is 0.\n"
50 "\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"
53 "\n"
54 ":IVariables:\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 "
65 "instance)"},
66 {"variant_level", T_LONG, offsetof(DBusPyArray, variant_level),
67 READONLY,
68 "The number of nested variants wrapping the real data. "
69 "0 if not in a variant."},
70 {NULL},
73 static void
74 Array_tp_dealloc (DBusPyArray *self)
76 Py_XDECREF(self->signature);
77 self->signature = NULL;
78 (PyList_Type.tp_dealloc)((PyObject *)self);
81 static PyObject *
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, "
93 "variant_level=%ld)",
94 self->super.ob_type->tp_name,
95 PyString_AS_STRING(parent_repr),
96 PyString_AS_STRING(sig_repr),
97 variant_level);
99 else {
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));
105 finally:
106 Py_XDECREF(parent_repr);
107 Py_XDECREF(sig_repr);
108 return my_repr;
111 static PyObject *
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
118 __init__ */
119 if (!self) return NULL;
120 Py_INCREF(Py_None);
121 self->signature = Py_None;
122 self->variant_level = 0;
123 if (kwargs) {
124 variant_level = PyDict_GetItem(kwargs, dbus_py_variant_level_const);
126 if (variant_level) {
127 self->variant_level = PyInt_AsLong(variant_level);
128 if (PyErr_Occurred()) {
129 Py_DECREF((PyObject *)self);
130 return NULL;
133 return (PyObject *)self;
136 static int
137 Array_tp_init (DBusPyArray *self, PyObject *args, PyObject *kwargs)
139 PyObject *obj = dbus_py_empty_tuple;
140 PyObject *signature = NULL;
141 PyObject *tuple;
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)) {
149 return -1;
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);
159 else {
160 signature = PyObject_CallFunction((PyObject *)&DBusPySignature_Type,
161 "(O)", signature);
162 if (!signature) return -1;
165 tuple = Py_BuildValue("(O)", obj);
166 if (!tuple) {
167 Py_DECREF(signature);
168 return -1;
170 if ((PyList_Type.tp_init)((PyObject *)self, tuple, NULL) < 0) {
171 Py_DECREF(tuple);
172 Py_DECREF(signature);
173 return -1;
175 Py_DECREF(tuple);
177 Py_XDECREF(self->signature);
178 self->signature = signature;
179 return 0;
182 PyTypeObject DBusPyArray_Type = {
183 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
185 "dbus.Array",
186 sizeof(DBusPyArray),
188 (destructor)Array_tp_dealloc, /* tp_dealloc */
189 0, /* tp_print */
190 0, /* tp_getattr */
191 0, /* tp_setattr */
192 0, /* tp_compare */
193 (reprfunc)Array_tp_repr, /* tp_repr */
194 0, /* tp_as_number */
195 0, /* tp_as_sequence */
196 0, /* tp_as_mapping */
197 0, /* tp_hash */
198 0, /* tp_call */
199 0, /* tp_str */
200 0, /* tp_getattro */
201 0, /* tp_setattro */
202 0, /* tp_as_buffer */
203 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
204 Array_tp_doc, /* tp_doc */
205 0, /* tp_traverse */
206 0, /* tp_clear */
207 0, /* tp_richcompare */
208 0, /* tp_weaklistoffset */
209 0, /* tp_iter */
210 0, /* tp_iternext */
211 0, /* tp_methods */
212 Array_tp_members, /* tp_members */
213 0, /* tp_getset */
214 0, /* tp_base */
215 0, /* tp_dict */
216 0, /* tp_descr_get */
217 0, /* tp_descr_set */
218 0, /* tp_dictoffset */
219 (initproc)Array_tp_init, /* tp_init */
220 0, /* tp_alloc */
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"
229 "\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"
234 "\n"
235 ":SupportedUsage:\n"
236 " ``from dbus import Dictionary`` or ``from dbus.types import Dictionary``\n"
237 "\n"
238 ":Constructor:\n"
239 " Dictionary([mapping_or_iterable][, signature][, variant_level])\n"
240 "\n"
241 " variant_level must be non-negative; the default is 0.\n"
242 "\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"
245 " element.\n"
246 "\n"
247 ":IVariables:\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),
260 READONLY,
261 "The number of nested variants wrapping the real data. "
262 "0 if not in a variant."},
263 {NULL},
266 static void
267 Dict_tp_dealloc (DBusPyDict *self)
269 Py_XDECREF(self->signature);
270 self->signature = NULL;
271 (PyDict_Type.tp_dealloc)((PyObject *)self);
274 static PyObject *
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),
290 variant_level);
292 else {
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));
298 finally:
299 Py_XDECREF(parent_repr);
300 Py_XDECREF(sig_repr);
301 return my_repr;
304 static PyObject *
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
311 __init__ */
312 if (!self) return NULL;
313 Py_INCREF(Py_None);
314 self->signature = Py_None;
315 self->variant_level = 0;
316 if (kwargs) {
317 variant_level = PyDict_GetItem(kwargs, dbus_py_variant_level_const);
319 if (variant_level) {
320 self->variant_level = PyInt_AsLong(variant_level);
321 if (PyErr_Occurred()) {
322 Py_DECREF((PyObject *)self);
323 return NULL;
326 return (PyObject *)self;
329 static int
330 Dict_tp_init(DBusPyDict *self, PyObject *args, PyObject *kwargs)
332 PyObject *obj = dbus_py_empty_tuple;
333 PyObject *signature = NULL;
334 PyObject *tuple;
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)) {
341 return -1;
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);
351 else {
352 signature = PyObject_CallFunction((PyObject *)&DBusPySignature_Type,
353 "(O)", signature);
354 if (!signature) return -1;
357 tuple = Py_BuildValue("(O)", obj);
358 if (!tuple) {
359 Py_DECREF(signature);
360 return -1;
363 if ((PyDict_Type.tp_init((PyObject *)self, tuple, NULL)) < 0) {
364 Py_DECREF(tuple);
365 Py_DECREF(signature);
366 return -1;
368 Py_DECREF(tuple);
370 Py_XDECREF(self->signature);
371 self->signature = signature;
372 return 0;
375 PyTypeObject DBusPyDict_Type = {
376 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
378 "dbus.Dictionary",
379 sizeof(DBusPyDict),
381 (destructor)Dict_tp_dealloc, /* tp_dealloc */
382 0, /* tp_print */
383 0, /* tp_getattr */
384 0, /* tp_setattr */
385 0, /* tp_compare */
386 (reprfunc)Dict_tp_repr, /* tp_repr */
387 0, /* tp_as_number */
388 0, /* tp_as_sequence */
389 0, /* tp_as_mapping */
390 0, /* tp_hash */
391 0, /* tp_call */
392 0, /* tp_str */
393 0, /* tp_getattro */
394 0, /* tp_setattro */
395 0, /* tp_as_buffer */
396 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
397 Dict_tp_doc, /* tp_doc */
398 0, /* tp_traverse */
399 0, /* tp_clear */
400 0, /* tp_richcompare */
401 0, /* tp_weaklistoffset */
402 0, /* tp_iter */
403 0, /* tp_iternext */
404 0, /* tp_methods */
405 Dict_tp_members, /* tp_members */
406 0, /* tp_getset */
407 0, /* tp_base */
408 0, /* tp_dict */
409 0, /* tp_descr_get */
410 0, /* tp_descr_set */
411 0, /* tp_dictoffset */
412 (initproc)Dict_tp_init, /* tp_init */
413 0, /* tp_alloc */
414 Dict_tp_new, /* tp_new */
417 /* Struct =========================================================== */
419 PyDoc_STRVAR(Struct_tp_doc,
420 "An structure containing items of possibly distinct types.\n"
421 "\n"
422 ":SupportedUsage:\n"
423 " ``from dbus import Struct`` or ``from dbus.types import Struct``\n"
424 "\n"
425 ":Constructor:\n"
426 " ``Struct(iterable[, signature: str][, variant_level: int]) -> Struct``\n"
427 "\n"
428 " D-Bus structs may not be empty, so the iterable argument is required.\n"
429 "\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"
432 "\n"
433 " variant_level must be non-negative; the default is 0.\n"
434 "\n"
435 ":IVariables:\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"
443 static PyObject *
444 Struct_tp_repr(PyObject *self)
446 PyObject *parent_repr = (PyTuple_Type.tp_repr)((PyObject *)self);
447 PyObject *sig, *sig_repr = NULL;
448 PyObject *vl_obj;
449 long variant_level;
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),
466 variant_level);
468 else {
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));
475 finally:
476 Py_XDECREF(parent_repr);
477 Py_XDECREF(sig_repr);
478 return my_repr;
481 static PyObject *
482 Struct_tp_new (PyTypeObject *cls, PyObject *args, PyObject *kwargs)
484 PyObject *signature = NULL;
485 PyObject *variantness = NULL;
486 PyObject *self;
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");
492 return NULL;
494 if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple, kwargs,
495 "|OO!:__new__", argnames,
496 &signature, &PyInt_Type,
497 &variantness)) {
498 return NULL;
500 if (!variantness) {
501 variantness = PyInt_FromLong(0);
504 self = (PyTuple_Type.tp_new)(cls, args, NULL);
505 if (!self)
506 return NULL;
507 if (PyTuple_Size(self) < 1) {
508 PyErr_SetString(PyExc_ValueError, "D-Bus structs may not be empty");
509 Py_DECREF(self);
510 return NULL;
513 if (PyObject_GenericSetAttr(self, dbus_py_variant_level_const, variantness) < 0) {
514 Py_DECREF(self);
515 return NULL;
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);
525 else {
526 signature = PyObject_CallFunction((PyObject *)&DBusPySignature_Type,
527 "(O)", signature);
528 if (!signature) {
529 Py_DECREF(self);
530 return NULL;
534 if (PyObject_GenericSetAttr(self, dbus_py_signature_const, signature) < 0) {
535 Py_DECREF(self);
536 Py_DECREF(signature);
537 return NULL;
539 Py_DECREF(signature);
540 return self;
543 PyTypeObject DBusPyStruct_Type = {
544 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
546 "dbus.Struct",
547 INT_MAX, /* placeholder */
549 0, /* tp_dealloc */
550 0, /* tp_print */
551 0, /* tp_getattr */
552 0, /* tp_setattr */
553 0, /* tp_compare */
554 (reprfunc)Struct_tp_repr, /* tp_repr */
555 0, /* tp_as_number */
556 0, /* tp_as_sequence */
557 0, /* tp_as_mapping */
558 0, /* tp_hash */
559 0, /* tp_call */
560 0, /* tp_str */
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 */
566 0, /* tp_traverse */
567 0, /* tp_clear */
568 0, /* tp_richcompare */
569 0, /* tp_weaklistoffset */
570 0, /* tp_iter */
571 0, /* tp_iternext */
572 0, /* tp_methods */
573 0, /* tp_members */
574 0, /* tp_getset */
575 0, /* tp_base */
576 0, /* tp_dict */
577 0, /* tp_descr_get */
578 0, /* tp_descr_set */
579 -sizeof(PyObject *), /* tp_dictoffset */
580 0, /* tp_init */
581 0, /* tp_alloc */
582 Struct_tp_new, /* tp_new */
585 dbus_bool_t
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;
604 return 1;
607 dbus_bool_t
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;
622 return 1;
625 /* vim:set ft=c cino< sw=4 sts=4 et: */