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
24 #include <structmember.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
),
41 "The number of nested variants wrapping the real data. "
42 "0 if not in a variant."},
47 DBusPythonInt_tp_new(PyTypeObject
*cls
, PyObject
*args
, PyObject
*kwargs
)
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");
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");
67 self
= (PyInt_Type
.tp_new
)(cls
, args
, NULL
);
69 ((DBusPyIntBase
*)self
)->variant_level
= variantness
;
75 DBusPythonInt_tp_repr(PyObject
*self
)
77 PyObject
*parent_repr
= (PyInt_Type
.tp_repr
)(self
);
78 long variant_level
= ((DBusPyIntBase
*)self
)->variant_level
;
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
),
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
);
97 PyTypeObject DBusPyIntBase_Type
= {
98 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type
))
100 "_dbus_bindings._IntBase",
101 sizeof(DBusPyIntBase
),
108 DBusPythonInt_tp_repr
, /* tp_repr */
109 0, /* tp_as_number */
110 0, /* tp_as_sequence */
111 0, /* tp_as_mapping */
117 0, /* tp_as_buffer */
118 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
, /* tp_flags */
119 DBusPythonInt_tp_doc
, /* tp_doc */
122 0, /* tp_richcompare */
123 0, /* tp_weaklistoffset */
127 DBusPythonInt_tp_members
, /* tp_members */
129 DEFERRED_ADDRESS(&PyInt_Type
), /* tp_base */
131 0, /* tp_descr_get */
132 0, /* tp_descr_set */
133 0, /* tp_dictoffset */
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
),
152 "The number of nested variants wrapping the real data. "
153 "0 if not in a variant."},
158 DBusPythonFloat_tp_new(PyTypeObject
*cls
, PyObject
*args
, PyObject
*kwargs
)
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");
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");
178 self
= (PyFloat_Type
.tp_new
)(cls
, args
, NULL
);
180 ((DBusPyFloatBase
*)self
)->variant_level
= variantness
;
186 DBusPythonFloat_tp_repr(PyObject
*self
)
188 PyObject
*parent_repr
= (PyFloat_Type
.tp_repr
)(self
);
189 long variant_level
= ((DBusPyFloatBase
*)self
)->variant_level
;
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
),
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
);
208 PyTypeObject DBusPyFloatBase_Type
= {
209 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type
))
211 "_dbus_bindings._FloatBase",
212 sizeof(DBusPyFloatBase
),
219 DBusPythonFloat_tp_repr
, /* tp_repr */
220 0, /* tp_as_number */
221 0, /* tp_as_sequence */
222 0, /* tp_as_mapping */
228 0, /* tp_as_buffer */
229 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
, /* tp_flags */
230 DBusPythonFloat_tp_doc
, /* tp_doc */
233 0, /* tp_richcompare */
234 0, /* tp_weaklistoffset */
238 DBusPythonFloat_tp_members
, /* tp_members */
240 DEFERRED_ADDRESS(&PyFloat_Type
), /* tp_base */
242 0, /* tp_descr_get */
243 0, /* tp_descr_set */
244 0, /* tp_dictoffset */
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"
258 DBusPythonString_tp_new(PyTypeObject
*cls
, PyObject
*args
, PyObject
*kwargs
)
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");
269 if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple
, kwargs
,
270 "|O!:__new__", argnames
,
271 &PyInt_Type
, &variantness
)) return NULL
;
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");
282 self
= (PyString_Type
.tp_new
)(cls
, args
, NULL
);
284 PyObject_GenericSetAttr(self
, dbus_py_variant_level_const
, variantness
);
290 DBusPythonString_tp_repr(PyObject
*self
)
292 PyObject
*parent_repr
= (PyString_Type
.tp_repr
)(self
);
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
),
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
);
316 PyTypeObject DBusPyStrBase_Type
= {
317 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type
))
319 "_dbus_bindings._StrBase",
320 INT_MAX
, /* placeholder */
327 DBusPythonString_tp_repr
, /* tp_repr */
328 0, /* tp_as_number */
329 0, /* tp_as_sequence */
330 0, /* tp_as_mapping */
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 */
341 0, /* tp_richcompare */
342 0, /* tp_weaklistoffset */
348 DEFERRED_ADDRESS(&PyString_Type
), /* tp_base */
350 0, /* tp_descr_get */
351 0, /* tp_descr_set */
352 -sizeof(void *), /* tp_dictoffset */
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"
366 DBusPythonLong_tp_new(PyTypeObject
*cls
, PyObject
*args
, PyObject
*kwargs
)
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");
377 if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple
, kwargs
,
378 "|O!:__new__", argnames
,
379 &PyInt_Type
, &variantness
)) return NULL
;
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");
390 self
= (PyLong_Type
.tp_new
)(cls
, args
, NULL
);
392 PyObject_GenericSetAttr(self
, dbus_py_variant_level_const
, variantness
);
398 DBusPythonLong_tp_repr(PyObject
*self
)
400 PyObject
*parent_repr
= (PyLong_Type
.tp_repr
)(self
);
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
);
410 my_repr
= PyString_FromFormat("%s(%s, variant_level=%ld)",
411 self
->ob_type
->tp_name
,
412 PyString_AS_STRING(parent_repr
),
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
);
424 PyTypeObject DBusPyLongBase_Type
= {
425 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type
))
427 "_dbus_bindings._LongBase",
428 INT_MAX
, /* placeholder */
435 DBusPythonLong_tp_repr
, /* tp_repr */
436 0, /* tp_as_number */
437 0, /* tp_as_sequence */
438 0, /* tp_as_mapping */
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 */
449 0, /* tp_richcompare */
450 0, /* tp_weaklistoffset */
456 DEFERRED_ADDRESS(&PyLong_Type
), /* tp_base */
458 0, /* tp_descr_get */
459 0, /* tp_descr_set */
460 -sizeof(PyObject
*), /* tp_dictoffset */
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
;
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
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
;
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;