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 */
135 PyType_GenericAlloc
, /* tp_alloc */
136 DBusPythonInt_tp_new
, /* tp_new */
137 PyObject_Del
, /* tp_free */
140 /* Support code for float subclasses. ================================ */
142 /* There's only one subclass at the moment (Double) but these are factored
143 out to make room for Float later. (Float is implemented and #if'd out) */
145 PyDoc_STRVAR(DBusPythonFloat_tp_doc
,\
146 "Base class for float subclasses with a ``variant_level`` attribute.\n"
147 "Do not rely on the existence of this class outside dbus-python.\n"
150 static PyMemberDef DBusPythonFloat_tp_members
[] = {
151 {"variant_level", T_LONG
, offsetof(DBusPyFloatBase
, variant_level
),
153 "The number of nested variants wrapping the real data. "
154 "0 if not in a variant."},
159 DBusPythonFloat_tp_new(PyTypeObject
*cls
, PyObject
*args
, PyObject
*kwargs
)
162 long variantness
= 0;
163 static char *argnames
[] = {"variant_level", NULL
};
165 if (PyTuple_Size(args
) > 1) {
166 PyErr_SetString(PyExc_TypeError
,
167 "__new__ takes at most one positional parameter");
170 if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple
, kwargs
,
171 "|l:__new__", argnames
,
172 &variantness
)) return NULL
;
173 if (variantness
< 0) {
174 PyErr_SetString(PyExc_ValueError
,
175 "variant_level must be non-negative");
179 self
= (PyFloat_Type
.tp_new
)(cls
, args
, NULL
);
181 ((DBusPyFloatBase
*)self
)->variant_level
= variantness
;
187 DBusPythonFloat_tp_repr(PyObject
*self
)
189 PyObject
*parent_repr
= (PyFloat_Type
.tp_repr
)(self
);
190 long variant_level
= ((DBusPyFloatBase
*)self
)->variant_level
;
193 if (!parent_repr
) return NULL
;
194 if (variant_level
> 0) {
195 my_repr
= PyString_FromFormat("%s(%s, variant_level=%ld)",
196 self
->ob_type
->tp_name
,
197 PyString_AS_STRING(parent_repr
),
201 my_repr
= PyString_FromFormat("%s(%s)", self
->ob_type
->tp_name
,
202 PyString_AS_STRING(parent_repr
));
204 /* whether my_repr is NULL or not: */
205 Py_DECREF(parent_repr
);
209 PyTypeObject DBusPyFloatBase_Type
= {
210 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type
))
212 "_dbus_bindings._FloatBase",
213 sizeof(DBusPyFloatBase
),
220 DBusPythonFloat_tp_repr
, /* tp_repr */
221 0, /* tp_as_number */
222 0, /* tp_as_sequence */
223 0, /* tp_as_mapping */
229 0, /* tp_as_buffer */
230 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
, /* tp_flags */
231 DBusPythonFloat_tp_doc
, /* tp_doc */
234 0, /* tp_richcompare */
235 0, /* tp_weaklistoffset */
239 DBusPythonFloat_tp_members
, /* tp_members */
241 DEFERRED_ADDRESS(&PyFloat_Type
), /* tp_base */
243 0, /* tp_descr_get */
244 0, /* tp_descr_set */
245 0, /* tp_dictoffset */
248 DBusPythonFloat_tp_new
, /* tp_new */
251 /* Support code for str subclasses ================================== */
253 PyDoc_STRVAR(DBusPythonString_tp_doc
,\
254 "Base class for str subclasses with a ``variant_level`` attribute.\n"
255 "Do not rely on the existence of this class outside dbus-python.\n"
259 DBusPythonString_tp_new(PyTypeObject
*cls
, PyObject
*args
, PyObject
*kwargs
)
262 PyObject
*variantness
= NULL
;
263 static char *argnames
[] = {"variant_level", NULL
};
265 if (PyTuple_Size(args
) > 1) {
266 PyErr_SetString(PyExc_TypeError
,
267 "__new__ takes at most one positional parameter");
270 if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple
, kwargs
,
271 "|O!:__new__", argnames
,
272 &PyInt_Type
, &variantness
)) return NULL
;
274 variantness
= PyInt_FromLong(0);
275 if (!variantness
) return NULL
;
277 if (PyInt_AS_LONG(variantness
) < 0) {
278 PyErr_SetString(PyExc_ValueError
,
279 "variant_level must be non-negative");
283 self
= (PyString_Type
.tp_new
)(cls
, args
, NULL
);
285 PyObject_GenericSetAttr(self
, dbus_py_variant_level_const
, variantness
);
291 DBusPythonString_tp_repr(PyObject
*self
)
293 PyObject
*parent_repr
= (PyString_Type
.tp_repr
)(self
);
298 if (!parent_repr
) return NULL
;
299 vl_obj
= PyObject_GetAttr(self
, dbus_py_variant_level_const
);
301 Py_DECREF(parent_repr
);
304 variant_level
= PyInt_AsLong(vl_obj
);
306 if (variant_level
> 0) {
307 my_repr
= PyString_FromFormat("%s(%s, variant_level=%ld)",
308 self
->ob_type
->tp_name
,
309 PyString_AS_STRING(parent_repr
),
313 my_repr
= PyString_FromFormat("%s(%s)", self
->ob_type
->tp_name
,
314 PyString_AS_STRING(parent_repr
));
316 /* whether my_repr is NULL or not: */
317 Py_DECREF(parent_repr
);
321 PyTypeObject DBusPyStrBase_Type
= {
322 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type
))
324 "_dbus_bindings._StrBase",
325 INT_MAX
, /* placeholder */
332 DBusPythonString_tp_repr
, /* tp_repr */
333 0, /* tp_as_number */
334 0, /* tp_as_sequence */
335 0, /* tp_as_mapping */
339 PyObject_GenericGetAttr
, /* tp_getattro */
340 dbus_py_immutable_setattro
, /* tp_setattro */
341 0, /* tp_as_buffer */
342 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
, /* tp_flags */
343 DBusPythonString_tp_doc
, /* tp_doc */
346 0, /* tp_richcompare */
347 0, /* tp_weaklistoffset */
353 DEFERRED_ADDRESS(&PyString_Type
), /* tp_base */
355 0, /* tp_descr_get */
356 0, /* tp_descr_set */
357 -sizeof(void *), /* tp_dictoffset */
360 DBusPythonString_tp_new
, /* tp_new */
363 /* Support code for long subclasses ================================= */
365 PyDoc_STRVAR(DBusPythonLong_tp_doc
,\
366 "Base class for ``long`` subclasses with a ``variant_level`` attribute.\n"
367 "Do not rely on the existence of this class outside dbus-python.\n"
371 DBusPythonLong_tp_new(PyTypeObject
*cls
, PyObject
*args
, PyObject
*kwargs
)
374 PyObject
*variantness
= NULL
;
375 static char *argnames
[] = {"variant_level", NULL
};
377 if (PyTuple_Size(args
) > 1) {
378 PyErr_SetString(PyExc_TypeError
,
379 "__new__ takes at most one positional parameter");
382 if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple
, kwargs
,
383 "|O!:__new__", argnames
,
384 &PyInt_Type
, &variantness
)) return NULL
;
386 variantness
= PyInt_FromLong(0);
387 if (!variantness
) return NULL
;
389 if (PyInt_AS_LONG(variantness
) < 0) {
390 PyErr_SetString(PyExc_ValueError
,
391 "variant_level must be non-negative");
395 self
= (PyLong_Type
.tp_new
)(cls
, args
, NULL
);
397 PyObject_GenericSetAttr(self
, dbus_py_variant_level_const
, variantness
);
403 DBusPythonLong_tp_repr(PyObject
*self
)
405 PyObject
*parent_repr
= (PyLong_Type
.tp_repr
)(self
);
410 if (!parent_repr
) return NULL
;
411 vl_obj
= PyObject_GetAttr(self
, dbus_py_variant_level_const
);
413 Py_DECREF(parent_repr
);
416 variant_level
= PyInt_AsLong(vl_obj
);
419 my_repr
= PyString_FromFormat("%s(%s, variant_level=%ld)",
420 self
->ob_type
->tp_name
,
421 PyString_AS_STRING(parent_repr
),
425 my_repr
= PyString_FromFormat("%s(%s)", self
->ob_type
->tp_name
,
426 PyString_AS_STRING(parent_repr
));
428 /* whether my_repr is NULL or not: */
429 Py_DECREF(parent_repr
);
433 PyTypeObject DBusPyLongBase_Type
= {
434 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type
))
436 "_dbus_bindings._LongBase",
437 INT_MAX
, /* placeholder */
444 DBusPythonLong_tp_repr
, /* tp_repr */
445 0, /* tp_as_number */
446 0, /* tp_as_sequence */
447 0, /* tp_as_mapping */
451 PyObject_GenericGetAttr
, /* tp_getattro */
452 dbus_py_immutable_setattro
, /* tp_setattro */
453 0, /* tp_as_buffer */
454 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
, /* tp_flags */
455 DBusPythonLong_tp_doc
, /* tp_doc */
458 0, /* tp_richcompare */
459 0, /* tp_weaklistoffset */
465 DEFERRED_ADDRESS(&PyLong_Type
), /* tp_base */
467 0, /* tp_descr_get */
468 0, /* tp_descr_set */
469 -sizeof(PyObject
*), /* tp_dictoffset */
472 DBusPythonLong_tp_new
, /* tp_new */
475 PyObject
*dbus_py_variant_level_const
= NULL
;
476 PyObject
*dbus_py_signature_const
= NULL
;
477 PyObject
*dbus_py__dbus_object_path__const
= NULL
;
480 dbus_py_init_abstract(void)
482 dbus_py__dbus_object_path__const
= PyString_InternFromString("__dbus_object_path__");
483 if (!dbus_py__dbus_object_path__const
) return 0;
485 dbus_py_variant_level_const
= PyString_InternFromString("variant_level");
486 if (!dbus_py_variant_level_const
) return 0;
488 dbus_py_signature_const
= PyString_InternFromString("signature");
489 if (!dbus_py_signature_const
) return 0;
491 DBusPyIntBase_Type
.tp_base
= &PyInt_Type
;
492 if (PyType_Ready(&DBusPyIntBase_Type
) < 0) return 0;
493 /* disable the tp_print copied from PyInt_Type, so tp_repr gets called as
495 DBusPyIntBase_Type
.tp_print
= NULL
;
497 DBusPyFloatBase_Type
.tp_base
= &PyFloat_Type
;
498 if (PyType_Ready(&DBusPyFloatBase_Type
) < 0) return 0;
499 DBusPyFloatBase_Type
.tp_print
= NULL
;
501 /* Add a pointer for the instance dict, aligning to sizeof(PyObject *)
502 * to make sure the offset of -sizeof(PyObject *) is right. */
503 DBusPyLongBase_Type
.tp_basicsize
= PyLong_Type
.tp_basicsize
504 + 2*sizeof(PyObject
*) - 1;
505 DBusPyLongBase_Type
.tp_basicsize
/= sizeof(PyObject
*);
506 DBusPyLongBase_Type
.tp_basicsize
*= sizeof(PyObject
*);
507 DBusPyLongBase_Type
.tp_base
= &PyLong_Type
;
508 if (PyType_Ready(&DBusPyLongBase_Type
) < 0) return 0;
509 DBusPyLongBase_Type
.tp_print
= NULL
;
511 DBusPyStrBase_Type
.tp_basicsize
= PyString_Type
.tp_basicsize
512 + 2*sizeof(PyObject
*) - 1;
513 DBusPyStrBase_Type
.tp_basicsize
/= sizeof(PyObject
*);
514 DBusPyStrBase_Type
.tp_basicsize
*= sizeof(PyObject
*);
515 DBusPyStrBase_Type
.tp_base
= &PyString_Type
;
516 if (PyType_Ready(&DBusPyStrBase_Type
) < 0) return 0;
517 DBusPyStrBase_Type
.tp_print
= NULL
;
523 dbus_py_insert_abstract_types(PyObject
*this_module
)
525 Py_INCREF(&DBusPyIntBase_Type
);
526 Py_INCREF(&DBusPyLongBase_Type
);
527 Py_INCREF(&DBusPyStrBase_Type
);
528 Py_INCREF(&DBusPyFloatBase_Type
);
529 if (PyModule_AddObject(this_module
, "_IntBase",
530 (PyObject
*)&DBusPyIntBase_Type
) < 0) return 0;
531 if (PyModule_AddObject(this_module
, "_LongBase",
532 (PyObject
*)&DBusPyLongBase_Type
) < 0) return 0;
533 if (PyModule_AddObject(this_module
, "_StrBase",
534 (PyObject
*)&DBusPyStrBase_Type
) < 0) return 0;
535 if (PyModule_AddObject(this_module
, "_FloatBase",
536 (PyObject
*)&DBusPyFloatBase_Type
) < 0) return 0;