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
26 #include <structmember.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
),
43 "The number of nested variants wrapping the real data. "
44 "0 if not in a variant."},
49 DBusPythonInt_tp_new(PyTypeObject
*cls
, PyObject
*args
, PyObject
*kwargs
)
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");
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");
69 self
= (PyInt_Type
.tp_new
)(cls
, args
, NULL
);
71 ((DBusPyIntBase
*)self
)->variant_level
= variantness
;
77 DBusPythonInt_tp_repr(PyObject
*self
)
79 PyObject
*parent_repr
= (PyInt_Type
.tp_repr
)(self
);
80 long variant_level
= ((DBusPyIntBase
*)self
)->variant_level
;
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
),
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
);
99 PyTypeObject DBusPyIntBase_Type
= {
100 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type
))
102 "_dbus_bindings._IntBase",
103 sizeof(DBusPyIntBase
),
110 DBusPythonInt_tp_repr
, /* tp_repr */
111 0, /* tp_as_number */
112 0, /* tp_as_sequence */
113 0, /* tp_as_mapping */
119 0, /* tp_as_buffer */
120 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
, /* tp_flags */
121 DBusPythonInt_tp_doc
, /* tp_doc */
124 0, /* tp_richcompare */
125 0, /* tp_weaklistoffset */
129 DBusPythonInt_tp_members
, /* tp_members */
131 DEFERRED_ADDRESS(&PyInt_Type
), /* tp_base */
133 0, /* tp_descr_get */
134 0, /* tp_descr_set */
135 0, /* tp_dictoffset */
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
),
154 "The number of nested variants wrapping the real data. "
155 "0 if not in a variant."},
160 DBusPythonFloat_tp_new(PyTypeObject
*cls
, PyObject
*args
, PyObject
*kwargs
)
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");
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");
180 self
= (PyFloat_Type
.tp_new
)(cls
, args
, NULL
);
182 ((DBusPyFloatBase
*)self
)->variant_level
= variantness
;
188 DBusPythonFloat_tp_repr(PyObject
*self
)
190 PyObject
*parent_repr
= (PyFloat_Type
.tp_repr
)(self
);
191 long variant_level
= ((DBusPyFloatBase
*)self
)->variant_level
;
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
),
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
);
210 PyTypeObject DBusPyFloatBase_Type
= {
211 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type
))
213 "_dbus_bindings._FloatBase",
214 sizeof(DBusPyFloatBase
),
221 DBusPythonFloat_tp_repr
, /* tp_repr */
222 0, /* tp_as_number */
223 0, /* tp_as_sequence */
224 0, /* tp_as_mapping */
230 0, /* tp_as_buffer */
231 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
, /* tp_flags */
232 DBusPythonFloat_tp_doc
, /* tp_doc */
235 0, /* tp_richcompare */
236 0, /* tp_weaklistoffset */
240 DBusPythonFloat_tp_members
, /* tp_members */
242 DEFERRED_ADDRESS(&PyFloat_Type
), /* tp_base */
244 0, /* tp_descr_get */
245 0, /* tp_descr_set */
246 0, /* tp_dictoffset */
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"
260 DBusPythonString_tp_new(PyTypeObject
*cls
, PyObject
*args
, PyObject
*kwargs
)
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");
271 if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple
, kwargs
,
272 "|O!:__new__", argnames
,
273 &PyInt_Type
, &variantness
)) return NULL
;
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");
284 self
= (PyString_Type
.tp_new
)(cls
, args
, NULL
);
286 PyObject_GenericSetAttr(self
, dbus_py_variant_level_const
, variantness
);
292 DBusPythonString_tp_repr(PyObject
*self
)
294 PyObject
*parent_repr
= (PyString_Type
.tp_repr
)(self
);
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
),
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
);
318 PyTypeObject DBusPyStrBase_Type
= {
319 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type
))
321 "_dbus_bindings._StrBase",
322 INT_MAX
, /* placeholder */
329 DBusPythonString_tp_repr
, /* tp_repr */
330 0, /* tp_as_number */
331 0, /* tp_as_sequence */
332 0, /* tp_as_mapping */
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 */
343 0, /* tp_richcompare */
344 0, /* tp_weaklistoffset */
350 DEFERRED_ADDRESS(&PyString_Type
), /* tp_base */
352 0, /* tp_descr_get */
353 0, /* tp_descr_set */
354 -sizeof(void *), /* tp_dictoffset */
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"
368 DBusPythonLong_tp_new(PyTypeObject
*cls
, PyObject
*args
, PyObject
*kwargs
)
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");
379 if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple
, kwargs
,
380 "|O!:__new__", argnames
,
381 &PyInt_Type
, &variantness
)) return NULL
;
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");
392 self
= (PyLong_Type
.tp_new
)(cls
, args
, NULL
);
394 PyObject_GenericSetAttr(self
, dbus_py_variant_level_const
, variantness
);
400 DBusPythonLong_tp_repr(PyObject
*self
)
402 PyObject
*parent_repr
= (PyLong_Type
.tp_repr
)(self
);
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
);
412 my_repr
= PyString_FromFormat("%s(%s, variant_level=%ld)",
413 self
->ob_type
->tp_name
,
414 PyString_AS_STRING(parent_repr
),
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
);
426 PyTypeObject DBusPyLongBase_Type
= {
427 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type
))
429 "_dbus_bindings._LongBase",
430 INT_MAX
, /* placeholder */
437 DBusPythonLong_tp_repr
, /* tp_repr */
438 0, /* tp_as_number */
439 0, /* tp_as_sequence */
440 0, /* tp_as_mapping */
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 */
451 0, /* tp_richcompare */
452 0, /* tp_weaklistoffset */
458 DEFERRED_ADDRESS(&PyLong_Type
), /* tp_base */
460 0, /* tp_descr_get */
461 0, /* tp_descr_set */
462 -sizeof(PyObject
*), /* tp_dictoffset */
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
;
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
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
;
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;