_dbus_bindings/pending-call.c: Fix memory leak of one Message per method call.
[dbus-python-phuang.git] / _dbus_bindings / abstract.c
blob478ac8681bee6b6795f096bb0ead132bd1b3f746
1 /* Subclasses of built-in Python types supporting extra D-Bus functionality.
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 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <Python.h>
24 #include <structmember.h>
26 #include <stdint.h>
28 #include "dbus_bindings-internal.h"
29 #include "types-internal.h"
31 /* Support code for int subclasses. ================================== */
33 PyDoc_STRVAR(DBusPythonInt_tp_doc,\
34 "Base class for int subclasses with a ``variant_level`` attribute.\n"
35 "Do not rely on the existence of this class outside dbus-python.\n"
38 static PyMemberDef DBusPythonInt_tp_members[] = {
39 {"variant_level", T_LONG, offsetof(DBusPyIntBase, variant_level),
40 READONLY,
41 "The number of nested variants wrapping the real data. "
42 "0 if not in a variant."},
43 {NULL},
46 static PyObject *
47 DBusPythonInt_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
49 PyObject *self;
50 long variantness = 0;
51 static char *argnames[] = {"variant_level", NULL};
53 if (PyTuple_Size(args) > 1) {
54 PyErr_SetString(PyExc_TypeError,
55 "__new__ takes at most one positional parameter");
56 return NULL;
58 if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple, kwargs,
59 "|l:__new__", argnames,
60 &variantness)) return NULL;
61 if (variantness < 0) {
62 PyErr_SetString(PyExc_ValueError,
63 "variant_level must be non-negative");
64 return NULL;
67 self = (PyInt_Type.tp_new)(cls, args, NULL);
68 if (self) {
69 ((DBusPyIntBase *)self)->variant_level = variantness;
71 return self;
74 static PyObject *
75 DBusPythonInt_tp_repr(PyObject *self)
77 PyObject *parent_repr = (PyInt_Type.tp_repr)(self);
78 long variant_level = ((DBusPyIntBase *)self)->variant_level;
79 PyObject *my_repr;
81 if (!parent_repr) return NULL;
82 if (variant_level > 0) {
83 my_repr = PyString_FromFormat("%s(%s, variant_level=%ld)",
84 self->ob_type->tp_name,
85 PyString_AS_STRING(parent_repr),
86 variant_level);
88 else {
89 my_repr = PyString_FromFormat("%s(%s)", self->ob_type->tp_name,
90 PyString_AS_STRING(parent_repr));
92 /* whether my_repr is NULL or not: */
93 Py_DECREF(parent_repr);
94 return my_repr;
97 PyTypeObject DBusPyIntBase_Type = {
98 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
100 "_dbus_bindings._IntBase",
101 sizeof(DBusPyIntBase),
103 0, /* tp_dealloc */
104 0, /* tp_print */
105 0, /* tp_getattr */
106 0, /* tp_setattr */
107 0, /* tp_compare */
108 DBusPythonInt_tp_repr, /* tp_repr */
109 0, /* tp_as_number */
110 0, /* tp_as_sequence */
111 0, /* tp_as_mapping */
112 0, /* tp_hash */
113 0, /* tp_call */
114 0, /* tp_str */
115 0, /* tp_getattro */
116 0, /* tp_setattro */
117 0, /* tp_as_buffer */
118 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
119 DBusPythonInt_tp_doc, /* tp_doc */
120 0, /* tp_traverse */
121 0, /* tp_clear */
122 0, /* tp_richcompare */
123 0, /* tp_weaklistoffset */
124 0, /* tp_iter */
125 0, /* tp_iternext */
126 0, /* tp_methods */
127 DBusPythonInt_tp_members, /* tp_members */
128 0, /* tp_getset */
129 DEFERRED_ADDRESS(&PyInt_Type), /* tp_base */
130 0, /* tp_dict */
131 0, /* tp_descr_get */
132 0, /* tp_descr_set */
133 0, /* tp_dictoffset */
134 0, /* tp_init */
135 0, /* tp_alloc */
136 DBusPythonInt_tp_new, /* tp_new */
139 /* Support code for float subclasses. ================================ */
141 /* There's only one subclass at the moment (Double) but these are factored
142 out to make room for Float later. (Float is implemented and #if'd out) */
144 PyDoc_STRVAR(DBusPythonFloat_tp_doc,\
145 "Base class for float subclasses with a ``variant_level`` attribute.\n"
146 "Do not rely on the existence of this class outside dbus-python.\n"
149 static PyMemberDef DBusPythonFloat_tp_members[] = {
150 {"variant_level", T_LONG, offsetof(DBusPyFloatBase, variant_level),
151 READONLY,
152 "The number of nested variants wrapping the real data. "
153 "0 if not in a variant."},
154 {NULL},
157 static PyObject *
158 DBusPythonFloat_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
160 PyObject *self;
161 long variantness = 0;
162 static char *argnames[] = {"variant_level", NULL};
164 if (PyTuple_Size(args) > 1) {
165 PyErr_SetString(PyExc_TypeError,
166 "__new__ takes at most one positional parameter");
167 return NULL;
169 if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple, kwargs,
170 "|l:__new__", argnames,
171 &variantness)) return NULL;
172 if (variantness < 0) {
173 PyErr_SetString(PyExc_ValueError,
174 "variant_level must be non-negative");
175 return NULL;
178 self = (PyFloat_Type.tp_new)(cls, args, NULL);
179 if (self) {
180 ((DBusPyFloatBase *)self)->variant_level = variantness;
182 return self;
185 static PyObject *
186 DBusPythonFloat_tp_repr(PyObject *self)
188 PyObject *parent_repr = (PyFloat_Type.tp_repr)(self);
189 long variant_level = ((DBusPyFloatBase *)self)->variant_level;
190 PyObject *my_repr;
192 if (!parent_repr) return NULL;
193 if (variant_level > 0) {
194 my_repr = PyString_FromFormat("%s(%s, variant_level=%ld)",
195 self->ob_type->tp_name,
196 PyString_AS_STRING(parent_repr),
197 variant_level);
199 else {
200 my_repr = PyString_FromFormat("%s(%s)", self->ob_type->tp_name,
201 PyString_AS_STRING(parent_repr));
203 /* whether my_repr is NULL or not: */
204 Py_DECREF(parent_repr);
205 return my_repr;
208 PyTypeObject DBusPyFloatBase_Type = {
209 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
211 "_dbus_bindings._FloatBase",
212 sizeof(DBusPyFloatBase),
214 0, /* tp_dealloc */
215 0, /* tp_print */
216 0, /* tp_getattr */
217 0, /* tp_setattr */
218 0, /* tp_compare */
219 DBusPythonFloat_tp_repr, /* tp_repr */
220 0, /* tp_as_number */
221 0, /* tp_as_sequence */
222 0, /* tp_as_mapping */
223 0, /* tp_hash */
224 0, /* tp_call */
225 0, /* tp_str */
226 0, /* tp_getattro */
227 0, /* tp_setattro */
228 0, /* tp_as_buffer */
229 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
230 DBusPythonFloat_tp_doc, /* tp_doc */
231 0, /* tp_traverse */
232 0, /* tp_clear */
233 0, /* tp_richcompare */
234 0, /* tp_weaklistoffset */
235 0, /* tp_iter */
236 0, /* tp_iternext */
237 0, /* tp_methods */
238 DBusPythonFloat_tp_members, /* tp_members */
239 0, /* tp_getset */
240 DEFERRED_ADDRESS(&PyFloat_Type), /* tp_base */
241 0, /* tp_dict */
242 0, /* tp_descr_get */
243 0, /* tp_descr_set */
244 0, /* tp_dictoffset */
245 0, /* tp_init */
246 0, /* tp_alloc */
247 DBusPythonFloat_tp_new, /* tp_new */
250 /* Support code for str subclasses ================================== */
252 PyDoc_STRVAR(DBusPythonString_tp_doc,\
253 "Base class for str subclasses with a ``variant_level`` attribute.\n"
254 "Do not rely on the existence of this class outside dbus-python.\n"
257 static PyObject *
258 DBusPythonString_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
260 PyObject *self;
261 PyObject *variantness = NULL;
262 static char *argnames[] = {"variant_level", NULL};
264 if (PyTuple_Size(args) > 1) {
265 PyErr_SetString(PyExc_TypeError,
266 "__new__ takes at most one positional parameter");
267 return NULL;
269 if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple, kwargs,
270 "|O!:__new__", argnames,
271 &PyInt_Type, &variantness)) return NULL;
272 if (!variantness) {
273 variantness = PyInt_FromLong(0);
274 if (!variantness) return NULL;
276 if (PyInt_AS_LONG(variantness) < 0) {
277 PyErr_SetString(PyExc_ValueError,
278 "variant_level must be non-negative");
279 return NULL;
282 self = (PyString_Type.tp_new)(cls, args, NULL);
283 if (self) {
284 PyObject_GenericSetAttr(self, dbus_py_variant_level_const, variantness);
286 return self;
289 static PyObject *
290 DBusPythonString_tp_repr(PyObject *self)
292 PyObject *parent_repr = (PyString_Type.tp_repr)(self);
293 PyObject *vl_obj;
294 PyObject *my_repr;
295 long variant_level;
297 if (!parent_repr) return NULL;
298 vl_obj = PyObject_GetAttr(self, dbus_py_variant_level_const);
299 if (!vl_obj) return NULL;
300 variant_level = PyInt_AsLong(vl_obj);
301 if (variant_level > 0) {
302 my_repr = PyString_FromFormat("%s(%s, variant_level=%ld)",
303 self->ob_type->tp_name,
304 PyString_AS_STRING(parent_repr),
305 variant_level);
307 else {
308 my_repr = PyString_FromFormat("%s(%s)", self->ob_type->tp_name,
309 PyString_AS_STRING(parent_repr));
311 /* whether my_repr is NULL or not: */
312 Py_DECREF(parent_repr);
313 return my_repr;
316 PyTypeObject DBusPyStrBase_Type = {
317 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
319 "_dbus_bindings._StrBase",
320 INT_MAX, /* placeholder */
322 0, /* tp_dealloc */
323 0, /* tp_print */
324 0, /* tp_getattr */
325 0, /* tp_setattr */
326 0, /* tp_compare */
327 DBusPythonString_tp_repr, /* tp_repr */
328 0, /* tp_as_number */
329 0, /* tp_as_sequence */
330 0, /* tp_as_mapping */
331 0, /* tp_hash */
332 0, /* tp_call */
333 0, /* tp_str */
334 PyObject_GenericGetAttr, /* tp_getattro */
335 dbus_py_immutable_setattro, /* tp_setattro */
336 0, /* tp_as_buffer */
337 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
338 DBusPythonString_tp_doc, /* tp_doc */
339 0, /* tp_traverse */
340 0, /* tp_clear */
341 0, /* tp_richcompare */
342 0, /* tp_weaklistoffset */
343 0, /* tp_iter */
344 0, /* tp_iternext */
345 0, /* tp_methods */
346 0, /* tp_members */
347 0, /* tp_getset */
348 DEFERRED_ADDRESS(&PyString_Type), /* tp_base */
349 0, /* tp_dict */
350 0, /* tp_descr_get */
351 0, /* tp_descr_set */
352 -sizeof(void *), /* tp_dictoffset */
353 0, /* tp_init */
354 0, /* tp_alloc */
355 DBusPythonString_tp_new, /* tp_new */
358 /* Support code for long subclasses ================================= */
360 PyDoc_STRVAR(DBusPythonLong_tp_doc,\
361 "Base class for ``long`` subclasses with a ``variant_level`` attribute.\n"
362 "Do not rely on the existence of this class outside dbus-python.\n"
365 static PyObject *
366 DBusPythonLong_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
368 PyObject *self;
369 PyObject *variantness = NULL;
370 static char *argnames[] = {"variant_level", NULL};
372 if (PyTuple_Size(args) > 1) {
373 PyErr_SetString(PyExc_TypeError,
374 "__new__ takes at most one positional parameter");
375 return NULL;
377 if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple, kwargs,
378 "|O!:__new__", argnames,
379 &PyInt_Type, &variantness)) return NULL;
380 if (!variantness) {
381 variantness = PyInt_FromLong(0);
382 if (!variantness) return NULL;
384 if (PyInt_AS_LONG(variantness) < 0) {
385 PyErr_SetString(PyExc_ValueError,
386 "variant_level must be non-negative");
387 return NULL;
390 self = (PyLong_Type.tp_new)(cls, args, NULL);
391 if (self) {
392 PyObject_GenericSetAttr(self, dbus_py_variant_level_const, variantness);
394 return self;
397 static PyObject *
398 DBusPythonLong_tp_repr(PyObject *self)
400 PyObject *parent_repr = (PyLong_Type.tp_repr)(self);
401 PyObject *vl_obj;
402 PyObject *my_repr;
403 long variant_level;
405 if (!parent_repr) return NULL;
406 vl_obj = PyObject_GetAttr(self, dbus_py_variant_level_const);
407 if (!vl_obj) return 0;
408 variant_level = PyInt_AsLong(vl_obj);
409 if (variant_level) {
410 my_repr = PyString_FromFormat("%s(%s, variant_level=%ld)",
411 self->ob_type->tp_name,
412 PyString_AS_STRING(parent_repr),
413 variant_level);
415 else {
416 my_repr = PyString_FromFormat("%s(%s)", self->ob_type->tp_name,
417 PyString_AS_STRING(parent_repr));
419 /* whether my_repr is NULL or not: */
420 Py_DECREF(parent_repr);
421 return my_repr;
424 PyTypeObject DBusPyLongBase_Type = {
425 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
427 "_dbus_bindings._LongBase",
428 INT_MAX, /* placeholder */
430 0, /* tp_dealloc */
431 0, /* tp_print */
432 0, /* tp_getattr */
433 0, /* tp_setattr */
434 0, /* tp_compare */
435 DBusPythonLong_tp_repr, /* tp_repr */
436 0, /* tp_as_number */
437 0, /* tp_as_sequence */
438 0, /* tp_as_mapping */
439 0, /* tp_hash */
440 0, /* tp_call */
441 0, /* tp_str */
442 PyObject_GenericGetAttr, /* tp_getattro */
443 dbus_py_immutable_setattro, /* tp_setattro */
444 0, /* tp_as_buffer */
445 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
446 DBusPythonLong_tp_doc, /* tp_doc */
447 0, /* tp_traverse */
448 0, /* tp_clear */
449 0, /* tp_richcompare */
450 0, /* tp_weaklistoffset */
451 0, /* tp_iter */
452 0, /* tp_iternext */
453 0, /* tp_methods */
454 0, /* tp_members */
455 0, /* tp_getset */
456 DEFERRED_ADDRESS(&PyLong_Type), /* tp_base */
457 0, /* tp_dict */
458 0, /* tp_descr_get */
459 0, /* tp_descr_set */
460 -sizeof(PyObject *), /* tp_dictoffset */
461 0, /* tp_init */
462 0, /* tp_alloc */
463 DBusPythonLong_tp_new, /* tp_new */
466 PyObject *dbus_py_variant_level_const = NULL;
467 PyObject *dbus_py_signature_const = NULL;
468 PyObject *dbus_py__dbus_object_path__const = NULL;
470 dbus_bool_t
471 dbus_py_init_abstract(void)
473 dbus_py__dbus_object_path__const = PyString_InternFromString("__dbus_object_path__");
474 if (!dbus_py__dbus_object_path__const) return 0;
476 dbus_py_variant_level_const = PyString_InternFromString("variant_level");
477 if (!dbus_py_variant_level_const) return 0;
479 dbus_py_signature_const = PyString_InternFromString("signature");
480 if (!dbus_py_signature_const) return 0;
482 DBusPyIntBase_Type.tp_base = &PyInt_Type;
483 if (PyType_Ready(&DBusPyIntBase_Type) < 0) return 0;
484 /* disable the tp_print copied from PyInt_Type, so tp_repr gets called as
485 desired */
486 DBusPyIntBase_Type.tp_print = NULL;
488 DBusPyFloatBase_Type.tp_base = &PyFloat_Type;
489 if (PyType_Ready(&DBusPyFloatBase_Type) < 0) return 0;
490 DBusPyFloatBase_Type.tp_print = NULL;
492 /* Add a pointer for the instance dict, aligning to sizeof(PyObject *)
493 * to make sure the offset of -sizeof(PyObject *) is right. */
494 DBusPyLongBase_Type.tp_basicsize = PyLong_Type.tp_basicsize
495 + 2*sizeof(PyObject *) - 1;
496 DBusPyLongBase_Type.tp_basicsize /= sizeof(PyObject *);
497 DBusPyLongBase_Type.tp_basicsize *= sizeof(PyObject *);
498 DBusPyLongBase_Type.tp_base = &PyLong_Type;
499 if (PyType_Ready(&DBusPyLongBase_Type) < 0) return 0;
500 DBusPyLongBase_Type.tp_print = NULL;
502 DBusPyStrBase_Type.tp_basicsize = PyString_Type.tp_basicsize
503 + 2*sizeof(PyObject *) - 1;
504 DBusPyStrBase_Type.tp_basicsize /= sizeof(PyObject *);
505 DBusPyStrBase_Type.tp_basicsize *= sizeof(PyObject *);
506 DBusPyStrBase_Type.tp_base = &PyString_Type;
507 if (PyType_Ready(&DBusPyStrBase_Type) < 0) return 0;
508 DBusPyStrBase_Type.tp_print = NULL;
510 return 1;
513 dbus_bool_t
514 dbus_py_insert_abstract_types(PyObject *this_module)
516 Py_INCREF(&DBusPyIntBase_Type);
517 Py_INCREF(&DBusPyLongBase_Type);
518 Py_INCREF(&DBusPyStrBase_Type);
519 Py_INCREF(&DBusPyFloatBase_Type);
520 if (PyModule_AddObject(this_module, "_IntBase",
521 (PyObject *)&DBusPyIntBase_Type) < 0) return 0;
522 if (PyModule_AddObject(this_module, "_LongBase",
523 (PyObject *)&DBusPyLongBase_Type) < 0) return 0;
524 if (PyModule_AddObject(this_module, "_StrBase",
525 (PyObject *)&DBusPyStrBase_Type) < 0) return 0;
526 if (PyModule_AddObject(this_module, "_FloatBase",
527 (PyObject *)&DBusPyFloatBase_Type) < 0) return 0;
529 return 1;