/* Subclasses of built-in Python types supporting extra D-Bus functionality. * * Copyright (C) 2006-2007 Collabora Ltd. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include "dbus_bindings-internal.h" #include #include #include "types-internal.h" /* Dict indexed by object IDs, whose values are nonzero variant levels * for immutable variable-sized D-Bus data types (_LongBase, _StrBase, Struct). * * This is a strange way to store them, but adding a __dict__ to the offending * objects seems even more error-prone, given that their sizes are variable! */ PyObject *_dbus_py_variant_levels = NULL; long dbus_py_variant_level_get(PyObject *obj) { PyObject *vl_obj; PyObject *key = PyLong_FromVoidPtr(obj); long variant_level; if (!key) { return -1; } vl_obj = PyDict_GetItem(_dbus_py_variant_levels, key); Py_CLEAR(key); if (!vl_obj) { /* PyDict_GetItem() does not set an exception when the key is missing. * In our case, it just means that there was no entry in the variant * dictionary for this object. Semantically, this is equivalent to a * variant level of 0. */ return 0; } variant_level = NATIVEINT_ASLONG(vl_obj); if (variant_level == -1 && PyErr_Occurred()) { /* variant_level < 0 can never be inserted into the dictionary; see * dbus_py_variant_level_set() below. The semantics of setting * variant_level < 0 is to delete it from the dictionary. */ return -1; } assert(variant_level >= 0); return variant_level; } dbus_bool_t dbus_py_variant_level_set(PyObject *obj, long variant_level) { /* key is the object's ID (= pointer) to avoid referencing it */ PyObject *key = PyLong_FromVoidPtr(obj); if (!key) { return FALSE; } if (variant_level <= 0) { if (PyDict_GetItem (_dbus_py_variant_levels, key)) { if (PyDict_DelItem (_dbus_py_variant_levels, key) < 0) { Py_CLEAR(key); return FALSE; } } } else { PyObject *vl_obj = NATIVEINT_FROMLONG(variant_level); if (!vl_obj) { Py_CLEAR(key); return FALSE; } if (PyDict_SetItem(_dbus_py_variant_levels, key, vl_obj) < 0) { Py_CLEAR(vl_obj); Py_CLEAR(key); return FALSE; } Py_CLEAR(vl_obj); } Py_CLEAR(key); return TRUE; } PyObject * dbus_py_variant_level_getattro(PyObject *obj, PyObject *name) { PyObject *key, *value; #ifdef PY3 if (PyUnicode_CompareWithASCIIString(name, "variant_level")) return PyObject_GenericGetAttr(obj, name); #else if (PyBytes_Check(name)) { Py_INCREF(name); } else if (PyUnicode_Check(name)) { name = PyUnicode_AsEncodedString(name, NULL, NULL); if (!name) { return NULL; } } else { PyErr_SetString(PyExc_TypeError, "attribute name must be string"); return NULL; } if (strcmp(PyBytes_AS_STRING(name), "variant_level")) { value = PyObject_GenericGetAttr(obj, name); Py_CLEAR(name); return value; } Py_CLEAR(name); #endif /* PY3 */ key = PyLong_FromVoidPtr(obj); if (!key) { return NULL; } value = PyDict_GetItem(_dbus_py_variant_levels, key); Py_CLEAR(key); if (!value) return NATIVEINT_FROMLONG(0); Py_INCREF(value); return value; } /* To be invoked by destructors. Clear the variant level without touching the * exception state */ void dbus_py_variant_level_clear(PyObject *self) { PyObject *et, *ev, *etb; /* avoid clobbering any pending exception */ PyErr_Fetch(&et, &ev, &etb); if (!dbus_py_variant_level_set(self, 0)) { /* should never happen */ PyErr_WriteUnraisable(self); } PyErr_Restore(et, ev, etb); } #ifndef PY3 /* Support code for int subclasses. ================================== */ PyDoc_STRVAR(DBusPythonInt_tp_doc,\ "Base class for int subclasses with a ``variant_level`` attribute.\n" "Do not rely on the existence of this class outside dbus-python.\n" ); static PyMemberDef DBusPythonInt_tp_members[] = { {"variant_level", T_LONG, offsetof(DBusPyIntBase, variant_level), READONLY, "The number of nested variants wrapping the real data. " "0 if not in a variant."}, {NULL}, }; static PyObject * DBusPythonInt_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs) { PyObject *self; long variantness = 0; static char *argnames[] = {"variant_level", NULL}; if (PyTuple_Size(args) > 1) { PyErr_SetString(PyExc_TypeError, "__new__ takes at most one positional parameter"); return NULL; } if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple, kwargs, "|l:__new__", argnames, &variantness)) return NULL; if (variantness < 0) { PyErr_SetString(PyExc_ValueError, "variant_level must be non-negative"); return NULL; } self = (PyInt_Type.tp_new)(cls, args, NULL); if (self) { ((DBusPyIntBase *)self)->variant_level = variantness; } return self; } static PyObject * DBusPythonInt_tp_repr(PyObject *self) { PyObject *parent_repr = (PyInt_Type.tp_repr)(self); long variant_level = ((DBusPyIntBase *)self)->variant_level; PyObject *my_repr; if (!parent_repr) return NULL; if (variant_level > 0) { my_repr = PyUnicode_FromFormat("%s(%V, variant_level=%ld)", Py_TYPE(self)->tp_name, REPRV(parent_repr), variant_level); } else { my_repr = PyUnicode_FromFormat("%s(%V)", Py_TYPE(self)->tp_name, REPRV(parent_repr)); } /* whether my_repr is NULL or not: */ Py_CLEAR(parent_repr); return my_repr; } PyTypeObject DBusPyIntBase_Type = { PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "_dbus_bindings._IntBase", sizeof(DBusPyIntBase), 0, 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ DBusPythonInt_tp_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ DBusPythonInt_tp_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ DBusPythonInt_tp_members, /* tp_members */ 0, /* tp_getset */ DEFERRED_ADDRESS(&PyInt_Type), /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ DBusPythonInt_tp_new, /* tp_new */ PyObject_Del, /* tp_free */ }; #endif /* !PY3 */ /* Support code for float subclasses. ================================ */ /* There's only one subclass at the moment (Double) but these are factored out to make room for Float later. (Float is implemented and #if'd out) */ PyDoc_STRVAR(DBusPythonFloat_tp_doc,\ "Base class for float subclasses with a ``variant_level`` attribute.\n" "Do not rely on the existence of this class outside dbus-python.\n" ); static PyMemberDef DBusPythonFloat_tp_members[] = { {"variant_level", T_LONG, offsetof(DBusPyFloatBase, variant_level), READONLY, "The number of nested variants wrapping the real data. " "0 if not in a variant."}, {NULL}, }; static PyObject * DBusPythonFloat_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs) { PyObject *self; long variantness = 0; static char *argnames[] = {"variant_level", NULL}; if (PyTuple_Size(args) > 1) { PyErr_SetString(PyExc_TypeError, "__new__ takes at most one positional parameter"); return NULL; } if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple, kwargs, "|l:__new__", argnames, &variantness)) return NULL; if (variantness < 0) { PyErr_SetString(PyExc_ValueError, "variant_level must be non-negative"); return NULL; } self = (PyFloat_Type.tp_new)(cls, args, NULL); if (self) { ((DBusPyFloatBase *)self)->variant_level = variantness; } return self; } static PyObject * DBusPythonFloat_tp_repr(PyObject *self) { PyObject *parent_repr = (PyFloat_Type.tp_repr)(self); long variant_level = ((DBusPyFloatBase *)self)->variant_level; PyObject *my_repr; if (!parent_repr) return NULL; if (variant_level > 0) { my_repr = PyUnicode_FromFormat("%s(%V, variant_level=%ld)", Py_TYPE(self)->tp_name, REPRV(parent_repr), variant_level); } else { my_repr = PyUnicode_FromFormat("%s(%V)", Py_TYPE(self)->tp_name, REPRV(parent_repr)); } /* whether my_repr is NULL or not: */ Py_CLEAR(parent_repr); return my_repr; } PyTypeObject DBusPyFloatBase_Type = { PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "_dbus_bindings._FloatBase", sizeof(DBusPyFloatBase), 0, 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ DBusPythonFloat_tp_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ DBusPythonFloat_tp_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ DBusPythonFloat_tp_members, /* tp_members */ 0, /* tp_getset */ DEFERRED_ADDRESS(&PyFloat_Type), /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ DBusPythonFloat_tp_new, /* tp_new */ }; #ifdef PY3 /* Support code for bytes subclasses ================================== */ PyDoc_STRVAR(DBusPythonBytes_tp_doc,\ "Base class for bytes subclasses with a ``variant_level`` attribute.\n" "Do not rely on the existence of this class outside dbus-python.\n" ); static PyObject * DBusPythonBytes_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs) { PyObject *self; long variantness = 0; static char *argnames[] = {"variant_level", NULL}; if (PyTuple_Size(args) > 1) { PyErr_SetString(PyExc_TypeError, "__new__ takes at most one positional parameter"); return NULL; } if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple, kwargs, "|l:__new__", argnames, &variantness)) return NULL; if (variantness < 0) { PyErr_SetString(PyExc_ValueError, "variant_level must be non-negative"); return NULL; } self = (PyBytes_Type.tp_new)(cls, args, NULL); if (self) { if (!dbus_py_variant_level_set(self, variantness)) { Py_CLEAR(self); return NULL; } } return self; } static PyObject * DBusPythonBytes_tp_repr(PyObject *self) { PyObject *parent_repr = (PyBytes_Type.tp_repr)(self); PyObject *vl_obj; PyObject *my_repr; long variant_level; if (!parent_repr) return NULL; vl_obj = PyObject_GetAttr(self, dbus_py_variant_level_const); if (!vl_obj) { Py_CLEAR(parent_repr); return NULL; } variant_level = NATIVEINT_ASLONG(vl_obj); Py_CLEAR(vl_obj); if (variant_level == -1 && PyErr_Occurred()) { Py_CLEAR(parent_repr); return NULL; } if (variant_level > 0) { my_repr = PyUnicode_FromFormat("%s(%V, variant_level=%ld)", Py_TYPE(self)->tp_name, REPRV(parent_repr), variant_level); } else { my_repr = PyUnicode_FromFormat("%s(%V)", Py_TYPE(self)->tp_name, REPRV(parent_repr)); } /* whether my_repr is NULL or not: */ Py_CLEAR(parent_repr); return my_repr; } static void DBusPyBytesBase_tp_dealloc(PyObject *self) { dbus_py_variant_level_clear(self); (PyBytes_Type.tp_dealloc)(self); } PyTypeObject DBusPyBytesBase_Type = { PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "_dbus_bindings._BytesBase", 0, 0, DBusPyBytesBase_tp_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ DBusPythonBytes_tp_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ dbus_py_variant_level_getattro, /* tp_getattro */ dbus_py_immutable_setattro, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ DBusPythonBytes_tp_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ DEFERRED_ADDRESS(&PyBytes_Type), /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ DBusPythonBytes_tp_new, /* tp_new */ }; #endif /* PY3 */ /* Support code for str subclasses ================================== */ PyDoc_STRVAR(DBusPythonString_tp_doc,\ "Base class for str subclasses with a ``variant_level`` attribute.\n" "Do not rely on the existence of this class outside dbus-python.\n" ); static PyObject * DBusPythonString_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs) { PyObject *self; long variantness = 0; static char *argnames[] = {"variant_level", NULL}; if (PyTuple_Size(args) > 1) { PyErr_SetString(PyExc_TypeError, "__new__ takes at most one positional parameter"); return NULL; } if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple, kwargs, "|l:__new__", argnames, &variantness)) return NULL; if (variantness < 0) { PyErr_SetString(PyExc_ValueError, "variant_level must be non-negative"); return NULL; } self = (NATIVESTR_TYPE.tp_new)(cls, args, NULL); if (self) { if (!dbus_py_variant_level_set(self, variantness)) { Py_CLEAR(self); return NULL; } } return self; } static PyObject * DBusPythonString_tp_repr(PyObject *self) { PyObject *parent_repr = (NATIVESTR_TYPE.tp_repr)(self); PyObject *vl_obj; PyObject *my_repr; long variant_level; if (!parent_repr) return NULL; vl_obj = PyObject_GetAttr(self, dbus_py_variant_level_const); if (!vl_obj) { Py_CLEAR(parent_repr); return NULL; } variant_level = NATIVEINT_ASLONG(vl_obj); Py_CLEAR(vl_obj); if (variant_level == -1 && PyErr_Occurred()) { Py_CLEAR(parent_repr); return NULL; } if (variant_level > 0) { my_repr = PyUnicode_FromFormat("%s(%V, variant_level=%ld)", Py_TYPE(self)->tp_name, REPRV(parent_repr), variant_level); } else { my_repr = PyUnicode_FromFormat("%s(%V)", Py_TYPE(self)->tp_name, REPRV(parent_repr)); } /* whether my_repr is NULL or not: */ Py_CLEAR(parent_repr); return my_repr; } static void DBusPyStrBase_tp_dealloc(PyObject *self) { dbus_py_variant_level_clear(self); (NATIVESTR_TYPE.tp_dealloc)(self); } PyTypeObject DBusPyStrBase_Type = { PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "_dbus_bindings._StrBase", 0, 0, DBusPyStrBase_tp_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ DBusPythonString_tp_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ dbus_py_variant_level_getattro, /* tp_getattro */ dbus_py_immutable_setattro, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ DBusPythonString_tp_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ DEFERRED_ADDRESS(&NATIVESTR_TYPE), /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ DBusPythonString_tp_new, /* tp_new */ }; /* Support code for long subclasses ================================= */ PyDoc_STRVAR(DBusPythonLong_tp_doc,\ "Base class for ``long`` subclasses with a ``variant_level`` attribute.\n" "Do not rely on the existence of this class outside dbus-python.\n" ); static PyObject * DBusPythonLong_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs) { PyObject *self; long variantness = 0; static char *argnames[] = {"variant_level", NULL}; if (PyTuple_Size(args) > 1) { PyErr_SetString(PyExc_TypeError, "__new__ takes at most one positional parameter"); return NULL; } if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple, kwargs, "|l:__new__", argnames, &variantness)) return NULL; if (variantness < 0) { PyErr_SetString(PyExc_ValueError, "variant_level must be non-negative"); return NULL; } self = (PyLong_Type.tp_new)(cls, args, NULL); if (self) { if (!dbus_py_variant_level_set(self, variantness)) { Py_CLEAR(self); return NULL; } } return self; } static PyObject * DBusPythonLong_tp_repr(PyObject *self) { PyObject *parent_repr = (PyLong_Type.tp_repr)(self); PyObject *vl_obj; PyObject *my_repr; long variant_level; if (!parent_repr) return NULL; vl_obj = PyObject_GetAttr(self, dbus_py_variant_level_const); if (!vl_obj) { Py_CLEAR(parent_repr); return NULL; } variant_level = NATIVEINT_ASLONG(vl_obj); Py_CLEAR(vl_obj); if (variant_level < 0 && PyErr_Occurred()) { Py_CLEAR(parent_repr); return NULL; } if (variant_level) { my_repr = PyUnicode_FromFormat("%s(%V, variant_level=%ld)", Py_TYPE(self)->tp_name, REPRV(parent_repr), variant_level); } else { my_repr = PyUnicode_FromFormat("%s(%V)", Py_TYPE(self)->tp_name, REPRV(parent_repr)); } /* whether my_repr is NULL or not: */ Py_CLEAR(parent_repr); return my_repr; } static void DBusPyLongBase_tp_dealloc(PyObject *self) { dbus_py_variant_level_clear(self); (PyLong_Type.tp_dealloc)(self); } PyTypeObject DBusPyLongBase_Type = { PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "_dbus_bindings._LongBase", 0, 0, DBusPyLongBase_tp_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ DBusPythonLong_tp_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ dbus_py_variant_level_getattro, /* tp_getattro */ dbus_py_immutable_setattro, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ DBusPythonLong_tp_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ DEFERRED_ADDRESS(&PyLong_Type), /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ DBusPythonLong_tp_new, /* tp_new */ }; PyObject *dbus_py_variant_level_const = NULL; PyObject *dbus_py_signature_const = NULL; PyObject *dbus_py__dbus_object_path__const = NULL; #ifdef PY3 #define INTERN (PyUnicode_InternFromString) #else /* Neither Python 2.6 nor 2.7 define the expected PyBytes_InternFromString * alias in bytesobject.h. */ #define INTERN (PyString_InternFromString) #endif dbus_bool_t dbus_py_init_abstract(void) { _dbus_py_variant_levels = PyDict_New(); if (!_dbus_py_variant_levels) return 0; dbus_py__dbus_object_path__const = INTERN("__dbus_object_path__"); if (!dbus_py__dbus_object_path__const) return 0; dbus_py_variant_level_const = INTERN("variant_level"); if (!dbus_py_variant_level_const) return 0; dbus_py_signature_const = INTERN("signature"); if (!dbus_py_signature_const) return 0; #ifdef PY3 DBusPyBytesBase_Type.tp_base = &PyBytes_Type; if (PyType_Ready(&DBusPyBytesBase_Type) < 0) return 0; DBusPyBytesBase_Type.tp_print = NULL; #else DBusPyIntBase_Type.tp_base = &PyInt_Type; if (PyType_Ready(&DBusPyIntBase_Type) < 0) return 0; /* disable the tp_print copied from PyInt_Type, so tp_repr gets called as desired */ DBusPyIntBase_Type.tp_print = NULL; #endif DBusPyFloatBase_Type.tp_base = &PyFloat_Type; if (PyType_Ready(&DBusPyFloatBase_Type) < 0) return 0; DBusPyFloatBase_Type.tp_print = NULL; DBusPyLongBase_Type.tp_base = &PyLong_Type; if (PyType_Ready(&DBusPyLongBase_Type) < 0) return 0; DBusPyLongBase_Type.tp_print = NULL; DBusPyStrBase_Type.tp_base = &NATIVESTR_TYPE; if (PyType_Ready(&DBusPyStrBase_Type) < 0) return 0; DBusPyStrBase_Type.tp_print = NULL; return 1; } dbus_bool_t dbus_py_insert_abstract_types(PyObject *this_module) { /* PyModule_AddObject steals a ref */ #ifdef PY3 Py_INCREF(&DBusPyBytesBase_Type); if (PyModule_AddObject(this_module, "_BytesBase", (PyObject *)&DBusPyBytesBase_Type) < 0) return 0; #else Py_INCREF(&DBusPyIntBase_Type); if (PyModule_AddObject(this_module, "_IntBase", (PyObject *)&DBusPyIntBase_Type) < 0) return 0; #endif Py_INCREF(&DBusPyLongBase_Type); Py_INCREF(&DBusPyStrBase_Type); Py_INCREF(&DBusPyFloatBase_Type); if (PyModule_AddObject(this_module, "_LongBase", (PyObject *)&DBusPyLongBase_Type) < 0) return 0; if (PyModule_AddObject(this_module, "_StrBase", (PyObject *)&DBusPyStrBase_Type) < 0) return 0; if (PyModule_AddObject(this_module, "_FloatBase", (PyObject *)&DBusPyFloatBase_Type) < 0) return 0; return 1; }