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 static PyObject
*variant_level_const
;
27 /* Support code for int subclasses. ================================== */
29 static PyTypeObject DBusPythonIntType
;
30 DEFINE_CHECK(DBusPythonInt
)
37 static PyMemberDef DBusPythonInt_tp_members
[] = {
38 {"variant_level", T_LONG
, offsetof(DBusPythonInt
, variant_level
),
40 "The number of nested variants wrapping the real data. "
41 "0 if not in a variant."},
46 DBusPythonInt_tp_new(PyTypeObject
*cls
, PyObject
*args
, PyObject
*kwargs
)
50 static char *argnames
[] = {"variant_level", NULL
};
52 if (PyTuple_Size(args
) > 1) {
53 PyErr_SetString(PyExc_TypeError
,
54 "__new__ takes at most one positional parameter");
57 if (!PyArg_ParseTupleAndKeywords(empty_tuple
, kwargs
,
58 "|l:__new__", argnames
,
59 &variantness
)) return NULL
;
60 if (variantness
< 0) {
61 PyErr_SetString(PyExc_ValueError
,
62 "variant_level must be non-negative");
66 self
= (PyInt_Type
.tp_new
)(cls
, args
, NULL
);
68 ((DBusPythonInt
*)self
)->variant_level
= variantness
;
74 DBusPythonInt_tp_repr(PyObject
*self
)
76 PyObject
*parent_repr
= (PyInt_Type
.tp_repr
)(self
);
77 long variant_level
= ((DBusPythonInt
*)self
)->variant_level
;
80 if (!parent_repr
) return NULL
;
81 if (variant_level
> 0) {
82 my_repr
= PyString_FromFormat("%s(%s, variant_level=%ld)",
83 self
->ob_type
->tp_name
,
84 PyString_AS_STRING(parent_repr
),
88 my_repr
= PyString_FromFormat("%s(%s)", self
->ob_type
->tp_name
,
89 PyString_AS_STRING(parent_repr
));
91 /* whether my_repr is NULL or not: */
92 Py_DECREF(parent_repr
);
96 static PyTypeObject DBusPythonIntType
= {
97 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type
))
99 "_dbus_bindings._DBusPythonInt",
100 sizeof(DBusPythonInt
),
107 DBusPythonInt_tp_repr
, /* tp_repr */
108 0, /* tp_as_number */
109 0, /* tp_as_sequence */
110 0, /* tp_as_mapping */
116 0, /* tp_as_buffer */
117 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
, /* tp_flags */
121 0, /* tp_richcompare */
122 0, /* tp_weaklistoffset */
126 DBusPythonInt_tp_members
, /* tp_members */
128 DEFERRED_ADDRESS(&PyInt_Type
), /* tp_base */
130 0, /* tp_descr_get */
131 0, /* tp_descr_set */
132 0, /* tp_dictoffset */
135 DBusPythonInt_tp_new
, /* tp_new */
138 /* Support code for float subclasses. ================================ */
140 /* There's only one subclass at the moment (Double) but these are factored
141 out to make room for Float later. (Float is implemented and #if'd out) */
143 static PyTypeObject DBusPythonFloatType
;
144 DEFINE_CHECK(DBusPythonFloat
)
151 static PyMemberDef DBusPythonFloat_tp_members
[] = {
152 {"variant_level", T_LONG
, offsetof(DBusPythonFloat
, 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(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 ((DBusPythonFloat
*)self
)->variant_level
= variantness
;
188 DBusPythonFloat_tp_repr(PyObject
*self
)
190 PyObject
*parent_repr
= (PyFloat_Type
.tp_repr
)(self
);
191 long variant_level
= ((DBusPythonFloat
*)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 static PyTypeObject DBusPythonFloatType
= {
211 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type
))
213 "_dbus_bindings._DBusPythonFloat",
214 sizeof(DBusPythonFloat
),
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 */
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 static PyTypeObject DBusPythonStringType
;
255 DEFINE_CHECK(DBusPythonString
)
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(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
, 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
, 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 static PyTypeObject DBusPythonStringType
= {
317 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type
))
319 "_dbus_bindings._DBusPythonString",
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 Glue_immutable_setattro
, /* tp_setattro */
336 0, /* tp_as_buffer */
337 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
, /* tp_flags */
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 static PyTypeObject DBusPythonLongType
;
361 DEFINE_CHECK(DBusPythonLong
)
364 DBusPythonLong_tp_new(PyTypeObject
*cls
, PyObject
*args
, PyObject
*kwargs
)
367 PyObject
*variantness
= NULL
;
368 static char *argnames
[] = {"variant_level", NULL
};
370 if (PyTuple_Size(args
) > 1) {
371 PyErr_SetString(PyExc_TypeError
,
372 "__new__ takes at most one positional parameter");
375 if (!PyArg_ParseTupleAndKeywords(empty_tuple
, kwargs
,
376 "|O!:__new__", argnames
,
377 &PyInt_Type
, &variantness
)) return NULL
;
379 variantness
= PyInt_FromLong(0);
380 if (!variantness
) return NULL
;
382 if (PyInt_AS_LONG(variantness
) < 0) {
383 PyErr_SetString(PyExc_ValueError
,
384 "variant_level must be non-negative");
388 self
= (PyLong_Type
.tp_new
)(cls
, args
, NULL
);
390 PyObject_GenericSetAttr(self
, variant_level_const
, variantness
);
396 DBusPythonLong_tp_repr(PyObject
*self
)
398 PyObject
*parent_repr
= (PyLong_Type
.tp_repr
)(self
);
403 if (!parent_repr
) return NULL
;
404 vl_obj
= PyObject_GetAttr(self
, variant_level_const
);
405 if (!vl_obj
) return 0;
406 variant_level
= PyInt_AsLong(vl_obj
);
408 my_repr
= PyString_FromFormat("%s(%s, variant_level=%ld)",
409 self
->ob_type
->tp_name
,
410 PyString_AS_STRING(parent_repr
),
414 my_repr
= PyString_FromFormat("%s(%s)", self
->ob_type
->tp_name
,
415 PyString_AS_STRING(parent_repr
));
417 /* whether my_repr is NULL or not: */
418 Py_DECREF(parent_repr
);
422 static PyTypeObject DBusPythonLongType
= {
423 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type
))
425 "_dbus_bindings._DBusPythonLong",
426 INT_MAX
, /* placeholder */
433 DBusPythonLong_tp_repr
, /* tp_repr */
434 0, /* tp_as_number */
435 0, /* tp_as_sequence */
436 0, /* tp_as_mapping */
440 PyObject_GenericGetAttr
, /* tp_getattro */
441 Glue_immutable_setattro
, /* tp_setattro */
442 0, /* tp_as_buffer */
443 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
, /* tp_flags */
447 0, /* tp_richcompare */
448 0, /* tp_weaklistoffset */
454 DEFERRED_ADDRESS(&PyLong_Type
), /* tp_base */
456 0, /* tp_descr_get */
457 0, /* tp_descr_set */
458 -sizeof(PyObject
*), /* tp_dictoffset */
461 DBusPythonLong_tp_new
, /* tp_new */
467 variant_level_const
= PyString_InternFromString("variant_level");
468 if (!variant_level_const
) return 0;
470 DBusPythonIntType
.tp_base
= &PyInt_Type
;
471 if (PyType_Ready(&DBusPythonIntType
) < 0) return 0;
472 /* disable the tp_print copied from PyInt_Type, so tp_repr gets called as
474 DBusPythonIntType
.tp_print
= NULL
;
476 DBusPythonFloatType
.tp_base
= &PyFloat_Type
;
477 if (PyType_Ready(&DBusPythonFloatType
) < 0) return 0;
478 DBusPythonFloatType
.tp_print
= NULL
;
480 /* Add a pointer for the instance dict, aligning to sizeof(PyObject *)
481 * to make sure the offset of -sizeof(PyObject *) is right. */
482 DBusPythonLongType
.tp_basicsize
= PyLong_Type
.tp_basicsize
483 + 2*sizeof(PyObject
*) - 1;
484 DBusPythonLongType
.tp_basicsize
/= sizeof(PyObject
*);
485 DBusPythonLongType
.tp_basicsize
*= sizeof(PyObject
*);
486 DBusPythonLongType
.tp_base
= &PyLong_Type
;
487 if (PyType_Ready(&DBusPythonLongType
) < 0) return 0;
488 DBusPythonLongType
.tp_print
= NULL
;
490 DBusPythonStringType
.tp_basicsize
= PyString_Type
.tp_basicsize
491 + 2*sizeof(PyObject
*) - 1;
492 DBusPythonStringType
.tp_basicsize
/= sizeof(PyObject
*);
493 DBusPythonStringType
.tp_basicsize
*= sizeof(PyObject
*);
494 DBusPythonStringType
.tp_base
= &PyString_Type
;
495 if (PyType_Ready(&DBusPythonStringType
) < 0) return 0;
496 DBusPythonStringType
.tp_print
= NULL
;
502 insert_abstract_types(PyObject
*this_module
)
504 Py_INCREF(&DBusPythonIntType
);
505 Py_INCREF(&DBusPythonLongType
);
506 Py_INCREF(&DBusPythonStringType
);
507 Py_INCREF(&DBusPythonFloatType
);
508 if (PyModule_AddObject(this_module
, "_DBusPythonInt",
509 (PyObject
*)&DBusPythonIntType
) < 0) return 0;
510 if (PyModule_AddObject(this_module
, "_DBusPythonLong",
511 (PyObject
*)&DBusPythonLongType
) < 0) return 0;
512 if (PyModule_AddObject(this_module
, "_DBusPythonString",
513 (PyObject
*)&DBusPythonStringType
) < 0) return 0;
514 if (PyModule_AddObject(this_module
, "_DBusPythonFloat",
515 (PyObject
*)&DBusPythonFloatType
) < 0) return 0;