summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am1
-rw-r--r--NEWS16
-rw-r--r--_dbus_bindings/abstract.c384
-rw-r--r--_dbus_bindings/bytes.c299
-rw-r--r--_dbus_bindings/conn-methods.c427
-rw-r--r--_dbus_bindings/containers.c771
-rw-r--r--_dbus_bindings/dbus_bindings-internal.h86
-rw-r--r--_dbus_bindings/float.c184
-rw-r--r--_dbus_bindings/int.c912
-rw-r--r--_dbus_bindings/message-append.c123
-rw-r--r--_dbus_bindings/message-get-args.c144
-rw-r--r--_dbus_bindings/message.c6
-rw-r--r--_dbus_bindings/module.c21
-rw-r--r--_dbus_bindings/signature.c181
-rw-r--r--_dbus_bindings/string.c455
-rw-r--r--_dbus_bindings/types-internal.h36
-rw-r--r--configure.ac2
-rw-r--r--dbus/__init__.py10
-rw-r--r--dbus/_dbus.py3
-rw-r--r--dbus/connection.py297
-rw-r--r--dbus/data.py564
-rw-r--r--dbus/dbus_bindings.py2
-rw-r--r--dbus/decorators.py5
-rw-r--r--dbus/service.py11
-rw-r--r--dbus/types.py17
-rw-r--r--test/cross-test-client.py11
-rwxr-xr-xtest/test-standalone.py2
27 files changed, 1919 insertions, 3051 deletions
diff --git a/Makefile.am b/Makefile.am
index fff5e2b..45fa47b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -21,6 +21,7 @@ nobase_python_PYTHON = \
dbus_bindings.py \
dbus/bus.py \
dbus/connection.py \
+ dbus/data.py \
dbus/dbus_bindings.py \
dbus/_dbus.py \
dbus/_version.py \
diff --git a/NEWS b/NEWS
index 5e43947..cba6f16 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,19 @@
+D-Bus Python Bindings, 'purity' branch (unreleased)
+===================================================
+
+* Implement the object-path tree, and user filters, in pure Python
+* Refactor _dbus_bindings to facilitate porting types to pure Python
+
+Roadmap:
+
+* Port types to pure Python
+* Implement parameterized types
+* Implement signature parsing and signature <-> type-sequence round trip in
+ pure Python
+* Implement message argument coercion in pure Python
+* Implement message serialization and deserialization in pure Python
+ (may need to be conditional on having dbus >= 1.1)
+
D-Bus Python Bindings 0.82.4 (unreleased)
=========================================
diff --git a/_dbus_bindings/abstract.c b/_dbus_bindings/abstract.c
index 9a4f350..f88bd8e 100644
--- a/_dbus_bindings/abstract.c
+++ b/_dbus_bindings/abstract.c
@@ -148,226 +148,6 @@ dbus_py_variant_level_clear(PyObject *self)
PyErr_Restore(et, ev, etb);
}
-/* 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 = PyString_FromFormat("%s(%s, variant_level=%ld)",
- self->ob_type->tp_name,
- PyString_AS_STRING(parent_repr),
- variant_level);
- }
- else {
- my_repr = PyString_FromFormat("%s(%s)", self->ob_type->tp_name,
- PyString_AS_STRING(parent_repr));
- }
- /* whether my_repr is NULL or not: */
- Py_DECREF(parent_repr);
- return my_repr;
-}
-
-PyTypeObject DBusPyIntBase_Type = {
- PyObject_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 */
-};
-
-/* 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 = PyString_FromFormat("%s(%s, variant_level=%ld)",
- self->ob_type->tp_name,
- PyString_AS_STRING(parent_repr),
- variant_level);
- }
- else {
- my_repr = PyString_FromFormat("%s(%s)", self->ob_type->tp_name,
- PyString_AS_STRING(parent_repr));
- }
- /* whether my_repr is NULL or not: */
- Py_DECREF(parent_repr);
- return my_repr;
-}
-
-PyTypeObject DBusPyFloatBase_Type = {
- PyObject_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 */
-};
-
/* Support code for str subclasses ================================== */
PyDoc_STRVAR(DBusPythonString_tp_doc,\
@@ -486,128 +266,51 @@ PyTypeObject DBusPyStrBase_Type = {
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"
-);
+PyObject *dbus_py_variant_level_const = NULL;
+PyObject *dbus_py_signature_const = NULL;
+PyObject *dbus_py__dbus_object_path__const = NULL;
-static PyObject *
-DBusPythonLong_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+PyObject *
+DBusPy_BuildConstructorKeywordArgs(long variant_level, const char *signature)
{
- PyObject *self;
- long variantness = 0;
- static char *argnames[] = {"variant_level", NULL};
+ PyObject *dict = PyDict_New();
+ PyObject *value;
+ int status;
- 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");
+ if (!dict)
return NULL;
- }
- self = (PyLong_Type.tp_new)(cls, args, NULL);
- if (self) {
- if (!dbus_py_variant_level_set(self, variantness)) {
- Py_DECREF(self);
+ if (variant_level != 0) {
+ value = PyInt_FromLong(variant_level);
+ if (!value) {
+ Py_DECREF(dict);
+ return NULL;
+ }
+ status = PyDict_SetItem(dict, dbus_py_variant_level_const, value);
+ Py_DECREF(value);
+ if (status < 0) {
+ Py_DECREF(dict);
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_DECREF(parent_repr);
- return NULL;
- }
- variant_level = PyInt_AsLong(vl_obj);
- Py_DECREF(vl_obj);
- if (variant_level) {
- my_repr = PyString_FromFormat("%s(%s, variant_level=%ld)",
- self->ob_type->tp_name,
- PyString_AS_STRING(parent_repr),
- variant_level);
- }
- else {
- my_repr = PyString_FromFormat("%s(%s)", self->ob_type->tp_name,
- PyString_AS_STRING(parent_repr));
+ if (signature != NULL) {
+ value = DBusPySignature_FromString(signature);
+ if (!value) {
+ Py_DECREF(dict);
+ return NULL;
+ }
+ status = PyDict_SetItem(dict, dbus_py_signature_const, value);
+ Py_DECREF(value);
+ if (status < 0) {
+ Py_DECREF(dict);
+ return NULL;
+ }
}
- /* whether my_repr is NULL or not: */
- Py_DECREF(parent_repr);
- return my_repr;
-}
-static void
-DBusPyLongBase_tp_dealloc(PyObject *self)
-{
- dbus_py_variant_level_clear(self);
- (PyLong_Type.tp_dealloc)(self);
+ return dict;
}
-PyTypeObject DBusPyLongBase_Type = {
- PyObject_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;
-
dbus_bool_t
dbus_py_init_abstract(void)
{
@@ -623,20 +326,6 @@ dbus_py_init_abstract(void)
dbus_py_signature_const = PyString_InternFromString("signature");
if (!dbus_py_signature_const) return 0;
- 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;
-
- 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 = &PyString_Type;
if (PyType_Ready(&DBusPyStrBase_Type) < 0) return 0;
DBusPyStrBase_Type.tp_print = NULL;
@@ -647,18 +336,9 @@ dbus_py_init_abstract(void)
dbus_bool_t
dbus_py_insert_abstract_types(PyObject *this_module)
{
- Py_INCREF(&DBusPyIntBase_Type);
- Py_INCREF(&DBusPyLongBase_Type);
Py_INCREF(&DBusPyStrBase_Type);
- Py_INCREF(&DBusPyFloatBase_Type);
- if (PyModule_AddObject(this_module, "_IntBase",
- (PyObject *)&DBusPyIntBase_Type) < 0) return 0;
- 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;
}
diff --git a/_dbus_bindings/bytes.c b/_dbus_bindings/bytes.c
index a5648fe..73bc67c 100644
--- a/_dbus_bindings/bytes.c
+++ b/_dbus_bindings/bytes.c
@@ -31,236 +31,129 @@
#include "dbus_bindings-internal.h"
#include "types-internal.h"
-PyDoc_STRVAR(Byte_tp_doc,
-"An unsigned byte: a subtype of int, with range restricted to [0, 255].\n"
-"\n"
-"A Byte b may be converted to a str of length 1 via str(b) == chr(b).\n"
-"\n"
-"Most of the time you don't want to use this class - it mainly exists\n"
-"for symmetry with the other D-Bus types. See `dbus.ByteArray` for a\n"
-"better way to handle arrays of Byte.\n"
-"\n"
-"Constructor::\n"
-"\n"
-" dbus.Byte(integer or str of length 1[, variant_level])\n"
-"\n"
-"``variant_level`` must be non-negative; the default is 0.\n"
-"\n"
-":IVariables:\n"
-" `variant_level` : int\n"
-" Indicates how many nested Variant containers this object\n"
-" is contained in: if a message's wire format has a variant containing a\n"
-" variant containing a byte, this is represented in Python by a\n"
-" Byte with variant_level==2.\n"
-);
+static PyObject *Byte = NULL;
+static PyObject *ByteArray = NULL;
-static PyObject *
-Byte_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+static dbus_bool_t
+do_import(void)
{
- PyObject *obj;
- PyObject *tuple;
- long variantness = 0;
- static char *argnames[] = {"variant_level", NULL};
+ PyObject *name;
+ PyObject *module;
- if (PyTuple_Size(args) > 1) {
- PyErr_SetString(PyExc_TypeError, "Byte constructor takes no more "
- "than one positional argument");
- 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;
- }
+ if (ByteArray != NULL && Byte != NULL)
+ return TRUE;
- /* obj is only a borrowed ref for the moment */
- obj = PyTuple_GetItem(args, 0);
+ Py_CLEAR(Byte);
+ Py_CLEAR(ByteArray);
- if (PyString_Check(obj)) {
- /* string of length 1, we hope */
- if (PyString_GET_SIZE(obj) != 1) {
- goto bad_arg;
- }
- obj = PyInt_FromLong((unsigned char)(PyString_AS_STRING(obj)[0]));
- }
- else if (PyInt_Check(obj)) {
- long i = PyInt_AS_LONG(obj);
+ name = PyString_FromString("dbus.data");
+ if (!name)
+ return FALSE;
+
+ module = PyImport_Import(name);
+ Py_DECREF(name);
+ if (!module)
+ return FALSE;
+
+ Byte = PyObject_GetAttrString(module, "Byte");
+ ByteArray = PyObject_GetAttrString(module, "ByteArray");
+ Py_DECREF(module);
- if (obj->ob_type == cls &&
- ((DBusPyIntBase *)obj)->variant_level == variantness) {
- Py_INCREF(obj);
- return obj;
- }
- if (i < 0 || i > 255) goto bad_range;
- /* else make it a new reference */
- Py_INCREF(obj);
+ if (Byte && !PyType_Check(Byte)) {
+ PyErr_SetString(PyExc_AssertionError, "Assertion failed: "
+ "isinstance(dbus.data.Byte, type)");
+ Byte = NULL;
}
- else {
- goto bad_arg;
+ if (ByteArray && !PyType_Check(ByteArray)) {
+ PyErr_SetString(PyExc_AssertionError, "Assertion failed: "
+ "isinstance(dbus.data.ByteArray, type)");
+ ByteArray = NULL;
}
- tuple = Py_BuildValue("(O)", obj);
- if (!tuple) return NULL;
- Py_DECREF(obj);
- obj = NULL;
+ return (ByteArray != NULL && Byte != NULL);
+}
- obj = DBusPyIntBase_Type.tp_new(cls, tuple, kwargs);
- Py_DECREF(tuple);
- tuple = NULL;
- return obj;
+int
+DBusPyByte_Check(PyObject *o)
+{
+ if (!Byte && !do_import())
+ return 0;
+ return PyObject_TypeCheck(o, (PyTypeObject *)Byte);
+}
-bad_arg:
- PyErr_SetString(PyExc_TypeError, "Expected a string of length 1, "
- "or an int in the range 0-255");
- return NULL;
-bad_range:
- PyErr_SetString(PyExc_ValueError, "Integer outside range 0-255");
- return NULL;
+int
+DBusPyByteArray_Check(PyObject *o)
+{
+ if (!ByteArray && !do_import())
+ return 0;
+ return PyObject_TypeCheck(o, (PyTypeObject *)ByteArray);
}
-static PyObject *
-Byte_tp_str(PyObject *self)
+PyObject *
+DBusPyByte_New(unsigned char value, long variant_level)
{
- unsigned char str[2] = { (unsigned char)PyInt_AS_LONG(self), 0 };
- return PyString_FromStringAndSize((char *)str, 1);
+ PyObject *args = NULL;
+ PyObject *kwargs = NULL;
+ PyObject *ret = NULL;
+
+ if (!Byte && !do_import())
+ return NULL;
+
+ if (variant_level != 0) {
+ kwargs = DBusPy_BuildConstructorKeywordArgs(variant_level, NULL);
+ if (!kwargs)
+ goto finally;
+ }
+
+ args = Py_BuildValue("(I)", (unsigned int) value);
+ if (!args)
+ goto finally;
+
+ ret = PyObject_Call(Byte, args, kwargs);
+
+finally:
+ Py_XDECREF(args);
+ Py_XDECREF(kwargs);
+ return ret;
}
-PyTypeObject DBusPyByte_Type = {
- PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
- 0,
- "dbus.Byte",
- 0,
- 0,
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- Byte_tp_str, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
- Byte_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(&PyInt_Type), /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- Byte_new, /* tp_new */
-};
+PyObject *
+DBusPyByteArray_New(const char *bytes, Py_ssize_t count, long variant_level)
+{
+ PyObject *args = NULL;
+ PyObject *kwargs = NULL;
+ PyObject *ret = NULL;
+
+ if (!ByteArray && !do_import())
+ return NULL;
+
+ if (variant_level != 0) {
+ kwargs = DBusPy_BuildConstructorKeywordArgs(variant_level, NULL);
+ if (!kwargs)
+ goto finally;
+ }
+
+ args = Py_BuildValue("(s#)", bytes, count);
+ if (!args)
+ goto finally;
-PyDoc_STRVAR(ByteArray_tp_doc,
-"ByteArray is a subtype of str which can be used when you want an\n"
-"efficient immutable representation of a D-Bus byte array (signature 'ay').\n"
-"\n"
-"By default, when byte arrays are converted from D-Bus to Python, they\n"
-"come out as a `dbus.Array` of `dbus.Byte`. This is just for symmetry with\n"
-"the other D-Bus types - in practice, what you usually want is the byte\n"
-"array represented as a string, using this class. To get this, pass the\n"
-"``byte_arrays=True`` keyword argument to any of these methods:\n"
-"\n"
-"* any D-Bus method proxy, or ``connect_to_signal``, on the objects returned\n"
-" by `Bus.get_object`\n"
-"* any D-Bus method on a `dbus.Interface`\n"
-"* `dbus.Interface.connect_to_signal`\n"
-"* `Bus.add_signal_receiver`\n"
-"\n"
-"Import via::\n"
-"\n"
-" from dbus import ByteArray\n"
-"\n"
-"Constructor::\n"
-"\n"
-" ByteArray(str)\n"
-);
+ ret = PyObject_Call(ByteArray, args, kwargs);
-PyTypeObject DBusPyByteArray_Type = {
- PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
- 0,
- "dbus.ByteArray",
- 0,
- 0,
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* 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 */
- ByteArray_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(&DBusPyStrBase_Type), /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- 0, /* tp_new */
-};
+finally:
+ Py_XDECREF(args);
+ Py_XDECREF(kwargs);
+ return ret;
+}
dbus_bool_t
dbus_py_init_byte_types(void)
{
- DBusPyByte_Type.tp_base = &DBusPyIntBase_Type;
- if (PyType_Ready(&DBusPyByte_Type) < 0) return 0;
- DBusPyByte_Type.tp_print = NULL;
-
- DBusPyByteArray_Type.tp_base = &DBusPyStrBase_Type;
- if (PyType_Ready(&DBusPyByteArray_Type) < 0) return 0;
- DBusPyByteArray_Type.tp_print = NULL;
-
return 1;
}
dbus_bool_t
-dbus_py_insert_byte_types(PyObject *this_module)
+dbus_py_insert_byte_types(PyObject *this_module UNUSED)
{
- Py_INCREF(&DBusPyByte_Type);
- if (PyModule_AddObject(this_module, "Byte",
- (PyObject *)&DBusPyByte_Type) < 0) return 0;
- Py_INCREF(&DBusPyByteArray_Type);
- if (PyModule_AddObject(this_module, "ByteArray",
- (PyObject *)&DBusPyByteArray_Type) < 0) return 0;
-
return 1;
}
diff --git a/_dbus_bindings/conn-methods.c b/_dbus_bindings/conn-methods.c
index 6fadc31..7e3273c 100644
--- a/_dbus_bindings/conn-methods.c
+++ b/_dbus_bindings/conn-methods.c
@@ -27,112 +27,6 @@
#include "dbus_bindings-internal.h"
#include "conn-internal.h"
-static void
-_object_path_unregister(DBusConnection *conn, void *user_data)
-{
- PyGILState_STATE gil = PyGILState_Ensure();
- PyObject *tuple = NULL;
- Connection *conn_obj = NULL;
- PyObject *callable;
-
- conn_obj = (Connection *)DBusPyConnection_ExistingFromDBusConnection(conn);
- if (!conn_obj) goto out;
- TRACE(conn_obj);
-
- DBG("Connection at %p unregistering object path %s",
- conn_obj, PyString_AS_STRING((PyObject *)user_data));
- tuple = DBusPyConnection_GetObjectPathHandlers((PyObject *)conn_obj, (PyObject *)user_data);
- if (!tuple) goto out;
- if (tuple == Py_None) goto out;
-
- DBG("%s", "... yes we have handlers for that object path");
-
- /* 0'th item is the unregisterer (if that's a word) */
- callable = PyTuple_GetItem(tuple, 0);
- if (callable && callable != Py_None) {
- DBG("%s", "... and we even have an unregisterer");
- /* any return from the unregisterer is ignored */
- Py_XDECREF(PyObject_CallFunctionObjArgs(callable, conn_obj, NULL));
- }
-out:
- Py_XDECREF(conn_obj);
- Py_XDECREF(tuple);
- /* the user_data (a Python str) is no longer ref'd by the DBusConnection */
- Py_XDECREF((PyObject *)user_data);
- if (PyErr_Occurred()) {
- PyErr_Print();
- }
- PyGILState_Release(gil);
-}
-
-static DBusHandlerResult
-_object_path_message(DBusConnection *conn, DBusMessage *message,
- void *user_data)
-{
- DBusHandlerResult ret;
- PyGILState_STATE gil = PyGILState_Ensure();
- Connection *conn_obj = NULL;
- PyObject *tuple = NULL;
- PyObject *msg_obj;
- PyObject *callable; /* borrowed */
-
- dbus_message_ref(message);
- msg_obj = DBusPyMessage_ConsumeDBusMessage(message);
- if (!msg_obj) {
- ret = DBUS_HANDLER_RESULT_NEED_MEMORY;
- goto out;
- }
-
- conn_obj = (Connection *)DBusPyConnection_ExistingFromDBusConnection(conn);
- if (!conn_obj) {
- ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- goto out;
- }
- TRACE(conn_obj);
-
- DBG("Connection at %p messaging object path %s",
- conn_obj, PyString_AS_STRING((PyObject *)user_data));
- DBG_DUMP_MESSAGE(message);
- tuple = DBusPyConnection_GetObjectPathHandlers((PyObject *)conn_obj, (PyObject *)user_data);
- if (!tuple || tuple == Py_None) {
- ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- goto out;
- }
-
- DBG("%s", "... yes we have handlers for that object path");
-
- /* 1st item (0-based) is the message callback */
- callable = PyTuple_GetItem(tuple, 1);
- if (!callable) {
- DBG("%s", "... error getting message handler from tuple");
- ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- }
- else if (callable == Py_None) {
- /* there was actually no handler after all */
- DBG("%s", "... but those handlers don't do messages");
- ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- }
- else {
- DBG("%s", "... and we have a message handler for that object path");
- ret = DBusPyConnection_HandleMessage(conn_obj, msg_obj, callable);
- }
-
-out:
- Py_XDECREF(msg_obj);
- Py_XDECREF(conn_obj);
- Py_XDECREF(tuple);
- if (PyErr_Occurred()) {
- PyErr_Print();
- }
- PyGILState_Release(gil);
- return ret;
-}
-
-static const DBusObjectPathVTable _object_path_vtable = {
- _object_path_unregister,
- _object_path_message,
-};
-
static DBusHandlerResult
_filter_message(DBusConnection *conn, DBusMessage *message, void *user_data)
{
@@ -651,324 +545,6 @@ Connection_remove_message_filter(Connection *self, PyObject *callable)
Py_RETURN_NONE;
}
-PyDoc_STRVAR(Connection__register_object_path__doc__,
-"register_object_path(path, on_message, on_unregister=None, fallback=False)\n"
-"\n"
-"Register a callback to be called when messages arrive at the given\n"
-"object-path. Used to export objects' methods on the bus in a low-level\n"
-"way. For the high-level interface to this functionality (usually\n"
-"recommended) see the `dbus.service.Object` base class.\n"
-"\n"
-":Parameters:\n"
-" `path` : str\n"
-" Object path to be acted on\n"
-" `on_message` : callable\n"
-" Called when a message arrives at the given object-path, with\n"
-" two positional parameters: the first is this Connection,\n"
-" the second is the incoming `dbus.lowlevel.Message`.\n"
-" `on_unregister` : callable or None\n"
-" If not None, called when the callback is unregistered.\n"
-" `fallback` : bool\n"
-" If True (the default is False), when a message arrives for a\n"
-" 'subdirectory' of the given path and there is no more specific\n"
-" handler, use this handler. Normally this handler is only run if\n"
-" the paths match exactly.\n"
-);
-static PyObject *
-Connection__register_object_path(Connection *self, PyObject *args,
- PyObject *kwargs)
-{
- dbus_bool_t ok;
- int fallback = 0;
- PyObject *callbacks, *path, *tuple, *on_message, *on_unregister = Py_None;
- static char *argnames[] = {"path", "on_message", "on_unregister",
- "fallback", NULL};
-
- TRACE(self);
- DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
- if (!Connection__require_main_loop(self, NULL)) {
- return NULL;
- }
- if (!PyArg_ParseTupleAndKeywords(args, kwargs,
- "OO|Oi:_register_object_path",
- argnames,
- &path,
- &on_message, &on_unregister,
- &fallback)) return NULL;
-
- /* Take a reference to path, which we give away to libdbus in a moment.
-
- Also, path needs to be a string (not a subclass which could do something
- mad) to preserve the desirable property that the DBusConnection can
- never strongly reference the Connection, even indirectly.
- */
- if (PyString_CheckExact(path)) {
- Py_INCREF(path);
- }
- else if (PyUnicode_Check(path)) {
- path = PyUnicode_AsUTF8String(path);
- if (!path) return NULL;
- }
- else if (PyString_Check(path)) {
- path = PyString_FromString(PyString_AS_STRING(path));
- if (!path) return NULL;
- }
- else {
- PyErr_SetString(PyExc_TypeError, "path must be a str or unicode object");
- return NULL;
- }
-
- if (!dbus_py_validate_object_path(PyString_AS_STRING(path))) {
- Py_DECREF(path);
- return NULL;
- }
-
- tuple = Py_BuildValue("(OO)", on_unregister, on_message);
- if (!tuple) {
- Py_DECREF(path);
- return NULL;
- }
-
- /* Guard against registering a handler that already exists. */
- callbacks = PyDict_GetItem(self->object_paths, path);
- if (callbacks && callbacks != Py_None) {
- PyErr_Format(PyExc_KeyError, "Can't register the object-path "
- "handler for '%s': there is already a handler",
- PyString_AS_STRING(path));
- Py_DECREF(tuple);
- Py_DECREF(path);
- return NULL;
- }
-
- /* Pre-allocate a slot in the dictionary, so we know we'll be able
- * to replace it with the callbacks without OOM.
- * This ensures we can keep libdbus' opinion of whether those
- * paths are handled in sync with our own. */
- if (PyDict_SetItem(self->object_paths, path, Py_None) < 0) {
- Py_DECREF(tuple);
- Py_DECREF(path);
- return NULL;
- }
-
- Py_BEGIN_ALLOW_THREADS
- if (fallback) {
- ok = dbus_connection_register_fallback(self->conn,
- PyString_AS_STRING(path),
- &_object_path_vtable,
- path);
- }
- else {
- ok = dbus_connection_register_object_path(self->conn,
- PyString_AS_STRING(path),
- &_object_path_vtable,
- path);
- }
- Py_END_ALLOW_THREADS
-
- if (ok) {
- if (PyDict_SetItem(self->object_paths, path, tuple) < 0) {
- /* That shouldn't have happened, we already allocated enough
- memory for it. Oh well, try to undo the registration to keep
- things in sync. If this fails too, we've leaked a bit of
- memory in libdbus, but tbh we should never get here anyway. */
- Py_BEGIN_ALLOW_THREADS
- ok = dbus_connection_unregister_object_path(self->conn,
- PyString_AS_STRING(path));
- Py_END_ALLOW_THREADS
- return NULL;
- }
- /* don't DECREF path: libdbus owns a ref now */
- Py_DECREF(tuple);
- Py_RETURN_NONE;
- }
- else {
- /* Oops, OOM. Tidy up, if we can, ignoring any error. */
- PyDict_DelItem(self->object_paths, path);
- PyErr_Clear();
- Py_DECREF(tuple);
- Py_DECREF(path);
- PyErr_NoMemory();
- return NULL;
- }
-}
-
-PyDoc_STRVAR(Connection__unregister_object_path__doc__,
-"unregister_object_path(path)\n\n"
-"Remove a previously registered handler for the given object path.\n"
-"\n"
-":Parameters:\n"
-" `path` : str\n"
-" The object path whose handler is to be removed\n"
-":Raises KeyError: if there is no handler registered for exactly that\n"
-" object path.\n"
-);
-static PyObject *
-Connection__unregister_object_path(Connection *self, PyObject *args,
- PyObject *kwargs)
-{
- dbus_bool_t ok;
- PyObject *path;
- PyObject *callbacks;
- static char *argnames[] = {"path", NULL};
-
- TRACE(self);
- DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
- if (!PyArg_ParseTupleAndKeywords(args, kwargs,
- "O:_unregister_object_path",
- argnames, &path)) return NULL;
-
- /* Take a ref to the path. Same comments as for _register_object_path. */
- if (PyString_CheckExact(path)) {
- Py_INCREF(path);
- }
- else if (PyUnicode_Check(path)) {
- path = PyUnicode_AsUTF8String(path);
- if (!path) return NULL;
- }
- else if (PyString_Check(path)) {
- path = PyString_FromString(PyString_AS_STRING(path));
- if (!path) return NULL;
- }
- else {
- PyErr_SetString(PyExc_TypeError, "path must be a str or unicode object");
- return NULL;
- }
-
- /* Guard against unregistering a handler that doesn't, in fact, exist,
- or whose unregistration is already in progress. */
- callbacks = PyDict_GetItem(self->object_paths, path);
- if (!callbacks || callbacks == Py_None) {
- PyErr_Format(PyExc_KeyError, "Can't unregister the object-path "
- "handler for '%s': there is no such handler",
- PyString_AS_STRING(path));
- Py_DECREF(path);
- return NULL;
- }
-
- /* Hang on to a reference to the callbacks for the moment. */
- Py_INCREF(callbacks);
-
- /* Get rid of the object-path while we still have the GIL, to
- guard against unregistering twice from different threads (which
- causes undefined behaviour in libdbus).
-
- Because deletion would make it possible for the re-insertion below
- to fail, we instead set the handler to None as a placeholder.
- */
- if (PyDict_SetItem(self->object_paths, path, Py_None) < 0) {
- /* If that failed, there's no need to be paranoid as below - the
- callbacks are still set, so we failed, but at least everything
- is in sync. */
- Py_DECREF(callbacks);
- Py_DECREF(path);
- return NULL;
- }
-
- /* BEGIN PARANOIA
- This is something of a critical section - the dict of object-paths
- and libdbus' internal structures are out of sync for a bit. We have
- to be able to cope with that.
-
- It's really annoying that dbus_connection_unregister_object_path
- can fail, *and* has undefined behaviour if the object path has
- already been unregistered. Either/or would be fine.
- */
-
- Py_BEGIN_ALLOW_THREADS
- ok = dbus_connection_unregister_object_path(self->conn,
- PyString_AS_STRING(path));
- Py_END_ALLOW_THREADS
-
- if (ok) {
- Py_DECREF(callbacks);
- PyDict_DelItem(self->object_paths, path);
- /* END PARANOIA on successful code path */
- /* The above can't fail unless by some strange trickery the key is no
- longer present. Ignore any errors. */
- Py_DECREF(path);
- PyErr_Clear();
- Py_RETURN_NONE;
- }
- else {
- /* Oops, OOM. Put the callbacks back in the dict so
- * we'll have another go if/when the user frees some memory
- * and tries calling this method again. */
- PyDict_SetItem(self->object_paths, path, callbacks);
- /* END PARANOIA on failing code path */
- /* If the SetItem failed, there's nothing we can do about it - but
- since we know it's an existing entry, it shouldn't be able to fail
- anyway. */
- Py_DECREF(path);
- Py_DECREF(callbacks);
- return PyErr_NoMemory();
- }
-}
-
-PyDoc_STRVAR(Connection_list_exported_child_objects__doc__,
-"list_exported_child_objects(path: str) -> list of str\n\n"
-"Return a list of the names of objects exported on this Connection as\n"
-"direct children of the given object path.\n"
-"\n"
-"Each name returned may be converted to a valid object path using\n"
-"``dbus.ObjectPath('%s%s%s' % (path, (path != '/' and '/' or ''), name))``.\n"
-"For the purposes of this function, every parent or ancestor of an exported\n"
-"object is considered to be an exported object, even if it's only an object\n"
-"synthesized by the library to support introspection.\n");
-static PyObject *
-Connection_list_exported_child_objects (Connection *self, PyObject *args,
- PyObject *kwargs)
-{
- const char *path;
- char **kids, **kid_ptr;
- dbus_bool_t ok;
- PyObject *ret;
- static char *argnames[] = {"path", NULL};
-
- DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", argnames, &path)) {
- return NULL;
- }
-
- if (!dbus_py_validate_object_path(path)) {
- return NULL;
- }
-
- Py_BEGIN_ALLOW_THREADS
- ok = dbus_connection_list_registered(self->conn, path, &kids);
- Py_END_ALLOW_THREADS
-
- if (!ok) {
- return PyErr_NoMemory();
- }
-
- ret = PyList_New(0);
- if (!ret) {
- return NULL;
- }
- for (kid_ptr = kids; *kid_ptr; kid_ptr++) {
- PyObject *tmp = PyString_FromString(*kid_ptr);
-
- if (!tmp) {
- Py_DECREF(ret);
- return NULL;
- }
- if (PyList_Append(ret, tmp) < 0) {
- Py_DECREF(tmp);
- Py_DECREF(ret);
- return NULL;
- }
- Py_DECREF(tmp);
- }
-
- dbus_free_string_array(kids);
-
- return ret;
-}
-
- /* dbus_connection_get_object_path_data - not useful to Python,
- * the object path data is just a PyString containing the path */
- /* dbus_connection_list_registered could be useful, though */
-
/* dbus_connection_set_change_sigpipe - sets global state */
/* Maxima. Does Python code ever need to manipulate these?
@@ -1013,13 +589,10 @@ struct PyMethodDef DBusPyConnection_tp_methods[] = {
ENTRY(get_peer_unix_user, METH_NOARGS),
ENTRY(get_peer_unix_process_id, METH_NOARGS),
ENTRY(add_message_filter, METH_O),
- ENTRY(_register_object_path, METH_VARARGS|METH_KEYWORDS),
ENTRY(remove_message_filter, METH_O),
ENTRY(send_message, METH_VARARGS),
ENTRY(send_message_with_reply, METH_VARARGS|METH_KEYWORDS),
ENTRY(send_message_with_reply_and_block, METH_VARARGS),
- ENTRY(_unregister_object_path, METH_VARARGS|METH_KEYWORDS),
- ENTRY(list_exported_child_objects, METH_VARARGS|METH_KEYWORDS),
{"_new_for_bus", (PyCFunction)DBusPyConnection_NewForBus,
METH_CLASS|METH_VARARGS|METH_KEYWORDS,
new_for_bus__doc__},
diff --git a/_dbus_bindings/containers.c b/_dbus_bindings/containers.c
index e80098f..cf6ace3 100644
--- a/_dbus_bindings/containers.c
+++ b/_dbus_bindings/containers.c
@@ -33,735 +33,166 @@
/* Array ============================================================ */
-PyDoc_STRVAR(Array_tp_doc,
-"An array of similar items, implemented as a subtype of list.\n"
-"\n"
-"As currently implemented, an Array behaves just like a list, but\n"
-"with the addition of a ``signature`` property set by the constructor;\n"
-"conversion of its items to D-Bus types is only done when it's sent in\n"
-"a Message. This might change in future so validation is done earlier.\n"
-"\n"
-"Constructor::\n"
-"\n"
-" dbus.Array([iterable][, signature][, variant_level])\n"
-"\n"
-"``variant_level`` must be non-negative; the default is 0.\n"
-"\n"
-"``signature`` is the D-Bus signature string for a single element of the\n"
-"array, or None. If not None it must represent a single complete type, the\n"
-"type of a single array item; the signature of the whole Array may be\n"
-"obtained by prepending ``a`` to the given signature.\n"
-"\n"
-"If None (the default), when the Array is sent over\n"
-"D-Bus, the item signature will be guessed from the first element.\n"
-"\n"
-":IVariables:\n"
-" `variant_level` : int\n"
-" Indicates how many nested Variant containers this object\n"
-" is contained in: if a message's wire format has a variant containing a\n"
-" variant containing an array, this is represented in Python by an\n"
-" Array with variant_level==2.\n"
-);
-
-static struct PyMemberDef Array_tp_members[] = {
- {"signature", T_OBJECT, offsetof(DBusPyArray, signature), READONLY,
- "The D-Bus signature of each element of this Array (a Signature "
- "instance)"},
- {"variant_level", T_LONG, offsetof(DBusPyArray, variant_level),
- READONLY,
- "The number of nested variants wrapping the real data. "
- "0 if not in a variant."},
- {NULL},
-};
-
-static void
-Array_tp_dealloc (DBusPyArray *self)
-{
- Py_XDECREF(self->signature);
- self->signature = NULL;
- (PyList_Type.tp_dealloc)((PyObject *)self);
-}
-
-static PyObject *
-Array_tp_repr(DBusPyArray *self)
-{
- PyObject *parent_repr = (PyList_Type.tp_repr)((PyObject *)self);
- PyObject *sig_repr = PyObject_Repr(self->signature);
- PyObject *my_repr = NULL;
- long variant_level = self->variant_level;
-
- if (!parent_repr) goto finally;
- if (!sig_repr) goto finally;
- if (variant_level > 0) {
- my_repr = PyString_FromFormat("%s(%s, signature=%s, "
- "variant_level=%ld)",
- self->super.ob_type->tp_name,
- PyString_AS_STRING(parent_repr),
- PyString_AS_STRING(sig_repr),
- variant_level);
- }
- else {
- my_repr = PyString_FromFormat("%s(%s, signature=%s)",
- self->super.ob_type->tp_name,
- PyString_AS_STRING(parent_repr),
- PyString_AS_STRING(sig_repr));
- }
-finally:
- Py_XDECREF(parent_repr);
- Py_XDECREF(sig_repr);
- return my_repr;
-}
-
-static PyObject *
-Array_tp_new (PyTypeObject *cls, PyObject *args, PyObject *kwargs)
-{
- PyObject *variant_level = NULL;
- DBusPyArray *self = (DBusPyArray *)(PyList_Type.tp_new)(cls, args, kwargs);
-
- /* variant_level is immutable, so handle it in __new__ rather than
- __init__ */
- if (!self) return NULL;
- Py_INCREF(Py_None);
- self->signature = Py_None;
- self->variant_level = 0;
- if (kwargs) {
- variant_level = PyDict_GetItem(kwargs, dbus_py_variant_level_const);
- }
- if (variant_level) {
- self->variant_level = PyInt_AsLong(variant_level);
- if (PyErr_Occurred()) {
- Py_DECREF((PyObject *)self);
- return NULL;
- }
- }
- return (PyObject *)self;
-}
+static PyObject *Array = NULL;
+static PyObject *Struct = NULL;
+static PyObject *Dictionary = NULL;
-static int
-Array_tp_init (DBusPyArray *self, PyObject *args, PyObject *kwargs)
+static dbus_bool_t
+do_import(void)
{
- PyObject *obj = dbus_py_empty_tuple;
- PyObject *signature = NULL;
- PyObject *tuple;
- PyObject *variant_level;
- /* variant_level is accepted but ignored - it's immutable, so
- * __new__ handles it */
- static char *argnames[] = {"iterable", "signature", "variant_level", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOO:__init__", argnames,
- &obj, &signature, &variant_level)) {
- return -1;
- }
+ PyObject *name;
+ PyObject *module;
- /* convert signature from a borrowed ref of unknown type to an owned ref
- of type Signature (or None) */
- if (!signature) signature = Py_None;
- if (signature == Py_None
- || PyObject_IsInstance(signature, (PyObject *)&DBusPySignature_Type)) {
- Py_INCREF(signature);
- }
- else {
- signature = PyObject_CallFunction((PyObject *)&DBusPySignature_Type,
- "(O)", signature);
- if (!signature) return -1;
- }
+ if (Array && Struct && Dictionary)
+ return TRUE;
- if (signature != Py_None) {
- const char *c_str = PyString_AS_STRING(signature);
+ Py_CLEAR(Array);
+ Py_CLEAR(Struct);
+ Py_CLEAR(Dictionary);
- if (!dbus_signature_validate_single(c_str, NULL)) {
- Py_DECREF(signature);
- PyErr_SetString(PyExc_ValueError,
- "There must be exactly one complete type in "
- "an Array's signature parameter");
- return -1;
- }
- }
-
- tuple = Py_BuildValue("(O)", obj);
- if (!tuple) {
- Py_DECREF(signature);
- return -1;
- }
- if ((PyList_Type.tp_init)((PyObject *)self, tuple, NULL) < 0) {
- Py_DECREF(tuple);
- Py_DECREF(signature);
- return -1;
- }
- Py_DECREF(tuple);
-
- Py_XDECREF(self->signature);
- self->signature = signature;
- return 0;
-}
+ name = PyString_FromString("dbus.data");
+ if (!name)
+ return FALSE;
-PyTypeObject DBusPyArray_Type = {
- PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
- 0,
- "dbus.Array",
- sizeof(DBusPyArray),
- 0,
- (destructor)Array_tp_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)Array_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 */
- Array_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 */
- Array_tp_members, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)Array_tp_init, /* tp_init */
- 0, /* tp_alloc */
- Array_tp_new, /* tp_new */
-};
+ module = PyImport_Import(name);
+ Py_DECREF(name);
+ if (!module)
+ return FALSE;
-/* Dict ============================================================= */
+ Array = PyObject_GetAttrString(module, "Array");
+ Struct = PyObject_GetAttrString(module, "Struct");
+ Dictionary = PyObject_GetAttrString(module, "Dictionary");
-PyDoc_STRVAR(Dict_tp_doc,
-"An mapping whose keys are similar and whose values are similar,\n"
-"implemented as a subtype of dict.\n"
-"\n"
-"As currently implemented, a Dictionary behaves just like a dict, but\n"
-"with the addition of a ``signature`` property set by the constructor;\n"
-"conversion of its items to D-Bus types is only done when it's sent in\n"
-"a Message. This may change in future so validation is done earlier.\n"
-"\n"
-"Constructor::\n"
-"\n"
-" Dictionary(mapping_or_iterable=(), signature=None, variant_level=0)\n"
-"\n"
-"``variant_level`` must be non-negative; the default is 0.\n"
-"\n"
-"``signature`` is either a string or None. If a string, it must consist\n"
-"of exactly two complete type signatures, representing the 'key' type\n"
-"(which must be a primitive type, i.e. one of \"bdginoqstuxy\")\n"
-"and the 'value' type. The signature of the whole Dictionary will be\n"
-"``a{xx}`` where ``xx`` is replaced by the given signature.\n"
-"\n"
-"If it is None (the default), when the Dictionary is sent over\n"
-"D-Bus, the key and value signatures will be guessed from an arbitrary\n"
-"element of the Dictionary.\n"
-"\n"
-":IVariables:\n"
-" `variant_level` : int\n"
-" Indicates how many nested Variant containers this object\n"
-" is contained in: if a message's wire format has a variant containing a\n"
-" variant containing an array of DICT_ENTRY, this is represented in\n"
-" Python by a Dictionary with variant_level==2.\n"
-);
-
-static struct PyMemberDef Dict_tp_members[] = {
- {"signature", T_OBJECT, offsetof(DBusPyDict, signature), READONLY,
- "The D-Bus signature of each key in this Dictionary, followed by "
- "that of each value in this Dictionary, as a Signature instance."},
- {"variant_level", T_LONG, offsetof(DBusPyDict, variant_level),
- READONLY,
- "The number of nested variants wrapping the real data. "
- "0 if not in a variant."},
- {NULL},
-};
-
-static void
-Dict_tp_dealloc (DBusPyDict *self)
-{
- Py_XDECREF(self->signature);
- self->signature = NULL;
- (PyDict_Type.tp_dealloc)((PyObject *)self);
-}
+ Py_DECREF(module);
-static PyObject *
-Dict_tp_repr(DBusPyDict *self)
-{
- PyObject *parent_repr = (PyDict_Type.tp_repr)((PyObject *)self);
- PyObject *sig_repr = PyObject_Repr(self->signature);
- PyObject *my_repr = NULL;
- long variant_level = self->variant_level;
-
- if (!parent_repr) goto finally;
- if (!sig_repr) goto finally;
- if (variant_level > 0) {
- my_repr = PyString_FromFormat("%s(%s, signature=%s, "
- "variant_level=%ld)",
- self->super.ob_type->tp_name,
- PyString_AS_STRING(parent_repr),
- PyString_AS_STRING(sig_repr),
- variant_level);
+ if (Array && !PyType_Check(Array)) {
+ PyErr_SetString(PyExc_AssertionError, "Assertion failed: "
+ "isinstance(dbus.data.Array, type)");
+ Array = NULL;
}
- else {
- my_repr = PyString_FromFormat("%s(%s, signature=%s)",
- self->super.ob_type->tp_name,
- PyString_AS_STRING(parent_repr),
- PyString_AS_STRING(sig_repr));
+ if (Struct && !PyType_Check(Struct)) {
+ PyErr_SetString(PyExc_AssertionError, "Assertion failed: "
+ "isinstance(dbus.data.Struct, type)");
+ Struct = NULL;
}
-finally:
- Py_XDECREF(parent_repr);
- Py_XDECREF(sig_repr);
- return my_repr;
+ if (Dictionary && !PyType_Check(Dictionary)) {
+ PyErr_SetString(PyExc_AssertionError, "Assertion failed: "
+ "isinstance(dbus.data.Dictionary, type)");
+ Dictionary = NULL;
+ }
+
+ return (Array != NULL && Struct != NULL && Dictionary != NULL);
}
-static PyObject *
-Dict_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+int
+DBusPyArray_Check(PyObject *o)
{
- DBusPyDict *self = (DBusPyDict *)(PyDict_Type.tp_new)(cls, args, kwargs);
- PyObject *variant_level = NULL;
-
- /* variant_level is immutable, so handle it in __new__ rather than
- __init__ */
- if (!self) return NULL;
- Py_INCREF(Py_None);
- self->signature = Py_None;
- self->variant_level = 0;
- if (kwargs) {
- variant_level = PyDict_GetItem(kwargs, dbus_py_variant_level_const);
- }
- if (variant_level) {
- self->variant_level = PyInt_AsLong(variant_level);
- if (PyErr_Occurred()) {
- Py_DECREF((PyObject *)self);
- return NULL;
- }
- }
- return (PyObject *)self;
+ if (!Array && !do_import())
+ return 0;
+ return PyObject_TypeCheck(o, (PyTypeObject *)Array);
}
-static int
-Dict_tp_init(DBusPyDict *self, PyObject *args, PyObject *kwargs)
+PyObject *
+DBusPyArray_New(const char *signature, long variant_level)
{
- PyObject *obj = dbus_py_empty_tuple;
- PyObject *signature = NULL;
- PyObject *tuple;
- PyObject *variant_level; /* ignored here - __new__ uses it */
- static char *argnames[] = {"mapping_or_iterable", "signature",
- "variant_level", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOO:__init__", argnames,
- &obj, &signature, &variant_level)) {
- return -1;
- }
+ PyObject *kwargs = NULL;
+ PyObject *ret = NULL;
- /* convert signature from a borrowed ref of unknown type to an owned ref
- of type Signature (or None) */
- if (!signature) signature = Py_None;
- if (signature == Py_None
- || PyObject_IsInstance(signature, (PyObject *)&DBusPySignature_Type)) {
- Py_INCREF(signature);
- }
- else {
- signature = PyObject_CallFunction((PyObject *)&DBusPySignature_Type,
- "(O)", signature);
- if (!signature) return -1;
- }
+ if (!Array && !do_import())
+ return NULL;
- if (signature != Py_None) {
- const char *c_str = PyString_AS_STRING(signature);
-
- switch (c_str[0]) {
- case DBUS_TYPE_BYTE:
- case DBUS_TYPE_BOOLEAN:
- case DBUS_TYPE_INT16:
- case DBUS_TYPE_UINT16:
- case DBUS_TYPE_INT32:
- case DBUS_TYPE_UINT32:
- case DBUS_TYPE_INT64:
- case DBUS_TYPE_UINT64:
- case DBUS_TYPE_DOUBLE:
-#ifdef WITH_DBUS_FLOAT32
- case DBUS_TYPE_FLOAT:
-#endif
- case DBUS_TYPE_STRING:
- case DBUS_TYPE_OBJECT_PATH:
- case DBUS_TYPE_SIGNATURE:
- break;
- default:
- Py_DECREF(signature);
- PyErr_SetString(PyExc_ValueError,
- "The key type in a Dictionary's signature "
- "must be a primitive type");
- return -1;
- }
-
- if (!dbus_signature_validate_single(c_str + 1, NULL)) {
- Py_DECREF(signature);
- PyErr_SetString(PyExc_ValueError,
- "There must be exactly two complete types in "
- "a Dictionary's signature parameter");
- return -1;
- }
+ if (variant_level != 0) {
+ kwargs = DBusPy_BuildConstructorKeywordArgs(variant_level, signature);
+ if (!kwargs)
+ goto finally;
}
- tuple = Py_BuildValue("(O)", obj);
- if (!tuple) {
- Py_DECREF(signature);
- return -1;
- }
+ ret = PyObject_Call(Array, dbus_py_empty_tuple, kwargs);
- if ((PyDict_Type.tp_init((PyObject *)self, tuple, NULL)) < 0) {
- Py_DECREF(tuple);
- Py_DECREF(signature);
- return -1;
- }
- Py_DECREF(tuple);
-
- Py_XDECREF(self->signature);
- self->signature = signature;
- return 0;
+finally:
+ Py_XDECREF(kwargs);
+ return ret;
}
-PyTypeObject DBusPyDict_Type = {
- PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
- 0,
- "dbus.Dictionary",
- sizeof(DBusPyDict),
- 0,
- (destructor)Dict_tp_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)Dict_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 */
- Dict_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 */
- Dict_tp_members, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)Dict_tp_init, /* tp_init */
- 0, /* tp_alloc */
- Dict_tp_new, /* tp_new */
-};
-
-/* Struct =========================================================== */
+/* Dict ============================================================= */
-static PyObject *struct_signatures;
-
-PyDoc_STRVAR(Struct_tp_doc,
-"An structure containing items of possibly distinct types.\n"
-"\n"
-"Constructor::\n"
-"\n"
-" dbus.Struct(iterable, signature=None, variant_level=0) -> Struct\n"
-"\n"
-"D-Bus structs may not be empty, so the iterable argument is required and\n"
-"may not be an empty iterable.\n"
-"\n"
-"``signature`` is either None, or a string representing the contents of the\n"
-"struct as one or more complete type signatures. The overall signature of\n"
-"the struct will be the given signature enclosed in parentheses, ``()``.\n"
-"\n"
-"If the signature is None (default) it will be guessed\n"
-"from the types of the items during construction.\n"
-"\n"
-"``variant_level`` must be non-negative; the default is 0.\n"
-"\n"
-":IVariables:\n"
-" `variant_level` : int\n"
-" Indicates how many nested Variant containers this object\n"
-" is contained in: if a message's wire format has a variant containing a\n"
-" variant containing a struct, this is represented in Python by a\n"
-" Struct with variant_level==2.\n"
-);
-
-static PyObject *
-Struct_tp_repr(PyObject *self)
+int
+DBusPyDictionary_Check(PyObject *o)
{
- PyObject *parent_repr = (PyTuple_Type.tp_repr)((PyObject *)self);
- PyObject *sig;
- PyObject *sig_repr = NULL;
- PyObject *key;
- long variant_level;
- PyObject *my_repr = NULL;
-
- if (!parent_repr) goto finally;
- key = PyLong_FromVoidPtr(self);
- if (!key) goto finally;
- sig = PyDict_GetItem(struct_signatures, key);
- Py_DECREF(key);
- if (!sig) sig = Py_None;
- sig_repr = PyObject_Repr(sig);
- if (!sig_repr) goto finally;
- variant_level = dbus_py_variant_level_get(self);
- if (variant_level > 0) {
- my_repr = PyString_FromFormat("%s(%s, signature=%s, "
- "variant_level=%ld)",
- self->ob_type->tp_name,
- PyString_AS_STRING(parent_repr),
- PyString_AS_STRING(sig_repr),
- variant_level);
- }
- else {
- my_repr = PyString_FromFormat("%s(%s, signature=%s)",
- self->ob_type->tp_name,
- PyString_AS_STRING(parent_repr),
- PyString_AS_STRING(sig_repr));
- }
-
-finally:
- Py_XDECREF(parent_repr);
- Py_XDECREF(sig_repr);
- return my_repr;
+ if (!Dictionary && !do_import())
+ return 0;
+ return PyObject_TypeCheck(o, (PyTypeObject *)Dictionary);
}
-static PyObject *
-Struct_tp_new (PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+PyObject *
+DBusPyDictionary_New(const char *signature, long variant_level)
{
- PyObject *signature = NULL;
- long variantness = 0;
- PyObject *self, *key;
- static char *argnames[] = {"signature", "variant_level", NULL};
-
- if (PyTuple_Size(args) != 1) {
- PyErr_SetString(PyExc_TypeError,
- "__new__ takes exactly one positional parameter");
- return NULL;
- }
- if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple, kwargs,
- "|Ol:__new__", argnames,
- &signature, &variantness)) {
- return NULL;
- }
- if (variantness < 0) {
- PyErr_SetString(PyExc_ValueError,
- "variant_level must be non-negative");
- return NULL;
- }
+ PyObject *kwargs = NULL;
+ PyObject *ret = NULL;
- self = (PyTuple_Type.tp_new)(cls, args, NULL);
- if (!self)
+ if (!Dictionary && !do_import())
return NULL;
- if (PyTuple_Size(self) < 1) {
- PyErr_SetString(PyExc_ValueError, "D-Bus structs may not be empty");
- Py_DECREF(self);
- return NULL;
- }
- if (!dbus_py_variant_level_set(self, variantness)) {
- Py_DECREF(self);
- return NULL;
+ if (variant_level != 0) {
+ kwargs = DBusPy_BuildConstructorKeywordArgs(variant_level, signature);
+ if (!kwargs)
+ goto finally;
}
- /* convert signature from a borrowed ref of unknown type to an owned ref
- of type Signature (or None) */
- if (!signature) signature = Py_None;
- if (signature == Py_None
- || PyObject_IsInstance(signature, (PyObject *)&DBusPySignature_Type)) {
- Py_INCREF(signature);
- }
- else {
- signature = PyObject_CallFunction((PyObject *)&DBusPySignature_Type,
- "(O)", signature);
- if (!signature) {
- Py_DECREF(self);
- return NULL;
- }
- }
+ ret = PyObject_Call(Dictionary, dbus_py_empty_tuple, kwargs);
- key = PyLong_FromVoidPtr(self);
- if (!key) {
- Py_DECREF(self);
- Py_DECREF(signature);
- return NULL;
- }
- if (PyDict_SetItem(struct_signatures, key, signature) < 0) {
- Py_DECREF(key);
- Py_DECREF(self);
- Py_DECREF(signature);
- return NULL;
- }
-
- Py_DECREF(key);
- Py_DECREF(signature);
- return self;
+finally:
+ Py_XDECREF(kwargs);
+ return ret;
}
-static void
-Struct_tp_dealloc(PyObject *self)
-{
- PyObject *et, *ev, *etb, *key;
-
- dbus_py_variant_level_clear(self);
- PyErr_Fetch(&et, &ev, &etb);
-
- key = PyLong_FromVoidPtr(self);
- if (key) {
- if (PyDict_GetItem(struct_signatures, key)) {
- if (PyDict_DelItem(struct_signatures, key) < 0) {
- /* should never happen */
- PyErr_WriteUnraisable(self);
- }
- }
- Py_DECREF(key);
- }
- else {
- /* not enough memory to free all the memory... leak the signature,
- * there's not much else we could do here */
- PyErr_WriteUnraisable(self);
- }
+/* Struct =========================================================== */
- PyErr_Restore(et, ev, etb);
- (PyTuple_Type.tp_dealloc)(self);
+int
+DBusPyStruct_Check(PyObject *o)
+{
+ if (!Struct && !do_import())
+ return 0;
+ return PyObject_TypeCheck(o, (PyTypeObject *)Struct);
}
PyObject *
-Struct_tp_getattro(PyObject *obj, PyObject *name)
+DBusPyStruct_New(PyObject *iterable, long variant_level)
{
- PyObject *key, *value;
+ PyObject *args = NULL;
+ PyObject *kwargs = NULL;
+ PyObject *ret = NULL;
- if (PyString_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");
+ if (!Struct && !do_import())
return NULL;
- }
- if (strcmp(PyString_AS_STRING(name), "signature")) {
- value = dbus_py_variant_level_getattro(obj, name);
- Py_DECREF(name);
- return value;
+ if (variant_level != 0) {
+ kwargs = DBusPy_BuildConstructorKeywordArgs(variant_level, NULL);
+ if (!kwargs)
+ goto finally;
}
- Py_DECREF(name);
-
- key = PyLong_FromVoidPtr(obj);
-
- if (!key) {
- return NULL;
- }
+ args = Py_BuildValue("(O)", iterable);
+ if (!args)
+ goto finally;
- value = PyDict_GetItem(struct_signatures, key);
- Py_DECREF(key);
+ ret = PyObject_Call(Struct, args, kwargs);
- if (!value)
- value = Py_None;
- Py_INCREF(value);
- return value;
+finally:
+ Py_XDECREF(args);
+ Py_XDECREF(kwargs);
+ return ret;
}
-PyTypeObject DBusPyStruct_Type = {
- PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
- 0,
- "dbus.Struct",
- 0,
- 0,
- Struct_tp_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)Struct_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 */
- Struct_tp_getattro, /* tp_getattro */
- dbus_py_immutable_setattro, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
- Struct_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 */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- Struct_tp_new, /* tp_new */
-};
-
dbus_bool_t
dbus_py_init_container_types(void)
{
- struct_signatures = PyDict_New();
- if (!struct_signatures) return 0;
-
- DBusPyArray_Type.tp_base = &PyList_Type;
- if (PyType_Ready(&DBusPyArray_Type) < 0) return 0;
- DBusPyArray_Type.tp_print = NULL;
-
- DBusPyDict_Type.tp_base = &PyDict_Type;
- if (PyType_Ready(&DBusPyDict_Type) < 0) return 0;
- DBusPyDict_Type.tp_print = NULL;
-
- DBusPyStruct_Type.tp_base = &PyTuple_Type;
- if (PyType_Ready(&DBusPyStruct_Type) < 0) return 0;
- DBusPyStruct_Type.tp_print = NULL;
-
return 1;
}
dbus_bool_t
-dbus_py_insert_container_types(PyObject *this_module)
+dbus_py_insert_container_types(PyObject *this_module UNUSED)
{
- Py_INCREF(&DBusPyArray_Type);
- if (PyModule_AddObject(this_module, "Array",
- (PyObject *)&DBusPyArray_Type) < 0) return 0;
-
- Py_INCREF(&DBusPyDict_Type);
- if (PyModule_AddObject(this_module, "Dictionary",
- (PyObject *)&DBusPyDict_Type) < 0) return 0;
-
- Py_INCREF(&DBusPyStruct_Type);
- if (PyModule_AddObject(this_module, "Struct",
- (PyObject *)&DBusPyStruct_Type) < 0) return 0;
-
return 1;
}
diff --git a/_dbus_bindings/dbus_bindings-internal.h b/_dbus_bindings/dbus_bindings-internal.h
index 1dfd6b2..6ffbc37 100644
--- a/_dbus_bindings/dbus_bindings-internal.h
+++ b/_dbus_bindings/dbus_bindings-internal.h
@@ -74,32 +74,6 @@ extern dbus_bool_t dbus_py_init_exception_types(void);
extern dbus_bool_t dbus_py_insert_exception_types(PyObject *this_module);
/* types */
-extern PyTypeObject DBusPyBoolean_Type;
-DEFINE_CHECK(DBusPyBoolean)
-extern PyTypeObject DBusPyObjectPath_Type, DBusPySignature_Type;
-DEFINE_CHECK(DBusPyObjectPath)
-DEFINE_CHECK(DBusPySignature)
-extern PyTypeObject DBusPyArray_Type, DBusPyDict_Type, DBusPyStruct_Type;
-DEFINE_CHECK(DBusPyArray)
-DEFINE_CHECK(DBusPyDict)
-DEFINE_CHECK(DBusPyStruct)
-extern PyTypeObject DBusPyByte_Type, DBusPyByteArray_Type;
-DEFINE_CHECK(DBusPyByteArray)
-DEFINE_CHECK(DBusPyByte)
-extern PyTypeObject DBusPyUTF8String_Type, DBusPyString_Type;
-DEFINE_CHECK(DBusPyUTF8String)
-DEFINE_CHECK(DBusPyString)
-extern PyTypeObject DBusPyDouble_Type;
-DEFINE_CHECK(DBusPyDouble)
-extern PyTypeObject DBusPyInt16_Type, DBusPyUInt16_Type;
-DEFINE_CHECK(DBusPyInt16)
-DEFINE_CHECK(DBusPyUInt16)
-extern PyTypeObject DBusPyInt32_Type, DBusPyUInt32_Type;
-DEFINE_CHECK(DBusPyInt32)
-DEFINE_CHECK(DBusPyUInt32)
-extern PyTypeObject DBusPyInt64_Type, DBusPyUInt64_Type;
-DEFINE_CHECK(DBusPyInt64)
-DEFINE_CHECK(DBusPyUInt64)
extern dbus_bool_t dbus_py_init_abstract(void);
extern dbus_bool_t dbus_py_init_signature(void);
extern dbus_bool_t dbus_py_init_int_types(void);
@@ -115,6 +89,63 @@ extern dbus_bool_t dbus_py_insert_float_types(PyObject *this_module);
extern dbus_bool_t dbus_py_insert_container_types(PyObject *this_module);
extern dbus_bool_t dbus_py_insert_byte_types(PyObject *this_module);
+int DBusPySignature_Check(PyObject *o);
+PyObject *DBusPySignature_FromString(const char *str);
+PyObject *DBusPySignature_FromStringObject(PyObject *o, int allow_none);
+PyObject *DBusPySignature_FromStringAndSize(const char *str, Py_ssize_t size);
+PyObject *DBusPySignature_FromStringAndVariantLevel(const char *str,
+ long variant_level);
+PyObject *dbus_py_get_signature_iter(PyObject *unused, PyObject *sig);
+
+int DBusPyBoolean_Check(PyObject *o);
+PyObject *DBusPyBoolean_New(int is_true, long variant_level);
+
+int DBusPyByte_Check(PyObject *o);
+PyObject *DBusPyByte_New(unsigned char value, long variant_level);
+
+int DBusPyByteArray_Check(PyObject *o);
+PyObject *DBusPyByteArray_New(const char *bytes, Py_ssize_t count,
+ long variant_level);
+
+int DBusPyArray_Check(PyObject *o);
+PyObject *DBusPyArray_New(const char *signature, long variant_level);
+
+int DBusPyDictionary_Check(PyObject *o);
+PyObject *DBusPyDictionary_New(const char *signature, long variant_level);
+
+int DBusPyStruct_Check(PyObject *o);
+PyObject *DBusPyStruct_New(PyObject *iterable, long variant_level);
+
+int DBusPyUTF8String_Check(PyObject *o);
+PyObject *DBusPyUTF8String_New(const char *utf8, long variant_level);
+
+int DBusPyString_Check(PyObject *o);
+PyObject *DBusPyString_New(const char *utf8, long variant_level);
+
+int DBusPyObjectPath_Check(PyObject *o);
+PyObject *DBusPyObjectPath_New(const char *utf8, long variant_level);
+
+int DBusPyDouble_Check(PyObject *o);
+PyObject *DBusPyDouble_New(double val, long variant_level);
+
+int DBusPyInt16_Check(PyObject *o);
+PyObject *DBusPyInt16_New(dbus_int16_t val, long variant_level);
+
+int DBusPyUInt16_Check(PyObject *o);
+PyObject *DBusPyUInt16_New(dbus_uint16_t val, long variant_level);
+
+int DBusPyInt32_Check(PyObject *o);
+PyObject *DBusPyInt32_New(dbus_int32_t val, long variant_level);
+
+int DBusPyUInt32_Check(PyObject *o);
+PyObject *DBusPyUInt32_New(dbus_uint32_t val, long variant_level);
+
+int DBusPyInt64_Check(PyObject *o);
+PyObject *DBusPyInt64_New(dbus_int64_t val, long variant_level);
+
+int DBusPyUInt64_Check(PyObject *o);
+PyObject *DBusPyUInt64_New(dbus_uint64_t val, long variant_level);
+
/* generic */
extern void dbus_py_take_gil_and_xdecref(PyObject *);
extern int dbus_py_immutable_setattro(PyObject *, PyObject *, PyObject *);
@@ -124,6 +155,8 @@ extern PyObject *dbus_py_tp_richcompare_by_pointer(PyObject *,
extern long dbus_py_tp_hash_by_pointer(PyObject *self);
extern PyObject *dbus_py_empty_tuple;
extern dbus_bool_t dbus_py_init_generic(void);
+PyObject *DBusPy_BuildConstructorKeywordArgs(long variant_level,
+ const char *signature);
/* message.c */
extern DBusMessage *DBusPyMessage_BorrowDBusMessage(PyObject *msg);
@@ -155,6 +188,7 @@ dbus_bool_t dbus_py_validate_object_path(const char *path);
#define dbus_py_validate_error_name dbus_py_validate_interface_name
/* debugging support */
+
void _dbus_py_assertion_failed(const char *);
#define DBUS_PY_RAISE_VIA_NULL_IF_FAIL(assertion) \
do { if (!(assertion)) { \
diff --git a/_dbus_bindings/float.c b/_dbus_bindings/float.c
index 5826ec3..8bafce9 100644
--- a/_dbus_bindings/float.c
+++ b/_dbus_bindings/float.c
@@ -31,128 +31,84 @@
#include "dbus_bindings-internal.h"
#include "types-internal.h"
-PyDoc_STRVAR(Double_tp_doc,
-"A double-precision floating point number (a subtype of float).");
-
-#ifdef WITH_DBUS_FLOAT32
-PyDoc_STRVAR(Float_tp_doc,
-"A single-precision floating point number (a subtype of float).");
-#endif
-
-PyTypeObject DBusPyDouble_Type = {
- PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
- 0,
- "dbus.Double",
- 0,
- 0,
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* 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 */
- Double_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(&DBusPythonFloatType), /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- 0, /* tp_new */
-};
-
-#ifdef WITH_DBUS_FLOAT32
-
-PyTypeObject DBusPyFloat_Type = {
- PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
- 0,
- "dbus.Float",
- 0,
- 0,
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* 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 */
- Float_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(&DBusPythonFloatType), /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- 0, /* tp_new */
-};
-#endif /* defined(WITH_DBUS_FLOAT32) */
+static PyObject *Double = NULL;
-dbus_bool_t
-dbus_py_init_float_types(void)
+static dbus_bool_t
+do_import(void)
{
- DBusPyDouble_Type.tp_base = &DBusPyFloatBase_Type;
- if (PyType_Ready(&DBusPyDouble_Type) < 0) return 0;
- DBusPyDouble_Type.tp_print = NULL;
+ PyObject *name;
+ PyObject *module;
-#ifdef WITH_DBUS_FLOAT32
- DBusPyFloat_Type.tp_base = &DBusPyFloatBase_Type;
- if (PyType_Ready(&DBusPyFloat_Type) < 0) return 0;
- DBusPyFloat_Type.tp_print = NULL;
-#endif
+ if (Double != NULL)
+ return TRUE;
- return 1;
+ Py_CLEAR(Double);
+
+ name = PyString_FromString("dbus.data");
+ if (!name)
+ return FALSE;
+
+ module = PyImport_Import(name);
+ Py_DECREF(name);
+ if (!module)
+ return FALSE;
+
+ Double = PyObject_GetAttrString(module, "Double");
+ Py_DECREF(module);
+
+ if (Double && !PyType_Check(Double)) {
+ PyErr_SetString(PyExc_AssertionError, "Assertion failed: "
+ "isinstance(dbus.data.Double, type)");
+ Double = NULL;
+ }
+
+ return (Double != NULL);
+}
+
+int
+DBusPyDouble_Check(PyObject *o)
+{
+ if (!Double && !do_import())
+ return 0;
+ return PyObject_TypeCheck(o, (PyTypeObject *)Double);
+}
+
+PyObject *
+DBusPyDouble_New(double value, long variant_level)
+{
+ PyObject *args = NULL;
+ PyObject *kwargs = NULL;
+ PyObject *ret = NULL;
+
+ if (!Double && !do_import())
+ return NULL;
+
+ if (variant_level != 0) {
+ kwargs = DBusPy_BuildConstructorKeywordArgs(variant_level, NULL);
+ if (!kwargs)
+ goto finally;
+ }
+
+ args = Py_BuildValue("(d)", value);
+ if (!args)
+ goto finally;
+
+ ret = PyObject_Call(Double, args, kwargs);
+
+finally:
+ Py_XDECREF(args);
+ Py_XDECREF(kwargs);
+ return ret;
}
dbus_bool_t
-dbus_py_insert_float_types(PyObject *this_module)
+dbus_py_init_float_types(void)
{
- Py_INCREF(&DBusPyDouble_Type);
- if (PyModule_AddObject(this_module, "Double",
- (PyObject *)&DBusPyDouble_Type) < 0) return 0;
-#ifdef WITH_DBUS_FLOAT32
- Py_INCREF(&DBusPyFloat_Type);
- if (PyModule_AddObject(this_module, "Float",
- (PyObject *)&DBusPyFloat_Type) < 0) return 0;
-#endif
+ return 1;
+}
+dbus_bool_t
+dbus_py_insert_float_types(PyObject *this_module UNUSED)
+{
return 1;
}
diff --git a/_dbus_bindings/int.c b/_dbus_bindings/int.c
index b669d57..3806d40 100644
--- a/_dbus_bindings/int.c
+++ b/_dbus_bindings/int.c
@@ -25,130 +25,201 @@
#include "types-internal.h"
-/* Specific types =================================================== */
-
-/* Boolean, a subclass of DBusPythonInt ============================= */
-
-PyDoc_STRVAR(Boolean_tp_doc,
-"A boolean, represented as a subtype of `int` (not `bool`, because `bool`\n"
-"cannot be subclassed).\n"
-"\n"
-"Constructor::\n"
-"\n"
-" dbus.Boolean(value[, variant_level]) -> Boolean\n"
-"\n"
-"``value`` is converted to 0 or 1 as if by ``int(bool(value))``.\n"
-"\n"
-"``variant_level`` must be non-negative; the default is 0.\n"
-"\n"
-":IVariables:\n"
-" `variant_level` : int\n"
-" Indicates how many nested Variant containers this object\n"
-" is contained in: if a message's wire format has a variant containing a\n"
-" variant containing a boolean, this is represented in Python by a\n"
-" Boolean with variant_level==2.\n"
-);
-
-static PyObject *
-Boolean_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+static PyObject *DBusPyBoolean = NULL;
+static PyObject *Int16 = NULL;
+static PyObject *UInt16 = NULL;
+static PyObject *Int32 = NULL;
+static PyObject *UInt32 = NULL;
+static PyObject *Int64 = NULL;
+static PyObject *UInt64 = NULL;
+
+static dbus_bool_t
+do_import(void)
{
- PyObject *tuple, *self, *value = Py_None;
- long variantness = 0;
- static char *argnames[] = {"_", "variant_level", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Ol:__new__", argnames,
- &value, &variantness)) return NULL;
- if (variantness < 0) {
- PyErr_SetString(PyExc_ValueError,
- "variant_level must be non-negative");
- return NULL;
+ PyObject *name;
+ PyObject *module;
+
+ if (DBusPyBoolean && Int16 && UInt16 && Int32 && UInt32 &&
+ Int64 && UInt64)
+ return TRUE;
+
+ Py_CLEAR(DBusPyBoolean);
+ Py_CLEAR(Int16);
+ Py_CLEAR(UInt16);
+ Py_CLEAR(Int32);
+ Py_CLEAR(UInt32);
+ Py_CLEAR(Int64);
+ Py_CLEAR(UInt64);
+
+ name = PyString_FromString("dbus.data");
+ if (!name)
+ return FALSE;
+
+ module = PyImport_Import(name);
+ Py_DECREF(name);
+ if (!module)
+ return FALSE;
+
+ DBusPyBoolean = PyObject_GetAttrString(module, "Boolean");
+ Int16 = PyObject_GetAttrString(module, "Int16");
+ UInt16 = PyObject_GetAttrString(module, "UInt16");
+ Int32 = PyObject_GetAttrString(module, "Int32");
+ UInt32 = PyObject_GetAttrString(module, "UInt32");
+ Int64 = PyObject_GetAttrString(module, "Int64");
+ UInt64 = PyObject_GetAttrString(module, "UInt64");
+ Py_DECREF(module);
+
+ if (DBusPyBoolean && !PyType_Check(DBusPyBoolean)) {
+ PyErr_SetString(PyExc_AssertionError, "Assertion failed: "
+ "isinstance(dbus.data.Boolean, type)");
+ DBusPyBoolean = NULL;
+ }
+ if (Int16 && !PyType_Check(Int16)) {
+ PyErr_SetString(PyExc_AssertionError, "Assertion failed: "
+ "isinstance(dbus.data.Int16, type)");
+ Int16 = NULL;
+ }
+ if (UInt16 && !PyType_Check(UInt16)) {
+ PyErr_SetString(PyExc_AssertionError, "Assertion failed: "
+ "isinstance(dbus.data.UInt16, type)");
+ UInt16 = NULL;
+ }
+ if (Int32 && !PyType_Check(Int32)) {
+ PyErr_SetString(PyExc_AssertionError, "Assertion failed: "
+ "isinstance(dbus.data.Int32, type)");
+ Int32 = NULL;
+ }
+ if (UInt32 && !PyType_Check(UInt32)) {
+ PyErr_SetString(PyExc_AssertionError, "Assertion failed: "
+ "isinstance(dbus.data.UInt32, type)");
+ UInt32 = NULL;
+ }
+ if (Int64 && !PyType_Check(Int64)) {
+ PyErr_SetString(PyExc_AssertionError, "Assertion failed: "
+ "isinstance(dbus.data.Int64, type)");
+ Int64 = NULL;
}
- tuple = Py_BuildValue("(i)", PyObject_IsTrue(value) ? 1 : 0);
- if (!tuple) return NULL;
- self = (DBusPyIntBase_Type.tp_new)(cls, tuple, kwargs);
- Py_DECREF(tuple);
- return self;
+ if (UInt64 && !PyType_Check(UInt64)) {
+ PyErr_SetString(PyExc_AssertionError, "Assertion failed: "
+ "isinstance(dbus.data.UInt64, type)");
+ UInt64 = NULL;
+ }
+
+ return DBusPyBoolean && Int16 && UInt16 && Int32 && UInt32 && Int64 &&
+ UInt64;
+}
+
+int
+DBusPyBoolean_Check(PyObject *o)
+{
+ if (!DBusPyBoolean && !do_import())
+ return 0;
+ return PyObject_TypeCheck(o, (PyTypeObject *)DBusPyBoolean);
}
-static PyObject *
-Boolean_tp_repr (PyObject *self)
+PyObject *
+DBusPyBoolean_New(int is_true, long variant_level)
{
- long variant_level = ((DBusPyIntBase *)self)->variant_level;
- if (variant_level > 0) {
- return PyString_FromFormat("%s(%s, variant_level=%ld)",
- self->ob_type->tp_name,
- PyInt_AsLong(self) ? "True" : "False",
- variant_level);
+ PyObject *args = NULL;
+ PyObject *kwargs = NULL;
+ PyObject *ret = NULL;
+
+ if (!DBusPyBoolean && !do_import())
+ return NULL;
+
+ if (variant_level != 0) {
+ kwargs = DBusPy_BuildConstructorKeywordArgs(variant_level, NULL);
+ if (!kwargs)
+ goto finally;
}
- return PyString_FromFormat("%s(%s)",
- self->ob_type->tp_name,
- PyInt_AsLong(self) ? "True" : "False");
+
+ args = Py_BuildValue("(i)", is_true);
+ if (!args)
+ goto finally;
+
+ ret = PyObject_Call(DBusPyBoolean, args, kwargs);
+
+finally:
+ Py_XDECREF(args);
+ Py_XDECREF(kwargs);
+ return ret;
}
-PyTypeObject DBusPyBoolean_Type = {
- PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
- 0,
- "dbus.Boolean",
- 0,
- 0,
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- Boolean_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 */
- Boolean_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(&DBusPyIntBase_Type), /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- Boolean_tp_new, /* tp_new */
-};
-
-/* Int16 ============================================================ */
-
-PyDoc_STRVAR(Int16_tp_doc,
-"A signed 16-bit integer between -0x8000 and +0x7FFF, represented as\n"
-"a subtype of `int`.\n"
-"\n"
-"Constructor::\n"
-"\n"
-" dbus.Int16(value: int[, variant_level: int]) -> Int16\n"
-"\n"
-"value must be within the allowed range, or OverflowError will be\n"
-"raised.\n"
-"\n"
-" variant_level must be non-negative; the default is 0.\n"
-"\n"
-":IVariables:\n"
-" `variant_level` : int\n"
-" Indicates how many nested Variant containers this object\n"
-" is contained in: if a message's wire format has a variant containing a\n"
-" variant containing an int16, this is represented in Python by an\n"
-" Int16 with variant_level==2.\n"
-);
+int
+DBusPyInt16_Check(PyObject *o)
+{
+ if (!Int16 && !do_import())
+ return 0;
+ return PyObject_TypeCheck(o, (PyTypeObject *)Int16);
+}
+
+int
+DBusPyUInt16_Check(PyObject *o)
+{
+ if (!UInt16 && !do_import())
+ return 0;
+ return PyObject_TypeCheck(o, (PyTypeObject *)UInt16);
+}
+
+int
+DBusPyInt32_Check(PyObject *o)
+{
+ if (!Int32 && !do_import())
+ return 0;
+ return PyObject_TypeCheck(o, (PyTypeObject *)Int32);
+}
+
+int
+DBusPyUInt32_Check(PyObject *o)
+{
+ if (!UInt32 && !do_import())
+ return 0;
+ return PyObject_TypeCheck(o, (PyTypeObject *)UInt32);
+}
+
+int
+DBusPyInt64_Check(PyObject *o)
+{
+ if (!Int64 && !do_import())
+ return 0;
+ return PyObject_TypeCheck(o, (PyTypeObject *)Int64);
+}
+
+int
+DBusPyUInt64_Check(PyObject *o)
+{
+ if (!UInt64 && !do_import())
+ return 0;
+ return PyObject_TypeCheck(o, (PyTypeObject *)UInt64);
+}
+
+PyObject *
+DBusPyInt16_New(dbus_int16_t value, long variant_level)
+{
+ PyObject *args = NULL;
+ PyObject *kwargs = NULL;
+ PyObject *ret = NULL;
+
+ if (!Int16 && !do_import())
+ return NULL;
+
+ if (variant_level != 0) {
+ kwargs = DBusPy_BuildConstructorKeywordArgs(variant_level, NULL);
+ if (!kwargs)
+ goto finally;
+ }
+
+ args = Py_BuildValue("(i)", (int)value);
+ if (!args)
+ goto finally;
+
+ ret = PyObject_Call(Int16, args, kwargs);
+
+finally:
+ Py_XDECREF(args);
+ Py_XDECREF(kwargs);
+ return ret;
+}
dbus_int16_t
dbus_py_int16_range_check(PyObject *obj)
@@ -163,81 +234,33 @@ dbus_py_int16_range_check(PyObject *obj)
return i;
}
-static PyObject *
-Int16_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+PyObject *
+DBusPyUInt16_New(dbus_uint16_t value, long variant_level)
{
- PyObject *self = (DBusPyIntBase_Type.tp_new)(cls, args, kwargs);
- if (self && dbus_py_int16_range_check(self) == -1 && PyErr_Occurred()) {
- Py_DECREF(self);
+ PyObject *args = NULL;
+ PyObject *kwargs = NULL;
+ PyObject *ret = NULL;
+
+ if (!UInt16 && !do_import())
return NULL;
+
+ if (variant_level != 0) {
+ kwargs = DBusPy_BuildConstructorKeywordArgs(variant_level, NULL);
+ if (!kwargs)
+ goto finally;
}
- return self;
-}
-PyTypeObject DBusPyInt16_Type = {
- PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
- 0,
- "dbus.Int16",
- 0,
- 0,
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* 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 */
- Int16_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(&DBusPyIntBase_Type), /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- Int16_tp_new, /* tp_new */
-};
-
-/* UInt16 =========================================================== */
-
-PyDoc_STRVAR(UInt16_tp_doc,
-"An unsigned 16-bit integer between 0 and 0xFFFF, represented as\n"
-"a subtype of `int`.\n"
-"\n"
-"Constructor::\n"
-"\n"
-" dbus.UInt16(value: int[, variant_level: int]) -> UInt16\n"
-"\n"
-"``value`` must be within the allowed range, or `OverflowError` will be\n"
-"raised.\n"
-"\n"
-"``variant_level`` must be non-negative; the default is 0.\n"
-"\n"
-":IVariables:\n"
-" `variant_level` : int\n"
-" Indicates how many nested Variant containers this object\n"
-" is contained in: if a message's wire format has a variant containing a\n"
-" variant containing a uint16, this is represented in Python by a\n"
-" UInt16 with variant_level==2.\n"
-);
+ args = Py_BuildValue("(I)", (unsigned int)value);
+ if (!args)
+ goto finally;
+
+ ret = PyObject_Call(UInt16, args, kwargs);
+
+finally:
+ Py_XDECREF(args);
+ Py_XDECREF(kwargs);
+ return ret;
+}
dbus_uint16_t
dbus_py_uint16_range_check(PyObject *obj)
@@ -252,82 +275,33 @@ dbus_py_uint16_range_check(PyObject *obj)
return i;
}
-static PyObject *
-UInt16_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+PyObject *
+DBusPyInt32_New(dbus_int32_t value, long variant_level)
{
- PyObject *self = (DBusPyIntBase_Type.tp_new)(cls, args, kwargs);
- if (self && dbus_py_uint16_range_check(self) == (dbus_uint16_t)(-1)
- && PyErr_Occurred()) {
- Py_DECREF (self);
+ PyObject *args = NULL;
+ PyObject *kwargs = NULL;
+ PyObject *ret = NULL;
+
+ if (!Int32 && !do_import())
return NULL;
+
+ if (variant_level != 0) {
+ kwargs = DBusPy_BuildConstructorKeywordArgs(variant_level, NULL);
+ if (!kwargs)
+ goto finally;
}
- return self;
-}
-PyTypeObject DBusPyUInt16_Type = {
- PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
- 0,
- "dbus.UInt16",
- 0,
- 0,
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* 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 */
- UInt16_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(&DBusPyIntBase_Type), /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- UInt16_tp_new, /* tp_new */
-};
-
-/* Int32 ============================================================ */
-
-PyDoc_STRVAR(Int32_tp_doc,
-"A signed 32-bit integer between -0x8000 0000 and +0x7FFF FFFF, represented as\n"
-"a subtype of `int`.\n"
-"\n"
-"Constructor::\n"
-"\n"
-" dbus.Int32(value: int[, variant_level: int]) -> Int32\n"
-"\n"
-"``value`` must be within the allowed range, or `OverflowError` will be\n"
-"raised.\n"
-"\n"
-"``variant_level`` must be non-negative; the default is 0.\n"
-"\n"
-":IVariables:\n"
-" `variant_level` : int\n"
-" Indicates how many nested Variant containers this object\n"
-" is contained in: if a message's wire format has a variant containing a\n"
-" variant containing an int32, this is represented in Python by an\n"
-" Int32 with variant_level==2.\n"
-);
+ args = Py_BuildValue("(l)", (long)value);
+ if (!args)
+ goto finally;
+
+ ret = PyObject_Call(Int32, args, kwargs);
+
+finally:
+ Py_XDECREF(args);
+ Py_XDECREF(kwargs);
+ return ret;
+}
dbus_int32_t
dbus_py_int32_range_check(PyObject *obj)
@@ -342,84 +316,33 @@ dbus_py_int32_range_check(PyObject *obj)
return i;
}
-static PyObject *
-Int32_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+PyObject *
+DBusPyUInt32_New(dbus_uint32_t value, long variant_level)
{
- PyObject *self = (DBusPyIntBase_Type.tp_new)(cls, args, kwargs);
- if (self && dbus_py_int32_range_check(self) == -1 && PyErr_Occurred()) {
- Py_DECREF(self);
+ PyObject *args = NULL;
+ PyObject *kwargs = NULL;
+ PyObject *ret = NULL;
+
+ if (!UInt32 && !do_import())
return NULL;
+
+ if (variant_level != 0) {
+ kwargs = DBusPy_BuildConstructorKeywordArgs(variant_level, NULL);
+ if (!kwargs)
+ goto finally;
}
- return self;
-}
-PyTypeObject DBusPyInt32_Type = {
- PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
- 0,
- "dbus.Int32",
- 0,
- 0,
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* 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 */
- Int32_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(&DBusPyIntBase_Type), /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- Int32_tp_new, /* tp_new */
-};
-
-/* UInt32 =========================================================== */
-
-PyDoc_STRVAR(UInt32_tp_doc,
-"An unsigned 32-bit integer between 0 and 0xFFFF FFFF, represented as a\n"
-"subtype of `long`.\n"
-"\n"
-"Note that this may be changed in future to be a subtype of `int` on\n"
-"64-bit platforms; applications should not rely on either behaviour.\n"
-"\n"
-"Constructor::\n"
-"\n"
-" dbus.UInt32(value: long[, variant_level: int]) -> UInt32\n"
-"\n"
-"``value`` must be within the allowed range, or `OverflowError` will be\n"
-"raised.\n"
-"\n"
-"``variant_level`` must be non-negative; the default is 0.\n"
-"\n"
-":IVariables:\n"
-" `variant_level` : int\n"
-" Indicates how many nested Variant containers this object\n"
-" is contained in: if a message's wire format has a variant containing a\n"
-" variant containing a uint32, this is represented in Python by a\n"
-" UInt32 with variant_level==2.\n"
-);
+ args = Py_BuildValue("(k)", (unsigned long)value);
+ if (!args)
+ goto finally;
+
+ ret = PyObject_Call(UInt32, args, kwargs);
+
+finally:
+ Py_XDECREF(args);
+ Py_XDECREF(kwargs);
+ return ret;
+}
dbus_uint32_t
dbus_py_uint32_range_check(PyObject *obj)
@@ -443,88 +366,33 @@ dbus_py_uint32_range_check(PyObject *obj)
return i;
}
-static PyObject *
-UInt32_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+PyObject *
+DBusPyInt64_New(dbus_int64_t value, long variant_level)
{
- PyObject *self = (DBusPyLongBase_Type.tp_new)(cls, args, kwargs);
- if (self && dbus_py_uint32_range_check(self) == (dbus_uint32_t)(-1)
- && PyErr_Occurred()) {
- Py_DECREF(self);
+ PyObject *args = NULL;
+ PyObject *kwargs = NULL;
+ PyObject *ret = NULL;
+
+ if (!Int64 && !do_import())
return NULL;
+
+ if (variant_level != 0) {
+ kwargs = DBusPy_BuildConstructorKeywordArgs(variant_level, NULL);
+ if (!kwargs)
+ goto finally;
}
- return self;
-}
-PyTypeObject DBusPyUInt32_Type = {
- PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
- 0,
- "dbus.UInt32",
- 0,
- 0,
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* 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 */
- UInt32_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(&DBusPyLongBase_Type), /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- UInt32_tp_new, /* tp_new */
-};
-
-/* Int64 =========================================================== */
-
-PyDoc_STRVAR(Int64_tp_doc,
-"A signed 64-bit integer between -0x8000 0000 0000 0000 and\n"
-"+0x7FFF FFFF FFFF FFFF, represented as a subtype of `long`.\n"
-"\n"
-"Note that this may be changed in future to be a subtype of `int` on\n"
-"64-bit platforms; applications should not rely on either behaviour.\n"
-"\n"
-"This type only works on platforms where the C compiler has suitable\n"
-"64-bit types, such as C99 ``long long``.\n"
-"\n"
-"Constructor::\n"
-"\n"
-" dbus.Int64(value: long[, variant_level: int]) -> Int64\n"
-"\n"
-"``value`` must be within the allowed range, or `OverflowError` will be\n"
-"raised.\n"
-"\n"
-"``variant_level`` must be non-negative; the default is 0.\n"
-"\n"
-":IVariables:\n"
-" `variant_level` : int\n"
-" Indicates how many nested Variant containers this object\n"
-" is contained in: if a message's wire format has a variant containing a\n"
-" variant containing an int64, this is represented in Python by an\n"
-" Int64 with variant_level==2.\n"
-);
+ args = Py_BuildValue("(L)", (PY_LONG_LONG)value);
+ if (!args)
+ goto finally;
+
+ ret = PyObject_Call(Int64, args, kwargs);
+
+finally:
+ Py_XDECREF(args);
+ Py_XDECREF(kwargs);
+ return ret;
+}
#ifdef DBUS_PYTHON_64_BIT_WORKS
dbus_int64_t
@@ -549,230 +417,66 @@ dbus_py_int64_range_check(PyObject *obj)
}
#endif
-static PyObject *
-Int64_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+PyObject *
+DBusPyUInt64_New(dbus_uint64_t value, long variant_level)
{
-#ifdef DBUS_PYTHON_64_BIT_WORKS
- PyObject *self = (DBusPyLongBase_Type.tp_new)(cls, args, kwargs);
- if (self && dbus_py_int64_range_check(self) == -1 && PyErr_Occurred()) {
- Py_DECREF(self);
+ PyObject *args = NULL;
+ PyObject *kwargs = NULL;
+ PyObject *ret = NULL;
+
+ if (!UInt64 && !do_import())
return NULL;
+
+ if (variant_level != 0) {
+ kwargs = DBusPy_BuildConstructorKeywordArgs(variant_level, NULL);
+ if (!kwargs)
+ goto finally;
}
- return self;
-#else
- PyErr_SetString(PyExc_NotImplementedError,
- "64-bit types are not available on this platform");
- return NULL;
-#endif
-}
-PyTypeObject DBusPyInt64_Type = {
- PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
- 0,
- "dbus.Int64",
- 0,
- 0,
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* 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 */
- Int64_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(&DBusPyLongBase_Type), /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- Int64_tp_new, /* tp_new */
-};
-
-/* UInt64 =========================================================== */
-
-PyDoc_STRVAR(UInt64_tp_doc,
-"An unsigned 64-bit integer between 0 and 0xFFFF FFFF FFFF FFFF,\n"
-"represented as a subtype of `long`.\n"
-"\n"
-"This type only exists on platforms where the C compiler has suitable\n"
-"64-bit types, such as C99 ``unsigned long long``.\n"
-"\n"
-"Constructor::\n"
-"\n"
-" dbus.UInt64(value: long[, variant_level: int]) -> UInt64\n"
-"\n"
-"``value`` must be within the allowed range, or `OverflowError` will be\n"
-"raised.\n"
-"\n"
-"``variant_level`` must be non-negative; the default is 0.\n"
-"\n"
-":IVariables:\n"
-" `variant_level` : int\n"
-" Indicates how many nested Variant containers this object\n"
-" is contained in: if a message's wire format has a variant containing a\n"
-" variant containing a uint64, this is represented in Python by a\n"
-" UInt64 with variant_level==2.\n"
-);
+ args = Py_BuildValue("(K)", (unsigned PY_LONG_LONG)value);
+ if (!args)
+ goto finally;
+ ret = PyObject_Call(UInt64, args, kwargs);
+
+finally:
+ Py_XDECREF(args);
+ Py_XDECREF(kwargs);
+ return ret;
+}
+
+#ifdef DBUS_PYTHON_64_BIT_WORKS
dbus_uint64_t
dbus_py_uint64_range_check(PyObject *obj)
{
unsigned PY_LONG_LONG i;
PyObject *long_obj = PyNumber_Long(obj);
- if (!long_obj) return (dbus_uint64_t)(-1);
+ if (!long_obj) return -1;
i = PyLong_AsUnsignedLongLong(long_obj);
- if (i == (unsigned PY_LONG_LONG)(-1) && PyErr_Occurred()) {
+ if (i == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred()) {
Py_DECREF(long_obj);
- return (dbus_uint64_t)(-1);
+ return -1;
}
if (i > UINT64_MAX) {
PyErr_SetString(PyExc_OverflowError, "Value out of range for UInt64");
Py_DECREF(long_obj);
- return (dbus_uint64_t)(-1);
+ return -1;
}
Py_DECREF(long_obj);
return i;
}
-
-static PyObject *
-UInt64_tp_new (PyTypeObject *cls, PyObject *args, PyObject *kwargs)
-{
-#ifdef DBUS_PYTHON_64_BIT_WORKS
- PyObject *self = (DBusPyLongBase_Type.tp_new)(cls, args, kwargs);
- if (self && dbus_py_uint64_range_check(self) == (dbus_uint64_t)(-1)
- && PyErr_Occurred()) {
- Py_DECREF(self);
- return NULL;
- }
- return self;
-#else
- PyErr_SetString(PyExc_NotImplementedError,
- "64-bit integer types are not supported on this platform");
- return NULL;
#endif
-}
-
-PyTypeObject DBusPyUInt64_Type = {
- PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
- 0,
- "dbus.UInt64",
- 0,
- 0,
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* 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 */
- UInt64_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(&DBusPyLongBase_Type), /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- UInt64_tp_new, /* tp_new */
-};
dbus_bool_t
dbus_py_init_int_types(void)
{
- DBusPyInt16_Type.tp_base = &DBusPyIntBase_Type;
- if (PyType_Ready(&DBusPyInt16_Type) < 0) return 0;
- /* disable the tp_print copied from PyInt_Type, so tp_repr gets called as
- desired */
- DBusPyInt16_Type.tp_print = NULL;
-
- DBusPyUInt16_Type.tp_base = &DBusPyIntBase_Type;
- if (PyType_Ready(&DBusPyUInt16_Type) < 0) return 0;
- DBusPyUInt16_Type.tp_print = NULL;
-
- DBusPyInt32_Type.tp_base = &DBusPyIntBase_Type;
- if (PyType_Ready(&DBusPyInt32_Type) < 0) return 0;
- DBusPyInt32_Type.tp_print = NULL;
-
- DBusPyUInt32_Type.tp_base = &DBusPyLongBase_Type;
- if (PyType_Ready(&DBusPyUInt32_Type) < 0) return 0;
- DBusPyUInt32_Type.tp_print = NULL;
-
-#if defined(DBUS_HAVE_INT64) && defined(HAVE_LONG_LONG)
- DBusPyInt64_Type.tp_base = &DBusPyLongBase_Type;
- if (PyType_Ready(&DBusPyInt64_Type) < 0) return 0;
- DBusPyInt64_Type.tp_print = NULL;
-
- DBusPyUInt64_Type.tp_base = &DBusPyLongBase_Type;
- if (PyType_Ready(&DBusPyUInt64_Type) < 0) return 0;
- DBusPyUInt64_Type.tp_print = NULL;
-#endif
return 1;
}
dbus_bool_t
-dbus_py_insert_int_types(PyObject *this_module)
+dbus_py_insert_int_types(PyObject *this_module UNUSED)
{
- Py_INCREF(&DBusPyInt16_Type);
- Py_INCREF(&DBusPyUInt16_Type);
- Py_INCREF(&DBusPyInt32_Type);
- Py_INCREF(&DBusPyUInt32_Type);
- Py_INCREF(&DBusPyInt64_Type);
- Py_INCREF(&DBusPyUInt64_Type);
- Py_INCREF(&DBusPyBoolean_Type);
- if (PyModule_AddObject(this_module, "Int16",
- (PyObject *)&DBusPyInt16_Type) < 0) return 0;
- if (PyModule_AddObject(this_module, "UInt16",
- (PyObject *)&DBusPyUInt16_Type) < 0) return 0;
- if (PyModule_AddObject(this_module, "Int32",
- (PyObject *)&DBusPyInt32_Type) < 0) return 0;
- if (PyModule_AddObject(this_module, "UInt32",
- (PyObject *)&DBusPyUInt32_Type) < 0) return 0;
- if (PyModule_AddObject(this_module, "Int64",
- (PyObject *)&DBusPyInt64_Type) < 0) return 0;
- if (PyModule_AddObject(this_module, "UInt64",
- (PyObject *)&DBusPyUInt64_Type) < 0) return 0;
- if (PyModule_AddObject(this_module, "Boolean",
- (PyObject *)&DBusPyBoolean_Type) < 0) return 0;
-
return 1;
}
diff --git a/_dbus_bindings/message-append.c b/_dbus_bindings/message-append.c
index 93b76c7..b161d08 100644
--- a/_dbus_bindings/message-append.c
+++ b/_dbus_bindings/message-append.c
@@ -28,35 +28,69 @@
#include "types-internal.h"
#include "message-internal.h"
+static PyObject *DBusPyTypeMixin = NULL;
+
+static dbus_bool_t
+do_import(void)
+{
+ PyObject *name;
+ PyObject *module;
+
+ if (DBusPyTypeMixin)
+ return TRUE;
+
+ Py_CLEAR(DBusPyTypeMixin);
+
+ name = PyString_FromString("dbus.data");
+ if (!name)
+ return FALSE;
+
+ module = PyImport_Import(name);
+ Py_DECREF(name);
+ if (!module)
+ return FALSE;
+
+ DBusPyTypeMixin = PyObject_GetAttrString(module, "_DBusTypeMixin");
+ Py_DECREF(module);
+
+ return (DBusPyTypeMixin != NULL);
+}
+
+/* When the types actually become pure-Python, this will only check for the
+ * common superclass DBusTypeMixin. During a transitional period, not all
+ * types subclass it, though.
+ */
+static int
+DBusTypeMixin_Check(PyObject *o)
+{
+ if (!DBusPyTypeMixin)
+ do_import();
+
+ if (DBusPyTypeMixin && PyObject_TypeCheck(o,
+ (PyTypeObject *)DBusPyTypeMixin))
+ return 1;
+
+ return (DBusPyStruct_Check(o) || DBusPyDictionary_Check(o)
+ || DBusPySignature_Check(o));
+}
+
/* Return the number of variants wrapping the given object. Return 0
* if the object is not a D-Bus type.
*/
static long
get_variant_level(PyObject *obj)
{
- if (DBusPyIntBase_Check(obj)) {
- return ((DBusPyIntBase *)obj)->variant_level;
- }
- else if (DBusPyFloatBase_Check(obj)) {
- return ((DBusPyFloatBase *)obj)->variant_level;
- }
- else if (DBusPyArray_Check(obj)) {
- return ((DBusPyArray *)obj)->variant_level;
- }
- else if (DBusPyDict_Check(obj)) {
- return ((DBusPyDict *)obj)->variant_level;
- }
- else if (DBusPyString_Check(obj)) {
- return ((DBusPyString *)obj)->variant_level;
- }
- else if (DBusPyLongBase_Check(obj) ||
- DBusPyStrBase_Check(obj) ||
- DBusPyStruct_Check(obj)) {
- return dbus_py_variant_level_get(obj);
- }
- else {
- return 0;
+ long ret = 0;
+
+ if (DBusTypeMixin_Check(obj)) {
+ PyObject *attr = PyObject_GetAttrString(obj, "variant_level");
+
+ if (attr && PyInt_Check(attr)) {
+ ret = PyInt_AS_LONG(attr);
+ }
+ Py_XDECREF(attr);
}
+ return ret;
}
char dbus_py_Message_append__doc__[] = (
@@ -298,10 +332,15 @@ _signature_string_from_pyobject(PyObject *obj, long *variant_level_ptr)
else if (PyList_Check(obj)) {
PyObject *tmp;
PyObject *ret = PyString_FromString(DBUS_TYPE_ARRAY_AS_STRING);
- if (!ret) return NULL;
- if (DBusPyArray_Check(obj) && PyString_Check(((DBusPyArray *)obj)->signature)) {
- PyString_Concat(&ret, ((DBusPyArray *)obj)->signature);
- return ret;
+ if (!ret)
+ return NULL;
+ if (DBusPyArray_Check(obj)) {
+ PyObject *sig = PyObject_GetAttr(obj, dbus_py_signature_const);
+
+ if (sig != NULL && PyString_Check(sig)) {
+ PyString_Concat(&ret, sig);
+ return ret;
+ }
}
if (PyList_GET_SIZE(obj) == 0) {
/* No items, so fail. Or should we guess "av"? */
@@ -320,14 +359,16 @@ _signature_string_from_pyobject(PyObject *obj, long *variant_level_ptr)
Py_ssize_t pos = 0;
PyObject *ret = NULL;
- if (DBusPyDict_Check(obj) && PyString_Check(((DBusPyDict *)obj)->signature)) {
- const char *sig = PyString_AS_STRING(((DBusPyDict *)obj)->signature);
+ if (DBusPyDictionary_Check(obj)) {
+ PyObject *sig = PyObject_GetAttr(obj, dbus_py_signature_const);
- return PyString_FromFormat((DBUS_TYPE_ARRAY_AS_STRING
- DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
- "%s"
- DBUS_DICT_ENTRY_END_CHAR_AS_STRING),
- sig);
+ if (sig != NULL && PyString_Check(sig)) {
+ return PyString_FromFormat((DBUS_TYPE_ARRAY_AS_STRING
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ "%s"
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING),
+ PyString_AS_STRING(sig));
+ }
}
if (!PyDict_Next(obj, &pos, &key, &value)) {
/* No items, so fail. Or should we guess "a{vv}"? */
@@ -384,7 +425,7 @@ dbus_py_Message_guess_signature(PyObject *unused UNUSED, PyObject *args)
/* if there were no args, easy */
if (PyTuple_GET_SIZE(args) == 0) {
DBG("%s", "Message_guess_signature: no args, so return Signature('')");
- return PyObject_CallFunction((PyObject *)&DBusPySignature_Type, "(s)", "");
+ return DBusPySignature_FromString("");
}
/* if there were args, the signature we want is, by construction,
@@ -402,9 +443,8 @@ dbus_py_Message_guess_signature(PyObject *unused UNUSED, PyObject *args)
Py_DECREF(tmp);
return NULL;
}
- ret = PyObject_CallFunction((PyObject *)&DBusPySignature_Type, "(s#)",
- PyString_AS_STRING(tmp) + 1,
- PyString_GET_SIZE(tmp) - 2);
+ ret = DBusPySignature_FromStringAndSize(PyString_AS_STRING(tmp) + 1,
+ PyString_GET_SIZE(tmp) - 2);
DBG("Message_guess_signature: returning Signature at %p \"%s\"", ret,
ret ? PyString_AS_STRING(ret) : "(NULL)");
Py_DECREF(tmp);
@@ -659,13 +699,14 @@ _message_iter_append_multi(DBusMessageIter *appender,
* variants, we want to produce an array of variants containing
* bytes, not strings.
*/
- PyObject *args = Py_BuildValue("(O)", contents);
PyObject *byte;
- if (!args)
+ if (!PyString_Check(contents)) {
+ PyErr_BadArgument();
break;
- byte = PyObject_Call((PyObject *)&DBusPyByte_Type, args, NULL);
- Py_DECREF(args);
+ }
+ byte = DBusPyByte_New(
+ (unsigned char)PyString_AS_STRING(contents)[0], 0);
if (!byte)
break;
ret = _message_iter_append_variant(&sub_appender, byte);
diff --git a/_dbus_bindings/message-get-args.c b/_dbus_bindings/message-get-args.c
index 7d55ffd..fd020d4 100644
--- a/_dbus_bindings/message-get-args.c
+++ b/_dbus_bindings/message-get-args.c
@@ -113,32 +113,26 @@ _message_iter_append_all_to_list(DBusMessageIter *iter, PyObject *list,
static inline PyObject *
_message_iter_get_dict(DBusMessageIter *iter,
Message_get_args_options *opts,
- PyObject *kwargs)
+ long variant_level)
{
DBusMessageIter entries;
char *sig_str = dbus_message_iter_get_signature(iter);
PyObject *sig;
PyObject *ret;
- int status;
if (!sig_str) {
PyErr_NoMemory();
return NULL;
}
- sig = PyObject_CallFunction((PyObject *)&DBusPySignature_Type,
- "(s#)", sig_str+2,
- (Py_ssize_t)strlen(sig_str)-3);
+ /* drop the trailing '}' and the leading 'a{' */
+ sig = DBusPySignature_FromStringAndSize(sig_str+2,
+ (Py_ssize_t)strlen(sig_str)-3);
dbus_free(sig_str);
if (!sig) {
return NULL;
}
- status = PyDict_SetItem(kwargs, dbus_py_signature_const, sig);
- Py_DECREF(sig);
- if (status < 0) {
- return NULL;
- }
- ret = PyObject_Call((PyObject *)&DBusPyDict_Type, dbus_py_empty_tuple, kwargs);
+ ret = DBusPyDictionary_New (PyString_AS_STRING (sig), variant_level);
if (!ret) {
return NULL;
}
@@ -148,6 +142,7 @@ _message_iter_get_dict(DBusMessageIter *iter,
PyObject *key = NULL;
PyObject *value = NULL;
DBusMessageIter kv;
+ int status;
DBG("%s", "dict entry...");
@@ -203,33 +198,8 @@ _message_iter_get_pyobject(DBusMessageIter *iter,
#endif
} u;
int type = dbus_message_iter_get_arg_type(iter);
- PyObject *args = NULL;
- PyObject *kwargs = NULL;
PyObject *ret = NULL;
- /* If the variant-level is >0, prepare a dict for the kwargs.
- * For variant wrappers optimize slightly by skipping this.
- */
- if (variant_level > 0 && type != DBUS_TYPE_VARIANT) {
- PyObject *variant_level_int;
-
- variant_level_int = PyInt_FromLong(variant_level);
- if (!variant_level_int) {
- return NULL;
- }
- kwargs = PyDict_New();
- if (!kwargs) {
- Py_DECREF(variant_level_int);
- return NULL;
- }
- if (PyDict_SetItem(kwargs, dbus_py_variant_level_const,
- variant_level_int) < 0) {
- Py_DECREF(variant_level_int);
- Py_DECREF(kwargs);
- return NULL;
- }
- Py_DECREF(variant_level_int);
- }
/* From here down you need to break from the switch to exit, so the
* dict is freed if necessary
*/
@@ -239,104 +209,75 @@ _message_iter_get_pyobject(DBusMessageIter *iter,
DBG("%s", "found a string");
dbus_message_iter_get_basic(iter, &u.s);
if (opts->utf8_strings) {
- args = Py_BuildValue("(s)", u.s);
- if (!args) break;
- ret = PyObject_Call((PyObject *)&DBusPyUTF8String_Type,
- args, kwargs);
+ ret = DBusPyUTF8String_New (u.s, variant_level);
}
else {
- args = Py_BuildValue("(N)", PyUnicode_DecodeUTF8(u.s,
- strlen(u.s),
- NULL));
- if (!args) {
- break;
- }
- ret = PyObject_Call((PyObject *)&DBusPyString_Type,
- args, kwargs);
+ ret = DBusPyString_New (u.s, variant_level);
}
break;
case DBUS_TYPE_SIGNATURE:
DBG("%s", "found a signature");
dbus_message_iter_get_basic(iter, &u.s);
- args = Py_BuildValue("(s)", u.s);
- if (!args) break;
- ret = PyObject_Call((PyObject *)&DBusPySignature_Type, args, kwargs);
+ ret = DBusPySignature_FromStringAndVariantLevel(u.s,
+ variant_level);
break;
case DBUS_TYPE_OBJECT_PATH:
DBG("%s", "found an object path");
dbus_message_iter_get_basic(iter, &u.s);
- args = Py_BuildValue("(s)", u.s);
- if (!args) break;
- ret = PyObject_Call((PyObject *)&DBusPyObjectPath_Type, args, kwargs);
+ ret = DBusPyObjectPath_New (u.s, variant_level);
break;
case DBUS_TYPE_DOUBLE:
DBG("%s", "found a double");
dbus_message_iter_get_basic(iter, &u.d);
- args = Py_BuildValue("(f)", u.d);
- if (!args) break;
- ret = PyObject_Call((PyObject *)&DBusPyDouble_Type, args, kwargs);
+ ret = DBusPyDouble_New (u.d, variant_level);
break;
#ifdef WITH_DBUS_FLOAT32
case DBUS_TYPE_FLOAT:
DBG("%s", "found a float");
dbus_message_iter_get_basic(iter, &u.f);
- args = Py_BuildValue("(f)", (double)u.f);
- if (!args) break;
- ret = PyObject_Call((PyObject *)&DBusPyFloat_Type, args, kwargs);
+ ret = DBusPyFloat_New (u.f, variant_level);
break;
#endif
case DBUS_TYPE_INT16:
DBG("%s", "found an int16");
dbus_message_iter_get_basic(iter, &u.i16);
- args = Py_BuildValue("(i)", (int)u.i16);
- if (!args) break;
- ret = PyObject_Call((PyObject *)&DBusPyInt16_Type, args, kwargs);
+ ret = DBusPyInt16_New (u.i16, variant_level);
break;
case DBUS_TYPE_UINT16:
DBG("%s", "found a uint16");
dbus_message_iter_get_basic(iter, &u.u16);
- args = Py_BuildValue("(i)", (int)u.u16);
- if (!args) break;
- ret = PyObject_Call((PyObject *)&DBusPyUInt16_Type, args, kwargs);
+ ret = DBusPyUInt16_New (u.u16, variant_level);
break;
case DBUS_TYPE_INT32:
DBG("%s", "found an int32");
dbus_message_iter_get_basic(iter, &u.i32);
- args = Py_BuildValue("(l)", (long)u.i32);
- if (!args) break;
- ret = PyObject_Call((PyObject *)&DBusPyInt32_Type, args, kwargs);
+ ret = DBusPyInt32_New (u.i32, variant_level);
break;
case DBUS_TYPE_UINT32:
DBG("%s", "found a uint32");
dbus_message_iter_get_basic(iter, &u.u32);
- args = Py_BuildValue("(k)", (unsigned long)u.u32);
- if (!args) break;
- ret = PyObject_Call((PyObject *)&DBusPyUInt32_Type, args, kwargs);
+ ret = DBusPyUInt32_New (u.u32, variant_level);
break;
#if defined(DBUS_HAVE_INT64) && defined(HAVE_LONG_LONG)
case DBUS_TYPE_INT64:
DBG("%s", "found an int64");
dbus_message_iter_get_basic(iter, &u.i64);
- args = Py_BuildValue("(L)", (PY_LONG_LONG)u.i64);
- if (!args) break;
- ret = PyObject_Call((PyObject *)&DBusPyInt64_Type, args, kwargs);
+ ret = DBusPyInt64_New (u.i64, variant_level);
break;
case DBUS_TYPE_UINT64:
DBG("%s", "found a uint64");
dbus_message_iter_get_basic(iter, &u.u64);
- args = Py_BuildValue("(K)", (unsigned PY_LONG_LONG)u.u64);
- if (!args) break;
- ret = PyObject_Call((PyObject *)&DBusPyUInt64_Type, args, kwargs);
+ ret = DBusPyUInt64_New (u.u64, variant_level);
break;
#else
case DBUS_TYPE_INT64:
@@ -350,19 +291,13 @@ _message_iter_get_pyobject(DBusMessageIter *iter,
case DBUS_TYPE_BYTE:
DBG("%s", "found a byte");
dbus_message_iter_get_basic(iter, &u.y);
- args = Py_BuildValue("(l)", (long)u.y);
- if (!args)
- break;
- ret = PyObject_Call((PyObject *)&DBusPyByte_Type, args, kwargs);
+ ret = DBusPyByte_New(u.y, variant_level);
break;
case DBUS_TYPE_BOOLEAN:
DBG("%s", "found a bool");
dbus_message_iter_get_basic(iter, &u.b);
- args = Py_BuildValue("(l)", (long)u.b);
- if (!args)
- break;
- ret = PyObject_Call((PyObject *)&DBusPyBoolean_Type, args, kwargs);
+ ret = DBusPyBoolean_New(u.b, variant_level);
break;
case DBUS_TYPE_ARRAY:
@@ -372,11 +307,7 @@ _message_iter_get_pyobject(DBusMessageIter *iter,
type = dbus_message_iter_get_element_type(iter);
if (type == DBUS_TYPE_DICT_ENTRY) {
DBG("%s", "no, actually it's a dict...");
- if (!kwargs) {
- kwargs = PyDict_New();
- if (!kwargs) break;
- }
- ret = _message_iter_get_dict(iter, opts, kwargs);
+ ret = _message_iter_get_dict(iter, opts, variant_level);
}
else if (opts->byte_arrays && type == DBUS_TYPE_BYTE) {
DBusMessageIter sub;
@@ -387,34 +318,23 @@ _message_iter_get_pyobject(DBusMessageIter *iter,
dbus_message_iter_get_fixed_array(&sub,
(const unsigned char **)&u.s,
&n);
- args = Py_BuildValue("(s#)", u.s, (Py_ssize_t)n);
- if (!args) break;
- ret = PyObject_Call((PyObject *)&DBusPyByteArray_Type,
- args, kwargs);
+ ret = DBusPyByteArray_New(u.s, n, variant_level);
}
else {
DBusMessageIter sub;
char *sig;
PyObject *sig_obj;
- int status;
DBG("%s", "a normal array...");
- if (!kwargs) {
- kwargs = PyDict_New();
- if (!kwargs) break;
- }
dbus_message_iter_recurse(iter, &sub);
sig = dbus_message_iter_get_signature(&sub);
if (!sig) break;
- sig_obj = PyObject_CallFunction((PyObject *)&DBusPySignature_Type,
- "(s)", sig);
+ sig_obj = DBusPySignature_FromString(sig);
dbus_free(sig);
if (!sig_obj) break;
- status = PyDict_SetItem(kwargs, dbus_py_signature_const, sig_obj);
+ ret = DBusPyArray_New(PyString_AS_STRING(sig_obj),
+ variant_level);
Py_DECREF(sig_obj);
- if (status < 0) break;
- ret = PyObject_Call((PyObject *)&DBusPyArray_Type,
- dbus_py_empty_tuple, kwargs);
if (!ret) break;
if (_message_iter_append_all_to_list(&sub, ret, opts) < 0) {
Py_DECREF(ret);
@@ -427,7 +347,6 @@ _message_iter_get_pyobject(DBusMessageIter *iter,
{
DBusMessageIter sub;
PyObject *list = PyList_New(0);
- PyObject *tuple;
DBG("%s", "found a struct...");
if (!list) break;
@@ -436,16 +355,9 @@ _message_iter_get_pyobject(DBusMessageIter *iter,
Py_DECREF(list);
break;
}
- tuple = Py_BuildValue("(O)", list);
- if (tuple) {
- ret = PyObject_Call((PyObject *)&DBusPyStruct_Type, tuple, kwargs);
- }
- else {
- ret = NULL;
- }
+ ret = DBusPyStruct_New(list, variant_level);
/* whether successful or not, we take the same action: */
Py_DECREF(list);
- Py_XDECREF(tuple);
}
break;
@@ -464,8 +376,6 @@ _message_iter_get_pyobject(DBusMessageIter *iter,
"message", type);
}
- Py_XDECREF(args);
- Py_XDECREF(kwargs);
return ret;
}
diff --git a/_dbus_bindings/message.c b/_dbus_bindings/message.c
index 8da8ffc..ec14f92 100644
--- a/_dbus_bindings/message.c
+++ b/_dbus_bindings/message.c
@@ -463,7 +463,7 @@ Message_get_path(Message *self, PyObject *unused UNUSED)
if (!c_str) {
Py_RETURN_NONE;
}
- return PyObject_CallFunction((PyObject *)&DBusPyObjectPath_Type, "(s)", c_str);
+ return DBusPyObjectPath_New(c_str, 0);
}
PyDoc_STRVAR(Message_get_path_decomposed__doc__,
@@ -546,9 +546,9 @@ Message_get_signature(Message *self, PyObject *unused UNUSED)
if (!self->msg) return DBusPy_RaiseUnusableMessage();
c_str = dbus_message_get_signature(self->msg);
if (!c_str) {
- return PyObject_CallFunction((PyObject *)&DBusPySignature_Type, "(s)", "");
+ c_str = "";
}
- return PyObject_CallFunction((PyObject *)&DBusPySignature_Type, "(s)", c_str);
+ return DBusPySignature_FromString(c_str);
}
PyDoc_STRVAR(Message_has_signature__doc__,
diff --git a/_dbus_bindings/module.c b/_dbus_bindings/module.c
index ddeb1f0..8dd756c 100644
--- a/_dbus_bindings/module.c
+++ b/_dbus_bindings/module.c
@@ -149,6 +149,25 @@ validate_object_path(PyObject *unused UNUSED, PyObject *args)
Py_RETURN_NONE;
}
+PyDoc_STRVAR(validate_signature__doc__,
+"validate_signature(signature)\n\n"
+"Raise ValueError if the given string is not a valid signature.\n");
+
+static PyObject *
+validate_signature(PyObject *unused UNUSED, PyObject *args)
+{
+ const char *s;
+
+ if (!PyArg_ParseTuple(args, "s:validate_signature", &s)) {
+ return NULL;
+ }
+ if (!dbus_signature_validate(s, NULL)) {
+ PyErr_SetString(PyExc_ValueError, "Corrupt type signature");
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
/* Global functions - main loop =====================================*/
/* The main loop if none is passed to the constructor */
@@ -224,11 +243,13 @@ static PyMethodDef module_functions[] = {
ENTRY(validate_member_name, METH_VARARGS),
ENTRY(validate_bus_name, METH_VARARGS|METH_KEYWORDS),
ENTRY(validate_object_path, METH_VARARGS),
+ ENTRY(validate_signature, METH_VARARGS),
ENTRY(set_default_main_loop, METH_VARARGS),
ENTRY(get_default_main_loop, METH_NOARGS),
/* validate_error_name is just implemented as validate_interface_name */
{"validate_error_name", validate_interface_name,
METH_VARARGS, validate_error_name__doc__},
+ {"get_signature_iter", dbus_py_get_signature_iter, METH_O, ""},
#undef ENTRY
{NULL, NULL, 0, NULL}
};
diff --git a/_dbus_bindings/signature.c b/_dbus_bindings/signature.c
index 6b31ab4..fef9a27 100644
--- a/_dbus_bindings/signature.c
+++ b/_dbus_bindings/signature.c
@@ -31,27 +31,37 @@
#include "dbus_bindings-internal.h"
#include "types-internal.h"
-PyDoc_STRVAR(Signature_tp_doc,
-"A string subclass whose values are restricted to valid D-Bus\n"
-"signatures. When iterated over, instead of individual characters it\n"
-"produces Signature instances representing single complete types.\n"
-"\n"
-"Constructor::\n"
-"\n"
-" ``Signature(value: str or unicode[, variant_level: int]) -> Signature``\n"
-"\n"
-"``value`` must be a valid D-Bus signature (zero or more single complete\n"
-"types).\n"
-"\n"
-"``variant_level`` must be non-negative; the default is 0.\n"
-"\n"
-":IVariables:\n"
-" `variant_level` : int\n"
-" Indicates how many nested Variant containers this object\n"
-" is contained in: if a message's wire format has a variant containing a\n"
-" variant containing a signature, this is represented in Python by a\n"
-" Signature with variant_level==2.\n"
-);
+static PyObject *Signature = NULL;
+
+static dbus_bool_t
+do_import(void)
+{
+ PyObject *name;
+ PyObject *module;
+
+ if (Signature != NULL)
+ return TRUE;
+
+ name = PyString_FromString("dbus.data");
+ if (!name)
+ return FALSE;
+
+ module = PyImport_Import(name);
+ Py_DECREF(name);
+ if (!module)
+ return FALSE;
+
+ Signature = PyObject_GetAttrString(module, "Signature");
+ Py_DECREF(module);
+
+ if (Signature && !PyType_Check(Signature)) {
+ PyErr_SetString(PyExc_AssertionError, "Assertion failed: "
+ "isinstance(dbus.data.Signature, type)");
+ Signature = NULL;
+ }
+
+ return (Signature != NULL);
+}
typedef struct {
PyObject_HEAD
@@ -78,7 +88,7 @@ SignatureIter_tp_iternext (SignatureIter *self)
sig = dbus_signature_iter_get_signature(&(self->iter));
if (!sig) return PyErr_NoMemory();
- obj = PyObject_CallFunction((PyObject *)&DBusPySignature_Type, "s", sig);
+ obj = PyObject_CallFunction(Signature, "s", sig);
dbus_free(sig);
if (!obj) return NULL;
@@ -142,16 +152,24 @@ static PyTypeObject SignatureIterType = {
0, /* tp_free */
};
-static PyObject *
-Signature_tp_iter (PyObject *self)
+PyObject *
+dbus_py_get_signature_iter (PyObject *unused UNUSED, PyObject *sig)
{
- SignatureIter *iter = PyObject_New(SignatureIter, &SignatureIterType);
- if (!iter) return NULL;
+ SignatureIter *iter;
+
+ if (!DBusPySignature_Check (sig)) {
+ PyErr_SetString(PyExc_TypeError, "A dbus.data.Signature is required");
+ }
- if (PyString_AS_STRING (self)[0]) {
- Py_INCREF(self);
- iter->string = self;
- dbus_signature_iter_init(&(iter->iter), PyString_AS_STRING(self));
+ iter = PyObject_New(SignatureIter, &SignatureIterType);
+
+ if (!iter)
+ return NULL;
+
+ if (PyString_AS_STRING (sig)[0]) {
+ Py_INCREF(sig);
+ iter->string = sig;
+ dbus_signature_iter_init(&(iter->iter), PyString_AS_STRING(sig));
}
else {
/* this is a null string, make a null iterator */
@@ -160,83 +178,66 @@ Signature_tp_iter (PyObject *self)
return (PyObject *)iter;
}
-static PyObject *
-Signature_tp_new (PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+PyObject *
+DBusPySignature_FromStringObject(PyObject *o, int allow_none)
{
- const char *str = NULL;
- PyObject *ignored;
- static char *argnames[] = {"object_path", "variant_level", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|O:__new__", argnames,
- &str, &ignored)) return NULL;
- if (!dbus_signature_validate(str, NULL)) {
- PyErr_SetString(PyExc_ValueError, "Corrupt type signature");
+ if (!Signature && !do_import())
return NULL;
+
+ if (allow_none && o == Py_None) {
+ Py_INCREF(o);
+ return o;
+ }
+ if (PyObject_TypeCheck(o, (PyTypeObject *)Signature)) {
+ Py_INCREF(o);
+ return o;
}
- return (DBusPyStrBase_Type.tp_new)(cls, args, kwargs);
+ return PyObject_CallFunction(Signature, "(O)", o);
}
-PyTypeObject DBusPySignature_Type = {
- PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
- 0,
- "dbus.Signature",
- 0,
- 0,
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* 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 */
- Signature_tp_doc, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- Signature_tp_iter, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- DEFERRED_ADDRESS(&DBusPythonStringType), /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- Signature_tp_new, /* tp_new */
- 0, /* tp_free */
-};
+PyObject *
+DBusPySignature_FromStringAndVariantLevel(const char *str, long variant_level)
+{
+ if (!Signature && !do_import())
+ return NULL;
+ return PyObject_CallFunction(Signature, "(sl)", str, variant_level);
+}
+
+PyObject *
+DBusPySignature_FromStringAndSize(const char *str, Py_ssize_t size)
+{
+ if (!Signature && !do_import())
+ return NULL;
+ return PyObject_CallFunction(Signature, "(s#)", str, size);
+}
+
+PyObject *
+DBusPySignature_FromString(const char *str)
+{
+ if (!Signature && !do_import())
+ return NULL;
+ return PyObject_CallFunction(Signature, "(s)", str);
+}
+
+int
+DBusPySignature_Check(PyObject *o)
+{
+ if (!Signature && !do_import())
+ return 0;
+ return PyObject_TypeCheck(o, (PyTypeObject *)Signature);
+}
dbus_bool_t
dbus_py_init_signature(void)
{
if (PyType_Ready(&SignatureIterType) < 0) return 0;
- DBusPySignature_Type.tp_base = &DBusPyStrBase_Type;
- if (PyType_Ready(&DBusPySignature_Type) < 0) return 0;
- DBusPySignature_Type.tp_print = NULL;
-
return 1;
}
dbus_bool_t
dbus_py_insert_signature(PyObject *this_module)
{
- Py_INCREF(&DBusPySignature_Type);
- if (PyModule_AddObject(this_module, "Signature",
- (PyObject *)&DBusPySignature_Type) < 0) return 0;
Py_INCREF(&SignatureIterType);
if (PyModule_AddObject(this_module, "_SignatureIter",
(PyObject *)&SignatureIterType) < 0) return 0;
diff --git a/_dbus_bindings/string.c b/_dbus_bindings/string.c
index 19eab2c..1aa1825 100644
--- a/_dbus_bindings/string.c
+++ b/_dbus_bindings/string.c
@@ -26,354 +26,173 @@
#include "types-internal.h"
#include <structmember.h>
-/* UTF-8 string representation ====================================== */
-
-PyDoc_STRVAR(UTF8String_tp_doc,
-"A string represented using UTF-8 - a subtype of `str`.\n"
-"\n"
-"All strings on D-Bus are required to be valid Unicode; in the \"wire\n"
-"protocol\" they're transported as UTF-8.\n"
-"\n"
-"By default, when byte arrays are converted from D-Bus to Python, they\n"
-"come out as a `dbus.String`, which is a subtype of `unicode`.\n"
-"If you prefer to get UTF-8 strings (as instances of this class) or you\n"
-"want to avoid the conversion overhead of going from UTF-8 to Python's\n"
-"internal Unicode representation, you can pass the ``utf8_strings=True``\n"
-"keyword argument to any of these methods:\n"
-"\n"
-"* any D-Bus method proxy, or ``connect_to_signal``, on the objects returned\n"
-" by `Bus.get_object`\n"
-"* any D-Bus method on a `dbus.Interface`\n"
-"* `dbus.Interface.connect_to_signal`\n"
-"* `Bus.add_signal_receiver`\n"
-"\n"
-"\n"
-"Constructor::\n"
-"\n"
-" dbus.UTF8String(value: str or unicode[, variant_level: int]) -> UTF8String\n"
-"\n"
-"If value is a str object it must be valid UTF-8.\n"
-"\n"
-"variant_level must be non-negative; the default is 0.\n"
-"\n"
-":IVariables:\n"
-" `variant_level` : int\n"
-" Indicates how many nested Variant containers this object\n"
-" is contained in: if a message's wire format has a variant containing a\n"
-" variant containing a string, this is represented in Python by a\n"
-" String or UTF8String with variant_level==2.\n"
-":Since: 0.80 (in older versions, use dbus.String)\n"
-);
-
-static PyObject *
-UTF8String_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+static PyObject *String = NULL;
+static PyObject *UTF8String = NULL;
+static PyObject *ObjectPath = NULL;
+
+static dbus_bool_t
+do_import(void)
{
- const char *str = NULL;
- long variantness = 0;
- static char *argnames[] = {"value", "variant_level", NULL};
- PyObject *unicode;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|l:__new__", argnames,
- &str, &variantness)) return NULL;
- unicode = PyUnicode_DecodeUTF8(str, strlen(str), NULL);
- if (!unicode) return NULL;
- Py_DECREF(unicode);
- return (DBusPyStrBase_Type.tp_new)(cls, args, kwargs);
+ PyObject *name;
+ PyObject *module;
+
+ if (String && ObjectPath && UTF8String)
+ return TRUE;
+
+ Py_CLEAR(String);
+ Py_CLEAR(UTF8String);
+ Py_CLEAR(ObjectPath);
+
+ name = PyString_FromString("dbus.data");
+ if (!name)
+ return FALSE;
+
+ module = PyImport_Import(name);
+ Py_DECREF(name);
+ if (!module)
+ return FALSE;
+
+ String = PyObject_GetAttrString(module, "String");
+ UTF8String = PyObject_GetAttrString(module, "UTF8String");
+ ObjectPath = PyObject_GetAttrString(module, "ObjectPath");
+ Py_DECREF(module);
+
+ if (String && !PyType_Check(String)) {
+ PyErr_SetString(PyExc_AssertionError, "Assertion failed: "
+ "isinstance(dbus.data.String, type)");
+ String = NULL;
+ }
+ if (UTF8String && !PyType_Check(UTF8String)) {
+ PyErr_SetString(PyExc_AssertionError, "Assertion failed: "
+ "isinstance(dbus.data.UTF8String, type)");
+ UTF8String = NULL;
+ }
+ if (ObjectPath && !PyType_Check(ObjectPath)) {
+ PyErr_SetString(PyExc_AssertionError, "Assertion failed: "
+ "isinstance(dbus.data.ObjectPath, type)");
+ ObjectPath = NULL;
+ }
+
+ return (String != NULL && UTF8String != NULL && ObjectPath != NULL);
}
-PyTypeObject DBusPyUTF8String_Type = {
- PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
- 0,
- "dbus.UTF8String",
- 0,
- 0,
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* 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 */
- UTF8String_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(&DBusPyStrBase_Type), /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- UTF8String_tp_new, /* tp_new */
-};
-
-/* Object path ====================================================== */
-
-PyDoc_STRVAR(ObjectPath_tp_doc,
-"A D-Bus object path, such as '/com/example/MyApp/Documents/abc'.\n"
-"\n"
-"ObjectPath is a subtype of str, and object-paths behave like strings.\n"
-"\n"
-"Constructor::\n"
-"\n"
-" dbus.ObjectPath(path: str, variant_level: int) -> ObjectPath\n"
-"\n"
-"path must be an ASCII string following the syntax of object paths.\n"
-"variant_level must be non-negative; the default is 0.\n"
-"\n"
-":IVariables:\n"
-" `variant_level` : int\n"
-" Indicates how many nested Variant containers this object\n"
-" is contained in: if a message's wire format has a variant containing a\n"
-" variant containing an object path, this is represented in Python by an\n"
-" ObjectPath with variant_level==2.\n"
-);
-
-static PyObject *
-ObjectPath_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+int
+DBusPyString_Check(PyObject *o)
{
- const char *str = NULL;
- long variantness = 0;
- static char *argnames[] = {"object_path", "variant_level", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|l:__new__", argnames,
- &str, &variantness)) return NULL;
- if (!dbus_py_validate_object_path(str)) {
- return NULL;
- }
- return (DBusPyStrBase_Type.tp_new)(cls, args, kwargs);
+ if (!String && !do_import())
+ return 0;
+ return PyObject_TypeCheck(o, (PyTypeObject *)String);
}
-PyTypeObject DBusPyObjectPath_Type = {
- PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
- 0,
- "dbus.ObjectPath",
- 0,
- 0,
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* 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 */
- ObjectPath_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(&DBusPyStrBase_Type), /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- ObjectPath_tp_new, /* tp_new */
-};
-
-/* Unicode string representation ==================================== */
-
-PyDoc_STRVAR(String_tp_doc,
-"A string represented using Unicode - a subtype of `unicode`.\n"
-"\n"
-"All strings on D-Bus are required to be valid Unicode; in the \"wire\n"
-"protocol\" they're transported as UTF-8.\n"
-"\n"
-"By default, when strings are converted from D-Bus to Python, they\n"
-"come out as this class. If you prefer to get UTF-8 strings (as instances\n"
-"of a subtype of `str`) or you want to avoid the conversion overhead of\n"
-"going from UTF-8 to Python's internal Unicode representation, see the\n"
-"documentation for `dbus.UTF8String`.\n"
-"\n"
-"Constructor::\n"
-"\n"
-" String(value: str or unicode[, variant_level: int]) -> String\n"
-"\n"
-"variant_level must be non-negative; the default is 0.\n"
-"\n"
-":IVariables:\n"
-" `variant_level` : int\n"
-" Indicates how many nested Variant containers this object\n"
-" is contained in: if a message's wire format has a variant containing a\n"
-" variant containing a string, this is represented in Python by a\n"
-" String or UTF8String with variant_level==2.\n"
-);
-
-static PyMemberDef String_tp_members[] = {
- {"variant_level", T_LONG, offsetof(DBusPyString, variant_level),
- READONLY,
- "The number of nested variants wrapping the real data. "
- "0 if not in a variant"},
- {NULL},
-};
-
-static PyObject *
-String_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
+PyObject *
+DBusPyString_New(const char *utf8, long variant_level)
{
- PyObject *self;
- long variantness = 0;
- static char *argnames[] = {"variant_level", NULL};
+ PyObject *args = NULL;
+ PyObject *kwargs = NULL;
+ PyObject *ret = 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");
+ if (!String && !do_import())
return NULL;
+
+ if (variant_level != 0) {
+ kwargs = DBusPy_BuildConstructorKeywordArgs(variant_level, NULL);
+ if (!kwargs)
+ goto finally;
}
- self = (PyUnicode_Type.tp_new)(cls, args, NULL);
- if (self) {
- ((DBusPyString *)self)->variant_level = variantness;
- }
- return self;
+
+ args = Py_BuildValue("(s)", utf8);
+ if (!args)
+ goto finally;
+
+ ret = PyObject_Call(String, args, kwargs);
+
+finally:
+ Py_XDECREF(args);
+ Py_XDECREF(kwargs);
+ return ret;
+}
+
+int
+DBusPyObjectPath_Check(PyObject *o)
+{
+ if (!ObjectPath && !do_import())
+ return 0;
+ return PyObject_TypeCheck(o, (PyTypeObject *)ObjectPath);
}
-static PyObject *
-String_tp_repr(PyObject *self)
+PyObject *
+DBusPyObjectPath_New(const char *utf8, long variant_level)
{
- PyObject *parent_repr = (PyUnicode_Type.tp_repr)(self);
- PyObject *my_repr;
+ PyObject *args = NULL;
+ PyObject *kwargs = NULL;
+ PyObject *ret = NULL;
- if (!parent_repr) {
+ if (!ObjectPath && !do_import())
return NULL;
+
+ if (variant_level != 0) {
+ kwargs = DBusPy_BuildConstructorKeywordArgs(variant_level, NULL);
+ if (!kwargs)
+ goto finally;
}
- if (((DBusPyString *)self)->variant_level > 0) {
- my_repr = PyString_FromFormat("%s(%s, variant_level=%ld)",
- self->ob_type->tp_name,
- PyString_AS_STRING(parent_repr),
- ((DBusPyString *)self)->variant_level);
- }
- else {
- my_repr = PyString_FromFormat("%s(%s)", self->ob_type->tp_name,
- PyString_AS_STRING(parent_repr));
- }
- /* whether my_repr is NULL or not: */
- Py_DECREF(parent_repr);
- return my_repr;
-}
-PyTypeObject DBusPyString_Type = {
- PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
- 0,
- "dbus.String",
- sizeof(DBusPyString),
- 0,
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- String_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 */
- PyObject_GenericGetAttr, /* tp_getattro */
- dbus_py_immutable_setattro, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
- String_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 */
- String_tp_members, /* tp_members */
- 0, /* tp_getset */
- DEFERRED_ADDRESS(&PyUnicode_Type), /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- String_tp_new, /* tp_new */
-};
+ args = Py_BuildValue("(s)", utf8);
+ if (!args)
+ goto finally;
-dbus_bool_t
-dbus_py_init_string_types(void)
+ ret = PyObject_Call(ObjectPath, args, kwargs);
+
+finally:
+ Py_XDECREF(args);
+ Py_XDECREF(kwargs);
+ return ret;
+}
+
+int
+DBusPyUTF8String_Check(PyObject *o)
{
- /* don't need to do strange contortions for unicode, since it's not a
- * "variable-size" object (it has a pointer to its data instead)
- */
- if (PyUnicode_Type.tp_itemsize != 0) {
- fprintf(stderr, "dbus-python is not compatible with this version of "
- "Python (unicode objects are assumed to be fixed-size)");
+ if (!UTF8String && !do_import())
return 0;
+ return PyObject_TypeCheck(o, (PyTypeObject *)UTF8String);
+}
+
+PyObject *
+DBusPyUTF8String_New(const char *utf8, long variant_level)
+{
+ PyObject *args = NULL;
+ PyObject *kwargs = NULL;
+ PyObject *ret = NULL;
+
+ if (!UTF8String && !do_import())
+ return NULL;
+
+ if (variant_level != 0) {
+ kwargs = DBusPy_BuildConstructorKeywordArgs(variant_level, NULL);
+ if (!kwargs)
+ goto finally;
}
- DBusPyString_Type.tp_base = &PyUnicode_Type;
- if (PyType_Ready(&DBusPyString_Type) < 0) return 0;
- DBusPyString_Type.tp_print = NULL;
- DBusPyUTF8String_Type.tp_base = &DBusPyStrBase_Type;
- if (PyType_Ready(&DBusPyUTF8String_Type) < 0) return 0;
- DBusPyUTF8String_Type.tp_print = NULL;
+ args = Py_BuildValue("(s)", utf8);
+ if (!args)
+ goto finally;
- DBusPyObjectPath_Type.tp_base = &DBusPyStrBase_Type;
- if (PyType_Ready(&DBusPyObjectPath_Type) < 0) return 0;
- DBusPyObjectPath_Type.tp_print = NULL;
+ ret = PyObject_Call(UTF8String, args, kwargs);
- DBusPyBoolean_Type.tp_base = &DBusPyIntBase_Type;
- if (PyType_Ready(&DBusPyBoolean_Type) < 0) return 0;
- DBusPyBoolean_Type.tp_print = NULL;
+finally:
+ Py_XDECREF(args);
+ Py_XDECREF(kwargs);
+ return ret;
+}
+dbus_bool_t
+dbus_py_init_string_types(void)
+{
return 1;
}
dbus_bool_t
-dbus_py_insert_string_types(PyObject *this_module)
+dbus_py_insert_string_types(PyObject *this_module UNUSED)
{
- Py_INCREF(&DBusPyObjectPath_Type);
- Py_INCREF(&DBusPyUTF8String_Type);
- Py_INCREF(&DBusPyString_Type);
- if (PyModule_AddObject(this_module, "ObjectPath",
- (PyObject *)&DBusPyObjectPath_Type) < 0) return 0;
- if (PyModule_AddObject(this_module, "UTF8String",
- (PyObject *)&DBusPyUTF8String_Type) < 0) return 0;
- if (PyModule_AddObject(this_module, "String",
- (PyObject *)&DBusPyString_Type) < 0) return 0;
-
return 1;
}
diff --git a/_dbus_bindings/types-internal.h b/_dbus_bindings/types-internal.h
index a5c8147..67f84c2 100644
--- a/_dbus_bindings/types-internal.h
+++ b/_dbus_bindings/types-internal.h
@@ -31,30 +31,6 @@
#ifndef DBUS_BINDINGS_TYPES_INTERNAL_H
#define DBUS_BINDINGS_TYPES_INTERNAL_H
-extern PyTypeObject DBusPyIntBase_Type;
-DEFINE_CHECK(DBusPyIntBase)
-
-typedef struct {
- PyIntObject base;
- long variant_level;
-} DBusPyIntBase;
-
-extern PyTypeObject DBusPyLongBase_Type;
-DEFINE_CHECK(DBusPyLongBase)
-
-extern PyTypeObject DBusPyFloatBase_Type;
-DEFINE_CHECK(DBusPyFloatBase)
-
-typedef struct {
- PyFloatObject base;
- long variant_level;
-} DBusPyFloatBase;
-
-typedef struct {
- PyUnicodeObject unicode;
- long variant_level;
-} DBusPyString;
-
extern PyTypeObject DBusPyStrBase_Type;
DEFINE_CHECK(DBusPyStrBase)
@@ -75,18 +51,6 @@ extern PyObject *dbus_py_variant_level_const;
extern PyObject *dbus_py_signature_const;
extern PyObject *dbus_py__dbus_object_path__const;
-typedef struct {
- PyListObject super;
- PyObject *signature;
- long variant_level;
-} DBusPyArray;
-
-typedef struct {
- PyDictObject super;
- PyObject *signature;
- long variant_level;
-} DBusPyDict;
-
PyObject *dbus_py_variant_level_getattro(PyObject *obj, PyObject *name);
dbus_bool_t dbus_py_variant_level_set(PyObject *obj, long variant_level);
void dbus_py_variant_level_clear(PyObject *obj);
diff --git a/configure.ac b/configure.ac
index dd7c32c..79e21e2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -9,7 +9,7 @@ m4_define(dbus_python_minor_version, 82)
m4_define(dbus_python_micro_version, 3)
m4_define(dbus_python_maybe_datestamp,
- m4_esyscmd([if test x]dbus_python_released[ != x1; then date +.%Y%m%d | tr -d '\n\r'; fi]))
+ m4_esyscmd([if test x]dbus_python_released[ != x1; then date +.purity%Y%m%d | tr -d '\n\r'; fi]))
m4_define(dbus_python_version, dbus_python_major_version.dbus_python_minor_version.dbus_python_micro_version[]dbus_python_maybe_datestamp)
diff --git a/dbus/__init__.py b/dbus/__init__.py
index e990ec3..c8c38d9 100644
--- a/dbus/__init__.py
+++ b/dbus/__init__.py
@@ -76,7 +76,7 @@ except ImportError:
# OLPC Sugar compatibility
import dbus.exceptions as exceptions
-import dbus.types as types
+import dbus.data as types
from _dbus_bindings import get_default_main_loop, set_default_main_loop,\
validate_interface_name, validate_member_name,\
@@ -93,10 +93,10 @@ from dbus.exceptions import MissingErrorHandlerException, \
UnknownMethodException, \
NameExistsException, \
DBusException
-from _dbus_bindings import ObjectPath, ByteArray, Signature, Byte, Boolean,\
- Int16, UInt16, Int32, UInt32, Int64, UInt64,\
- Double, String, Array, Struct, Dictionary, \
- UTF8String
+from dbus.data import ObjectPath, ByteArray, Signature, Byte, Boolean,\
+ Int16, UInt16, Int32, UInt32, Int64, UInt64,\
+ Double, String, Array, Struct, Dictionary, \
+ UTF8String
from dbus._dbus import Bus, SystemBus, SessionBus, StarterBus
from dbus.proxies import Interface
diff --git a/dbus/_dbus.py b/dbus/_dbus.py
index 18747c0..2b1c20f 100644
--- a/dbus/_dbus.py
+++ b/dbus/_dbus.py
@@ -37,13 +37,14 @@ from traceback import print_exc
from dbus.exceptions import DBusException
from _dbus_bindings import BUS_DAEMON_NAME, BUS_DAEMON_PATH,\
- BUS_DAEMON_IFACE, UTF8String,\
+ BUS_DAEMON_IFACE,\
validate_member_name, validate_interface_name,\
validate_bus_name, validate_object_path,\
BUS_SESSION, BUS_SYSTEM, BUS_STARTER,\
DBUS_START_REPLY_SUCCESS, \
DBUS_START_REPLY_ALREADY_RUNNING
from dbus.bus import BusConnection
+from dbus.data import UTF8String
from dbus.lowlevel import SignalMessage
try:
diff --git a/dbus/connection.py b/dbus/connection.py
index 3a551ea..ca61c5a 100644
--- a/dbus/connection.py
+++ b/dbus/connection.py
@@ -31,20 +31,27 @@ except ImportError:
import weakref
from _dbus_bindings import Connection as _Connection, \
- LOCAL_PATH, LOCAL_IFACE, \
+ LOCAL_PATH, LOCAL_IFACE, PEER_IFACE, \
validate_interface_name, validate_member_name,\
validate_bus_name, validate_object_path,\
- validate_error_name, \
- UTF8String
+ validate_error_name
+from _dbus_bindings import DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
+ as _INTROSPECT_DOCTYPE
+from dbus.data import UTF8String, ObjectPath
from dbus.exceptions import DBusException
from dbus.lowlevel import ErrorMessage, MethodCallMessage, SignalMessage, \
- MethodReturnMessage, HANDLER_RESULT_NOT_YET_HANDLED
+ MethodReturnMessage, \
+ HANDLER_RESULT_NOT_YET_HANDLED, \
+ HANDLER_RESULT_HANDLED
from dbus.proxies import ProxyObject
_logger = logging.getLogger('dbus.connection')
+_ROOT = ObjectPath('/')
+
+
def _noop(*args, **kwargs):
pass
@@ -253,7 +260,23 @@ class Connection(_Connection):
self._signals_lock = thread.allocate_lock()
"""Lock used to protect signal data structures"""
- self.add_message_filter(self.__class__._signal_func)
+ self._object_tree_lock = thread.allocate_lock()
+ """Lock used to protect _object_paths and _object_tree"""
+
+ self._object_paths = {}
+ """Dict mapping object path to one of:
+
+ - a tuple (on_message, on_unregister, fallback)
+ - a tuple (None, None, False), meaning this is a "synthetic"
+ object created as a parent or ancestor for a real object
+ """
+
+ self._object_children = {}
+ """Dict mapping object paths to sets of children"""
+
+ self._filters = []
+
+ super(Connection, self).add_message_filter(self.__class__._filter)
def activate_name_owner(self, bus_name):
"""Return the unique name for the given bus name, activating it
@@ -493,23 +516,6 @@ class Connection(_Connection):
# Now called without the signals lock held (it was held in <= 0.81.0)
pass
- def _signal_func(self, message):
- """D-Bus filter function. Handle signals by dispatching to Python
- callbacks kept in the match-rule tree.
- """
-
- if not isinstance(message, SignalMessage):
- return HANDLER_RESULT_NOT_YET_HANDLED
-
- dbus_interface = message.get_interface()
- path = message.get_path()
- signal_name = message.get_member()
-
- for match in self._iter_easy_matches(path, dbus_interface,
- signal_name):
- match.maybe_handle_message(message)
- return HANDLER_RESULT_NOT_YET_HANDLED
-
def call_async(self, bus_name, object_path, dbus_interface, method,
signature, args, reply_handler, error_handler,
timeout=-1.0, utf8_strings=False, byte_arrays=False,
@@ -612,3 +618,250 @@ class Connection(_Connection):
return args_list[0]
else:
return tuple(args_list)
+
+ # Export functionality
+
+ def _register_object_path(self, path, on_message, on_unregister=None,
+ fallback=False):
+ """Register a callback to be called when messages arrive at the given
+ object-path. Used to export objects' methods on the bus in a low-level
+ way. Use `dbus.service.Object` instead.
+
+ :Parameters:
+ `path` : dbus.ObjectPath or other str
+ Object path to be acted on
+ `on_message` : callable
+ Called when a message arrives at the given object-path, with
+ two positional parameters: the first is this Connection,
+ the second is the incoming `dbus.lowlevel.Message`.
+ `on_unregister` : callable or None
+ If not None, called when the callback is unregistered, with
+ two positional parameters: the first is this Connection,
+ the second is the path at which the object is no longer
+ registered.
+ `fallback` : bool
+ If True (the default is False), when a message arrives for a
+ 'subdirectory' of the given path and there is no more specific
+ handler, use this handler. Normally this handler is only run if
+ the paths match exactly.
+ """
+ self._require_main_loop()
+ path = ObjectPath(path)
+ parent, tail = path.rsplit('/', 1)
+ if on_message is None:
+ raise TypeError('None may not be registered as an object-path '
+ 'handler')
+
+ self._object_tree_lock.acquire()
+ paths = self._object_paths
+ children = self._object_children
+ try:
+ if path in paths:
+ old_on_message, unused, unused = paths[path]
+ if old_on_message:
+ raise KeyError("Can't register the object-path handler "
+ "for %r: there is already a handler" % path)
+
+ while tail:
+ parent = ObjectPath(parent or _ROOT)
+ # make sure there's at least a synthetic parent
+ paths.setdefault(parent, (None, None, False))
+ # give the parent an appropriate child
+ children.setdefault(parent, set()).add(tail)
+ # walk upwards
+ parent, tail = parent.rsplit('/', 1)
+
+ paths[path] = (on_message, on_unregister, fallback)
+ finally:
+ self._object_tree_lock.release()
+
+ def _unregister_object_path(self, path):
+ """Remove a previously registered handler for the given object path.
+
+ :Parameters:
+ `path` : dbus.ObjectPath or other str
+ The object path whose handler is to be removed
+ :Raises KeyError: if there is no handler registered for exactly that
+ object path.
+ """
+ path = ObjectPath(path)
+ parent, tail = path.rsplit('/', 1)
+
+ self._object_tree_lock.acquire()
+ paths = self._object_paths
+ children = self._object_children
+ try:
+ unused, on_unregister, unused = paths.pop(path)
+
+ while tail:
+ parent = ObjectPath(parent or _ROOT)
+ kids = children.get(parent)
+ if kids is not None:
+ kids.discard(tail)
+ if kids:
+ # parent still has other children, don't delete it
+ break
+ else:
+ del children[parent]
+ parent_on_message, unused, unused = paths[parent]
+ if parent_on_message is not None:
+ # parent is a real object, don't delete it
+ break
+ del paths[parent]
+ # walk upwards
+ parent, tail = parent.rsplit('/', 1)
+ finally:
+ self._object_tree_lock.release()
+
+ if on_unregister is not None:
+ on_unregister(self, path)
+
+ def list_exported_child_objects(self, path):
+ """Return a list of the names of objects exported on this Connection
+ as direct children of the given object path.
+
+ Each name ``n`` returned may be converted to a valid object path using
+ ``dbus.ObjectPath('%s%s%s' % (path, (path != '/' and '/' or ''), n))``.
+ For the purposes of this function, every parent or ancestor of an
+ exported object is considered to be an exported object, even if it's
+ only an object synthesized by the library to support introspection.
+ """
+ return list(self._object_children.get(path, ()))
+
+ def _handle_method_call(self, msg):
+ path = msg.get_path()
+ on_message = None
+ absent = True
+ self._object_tree_lock.acquire()
+ try:
+ try:
+ on_message, on_unregister, fallback = self._object_paths[path]
+ except KeyError:
+ parent, tail = path.rsplit('/', 1)
+ while parent:
+ on_message, on_unregister, fallback \
+ = self._object_paths.get(parent, (None, None, False))
+ if fallback:
+ print "Found fallback handler at %s", parent
+ absent = False
+ break
+ parent, tail = parent.rsplit('/', 1)
+ else:
+ print "Found handler at %s", path
+ absent = False
+ finally:
+ self._object_tree_lock.release()
+
+ if absent:
+ # There's nothing there, and it's not an ancestor of any object
+ # FIXME: Raise UnknownObject once it's specified
+ reply = ErrorMessage(msg,
+ 'org.freedesktop.DBus.Error.UnknownMethod',
+ 'There is no object at %s' % path)
+ self.send_message(reply)
+ elif on_message is None:
+ # It's a synthetic object that's an ancestor of a real object.
+ # It supports Introspect and nothing else
+ reflection_data = _INTROSPECT_DOCTYPE
+ reflection_data += '<node name="%s">\n' % path
+ for kid in self._object_children.get(path, ()):
+ reflection_data += ' <node name="%s"/>\n' % kid
+ reflection_data += '</node>\n'
+ reply = MethodReturnMessage(msg)
+ reply.append(reflection_data, signature='s')
+ self.send_message(reply)
+ else:
+ # It's a real object and can return whatever it likes
+ try:
+ on_message(self, msg)
+ except:
+ logging.basicConfig()
+ _logger.error('Error in message handler:',
+ exc_info=1)
+
+ def _filter(self, message):
+ try:
+ self.__filter(message)
+ except:
+ logging.basicConfig()
+ _logger.error('Internal error while filtering message:',
+ exc_info=1)
+
+ def __filter(self, message):
+ # Step 1. Pass any method replies to DBusPendingCall or
+ # send_with_reply_and_block if they're for us.
+ # - libdbus still does this for us
+
+ # Step 1 1/2. Process the standardized org.freedesktop.DBus.Peer
+ # interface. libdbus does this before any filters, so so will we.
+ # FIXME: while we're using libdbus, this code won't ever run
+
+ if (isinstance(message, MethodCallMessage) and
+ message.get_interface() == PEER_IFACE):
+ member = message.get_member()
+ if member == 'Ping':
+ # send an empty reply
+ reply = MethodReturnMessage(message)
+ elif member == 'GetMachineID':
+ reply = ErrorMessage(message,
+ 'org.freedesktop.DBus.Error.UnknownMethod',
+ 'dbus-python does not yet implement Peer.GetMachineID')
+ else:
+ reply = ErrorMessage(message,
+ 'org.freedesktop.DBus.Error.UnknownMethod',
+ 'Unrecognised Peer method %s' % member)
+ self.send_message(reply)
+ return HANDLER_RESULT_HANDLED
+
+
+ # Step 2a. Check for signals - this filter always ran first
+ # in older dbus-pythons, so it runs first here
+
+ if isinstance(message, SignalMessage):
+ dbus_interface = message.get_interface()
+ path = message.get_path()
+ signal_name = message.get_member()
+
+ for match in self._iter_easy_matches(path, dbus_interface,
+ signal_name):
+ try:
+ match.maybe_handle_message(message)
+ except:
+ logging.basicConfig()
+ _logger.error('Internal error handling D-Bus signal:',
+ exc_info=1)
+
+ # Step 2b. Run user-defined filters
+ for filter in self._filters:
+ try:
+ ret = filter(self, message)
+ except:
+ logging.basicConfig()
+ _logger.error('User-defined message filter raised exception:',
+ exc_info=1)
+ ret = NotImplemented
+ if ret is NotImplemented or ret == HANDLER_RESULT_NOT_YET_HANDLED:
+ continue
+ elif ret is None or ret == HANDLER_RESULT_HANDLED:
+ break
+ elif isinstance(ret, (int, long)):
+ _logger.error('Return from message filter should be None, '
+ 'NotImplemented, '
+ 'dbus.lowlevel.HANDLER_RESULT_HANDLED or '
+ 'dbus.lowlevel.HANDLER_RESULT_NOT_YET_HANDLED, '
+ 'not %r', ret)
+
+ # Step 3. Pass method calls to registered objects at that path
+ if isinstance(message, MethodCallMessage):
+ try:
+ self._handle_method_call(message)
+ except:
+ logging.basicConfig()
+ _logger.error('Internal error handling method call:',
+ exc_info=1)
+
+ # We should be the only ones doing anything with messages now, so...
+ return HANDLER_RESULT_HANDLED
+
+ def add_message_filter(self):
+ self._filters.append(filter)
diff --git a/dbus/data.py b/dbus/data.py
new file mode 100644
index 0000000..08cdf60
--- /dev/null
+++ b/dbus/data.py
@@ -0,0 +1,564 @@
+"""D-Bus data types.
+
+The module isn't called "types" due to the name clash with the top-level
+types module, which is problematic in Scratchbox.
+"""
+
+# Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/>
+#
+# 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.
+
+Copyright holders and licensing are indicated in the source files.
+__all__ = ('ObjectPath', 'ByteArray', 'Signature', 'Byte', 'Boolean',
+ 'Int16', 'UInt16', 'Int32', 'UInt32', 'Int64', 'UInt64',
+ 'Double', 'String', 'Array', 'Struct', 'Dictionary',
+ 'UTF8String')
+
+from sys import maxint
+
+from _dbus_bindings import validate_object_path, validate_signature, \
+ get_signature_iter
+
+
+class _DBusTypeMixin(object):
+ # Base class for D-Bus data types. Must be mixed-in with a class that
+ # allows a _dbus_variant_level attribute.
+ #
+ # Do not use this class, or assume that it exists, outside dbus-python.
+
+ # Slightly odd implementation which deserves a comment:
+ #
+ # Some of the types we want to subtype have a layout which
+ # means we can't use __slots__ and must give them a __dict__. Others
+ # are fine for __slots__. So, we have to make the decision per-subclass.
+ #
+ # Omitting __slots__ here would give all subtypes a __dict__, which would
+ # be a waste of memory for the ones that don't need it (all mutable types,
+ # plus unicode). So we give it no slots, and add either a slot or a
+ # __dict__ (as appropriate) in the subclasses.
+
+ __slots__ = ()
+
+ def __new__(cls, value, variant_level=0):
+ if variant_level < 0:
+ raise ValueError('variant_level must be non-negative')
+ self = super(_DBusTypeMixin, cls).__new__(cls, value)
+ self._dbus_variant_level = variant_level
+ return self
+
+ @property
+ def variant_level(self):
+ """Indicates how many nested Variant containers this object is
+ contained in: if a message's wire format has a variant containing
+ a variant containing an `Int32`, this is represented in Python by an
+ `Int32` object with ``variant_level == 2``.
+ """
+ return self._dbus_variant_level
+
+ def __repr__(self):
+ variant_level = self._dbus_variant_level
+ parent_repr = super(_DBusTypeMixin, self).__repr__()
+ if variant_level:
+ return '%s(%s, variant_level=%d)' % (self.__class__.__name__,
+ parent_repr, variant_level)
+ else:
+ return '%s(%s)' % (self.__class__.__name__, parent_repr)
+
+
+class ByteArray(_DBusTypeMixin, str):
+ """ByteArray is a subtype of str which can be used when you want an
+ efficient immutable representation of a D-Bus byte array (signature 'ay').
+
+ By default, when byte arrays are converted from D-Bus to Python, they
+ come out as a `dbus.Array` of `dbus.Byte`. This is just for symmetry with
+ the other D-Bus types - in practice, what you usually want is the byte
+ array represented as a string, using this class. To get this, pass the
+ ``byte_arrays=True`` keyword argument to any of these methods:
+
+ * any D-Bus method proxy, or ``connect_to_signal``, on the objects returned
+ by `Bus.get_object`
+ * any D-Bus method on a `dbus.Interface`
+ * `dbus.Interface.connect_to_signal`
+ * `Bus.add_signal_receiver`
+
+ Import via::
+
+ from dbus import ByteArray
+
+ Constructor::
+
+ ByteArray(value: str)
+ """
+
+
+class Byte(_DBusTypeMixin, int):
+ """An unsigned byte: a subtype of int, with range restricted to [0, 255].
+
+ A Byte b may be converted to a str of length 1 via str(b) == chr(b).
+
+ Most of the time you don't want to use this class - it mainly exists
+ for symmetry with the other D-Bus types. See `dbus.ByteArray` for a
+ better way to handle arrays of Byte.
+
+ Constructor::
+
+ dbus.Byte(value: integer or str of length 1[, variant_level: integer])
+ """
+
+ def __new__(cls, value=0, variant_level=0):
+ if isinstance(value, str):
+ if len(value) != 1:
+ raise TypeError('A string argument to Byte.__new__() must '
+ 'be a single byte, not %r' % value)
+ value = ord(value)
+ elif not isinstance(value, (int, long)):
+ raise TypeError('Argument to Byte.__new__() must be a str, int '
+ 'or long, not %r' % value)
+
+ if value < 0 or value > 255:
+ raise TypeError('Argument %r to Byte.__new__() not in range(256)'
+ % value)
+
+ return super(Byte, cls).__new__(cls, value, variant_level)
+
+ def __str__(self):
+ return chr(self)
+
+
+class String(_DBusTypeMixin, unicode):
+ """A human-readable string: a subtype of `unicode`, with U+0000 disallowed.
+
+ All strings on D-Bus are required to be valid Unicode; in the "wire
+ protocol" they're transported as UTF-8.
+
+ By default, when strings are converted from D-Bus to Python, they come
+ out as this class. If you prefer to get UTF-8 strings (as instances of
+ a subtype of `str`) or you want to avoid the conversion overhead of
+ going from UTF-8 to Python's internal Unicode representation, see the
+ documentation for `dbus.UTF8String`.
+ """
+ __slots__ = ('_dbus_variant_level',)
+
+ def __new__(cls, value=u'', variant_level=0):
+
+ if isinstance(value, str):
+ try:
+ value = value.decode('utf8')
+ except UnicodeError, e:
+ raise UnicodeError('A str argument to String.__new__ must be '
+ 'UTF-8: %s', e)
+ elif not isinstance(value, unicode):
+ raise TypeError('String.__new__ requires a unicode or UTF-8 str, '
+ 'not %r' % value)
+
+ if u'\0' in value:
+ raise TypeError(r'D-Bus strings cannot contain u"\0", but %r does'
+ % value)
+
+ return super(String, cls).__new__(cls, value, variant_level)
+
+
+class UTF8String(_DBusTypeMixin, str):
+ r"""A human-readable string represented as UTF-8; a subtype of `str`,
+ with '\0' disallowed.
+
+ By default, when byte arrays are converted from D-Bus to Python, they
+ come out as a `dbus.String`, which is a subtype of `unicode`.
+ If you prefer to get UTF-8 strings (as instances of this class) or you
+ want to avoid the conversion overhead of going from UTF-8 to Python's
+ internal Unicode representation, you can pass the ``utf8_strings=True``
+ keyword argument to any of these methods:
+
+ * any D-Bus method proxy, or ``connect_to_signal``, on the objects returned
+ by `Bus.get_object`
+ * any D-Bus method on a `dbus.Interface`
+ * `dbus.Interface.connect_to_signal`
+ * `Bus.add_signal_receiver`
+
+ :Since: 0.80 (in older versions, use dbus.String)
+ """
+
+ def __new__(cls, value='', variant_level=0):
+
+ if isinstance(value, str):
+ try:
+ # evaluating for its side-effect of performing validation
+ value.decode('utf8')
+ except UnicodeError, e:
+ raise UnicodeError('A str argument to UTF8String.__new__ must '
+ 'be UTF-8: %s', e)
+ elif isinstance(value, unicode):
+ value = value.encode('utf8')
+ else:
+ raise TypeError('UTF8String.__new__ requires a unicode or UTF-8 '
+ 'str, not %r' % value)
+
+ if '\0' in value:
+ raise TypeError(r'D-Bus strings cannot contain "\0", but %r does'
+ % value)
+
+ return super(UTF8String, cls).__new__(cls, value, variant_level)
+
+
+class ObjectPath(_DBusTypeMixin, str):
+ """A D-Bus object path, such as '/com/example/MyApp/Documents/abc'.
+
+ ObjectPath is a subtype of str, and object-paths behave like strings.
+ """
+
+ def __new__(cls, value, variant_level=0):
+ if isinstance(value, unicode):
+ value = value.encode('ascii')
+ elif not isinstance(value, str):
+ raise TypeError('ObjectPath.__new__ requires a unicode or '
+ 'str instance, not %r' % value)
+
+ validate_object_path(value)
+
+ return super(ObjectPath, cls).__new__(cls, value, variant_level)
+
+
+class Boolean(_DBusTypeMixin, int):
+ """A boolean, represented as a subtype of `int` (not `bool`, because
+ `bool` cannot be subclassed).
+ """
+
+ __slots__ = ('_dbus_variant_level',)
+
+ def __new__(cls, value=False, variant_level=0):
+ return super(Boolean, cls).__new__(cls, bool(value), variant_level)
+
+ def __repr__(self):
+ variant_level = self._dbus_variant_level
+ bool_repr = self and 'True' or 'False'
+ if variant_level:
+ return '%s(%s, variant_level=%d)' % (self.__class__.__name__,
+ bool_repr, variant_level)
+ else:
+ return '%s(%s)' % (self.__class__.__name__, bool_repr)
+
+
+if maxint >= 0x7FFFFFFFFFFFFFFFL:
+ _I64 = int
+ if maxint >= 0xFFFFFFFFFFFFFFFFL:
+ _U64 = int
+ else:
+ _U64 = long
+else:
+ _I64 = long
+ _U64 = long
+
+class Int16(_DBusTypeMixin, int):
+ """A signed 16-bit integer between -0x8000 and +0x7FFF, represented as a
+ subtype of `int`.
+ """
+
+ __slots__ = ('_dbus_variant_level',)
+
+ def __new__(cls, value=0, variant_level=0):
+ self = super(Int16, cls).__new__(cls, value, variant_level)
+ if self < -0x8000 or self > 0x7FFF:
+ raise OverflowError('Value %r out of range for Int16'
+ % value)
+ return self
+
+class UInt16(_DBusTypeMixin, int):
+ """An unsigned 16-bit integer between 0 and +0xFFFF, represented as a
+ subtype of `int`.
+ """
+
+ __slots__ = ('_dbus_variant_level',)
+
+ def __new__(cls, value=0, variant_level=0):
+ self = super(UInt16, cls).__new__(cls, value, variant_level)
+ if self < 0 or self > 0xFFFF:
+ raise OverflowError('Value %r out of range for UInt16'
+ % value)
+ return self
+
+class Int32(_DBusTypeMixin, int):
+ """A signed 32-bit integer between -0x8000 0000 and +0x7FFF FFFF,
+ represented as a subtype of `int`.
+ """
+
+ __slots__ = ('_dbus_variant_level',)
+
+ def __new__(cls, value=0, variant_level=0):
+ self = super(Int32, cls).__new__(cls, value, variant_level)
+ if self < -0x80000000 or self > 0x7FFFFFFF:
+ raise OverflowError('Value %r out of range for Int32'
+ % value)
+ return self
+
+class UInt32(_DBusTypeMixin, _I64):
+ """An unsigned 32-bit integer between 0 and +0xFFFF FFFF, represented as a
+ subtype of either `int` or `long` (platform-dependent and subject to
+ change).
+ """
+
+ if _I64 is int:
+ __slots__ = ('_dbus_variant_level',)
+
+ def __new__(cls, value=0, variant_level=0):
+ self = super(UInt32, cls).__new__(cls, value, variant_level)
+ if self < 0 or self > 0xFFFFFFFFL:
+ raise OverflowError('Value %r out of range for UInt32'
+ % value)
+ return self
+
+class Int64(_DBusTypeMixin, _I64):
+ """A signed 64-bit integer between -0x8000 0000 0000 0000 and
+ +0x7FFF FFFF FFFF FFFF,
+ represented as a subtype of `int`.
+ """
+
+ if _I64 is int:
+ __slots__ = ('_dbus_variant_level',)
+
+ def __new__(cls, value=0, variant_level=0):
+ self = super(Int64, cls).__new__(cls, value, variant_level)
+ if self < -0x8000000000000000L or self > 0x7FFFFFFFFFFFFFFFL:
+ raise OverflowError('Value %r out of range for Int64'
+ % value)
+ return self
+
+class UInt64(_DBusTypeMixin, _U64):
+ """An unsigned 64-bit integer between 0 and +0xFFFF FFFF FFFF FFFF,
+ represented as a subtype of either `int` or `long` (platform-dependent and
+ subject to change).
+ """
+
+ if _U64 is int:
+ __slots__ = ('_dbus_variant_level',)
+
+ def __new__(cls, value=0, variant_level=0):
+ self = super(UInt64, cls).__new__(cls, value, variant_level)
+ if self < 0 or self > 0xFFFFFFFFFFFFFFFFL:
+ raise OverflowError('Value %r out of range for UInt64'
+ % value)
+ return self
+
+class Double(_DBusTypeMixin, float):
+ """A double-precision floating-point number, represented as a subtype
+ of `float`."""
+
+ __slots__ = ('_dbus_variant_level',)
+
+ def __new__(cls, value=0.0, variant_level=0):
+ return super(Double, cls).__new__(cls, value, variant_level)
+
+class Array(_DBusTypeMixin, list):
+ """An array of items of the same type, implemented as a subtype of
+ list.
+
+ As currently implemented, an Array behaves just like a list, but with
+ the addition of a ``signature`` property set by the constructor;
+ conversion of its items to D-Bus types is only done when it's sent
+ in a Message. This might change in future so validation is done earlier.
+ """
+
+ __slots__ = ('_dbus_variant_level', '_signature')
+
+ @property
+ def signature(self):
+ """The D-Bus signature of each element of this Array (a Signature
+ instance), or None if unspecified. Read-only.
+
+ The signature of an Array ``arr`` is given by ``'a' + arr.signature``.
+
+ If None, when the Array is sent over D-Bus, the signature will be
+ guessed from the first element. Try to avoid this if possible.
+ """
+ return self._signature
+
+ def __new__(cls, iterable=(), signature=None, variant_level=0):
+ """"""
+
+ if signature is not None:
+ signature = Signature(signature)
+
+ if len(tuple(signature)) != 1:
+ raise ValueError("There must be exactly one complete type "
+ "in an Array's signature parameter")
+
+ self = super(Array, cls).__new__(cls, iterable,
+ variant_level=variant_level)
+ self._signature = signature
+ return self
+
+ def __init__(self, iterable=(), signature=None, variant_level=0):
+ super(Array, self).__init__(iterable)
+
+def TypedArray(inner_signature):
+ inner_signature = Signature(inner_signature)
+
+ class Subclass(Array):
+ signature = inner_signature
+
+ def __new__(self, iterable=(), variant_level=0):
+ return super(Subclass, cls).__new__(cls, iterable,
+ signature=inner_signature,
+ variant_level=variant_level)
+
+ def __init__(self, iterable=(), variant_level=0):
+ return super(Subclass, cls).__new__(cls, iterable,
+ signature=inner_signature,
+ variant_level=variant_level)
+
+ Subclass.__name__ = "TypedArray('%s')" % inner_signature
+ return Subclass
+
+
+class Dictionary(_DBusTypeMixin, dict):
+ """A mapping from keys of consistent types to values of consistent types,
+ implemented as a subtype of dict.
+
+ As currently implemented, a Dictionary behaves just like a dict, but with
+ the addition of a ``signature`` property set by the constructor;
+ conversion of its items to D-Bus types is only done when it's sent
+ in a Message. This might change in future so validation is done earlier.
+ """
+
+ __slots__ = ('_dbus_variant_level', '_signature')
+
+ @property
+ def signature(self):
+ """The D-Bus signature of each pair in this Dictionary (a Signature
+ instance), or None if unspecified. Read-only.
+
+ The signature of a Dictionary ``d`` is given by
+ ``'a{' + d.signature + '}'``.
+
+ If None, when the Dictionary is sent over D-Bus, the signature will be
+ guessed from an arbitrarily chosen element. Try to avoid this if
+ possible.
+ """
+ return self._signature
+
+ def __new__(cls, mapping_or_iterable=(), signature=None, variant_level=0):
+ """"""
+
+ if signature is not None:
+ signature = Signature(signature)
+
+ if len(tuple(signature)) != 2:
+ raise ValueError("There must be exactly two complete types "
+ "in a Dictionary's signature parameter")
+
+ # FIXME: there should be a better way to do this
+ if signature[0] not in 'ybnhiutxdsog':
+ raise ValueError("The key type in a Dictionary's signature "
+ "must be a primitive type")
+
+ self = super(Dictionary, cls).__new__(cls, mapping_or_iterable,
+ variant_level=variant_level)
+ self._signature = signature
+ return self
+
+ def __init__(self, mapping_or_iterable=(), signature=None,
+ variant_level=0):
+ super(Dictionary, self).__init__(mapping_or_iterable)
+
+def TypedDictionary(inner_signature):
+ inner_signature = Signature(inner_signature)
+
+ class Subclass(Dictionary):
+ signature = inner_signature
+
+ def __new__(self, iterable=(), variant_level=0):
+ return super(Subclass, cls).__new__(cls, iterable,
+ signature=inner_signature,
+ variant_level=variant_level)
+
+ def __init__(self, iterable=(), variant_level=0):
+ return super(Subclass, cls).__new__(cls, iterable,
+ signature=inner_signature,
+ variant_level=variant_level)
+
+ Subclass.__name__ = "TypedDictionary('%s')" % inner_signature
+ return Subclass
+
+
+class Struct(_DBusTypeMixin, tuple):
+ """A structure containing items of fixed, possibly different types.
+
+ D-Bus structs may not be empty, so the iterable argument is required and
+ may not be an empty iterable.
+ """
+
+ @property
+ def signature(self):
+ """The D-Bus signature of each pair in this Dictionary (a Signature
+ instance), or None if unspecified. Read-only.
+
+ The signature of a Struct ``s`` is given by
+ ``'(' + s.signature + ')'``.
+
+ If None, when the Struct is sent over D-Bus, the signature will be
+ guessed from the elements.
+ """
+ return self._signature
+
+ def __new__(cls, iterable, signature=None, variant_level=0):
+ """"""
+
+ if signature is not None:
+ signature = Signature(signature)
+
+ if len(tuple(signature)) < 1:
+ raise ValueError("D-Bus structs cannot be empty")
+
+ self = super(Struct, cls).__new__(cls, iterable,
+ variant_level=variant_level)
+ self._signature = signature
+ return self
+
+def TypedStruct(inner_signature):
+ inner_signature = Signature(inner_signature)
+
+ class Subclass(Struct):
+ signature = inner_signature
+
+ def __new__(self, iterable=(), variant_level=0):
+ return super(Subclass, cls).__new__(cls, iterable,
+ signature=inner_signature,
+ variant_level=variant_level)
+
+ def __init__(self, iterable=(), variant_level=0):
+ return super(Subclass, cls).__new__(cls, iterable,
+ signature=inner_signature,
+ variant_level=variant_level)
+
+ Subclass.__name__ = "TypedStruct('%s')" % inner_signature
+ return Subclass
+
+
+class Signature(_DBusTypeMixin, str):
+ """A string subclass whose values are restricted to valid D-Bus signatures.
+ When iterated over, instead of individual characters it produces
+ Signature instances representing single complete types."""
+
+ def __new__(cls, signature, variant_level=0):
+ validate_signature(signature)
+ return super(Signature, cls).__new__(cls, signature, variant_level)
+
+ def __iter__(self):
+ return get_signature_iter(self)
diff --git a/dbus/dbus_bindings.py b/dbus/dbus_bindings.py
index a45ca9f..e996e7e 100644
--- a/dbus/dbus_bindings.py
+++ b/dbus/dbus_bindings.py
@@ -20,7 +20,7 @@ from dbus.exceptions import DBusException
class ConnectionError(Exception): pass
# Types
-from dbus.types import *
+from dbus.data import *
# Messages
from _dbus_bindings import Message, SignalMessage as Signal,\
diff --git a/dbus/decorators.py b/dbus/decorators.py
index a5ca281..dce493a 100644
--- a/dbus/decorators.py
+++ b/dbus/decorators.py
@@ -30,9 +30,10 @@ __docformat__ = 'restructuredtext'
import inspect
-from dbus import validate_interface_name, Signature, validate_member_name
-from dbus.lowlevel import SignalMessage
+from dbus import validate_interface_name, validate_member_name
+from dbus.data import Signature
from dbus.exceptions import DBusException
+from dbus.lowlevel import SignalMessage
def method(dbus_interface, in_signature=None, out_signature=None,
diff --git a/dbus/service.py b/dbus/service.py
index df9412a..1d104b9 100644
--- a/dbus/service.py
+++ b/dbus/service.py
@@ -36,8 +36,9 @@ except ImportError:
import dummy_thread as thread
import _dbus_bindings
-from dbus import SessionBus, Signature, Struct, validate_bus_name, \
- validate_object_path, INTROSPECTABLE_IFACE, ObjectPath
+from dbus import SessionBus, validate_bus_name, validate_object_path, \
+ INTROSPECTABLE_INTERFACE
+from dbus.data import Struct, Signature, ObjectPath
from dbus.decorators import method, signal
from dbus.exceptions import DBusException, \
NameExistsException, \
@@ -630,10 +631,10 @@ class Object(Interface):
finally:
self._locations_lock.release()
- def _unregister_cb(self, connection):
+ def _unregister_cb(self, connection, path):
# there's not really enough information to do anything useful here
- _logger.info('Unregistering exported object %r from some path '
- 'on %r', self, connection)
+ _logger.info('Unregistering exported object %r from %r '
+ 'on %r', self, path, connection)
def _message_cb(self, connection, message):
try:
diff --git a/dbus/types.py b/dbus/types.py
index cc4a678..d094bd9 100644
--- a/dbus/types.py
+++ b/dbus/types.py
@@ -1,9 +1,18 @@
+"""dbus.types is deprecated due to a name clash with the types module in the
+standard library, which causes problems in Scratchbox.
+
+For maximum compatibility, import these types from the top-level dbus package
+instead.
+
+:Deprecated: since <unreleased 'purity' branch>."""
+
__all__ = ('ObjectPath', 'ByteArray', 'Signature', 'Byte', 'Boolean',
'Int16', 'UInt16', 'Int32', 'UInt32', 'Int64', 'UInt64',
'Double', 'String', 'Array', 'Struct', 'Dictionary',
'UTF8String')
-from _dbus_bindings import ObjectPath, ByteArray, Signature, Byte,\
- Int16, UInt16, Int32, UInt32,\
- Int64, UInt64, Dictionary, Array, \
- String, Boolean, Double, Struct, UTF8String
+from warnings import warn as _warn
+
+from dbus.data import *
+
+_warn(__doc__, DeprecationWarning, stacklevel=2)
diff --git a/test/cross-test-client.py b/test/cross-test-client.py
index f192167..571098b 100644
--- a/test/cross-test-client.py
+++ b/test/cross-test-client.py
@@ -27,7 +27,6 @@ import logging
import gobject
from dbus import SessionBus, Interface, Array, Byte, Double, Boolean, ByteArray, Int16, Int32, Int64, UInt16, UInt32, UInt64, String, UTF8String, Struct, Dictionary
-from dbus.service import BusName
import dbus.glib
from crosstest import CROSS_TEST_PATH, CROSS_TEST_BUS_NAME,\
@@ -379,13 +378,9 @@ class Client(SignalTestsImpl):
if __name__ == '__main__':
- # FIXME: should be possible to export objects without a bus name
- if 0:
- client = Client(dbus.SessionBus(), '/Client')
- else:
- # the Java cross test's interpretation is that the client should be
- # at /Test too
- client = Client(dbus.SessionBus(), '/Test')
+ # the Java cross test's interpretation is that the client should be
+ # at /Test too
+ client = Client(SessionBus(), '/Test')
gobject.idle_add(client.run_client)
loop = gobject.MainLoop()
diff --git a/test/test-standalone.py b/test/test-standalone.py
index 929fc37..27177a0 100755
--- a/test/test-standalone.py
+++ b/test/test-standalone.py
@@ -37,7 +37,7 @@ pydir = os.path.normpath(os.environ["DBUS_TOP_SRCDIR"])
import _dbus_bindings
import dbus
-import dbus.types as types
+import dbus.data as types
# Check that we're using the right versions
if not dbus.__file__.startswith(pydir):