Add Makefile target maintainer-update-website to update d.fd.o/doc/dbus-python
[dbus-python-phuang.git] / _dbus_bindings / abstract.c
blobac9a429d12d2c311414769fb30db411204f666de
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 * 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 /* Support code for int subclasses. ================================== */
35 PyDoc_STRVAR(DBusPythonInt_tp_doc,\
36 "Base class for int subclasses with a ``variant_level`` attribute.\n"
37 "Do not rely on the existence of this class outside dbus-python.\n"
40 static PyMemberDef DBusPythonInt_tp_members[] = {
41 {"variant_level", T_LONG, offsetof(DBusPyIntBase, variant_level),
42 READONLY,
43 "The number of nested variants wrapping the real data. "
44 "0 if not in a variant."},
45 {NULL},
48 static PyObject *
49 DBusPythonInt_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
51 PyObject *self;
52 long variantness = 0;
53 static char *argnames[] = {"variant_level", NULL};
55 if (PyTuple_Size(args) > 1) {
56 PyErr_SetString(PyExc_TypeError,
57 "__new__ takes at most one positional parameter");
58 return NULL;
60 if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple, kwargs,
61 "|l:__new__", argnames,
62 &variantness)) return NULL;
63 if (variantness < 0) {
64 PyErr_SetString(PyExc_ValueError,
65 "variant_level must be non-negative");
66 return NULL;
69 self = (PyInt_Type.tp_new)(cls, args, NULL);
70 if (self) {
71 ((DBusPyIntBase *)self)->variant_level = variantness;
73 return self;
76 static PyObject *
77 DBusPythonInt_tp_repr(PyObject *self)
79 PyObject *parent_repr = (PyInt_Type.tp_repr)(self);
80 long variant_level = ((DBusPyIntBase *)self)->variant_level;
81 PyObject *my_repr;
83 if (!parent_repr) return NULL;
84 if (variant_level > 0) {
85 my_repr = PyString_FromFormat("%s(%s, variant_level=%ld)",
86 self->ob_type->tp_name,
87 PyString_AS_STRING(parent_repr),
88 variant_level);
90 else {
91 my_repr = PyString_FromFormat("%s(%s)", self->ob_type->tp_name,
92 PyString_AS_STRING(parent_repr));
94 /* whether my_repr is NULL or not: */
95 Py_DECREF(parent_repr);
96 return my_repr;
99 PyTypeObject DBusPyIntBase_Type = {
100 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
102 "_dbus_bindings._IntBase",
103 sizeof(DBusPyIntBase),
105 0, /* tp_dealloc */
106 0, /* tp_print */
107 0, /* tp_getattr */
108 0, /* tp_setattr */
109 0, /* tp_compare */
110 DBusPythonInt_tp_repr, /* tp_repr */
111 0, /* tp_as_number */
112 0, /* tp_as_sequence */
113 0, /* tp_as_mapping */
114 0, /* tp_hash */
115 0, /* tp_call */
116 0, /* tp_str */
117 0, /* tp_getattro */
118 0, /* tp_setattro */
119 0, /* tp_as_buffer */
120 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
121 DBusPythonInt_tp_doc, /* tp_doc */
122 0, /* tp_traverse */
123 0, /* tp_clear */
124 0, /* tp_richcompare */
125 0, /* tp_weaklistoffset */
126 0, /* tp_iter */
127 0, /* tp_iternext */
128 0, /* tp_methods */
129 DBusPythonInt_tp_members, /* tp_members */
130 0, /* tp_getset */
131 DEFERRED_ADDRESS(&PyInt_Type), /* tp_base */
132 0, /* tp_dict */
133 0, /* tp_descr_get */
134 0, /* tp_descr_set */
135 0, /* tp_dictoffset */
136 0, /* tp_init */
137 0, /* tp_alloc */
138 DBusPythonInt_tp_new, /* tp_new */
141 /* Support code for float subclasses. ================================ */
143 /* There's only one subclass at the moment (Double) but these are factored
144 out to make room for Float later. (Float is implemented and #if'd out) */
146 PyDoc_STRVAR(DBusPythonFloat_tp_doc,\
147 "Base class for float subclasses with a ``variant_level`` attribute.\n"
148 "Do not rely on the existence of this class outside dbus-python.\n"
151 static PyMemberDef DBusPythonFloat_tp_members[] = {
152 {"variant_level", T_LONG, offsetof(DBusPyFloatBase, variant_level),
153 READONLY,
154 "The number of nested variants wrapping the real data. "
155 "0 if not in a variant."},
156 {NULL},
159 static PyObject *
160 DBusPythonFloat_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
162 PyObject *self;
163 long variantness = 0;
164 static char *argnames[] = {"variant_level", NULL};
166 if (PyTuple_Size(args) > 1) {
167 PyErr_SetString(PyExc_TypeError,
168 "__new__ takes at most one positional parameter");
169 return NULL;
171 if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple, kwargs,
172 "|l:__new__", argnames,
173 &variantness)) return NULL;
174 if (variantness < 0) {
175 PyErr_SetString(PyExc_ValueError,
176 "variant_level must be non-negative");
177 return NULL;
180 self = (PyFloat_Type.tp_new)(cls, args, NULL);
181 if (self) {
182 ((DBusPyFloatBase *)self)->variant_level = variantness;
184 return self;
187 static PyObject *
188 DBusPythonFloat_tp_repr(PyObject *self)
190 PyObject *parent_repr = (PyFloat_Type.tp_repr)(self);
191 long variant_level = ((DBusPyFloatBase *)self)->variant_level;
192 PyObject *my_repr;
194 if (!parent_repr) return NULL;
195 if (variant_level > 0) {
196 my_repr = PyString_FromFormat("%s(%s, variant_level=%ld)",
197 self->ob_type->tp_name,
198 PyString_AS_STRING(parent_repr),
199 variant_level);
201 else {
202 my_repr = PyString_FromFormat("%s(%s)", self->ob_type->tp_name,
203 PyString_AS_STRING(parent_repr));
205 /* whether my_repr is NULL or not: */
206 Py_DECREF(parent_repr);
207 return my_repr;
210 PyTypeObject DBusPyFloatBase_Type = {
211 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
213 "_dbus_bindings._FloatBase",
214 sizeof(DBusPyFloatBase),
216 0, /* tp_dealloc */
217 0, /* tp_print */
218 0, /* tp_getattr */
219 0, /* tp_setattr */
220 0, /* tp_compare */
221 DBusPythonFloat_tp_repr, /* tp_repr */
222 0, /* tp_as_number */
223 0, /* tp_as_sequence */
224 0, /* tp_as_mapping */
225 0, /* tp_hash */
226 0, /* tp_call */
227 0, /* tp_str */
228 0, /* tp_getattro */
229 0, /* tp_setattro */
230 0, /* tp_as_buffer */
231 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
232 DBusPythonFloat_tp_doc, /* tp_doc */
233 0, /* tp_traverse */
234 0, /* tp_clear */
235 0, /* tp_richcompare */
236 0, /* tp_weaklistoffset */
237 0, /* tp_iter */
238 0, /* tp_iternext */
239 0, /* tp_methods */
240 DBusPythonFloat_tp_members, /* tp_members */
241 0, /* tp_getset */
242 DEFERRED_ADDRESS(&PyFloat_Type), /* tp_base */
243 0, /* tp_dict */
244 0, /* tp_descr_get */
245 0, /* tp_descr_set */
246 0, /* tp_dictoffset */
247 0, /* tp_init */
248 0, /* tp_alloc */
249 DBusPythonFloat_tp_new, /* tp_new */
252 /* Support code for str subclasses ================================== */
254 PyDoc_STRVAR(DBusPythonString_tp_doc,\
255 "Base class for str subclasses with a ``variant_level`` attribute.\n"
256 "Do not rely on the existence of this class outside dbus-python.\n"
259 static PyObject *
260 DBusPythonString_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
262 PyObject *self;
263 PyObject *variantness = NULL;
264 static char *argnames[] = {"variant_level", NULL};
266 if (PyTuple_Size(args) > 1) {
267 PyErr_SetString(PyExc_TypeError,
268 "__new__ takes at most one positional parameter");
269 return NULL;
271 if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple, kwargs,
272 "|O!:__new__", argnames,
273 &PyInt_Type, &variantness)) return NULL;
274 if (!variantness) {
275 variantness = PyInt_FromLong(0);
276 if (!variantness) return NULL;
278 if (PyInt_AS_LONG(variantness) < 0) {
279 PyErr_SetString(PyExc_ValueError,
280 "variant_level must be non-negative");
281 return NULL;
284 self = (PyString_Type.tp_new)(cls, args, NULL);
285 if (self) {
286 PyObject_GenericSetAttr(self, dbus_py_variant_level_const, variantness);
288 return self;
291 static PyObject *
292 DBusPythonString_tp_repr(PyObject *self)
294 PyObject *parent_repr = (PyString_Type.tp_repr)(self);
295 PyObject *vl_obj;
296 PyObject *my_repr;
297 long variant_level;
299 if (!parent_repr) return NULL;
300 vl_obj = PyObject_GetAttr(self, dbus_py_variant_level_const);
301 if (!vl_obj) return NULL;
302 variant_level = PyInt_AsLong(vl_obj);
303 if (variant_level > 0) {
304 my_repr = PyString_FromFormat("%s(%s, variant_level=%ld)",
305 self->ob_type->tp_name,
306 PyString_AS_STRING(parent_repr),
307 variant_level);
309 else {
310 my_repr = PyString_FromFormat("%s(%s)", self->ob_type->tp_name,
311 PyString_AS_STRING(parent_repr));
313 /* whether my_repr is NULL or not: */
314 Py_DECREF(parent_repr);
315 return my_repr;
318 PyTypeObject DBusPyStrBase_Type = {
319 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
321 "_dbus_bindings._StrBase",
322 INT_MAX, /* placeholder */
324 0, /* tp_dealloc */
325 0, /* tp_print */
326 0, /* tp_getattr */
327 0, /* tp_setattr */
328 0, /* tp_compare */
329 DBusPythonString_tp_repr, /* tp_repr */
330 0, /* tp_as_number */
331 0, /* tp_as_sequence */
332 0, /* tp_as_mapping */
333 0, /* tp_hash */
334 0, /* tp_call */
335 0, /* tp_str */
336 PyObject_GenericGetAttr, /* tp_getattro */
337 dbus_py_immutable_setattro, /* tp_setattro */
338 0, /* tp_as_buffer */
339 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
340 DBusPythonString_tp_doc, /* tp_doc */
341 0, /* tp_traverse */
342 0, /* tp_clear */
343 0, /* tp_richcompare */
344 0, /* tp_weaklistoffset */
345 0, /* tp_iter */
346 0, /* tp_iternext */
347 0, /* tp_methods */
348 0, /* tp_members */
349 0, /* tp_getset */
350 DEFERRED_ADDRESS(&PyString_Type), /* tp_base */
351 0, /* tp_dict */
352 0, /* tp_descr_get */
353 0, /* tp_descr_set */
354 -sizeof(void *), /* tp_dictoffset */
355 0, /* tp_init */
356 0, /* tp_alloc */
357 DBusPythonString_tp_new, /* tp_new */
360 /* Support code for long subclasses ================================= */
362 PyDoc_STRVAR(DBusPythonLong_tp_doc,\
363 "Base class for ``long`` subclasses with a ``variant_level`` attribute.\n"
364 "Do not rely on the existence of this class outside dbus-python.\n"
367 static PyObject *
368 DBusPythonLong_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
370 PyObject *self;
371 PyObject *variantness = NULL;
372 static char *argnames[] = {"variant_level", NULL};
374 if (PyTuple_Size(args) > 1) {
375 PyErr_SetString(PyExc_TypeError,
376 "__new__ takes at most one positional parameter");
377 return NULL;
379 if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple, kwargs,
380 "|O!:__new__", argnames,
381 &PyInt_Type, &variantness)) return NULL;
382 if (!variantness) {
383 variantness = PyInt_FromLong(0);
384 if (!variantness) return NULL;
386 if (PyInt_AS_LONG(variantness) < 0) {
387 PyErr_SetString(PyExc_ValueError,
388 "variant_level must be non-negative");
389 return NULL;
392 self = (PyLong_Type.tp_new)(cls, args, NULL);
393 if (self) {
394 PyObject_GenericSetAttr(self, dbus_py_variant_level_const, variantness);
396 return self;
399 static PyObject *
400 DBusPythonLong_tp_repr(PyObject *self)
402 PyObject *parent_repr = (PyLong_Type.tp_repr)(self);
403 PyObject *vl_obj;
404 PyObject *my_repr;
405 long variant_level;
407 if (!parent_repr) return NULL;
408 vl_obj = PyObject_GetAttr(self, dbus_py_variant_level_const);
409 if (!vl_obj) return 0;
410 variant_level = PyInt_AsLong(vl_obj);
411 if (variant_level) {
412 my_repr = PyString_FromFormat("%s(%s, variant_level=%ld)",
413 self->ob_type->tp_name,
414 PyString_AS_STRING(parent_repr),
415 variant_level);
417 else {
418 my_repr = PyString_FromFormat("%s(%s)", self->ob_type->tp_name,
419 PyString_AS_STRING(parent_repr));
421 /* whether my_repr is NULL or not: */
422 Py_DECREF(parent_repr);
423 return my_repr;
426 PyTypeObject DBusPyLongBase_Type = {
427 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
429 "_dbus_bindings._LongBase",
430 INT_MAX, /* placeholder */
432 0, /* tp_dealloc */
433 0, /* tp_print */
434 0, /* tp_getattr */
435 0, /* tp_setattr */
436 0, /* tp_compare */
437 DBusPythonLong_tp_repr, /* tp_repr */
438 0, /* tp_as_number */
439 0, /* tp_as_sequence */
440 0, /* tp_as_mapping */
441 0, /* tp_hash */
442 0, /* tp_call */
443 0, /* tp_str */
444 PyObject_GenericGetAttr, /* tp_getattro */
445 dbus_py_immutable_setattro, /* tp_setattro */
446 0, /* tp_as_buffer */
447 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
448 DBusPythonLong_tp_doc, /* tp_doc */
449 0, /* tp_traverse */
450 0, /* tp_clear */
451 0, /* tp_richcompare */
452 0, /* tp_weaklistoffset */
453 0, /* tp_iter */
454 0, /* tp_iternext */
455 0, /* tp_methods */
456 0, /* tp_members */
457 0, /* tp_getset */
458 DEFERRED_ADDRESS(&PyLong_Type), /* tp_base */
459 0, /* tp_dict */
460 0, /* tp_descr_get */
461 0, /* tp_descr_set */
462 -sizeof(PyObject *), /* tp_dictoffset */
463 0, /* tp_init */
464 0, /* tp_alloc */
465 DBusPythonLong_tp_new, /* tp_new */
468 PyObject *dbus_py_variant_level_const = NULL;
469 PyObject *dbus_py_signature_const = NULL;
470 PyObject *dbus_py__dbus_object_path__const = NULL;
472 dbus_bool_t
473 dbus_py_init_abstract(void)
475 dbus_py__dbus_object_path__const = PyString_InternFromString("__dbus_object_path__");
476 if (!dbus_py__dbus_object_path__const) return 0;
478 dbus_py_variant_level_const = PyString_InternFromString("variant_level");
479 if (!dbus_py_variant_level_const) return 0;
481 dbus_py_signature_const = PyString_InternFromString("signature");
482 if (!dbus_py_signature_const) return 0;
484 DBusPyIntBase_Type.tp_base = &PyInt_Type;
485 if (PyType_Ready(&DBusPyIntBase_Type) < 0) return 0;
486 /* disable the tp_print copied from PyInt_Type, so tp_repr gets called as
487 desired */
488 DBusPyIntBase_Type.tp_print = NULL;
490 DBusPyFloatBase_Type.tp_base = &PyFloat_Type;
491 if (PyType_Ready(&DBusPyFloatBase_Type) < 0) return 0;
492 DBusPyFloatBase_Type.tp_print = NULL;
494 /* Add a pointer for the instance dict, aligning to sizeof(PyObject *)
495 * to make sure the offset of -sizeof(PyObject *) is right. */
496 DBusPyLongBase_Type.tp_basicsize = PyLong_Type.tp_basicsize
497 + 2*sizeof(PyObject *) - 1;
498 DBusPyLongBase_Type.tp_basicsize /= sizeof(PyObject *);
499 DBusPyLongBase_Type.tp_basicsize *= sizeof(PyObject *);
500 DBusPyLongBase_Type.tp_base = &PyLong_Type;
501 if (PyType_Ready(&DBusPyLongBase_Type) < 0) return 0;
502 DBusPyLongBase_Type.tp_print = NULL;
504 DBusPyStrBase_Type.tp_basicsize = PyString_Type.tp_basicsize
505 + 2*sizeof(PyObject *) - 1;
506 DBusPyStrBase_Type.tp_basicsize /= sizeof(PyObject *);
507 DBusPyStrBase_Type.tp_basicsize *= sizeof(PyObject *);
508 DBusPyStrBase_Type.tp_base = &PyString_Type;
509 if (PyType_Ready(&DBusPyStrBase_Type) < 0) return 0;
510 DBusPyStrBase_Type.tp_print = NULL;
512 return 1;
515 dbus_bool_t
516 dbus_py_insert_abstract_types(PyObject *this_module)
518 Py_INCREF(&DBusPyIntBase_Type);
519 Py_INCREF(&DBusPyLongBase_Type);
520 Py_INCREF(&DBusPyStrBase_Type);
521 Py_INCREF(&DBusPyFloatBase_Type);
522 if (PyModule_AddObject(this_module, "_IntBase",
523 (PyObject *)&DBusPyIntBase_Type) < 0) return 0;
524 if (PyModule_AddObject(this_module, "_LongBase",
525 (PyObject *)&DBusPyLongBase_Type) < 0) return 0;
526 if (PyModule_AddObject(this_module, "_StrBase",
527 (PyObject *)&DBusPyStrBase_Type) < 0) return 0;
528 if (PyModule_AddObject(this_module, "_FloatBase",
529 (PyObject *)&DBusPyFloatBase_Type) < 0) return 0;
531 return 1;