=== added file 'PY3PORT.rst' --- PY3PORT.rst 1970-01-01 00:00:00 +0000 +++ PY3PORT.rst 2011-12-05 23:15:44 +0000 @@ -0,0 +1,226 @@ +=============================== +Porting python-dbus to Python 3 +=============================== + +This is an experimental port to Python 3.x where x >= 2. There are lots of +great sources for porting C extensions to Python 3, including: + + * http://python3porting.com/toc.html + * http://docs.python.org/howto/cporting.html + * http://docs.python.org/py3k/c-api/index.html + +I also consulted an early take on this port by John Palmieri and David Malcolm +in the context of Fedora: + + * https://bugs.freedesktop.org/show_bug.cgi?id=26420 + +although I have made some different choices. The patches in that tracker +issue also don't cover porting the Python bits (e.g. the test suite), nor the +pygtk -> pygi porting, both which I've also attempted to do in this branch. + +This document outlines my notes and strategies for doing this port. Please +feel free to contact me with any bugs, issues, disagreements, suggestions, +kudos, and curses. + +Barry Warsaw +barry@python.org +2011-11-11 + + +User visible changes +==================== + +You've got some dbus-python code that works great in Python 2. This branch +should generally allow your existing Python 2 code to continue to work +unchanged. There are a few changes you'll notice in Python 2 though:: + + - The minimum supported Python 2 version is 2.6. + - All object reprs are unicodes. This change was made because it greatly + simplifies the implementation and cross-compatibility with Python 3. + - Some values which were ints are now longs. Primarily, this affects the + type of the `variant_level` attributes. + - There is a new `dbus._BytesBase` class, but it is unused in Python 2. + - `dbus.Byte` can be constructed from a 1-character str or unicode object. + - Some exception strings have changed. + - `MethodCallMessage` and `SignalMessage` objects have better reprs now. + +What do you need to do to port that to Python 3? Here are the user visible +changes you should be aware of. Python 3.2 is the minimal required version:: + + - `ByteArray`s must be initialed with bytes objects, not unicodes. Use `b''` + literals in the constructor. This also works in Python 2, where bytes + objects are aliases for 8-bit strings. + - `ByteArray`s now derive from the new `dbus._BytesBase` class instead of + `dbus._StrBase`. + - `dbus.Byte` can be constructed from a 1-character byte or str object. + - `dbus.UTF8String` is gone. Use `dbus.String`. + - `dbus._IntBase` is gone. Use `dbus._LongBase`. + - All longs are now ints, since Python 3 has only a single int type. This + also means that the class hierarchy for the dbus numeric types has changed + (all derive from int in Python 3). + - Some exception strings have changed. + - `dbus.is_py3` is a new flag that is True when running under Python 3. + - `dbus.keywords()` is a new function that helps with writing compatible code + under Python 2 and Python 3. It filters out `utf8_string` arguments under + Python 3. + - `MethodCallMessage` and `SignalMessage` objects have better reprs now. + + +Bytes vs. Strings +================= + +All strings in dbus are defined as UTF-8: + +http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-signatures + +However, the dbus C API accepts `char*` which must be UTF-8 strings NUL +terminated and no other NUL bytes. + +This page describes the mapping between Python types and dbus types: + + http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html#basic-types + +Notice that it maps dbus `string` (`'s'`) to `dbus.String` (unicode) or +`dbus.UTF8String` (str). Also notice that there is no direct dbus equivalent +of Python's bytes type (although dbus does have byte arrays), so I am mapping +dbus strings to unicodes in all cases, and getting rid of `dbus.UTF8String` in +Python 3. I've also added a `dbus._BytesBase` type which is unused in Python +2, but which forms the base class for `dbus.ByteArray` in Python 3. + +In Python 3, object paths (`'o'` or `dbus.ObjectPath`), signatures (`'g'` or +`dbus.Signature`), bus names, interfaces, and methods are all strings. A +previous aborted effort was made to use bytes for these, which at first blush +makes some sense. Practicality beats purity though, and this approach tended +to impose too many changes on user code, and caused lots of difficult to track +down problems, so they are all str (i.e. unicode) in Python 3. + +(As an example, dbus-python's callback dispatching pretty much assumes all +these things are strings. When they are bytes, the fact that `'foo' != b'foo'` +causes dispatch matching to fail in difficult to debug ways. Even bus names +are not immune, since they do things like `bus_name[:1] == ':'` which fails in +multiple ways when `bus_name` is a bytes. For sanity purposes, these are all +unicode strings now, and we just eat the complexity at the C level.) + +I am using `#include `, which exposes the PyBytes API to Python +2.6 and 2.7, and I have converted all internal PyString calls to PyBytes +calls. Where this is inappropriate, we'll use PyUnicode calls explicitly. +E.g. all repr() implementations now return unicodes. Most of these changes +shouldn't be noticed, even in existing Python 2 code. + +Generally, I've left the descriptions and docstrings saying "str" instead of +"unicode" since there's no distinction in Python 3. + +APIs which previously returned PyStrings will usually return PyUnicodes, not +PyBytes. + + +Ints vs. Longs +============== + +Python 3 only has PyLong types; PyInts are gone. For that reason, I've +switched all PyInt calls to use PyLong in both Python 2 and Python 3. Python +3.0 had a nice `` header that aliased PyInt to PyLong, but that's +gone as of Python 3.1, and the minimal required Python 3 version is 3.2. + +In the above page mapping basic types, you'll notice that the Python int type +is mapped to 32-bit signed integers ('i') and the Python long type is mapped +to 64-bit signed integers ('x'). Python 3 doesn't have this distinction, so +that mapping is removed. Use `dbus.UInt32` if you must have 32-bit signed +integers. + +APIs which accepted ints in Python 2 will still do so, but they'll also now +accept longs. These APIs obviously only accept longs in Python 3. + +Long literals in Python code are an interesting thing to have to port. Don't +use them if you want your code to work in both Python versions. + +`dbus._IntBase` is removed in Python 3, you only have `dbus._LongBase`, which +inherits from a Python 3 int (i.e. a PyLong). + + +Macros +====== + +In types-internal.h, I define `PY3K` when `PY_MAJOR_VERSION` >= 3, so you'll +see ifdefs on the former symbol within the C code. + +Python 3 really could use a PY_REFCNT() wrapper for ob_refcnt access. + + +PyCapsule vs. PyCObject +======================= + +`_dbus_bindings._C_API` is an attribute exposed to Python in the module. In +Python 2, this is a PyCObject, but these do not exist in Python >= 3.2, so it +is replaced with a PyCapsules for Python 3. However, since PyCapsules were +only introduced in Python 2.7, and I want to support Python 2.6, PyCObjects +are still used when this module is compiled for Python 2. + + +Python level compatibility +========================== + +`from dbus import is_py3` gives you a flag to check if you must do something +different in Python 3. In general I use this flag to support both versions in +one set of sources, which seems better than trying to use 2to3. + + +Miscellaneous +============= + +The PyDoc_STRVAR() documentation is probably out of date. Once the API +choices have been green-lighted upstream, I'll make a pass through the code to +update them. It might be tricky based on any differences between Python 2 and +Python 3. + +There were a few places where I noticed what might be considered bugs, +unchecked exception conditions, or possible reference count leaks. In these +cases, I've just fixed what I can and hopefully haven't made the situation +worse. + +`dbus_py_variant_level_get()` did not check possible error conditions, nor did +their callers. When `dbus_py_variant_level_get()` encounters an error, it now +returns -1, and callers check this. + +As much as possible, I've refrained from general code cleanups (e.g. 80 +columns), unless it just bugged me too much or I touched the code for reasons +related to the port. I've also tried to stick to existing C code style, +e.g. through the use of pervasive `Py_CLEAR()` calls, comparison against NULL +usually with `!foo`, and such. As Bart Simpson might write on his classroom +blackboard:: + + This is not a rewrite + This is not a rewrite + This is not a rewrite + This is not a rewrite + ... + +and so on. Well, mostly ;). + +I think I fixed a reference leak in `DBusPyServer_set_auth_mechanisms()`. +`PySequence_Fast()` returns a new reference, which wasn't getting decref'd in +any return path. + + - Metaclasses are declared differently in Python 3. I had to use `exec()`. + - `iteritems()` and friends are gone. I dropped the "iter" prefixes. + - `xrange() is gone. I changed them to use `range()`. + - `isSequenceType()` is gone in Python 3, so I use a different idiom there. + - `__next__()` vs. `next()` + - `PyUnicode_FromFormat()` `%V` flag is a clever hack! + - `sys.version_info` is a tuple in Python 2.6, not a namedtuple. i.e. there + is no `sys.version_info.major` + - `PyArg_Parse()`: No 'y' code in Python 2; in Python 3, no equivalent of 'z' + for bytes objects. + + +Open issues +=========== + +Here are a few things that still need to be done, or for which there may be +open questions:: + + - Update all C extension docstrings for accuracy. + - Should `dbus.ByteArray` - which is a subclass of `dbus._BytesBase` which is + itself a subclass of bytes, i.e. str in Python 2 - accept UTF8 encoded + unicode strings? Currently, no, they must be bytes in Python 3, str in + Python 2. === modified file '_dbus_bindings/Makefile.am' --- _dbus_bindings/Makefile.am 2011-05-18 09:37:15 +0000 +++ _dbus_bindings/Makefile.am 2011-12-05 16:25:34 +0000 @@ -1,7 +1,8 @@ pyexec_LTLIBRARIES = _dbus_bindings.la AM_CPPFLAGS = -I$(top_srcdir)/include $(DBUS_CFLAGS) $(PYTHON_INCLUDES) -AM_LDFLAGS = -module -avoid-version -export-symbols-regex init_dbus_bindings \ +AM_LDFLAGS = -module -avoid-version \ + -export-symbols-regex \(PyInit__\|init_\)dbus_bindings \ $(DBUS_LIBS) _dbus_bindings_la_SOURCES = \ abstract.c \ === modified file '_dbus_bindings/abstract.c' --- _dbus_bindings/abstract.c 2010-12-02 17:27:34 +0000 +++ _dbus_bindings/abstract.c 2011-12-05 20:04:28 +0000 @@ -44,17 +44,32 @@ { PyObject *vl_obj; PyObject *key = PyLong_FromVoidPtr(obj); + long variant_level; if (!key) { - return 0; + return -1; } vl_obj = PyDict_GetItem(_dbus_py_variant_levels, key); Py_CLEAR(key); - if (!vl_obj) + if (!vl_obj) { + /* PyDict_GetItem() does not set an exception. This just means that + * there was no entry in the variant dictionary for this object, which + * is equivalent to variant level 0. + */ return 0; - return PyInt_AsLong(vl_obj); + } + variant_level = PyLong_AsLong(vl_obj); + if (variant_level == -1 && PyErr_Occurred()) { + /* variant_level < 0 can never be inserted into the dictionary; see + * dbus_py_variant_level_set() below. The semantics of setting + * variant_level < 0 is to delete it from the dictionary. + */ + return -1; + } + assert(variant_level >= 0); + return variant_level; } dbus_bool_t @@ -76,7 +91,7 @@ } } else { - PyObject *vl_obj = PyInt_FromLong(variant_level); + PyObject *vl_obj = PyLong_FromLong(variant_level); if (!vl_obj) { Py_CLEAR(key); return FALSE; @@ -95,6 +110,11 @@ { PyObject *key, *value; +#ifdef PY3K + if (PyUnicode_CompareWithASCIIString(name, "variant_level")) { + return PyObject_GenericGetAttr(obj, name); + } +#else /* Python 2 */ if (PyString_Check(name)) { Py_INCREF(name); } @@ -116,6 +136,7 @@ } Py_CLEAR(name); +#endif /* PY3K */ key = PyLong_FromVoidPtr(obj); @@ -127,7 +148,7 @@ Py_CLEAR(key); if (!value) - return PyInt_FromLong(0); + return PyLong_FromLong(0); Py_INCREF(value); return value; } @@ -148,6 +169,7 @@ PyErr_Restore(et, ev, etb); } +#ifndef PY3K /* Support code for int subclasses. ================================== */ PyDoc_STRVAR(DBusPythonInt_tp_doc,\ @@ -200,14 +222,14 @@ 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); + my_repr = PyUnicode_FromFormat("%s(%V, variant_level=%ld)", + Py_TYPE(self)->tp_name, + REPRV(parent_repr), + variant_level); } else { - my_repr = PyString_FromFormat("%s(%s)", self->ob_type->tp_name, - PyString_AS_STRING(parent_repr)); + my_repr = PyUnicode_FromFormat("%s(%V)", Py_TYPE(self)->tp_name, + REPRV(parent_repr)); } /* whether my_repr is NULL or not: */ Py_CLEAR(parent_repr); @@ -215,8 +237,7 @@ } PyTypeObject DBusPyIntBase_Type = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "_dbus_bindings._IntBase", sizeof(DBusPyIntBase), 0, @@ -256,6 +277,7 @@ DBusPythonInt_tp_new, /* tp_new */ PyObject_Del, /* tp_free */ }; +#endif /* !PY3K */ /* Support code for float subclasses. ================================ */ @@ -312,14 +334,14 @@ 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); + my_repr = PyUnicode_FromFormat("%s(%V, variant_level=%ld)", + Py_TYPE(self)->tp_name, + REPRV(parent_repr), + variant_level); } else { - my_repr = PyString_FromFormat("%s(%s)", self->ob_type->tp_name, - PyString_AS_STRING(parent_repr)); + my_repr = PyUnicode_FromFormat("%s(%V)", Py_TYPE(self)->tp_name, + REPRV(parent_repr)); } /* whether my_repr is NULL or not: */ Py_CLEAR(parent_repr); @@ -327,8 +349,7 @@ } PyTypeObject DBusPyFloatBase_Type = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "_dbus_bindings._FloatBase", sizeof(DBusPyFloatBase), 0, @@ -368,6 +389,127 @@ DBusPythonFloat_tp_new, /* tp_new */ }; +/* Support code for bytes subclasses ================================== */ + +PyDoc_STRVAR(DBusPythonBytes_tp_doc,\ +"Base class for bytes subclasses with a ``variant_level`` attribute.\n" +"Do not rely on the existence of this class outside dbus-python.\n" +); + +static PyObject * +DBusPythonBytes_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs) +{ + PyObject *self; + long variantness = 0; + static char *argnames[] = {"variant_level", NULL}; + + if (PyTuple_Size(args) > 1) { + PyErr_SetString(PyExc_TypeError, + "__new__ takes at most one positional parameter"); + return NULL; + } + if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple, kwargs, + "|l:__new__", argnames, + &variantness)) return NULL; + if (variantness < 0) { + PyErr_SetString(PyExc_ValueError, + "variant_level must be non-negative"); + return NULL; + } + + self = (PyBytes_Type.tp_new)(cls, args, NULL); + if (self) { + if (!dbus_py_variant_level_set(self, variantness)) { + Py_CLEAR(self); + return NULL; + } + } + return self; +} + +static PyObject * +DBusPythonBytes_tp_repr(PyObject *self) +{ + PyObject *parent_repr = (PyBytes_Type.tp_repr)(self); + PyObject *vl_obj; + PyObject *my_repr; + long variant_level; + + if (!parent_repr) return NULL; + vl_obj = PyObject_GetAttr(self, dbus_py_variant_level_const); + if (!vl_obj) { + Py_CLEAR(parent_repr); + return NULL; + } + variant_level = PyLong_AsLong(vl_obj); + Py_CLEAR(vl_obj); + if (variant_level == -1 && PyErr_Occurred()) { + Py_CLEAR(parent_repr); + return NULL; + } + if (variant_level > 0) { + my_repr = PyUnicode_FromFormat("%s(%V, variant_level=%ld)", + Py_TYPE(self)->tp_name, + REPRV(parent_repr), + variant_level); + } + else { + my_repr = PyUnicode_FromFormat("%s(%V)", Py_TYPE(self)->tp_name, + REPRV(parent_repr)); + } + /* whether my_repr is NULL or not: */ + Py_CLEAR(parent_repr); + return my_repr; +} + +static void +DBusPyBytesBase_tp_dealloc(PyObject *self) +{ + dbus_py_variant_level_clear(self); + (PyBytes_Type.tp_dealloc)(self); +} + +PyTypeObject DBusPyBytesBase_Type = { + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) + "_dbus_bindings._BytesBase", + 0, + 0, + DBusPyBytesBase_tp_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + DBusPythonBytes_tp_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + dbus_py_variant_level_getattro, /* tp_getattro */ + dbus_py_immutable_setattro, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + DBusPythonBytes_tp_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + DEFERRED_ADDRESS(&PyBytes_Type), /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + DBusPythonBytes_tp_new, /* tp_new */ +}; + /* Support code for str subclasses ================================== */ PyDoc_STRVAR(DBusPythonString_tp_doc,\ @@ -396,7 +538,11 @@ return NULL; } - self = (PyString_Type.tp_new)(cls, args, NULL); +#ifdef PY3K + self = (PyUnicode_Type.tp_new)(cls, args, NULL); +#else + self = (PyBytes_Type.tp_new)(cls, args, NULL); +#endif if (self) { if (!dbus_py_variant_level_set(self, variantness)) { Py_CLEAR(self); @@ -409,7 +555,11 @@ static PyObject * DBusPythonString_tp_repr(PyObject *self) { - PyObject *parent_repr = (PyString_Type.tp_repr)(self); +#ifdef PY3K + PyObject *parent_repr = (PyUnicode_Type.tp_repr)(self); +#else + PyObject *parent_repr = (PyBytes_Type.tp_repr)(self); +#endif PyObject *vl_obj; PyObject *my_repr; long variant_level; @@ -420,17 +570,21 @@ Py_CLEAR(parent_repr); return NULL; } - variant_level = PyInt_AsLong(vl_obj); + variant_level = PyLong_AsLong(vl_obj); Py_CLEAR(vl_obj); + if (variant_level == -1 && PyErr_Occurred()) { + Py_CLEAR(parent_repr); + return NULL; + } if (variant_level > 0) { - my_repr = PyString_FromFormat("%s(%s, variant_level=%ld)", - self->ob_type->tp_name, - PyString_AS_STRING(parent_repr), - variant_level); + my_repr = PyUnicode_FromFormat("%s(%V, variant_level=%ld)", + Py_TYPE(self)->tp_name, + REPRV(parent_repr), + variant_level); } else { - my_repr = PyString_FromFormat("%s(%s)", self->ob_type->tp_name, - PyString_AS_STRING(parent_repr)); + my_repr = PyUnicode_FromFormat("%s(%V)", Py_TYPE(self)->tp_name, + REPRV(parent_repr)); } /* whether my_repr is NULL or not: */ Py_CLEAR(parent_repr); @@ -441,12 +595,15 @@ DBusPyStrBase_tp_dealloc(PyObject *self) { dbus_py_variant_level_clear(self); - (PyString_Type.tp_dealloc)(self); +#ifdef PY3K + (PyUnicode_Type.tp_dealloc)(self); +#else + (PyBytes_Type.tp_dealloc)(self); +#endif } PyTypeObject DBusPyStrBase_Type = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "_dbus_bindings._StrBase", 0, 0, @@ -476,7 +633,11 @@ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ - DEFERRED_ADDRESS(&PyString_Type), /* tp_base */ +#ifdef PY3K + DEFERRED_ADDRESS(&PyUnicode_Type), /* tp_base */ +#else + DEFERRED_ADDRESS(&PyBytes_Type), /* tp_base */ +#endif 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ @@ -538,17 +699,21 @@ Py_CLEAR(parent_repr); return NULL; } - variant_level = PyInt_AsLong(vl_obj); + variant_level = PyLong_AsLong(vl_obj); Py_CLEAR(vl_obj); + if (variant_level == -1 && PyErr_Occurred()) { + Py_CLEAR(parent_repr); + return NULL; + } if (variant_level) { - my_repr = PyString_FromFormat("%s(%s, variant_level=%ld)", - self->ob_type->tp_name, - PyString_AS_STRING(parent_repr), - variant_level); + my_repr = PyUnicode_FromFormat("%s(%V, variant_level=%ld)", + Py_TYPE(self)->tp_name, + REPRV(parent_repr), + variant_level); } else { - my_repr = PyString_FromFormat("%s(%s)", self->ob_type->tp_name, - PyString_AS_STRING(parent_repr)); + my_repr = PyUnicode_FromFormat("%s(%V)", Py_TYPE(self)->tp_name, + REPRV(parent_repr)); } /* whether my_repr is NULL or not: */ Py_CLEAR(parent_repr); @@ -563,8 +728,7 @@ } PyTypeObject DBusPyLongBase_Type = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "_dbus_bindings._LongBase", 0, 0, @@ -608,26 +772,37 @@ PyObject *dbus_py_signature_const = NULL; PyObject *dbus_py__dbus_object_path__const = NULL; +#ifdef PY3K +#define INTERN PyUnicode_InternFromString +#else +/* Neither Python 2.6 nor 2.7 define the expected PyBytes_InternFromString + * alias in bytesobject.h. + */ +#define INTERN PyString_InternFromString +#endif + dbus_bool_t dbus_py_init_abstract(void) { _dbus_py_variant_levels = PyDict_New(); if (!_dbus_py_variant_levels) return 0; - dbus_py__dbus_object_path__const = PyString_InternFromString("__dbus_object_path__"); + dbus_py__dbus_object_path__const = INTERN("__dbus_object_path__"); if (!dbus_py__dbus_object_path__const) return 0; - dbus_py_variant_level_const = PyString_InternFromString("variant_level"); + dbus_py_variant_level_const = INTERN("variant_level"); if (!dbus_py_variant_level_const) return 0; - dbus_py_signature_const = PyString_InternFromString("signature"); + dbus_py_signature_const = INTERN("signature"); if (!dbus_py_signature_const) return 0; +#ifndef PY3K DBusPyIntBase_Type.tp_base = &PyInt_Type; if (PyType_Ready(&DBusPyIntBase_Type) < 0) return 0; /* disable the tp_print copied from PyInt_Type, so tp_repr gets called as desired */ DBusPyIntBase_Type.tp_print = NULL; +#endif DBusPyFloatBase_Type.tp_base = &PyFloat_Type; if (PyType_Ready(&DBusPyFloatBase_Type) < 0) return 0; @@ -637,7 +812,15 @@ if (PyType_Ready(&DBusPyLongBase_Type) < 0) return 0; DBusPyLongBase_Type.tp_print = NULL; - DBusPyStrBase_Type.tp_base = &PyString_Type; + DBusPyBytesBase_Type.tp_base = &PyBytes_Type; + if (PyType_Ready(&DBusPyBytesBase_Type) < 0) return 0; + DBusPyBytesBase_Type.tp_print = NULL; + +#ifdef PY3K + DBusPyStrBase_Type.tp_base = &PyUnicode_Type; +#else + DBusPyStrBase_Type.tp_base = &PyBytes_Type; +#endif if (PyType_Ready(&DBusPyStrBase_Type) < 0) return 0; DBusPyStrBase_Type.tp_print = NULL; @@ -648,14 +831,21 @@ dbus_py_insert_abstract_types(PyObject *this_module) { /* PyModule_AddObject steals a ref */ +#ifndef PY3K Py_INCREF(&DBusPyIntBase_Type); +#endif Py_INCREF(&DBusPyLongBase_Type); + Py_INCREF(&DBusPyBytesBase_Type); Py_INCREF(&DBusPyStrBase_Type); Py_INCREF(&DBusPyFloatBase_Type); +#ifndef PY3K if (PyModule_AddObject(this_module, "_IntBase", (PyObject *)&DBusPyIntBase_Type) < 0) return 0; +#endif if (PyModule_AddObject(this_module, "_LongBase", (PyObject *)&DBusPyLongBase_Type) < 0) return 0; + if (PyModule_AddObject(this_module, "_BytesBase", + (PyObject *)&DBusPyBytesBase_Type) < 0) return 0; if (PyModule_AddObject(this_module, "_StrBase", (PyObject *)&DBusPyStrBase_Type) < 0) return 0; if (PyModule_AddObject(this_module, "_FloatBase", === modified file '_dbus_bindings/bus.c' --- _dbus_bindings/bus.c 2010-12-02 16:31:07 +0000 +++ _dbus_bindings/bus.c 2011-12-01 22:17:28 +0000 @@ -42,7 +42,14 @@ dbus_error_init(&error); - if (first && PyString_Check(first)) { + if (first && +#ifdef PY3K + PyUnicode_Check(first) +#else + PyString_Check(first) +#endif + ) + { dbus_bool_t ret; /* It's a custom address. First connect to it, then register. */ @@ -62,7 +69,12 @@ return (PyObject *)self; } - else if (!first || PyInt_Check(first)) { + else if (!first || PyLong_Check(first) +#ifndef PY3K + || PyInt_Check(first) +#endif + ) + { long type; PyObject *libdbusconn; PyObject *new_args; @@ -73,7 +85,7 @@ DBUS_BUS_SESSION. */ if (first) { - type = PyInt_AsLong(first); + type = PyLong_AsLong(first); if (type != DBUS_BUS_SESSION && type != DBUS_BUS_SYSTEM && type != DBUS_BUS_STARTER) { @@ -142,7 +154,11 @@ return DBusPyException_SetString("This connection has no unique name " "yet"); } - return PyString_FromString(name); +#ifdef PY3K + return PyUnicode_FromString(name); +#else + return PyBytes_FromString(name); +#endif } PyObject * === modified file '_dbus_bindings/bytes.c' --- _dbus_bindings/bytes.c 2010-12-02 17:27:34 +0000 +++ _dbus_bindings/bytes.c 2011-12-05 17:56:45 +0000 @@ -60,6 +60,7 @@ PyObject *obj; PyObject *tuple; long variantness = 0; + long my_variant_level; static char *argnames[] = {"variant_level", NULL}; if (PyTuple_Size(args) > 1) { @@ -79,17 +80,30 @@ /* obj is only a borrowed ref for the moment */ obj = PyTuple_GetItem(args, 0); - if (PyString_Check(obj)) { - /* string of length 1, we hope */ - if (PyString_GET_SIZE(obj) != 1) { + if (PyBytes_Check(obj)) { + /* bytes/(Python 2)string of length 1, we hope */ + if (PyBytes_GET_SIZE(obj) != 1) { goto bad_arg; } - obj = PyInt_FromLong((unsigned char)(PyString_AS_STRING(obj)[0])); - } + obj = PyLong_FromLong((unsigned char)(PyBytes_AS_STRING(obj)[0])); + } + else if (PyUnicode_Check(obj)) { + PyObject *obj_as_bytes = PyUnicode_AsUTF8String(obj); + if (!obj_as_bytes) { + return NULL; + } + obj = PyLong_FromLong( + (unsigned char)(PyBytes_AS_STRING(obj_as_bytes)[0])); + Py_CLEAR(obj_as_bytes); + } +#ifndef PY3K else if (PyInt_Check(obj)) { - long i = PyInt_AS_LONG(obj); - - if (obj->ob_type == cls && + long i = PyInt_AsLong(obj); + + if (i == -1 && PyErr_Occurred()) + goto bad_arg; + + if (Py_TYPE(obj) == cls && ((DBusPyIntBase *)obj)->variant_level == variantness) { Py_INCREF(obj); return obj; @@ -98,6 +112,28 @@ /* else make it a new reference */ Py_INCREF(obj); } +#endif + else if (PyLong_Check(obj)) { + long i = PyLong_AsLong(obj); + + if (i == -1 && PyErr_Occurred()) + goto bad_arg; + +#ifdef PY3K + my_variant_level = dbus_py_variant_level_get(obj); + if (my_variant_level < 0) + return NULL; +#else + my_variant_level = ((DBusPyIntBase *)obj)->variant_level; +#endif + if (Py_TYPE(obj) == cls && my_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); + } else { goto bad_arg; } @@ -106,12 +142,16 @@ if (!tuple) return NULL; Py_CLEAR(obj); +#ifdef PY3K + obj = DBusPyLongBase_Type.tp_new(cls, tuple, kwargs); +#else obj = DBusPyIntBase_Type.tp_new(cls, tuple, kwargs); +#endif Py_CLEAR(tuple); return obj; bad_arg: - PyErr_SetString(PyExc_TypeError, "Expected a string of length 1, " + PyErr_SetString(PyExc_TypeError, "Expected a bytes or str of length 1, " "or an int in the range 0-255"); return NULL; bad_range: @@ -122,13 +162,22 @@ static PyObject * Byte_tp_str(PyObject *self) { - unsigned char str[2] = { (unsigned char)PyInt_AS_LONG(self), 0 }; - return PyString_FromStringAndSize((char *)str, 1); + long i = PyLong_AsLong(self); + unsigned char str[2] = { 0, 0 }; + + if (i == -1 && PyErr_Occurred()) { + return NULL; + } + if (i < 0 || i > 255) { + PyErr_SetString(PyExc_RuntimeError, "Integer outside range 0-255"); + return NULL; + } + str[0] = (unsigned char)i; + return PyUnicode_FromStringAndSize((char *)str, 1); } PyTypeObject DBusPyByte_Type = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "dbus.Byte", 0, 0, @@ -158,7 +207,11 @@ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ - DEFERRED_ADDRESS(&PyInt_Type), /* tp_base */ +#ifdef PY3K + DEFERRED_ADDRESS(&DBusPyLongBase_Type), /* tp_base */ +#else + DEFERRED_ADDRESS(&DBusPyIntBase_Type), /* tp_base */ +#endif 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ @@ -194,8 +247,7 @@ ); PyTypeObject DBusPyByteArray_Type = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "dbus.ByteArray", 0, 0, @@ -225,7 +277,11 @@ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ +#ifdef PY3K + DEFERRED_ADDRESS(&DBusPyBytesBase_Type), /* tp_base */ +#else DEFERRED_ADDRESS(&DBusPyStrBase_Type), /* tp_base */ +#endif 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ @@ -238,11 +294,19 @@ dbus_bool_t dbus_py_init_byte_types(void) { +#ifdef PY3K + DBusPyByte_Type.tp_base = &DBusPyLongBase_Type; +#else DBusPyByte_Type.tp_base = &DBusPyIntBase_Type; +#endif if (PyType_Ready(&DBusPyByte_Type) < 0) return 0; DBusPyByte_Type.tp_print = NULL; +#ifdef PY3K + DBusPyByteArray_Type.tp_base = &DBusPyBytesBase_Type; +#else DBusPyByteArray_Type.tp_base = &DBusPyStrBase_Type; +#endif if (PyType_Ready(&DBusPyByteArray_Type) < 0) return 0; DBusPyByteArray_Type.tp_print = NULL; === modified file '_dbus_bindings/conn-methods.c' --- _dbus_bindings/conn-methods.c 2011-05-17 17:06:40 +0000 +++ _dbus_bindings/conn-methods.c 2011-12-01 22:47:17 +0000 @@ -40,7 +40,7 @@ TRACE(conn_obj); DBG("Connection at %p unregistering object path %s", - conn_obj, PyString_AS_STRING((PyObject *)user_data)); + conn_obj, PyBytes_AS_STRING((PyObject *)user_data)); tuple = DBusPyConnection_GetObjectPathHandlers((PyObject *)conn_obj, (PyObject *)user_data); if (!tuple) goto out; if (tuple == Py_None) goto out; @@ -91,7 +91,7 @@ TRACE(conn_obj); DBG("Connection at %p messaging object path %s", - conn_obj, PyString_AS_STRING((PyObject *)user_data)); + conn_obj, PyBytes_AS_STRING((PyObject *)user_data)); DBG_DUMP_MESSAGE(message); tuple = DBusPyConnection_GetObjectPathHandlers((PyObject *)conn_obj, (PyObject *)user_data); if (!tuple || tuple == Py_None) { @@ -562,7 +562,7 @@ ok = dbus_connection_get_unix_fd (self->conn, &fd); Py_END_ALLOW_THREADS if (!ok) Py_RETURN_NONE; - return PyInt_FromLong(fd); + return PyLong_FromLong(fd); } PyDoc_STRVAR(Connection_get_peer_unix_user__doc__, @@ -702,6 +702,7 @@ { dbus_bool_t ok; int fallback = 0; + char *path_bytes; PyObject *callbacks, *path, *tuple, *on_message, *on_unregister = Py_None; static char *argnames[] = {"path", "on_message", "on_unregister", "fallback", NULL}; @@ -724,23 +725,25 @@ mad) to preserve the desirable property that the DBusConnection can never strongly reference the Connection, even indirectly. */ - if (PyString_CheckExact(path)) { + if (PyBytes_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)); + else if (PyBytes_Check(path)) { + path = PyBytes_FromString(PyBytes_AS_STRING(path)); if (!path) return NULL; } else { - PyErr_SetString(PyExc_TypeError, "path must be a str or unicode object"); + PyErr_SetString(PyExc_TypeError, + "path must be a unicode or bytes object"); return NULL; } + path_bytes = PyBytes_AS_STRING(path); - if (!dbus_py_validate_object_path(PyString_AS_STRING(path))) { + if (!dbus_py_validate_object_path(path_bytes)) { Py_CLEAR(path); return NULL; } @@ -756,7 +759,7 @@ 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)); + PyBytes_AS_STRING(path)); Py_CLEAR(tuple); Py_CLEAR(path); return NULL; @@ -775,13 +778,13 @@ Py_BEGIN_ALLOW_THREADS if (fallback) { ok = dbus_connection_register_fallback(self->conn, - PyString_AS_STRING(path), + path_bytes, &_object_path_vtable, path); } else { ok = dbus_connection_register_object_path(self->conn, - PyString_AS_STRING(path), + path_bytes, &_object_path_vtable, path); } @@ -795,7 +798,7 @@ 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)); + path_bytes); Py_END_ALLOW_THREADS return NULL; } @@ -829,6 +832,7 @@ PyObject *kwargs) { dbus_bool_t ok; + char *path_bytes; PyObject *path; PyObject *callbacks; static char *argnames[] = {"path", NULL}; @@ -840,21 +844,23 @@ argnames, &path)) return NULL; /* Take a ref to the path. Same comments as for _register_object_path. */ - if (PyString_CheckExact(path)) { + if (PyBytes_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)); + else if (PyBytes_Check(path)) { + path = PyBytes_FromString(PyBytes_AS_STRING(path)); if (!path) return NULL; } else { - PyErr_SetString(PyExc_TypeError, "path must be a str or unicode object"); + PyErr_SetString(PyExc_TypeError, + "path must be a unicode or bytes object"); return NULL; } + path_bytes = PyBytes_AS_STRING(path); /* Guard against unregistering a handler that doesn't, in fact, exist, or whose unregistration is already in progress. */ @@ -862,7 +868,7 @@ 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)); + path_bytes); Py_CLEAR(path); return NULL; } @@ -897,8 +903,7 @@ */ Py_BEGIN_ALLOW_THREADS - ok = dbus_connection_unregister_object_path(self->conn, - PyString_AS_STRING(path)); + ok = dbus_connection_unregister_object_path(self->conn, path_bytes); Py_END_ALLOW_THREADS if (ok) { @@ -968,7 +973,11 @@ return NULL; } for (kid_ptr = kids; *kid_ptr; kid_ptr++) { +#ifdef PY3K + PyObject *tmp = PyUnicode_FromString(*kid_ptr); +#else PyObject *tmp = PyString_FromString(*kid_ptr); +#endif if (!tmp) { Py_CLEAR(ret); === modified file '_dbus_bindings/conn.c' --- _dbus_bindings/conn.c 2010-12-02 17:27:34 +0000 +++ _dbus_bindings/conn.c 2011-12-05 16:12:22 +0000 @@ -99,7 +99,7 @@ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } else { - long i = PyInt_AsLong(obj); + long i = PyLong_AsLong(obj); DBG("%p: handler %p returned %ld", conn, callable, i); Py_CLEAR(obj); if (i == -1 && PyErr_Occurred()) { @@ -232,6 +232,7 @@ self->has_mainloop = (mainloop != Py_None); self->conn = NULL; self->filters = PyList_New(0); + self->weaklist = NULL; if (!self->filters) goto err; self->object_paths = PyDict_New(); if (!self->object_paths) goto err; @@ -298,7 +299,6 @@ Connection_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs) { DBusConnection *conn; - const char *address; PyObject *address_or_conn; DBusError error; PyObject *self, *mainloop = NULL; @@ -317,7 +317,29 @@ conn = dbus_connection_ref (wrapper->conn); } - else if ((address = PyString_AsString(address_or_conn)) != NULL) { + else if ( +#ifdef PY3K + !PyUnicode_Check(address_or_conn) +#else + !PyBytes_Check(address_or_conn) +#endif + ) + { + PyErr_SetString(PyExc_TypeError, "connection or str expected"); + return NULL; + } + else { + const char *address; +#ifdef PY3K + PyObject *address_as_bytes; + + if (!(address_as_bytes = PyUnicode_AsUTF8String(address_or_conn))) + return NULL; + address = PyBytes_AS_STRING(address_as_bytes); +#else + address = PyBytes_AS_STRING(address_or_conn); +#endif + dbus_error_init(&error); /* We always open a private connection (at the libdbus level). Sharing @@ -326,14 +348,14 @@ conn = dbus_connection_open_private(address, &error); Py_END_ALLOW_THREADS +#ifdef PY3K + Py_CLEAR(address_as_bytes); +#endif if (!conn) { DBusPyException_ConsumeError(&error); return NULL; } } - else { - return NULL; - } self = DBusPyConnection_NewConsumingDBusConnection(cls, conn, mainloop); TRACE(self); @@ -398,14 +420,13 @@ DBG("Connection at %p: freeing self", self); PyErr_Restore(et, ev, etb); - (self->ob_type->tp_free)((PyObject *)self); + (Py_TYPE(self)->tp_free)((PyObject *)self); } /* Connection type object =========================================== */ PyTypeObject DBusPyConnection_Type = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ + PyVarObject_HEAD_INIT(NULL, 0) "_dbus_bindings.Connection", /*tp_name*/ sizeof(Connection), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -425,7 +446,11 @@ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ +#ifdef PY3K + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, +#else Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS | Py_TPFLAGS_BASETYPE, +#endif Connection_tp_doc, /*tp_doc*/ 0, /*tp_traverse*/ 0, /*tp_clear*/ === modified file '_dbus_bindings/containers.c' --- _dbus_bindings/containers.c 2011-05-18 09:37:15 +0000 +++ _dbus_bindings/containers.c 2011-12-02 00:52:37 +0000 @@ -92,18 +92,18 @@ 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); + my_repr = PyUnicode_FromFormat("%s(%V, signature=%V, " + "variant_level=%ld)", + Py_TYPE(&self->super)->tp_name, + REPRV(parent_repr), + REPRV(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)); + my_repr = PyUnicode_FromFormat("%s(%V, signature=%V)", + Py_TYPE(&self->super)->tp_name, + REPRV(parent_repr), + REPRV(sig_repr)); } finally: Py_CLEAR(parent_repr); @@ -127,11 +127,12 @@ variant_level = PyDict_GetItem(kwargs, dbus_py_variant_level_const); } if (variant_level) { - self->variant_level = PyInt_AsLong(variant_level); - if (PyErr_Occurred()) { - Py_CLEAR(self); - return NULL; - } + long new_variant_level = PyLong_AsLong(variant_level); + if (new_variant_level == -1 && PyErr_Occurred()) { + Py_CLEAR(self); + return NULL; + } + self->variant_level = new_variant_level; } return (PyObject *)self; } @@ -166,15 +167,41 @@ } if (signature != Py_None) { - const char *c_str = PyString_AS_STRING(signature); + const char *c_str; + PyObject *signature_as_bytes; + + if ( +#ifdef PY3K + !PyUnicode_Check(signature) +#else + !PyBytes_Check(signature) +#endif + ) + { + PyErr_SetString(PyExc_TypeError, "str expected"); + Py_CLEAR(signature); + return -1; + } +#ifdef PY3K + if (!(signature_as_bytes = PyUnicode_AsUTF8String(signature))) { + Py_CLEAR(signature); + return -1; + } +#else + signature_as_bytes = signature; + Py_INCREF(signature_as_bytes); +#endif + c_str = PyBytes_AS_STRING(signature_as_bytes); if (!dbus_signature_validate_single(c_str, NULL)) { Py_CLEAR(signature); + Py_CLEAR(signature_as_bytes); PyErr_SetString(PyExc_ValueError, "There must be exactly one complete type in " "an Array's signature parameter"); return -1; } + Py_CLEAR(signature_as_bytes); } tuple = Py_BuildValue("(O)", obj); @@ -195,8 +222,7 @@ } PyTypeObject DBusPyArray_Type = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "dbus.Array", sizeof(DBusPyArray), 0, @@ -300,18 +326,18 @@ 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); + my_repr = PyUnicode_FromFormat("%s(%V, signature=%V, " + "variant_level=%ld)", + Py_TYPE(&self->super)->tp_name, + REPRV(parent_repr), + REPRV(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)); + my_repr = PyUnicode_FromFormat("%s(%V, signature=%V)", + Py_TYPE(&self->super)->tp_name, + REPRV(parent_repr), + REPRV(sig_repr)); } finally: Py_CLEAR(parent_repr); @@ -335,11 +361,12 @@ variant_level = PyDict_GetItem(kwargs, dbus_py_variant_level_const); } if (variant_level) { - self->variant_level = PyInt_AsLong(variant_level); - if (PyErr_Occurred()) { - Py_CLEAR(self); - return NULL; - } + long new_variant_level = PyLong_AsLong(variant_level); + if (new_variant_level == -1 && PyErr_Occurred()) { + Py_CLEAR(self); + return NULL; + } + self->variant_level = new_variant_level; } return (PyObject *)self; } @@ -373,8 +400,32 @@ } if (signature != Py_None) { - const char *c_str = PyString_AS_STRING(signature); - + const char *c_str; + PyObject *signature_as_bytes; + + if ( +#ifdef PY3K + !PyUnicode_Check(signature) +#else + !PyBytes_Check(signature) +#endif + ) + { + PyErr_SetString(PyExc_TypeError, "str expected"); + Py_CLEAR(signature); + return -1; + } +#ifdef PY3K + if (!(signature_as_bytes = PyUnicode_AsUTF8String(signature))) { + Py_CLEAR(signature); + return -1; + } +#else + signature_as_bytes = signature; + Py_INCREF(signature_as_bytes); +#endif + + c_str = PyBytes_AS_STRING(signature_as_bytes); switch (c_str[0]) { case DBUS_TYPE_BYTE: case DBUS_TYPE_BOOLEAN: @@ -397,6 +448,7 @@ break; default: Py_CLEAR(signature); + Py_CLEAR(signature_as_bytes); PyErr_SetString(PyExc_ValueError, "The key type in a Dictionary's signature " "must be a primitive type"); @@ -405,11 +457,13 @@ if (!dbus_signature_validate_single(c_str + 1, NULL)) { Py_CLEAR(signature); + Py_CLEAR(signature_as_bytes); PyErr_SetString(PyExc_ValueError, "There must be exactly two complete types in " "a Dictionary's signature parameter"); return -1; } + Py_CLEAR(signature_as_bytes); } tuple = Py_BuildValue("(O)", obj); @@ -431,8 +485,7 @@ } PyTypeObject DBusPyDict_Type = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "dbus.Dictionary", sizeof(DBusPyDict), 0, @@ -523,18 +576,18 @@ 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); + my_repr = PyUnicode_FromFormat("%s(%V, signature=%V, " + "variant_level=%ld)", + Py_TYPE(self)->tp_name, + REPRV(parent_repr), + REPRV(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)); + my_repr = PyUnicode_FromFormat("%s(%V, signature=%V)", + Py_TYPE(self)->tp_name, + REPRV(parent_repr), + REPRV(sig_repr)); } finally: @@ -648,6 +701,11 @@ { PyObject *key, *value; +#ifdef PY3K + if (PyUnicode_CompareWithASCIIString(name, "signature")) { + return dbus_py_variant_level_getattro(obj, name); + } +#else if (PyString_Check(name)) { Py_INCREF(name); } @@ -667,8 +725,8 @@ Py_CLEAR(name); return value; } - Py_CLEAR(name); +#endif key = PyLong_FromVoidPtr(obj); @@ -686,8 +744,7 @@ } PyTypeObject DBusPyStruct_Type = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "dbus.Struct", 0, 0, === modified file '_dbus_bindings/dbus_bindings-internal.h' --- _dbus_bindings/dbus_bindings-internal.h 2011-11-15 16:32:16 +0000 +++ _dbus_bindings/dbus_bindings-internal.h 2011-12-02 00:42:16 +0000 @@ -48,10 +48,34 @@ } \ static inline int type##_CheckExact (PyObject *o) \ { \ - return ((o)->ob_type == &type##_Type); \ + return (Py_TYPE(o) == &type##_Type); \ } +/* This is a clever little trick to make writing the various object reprs + * easier. It relies on Python's %V format option which consumes two + * arguments. The first is a unicode object which may be NULL, and the second + * is a char* which will be used if the first parameter is NULL. + * + * The issue is that we don't know whether the `parent_repr` at the call site + * is a unicode or a bytes (a.k.a. 8-bit string). Under Python 3, it will + * always be a unicode. Under Python 2 it will *probably* be a bytes/str, but + * could potentially be a unicode. So, we check the type, and if it's a + * unicode, we pass that as the first argument, leaving NULL as the second + * argument (since it will never be checked). However, if the object is not a + * unicode, it better be a bytes. In that case, we'll pass NULL as the first + * argument so that the second one gets used, and we'll dig the char* out of + * the bytes object for that purpose. + */ +#define REPRV(obj) \ + (PyUnicode_Check(obj) ? (obj) : NULL), \ + (PyUnicode_Check(obj) ? NULL : PyBytes_AS_STRING(obj)) + + +#ifdef PY3K +PyMODINIT_FUNC PyInit__dbus_bindings(void); +#else PyMODINIT_FUNC init_dbus_bindings(void); +#endif /* conn.c */ extern PyTypeObject DBusPyConnection_Type; @@ -89,9 +113,12 @@ extern PyTypeObject DBusPyByte_Type, DBusPyByteArray_Type; DEFINE_CHECK(DBusPyByteArray) DEFINE_CHECK(DBusPyByte) -extern PyTypeObject DBusPyUTF8String_Type, DBusPyString_Type; +extern PyTypeObject DBusPyString_Type; +DEFINE_CHECK(DBusPyString) +#ifndef PY3K +extern PyTypeObject DBusPyUTF8String_Type; DEFINE_CHECK(DBusPyUTF8String) -DEFINE_CHECK(DBusPyString) +#endif extern PyTypeObject DBusPyDouble_Type; DEFINE_CHECK(DBusPyDouble) extern PyTypeObject DBusPyInt16_Type, DBusPyUInt16_Type; @@ -205,11 +232,13 @@ void _dbus_py_whereami(void); void _dbus_py_dbg_dump_message(DBusMessage *); -# define TRACE(self) do { fprintf(stderr, "TRACE: <%s at %p> in %s, " \ - "%d refs\n", \ - self->ob_type->tp_name, \ - self, __func__, \ - self->ob_refcnt); } while (0) +# define TRACE(self) do { \ + fprintf(stderr, "TRACE: <%s at %p> in %s, " \ + "%d refs\n", \ + self ? Py_TYPE(self)->tp_name : NULL, \ + self, __func__, \ + self ? (int)Py_REFCNT(self) : 0); \ + } while (0) # define DBG(format, ...) fprintf(stderr, "DEBUG: " format "\n",\ __VA_ARGS__) # define DBG_EXC(format, ...) do {DBG(format, __VA_ARGS__); \ === modified file '_dbus_bindings/exceptions.c' --- _dbus_bindings/exceptions.c 2010-12-02 17:39:08 +0000 +++ _dbus_bindings/exceptions.c 2011-12-02 00:42:53 +0000 @@ -37,7 +37,7 @@ return TRUE; } - name = PyString_FromString("dbus.exceptions"); + name = PyUnicode_FromString("dbus.exceptions"); if (name == NULL) { return FALSE; } @@ -81,7 +81,7 @@ } if (error->name) { - PyObject *name = PyString_FromString(error->name); + PyObject *name = PyUnicode_FromString(error->name); int ret; if (!name) === modified file '_dbus_bindings/float.c' --- _dbus_bindings/float.c 2010-12-02 17:27:34 +0000 +++ _dbus_bindings/float.c 2011-12-02 00:52:43 +0000 @@ -40,8 +40,7 @@ #endif PyTypeObject DBusPyDouble_Type = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "dbus.Double", 0, 0, @@ -84,8 +83,7 @@ #ifdef WITH_DBUS_FLOAT32 PyTypeObject DBusPyFloat_Type = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "dbus.Float", 0, 0, === modified file '_dbus_bindings/generic.c' --- _dbus_bindings/generic.c 2010-12-02 16:31:07 +0000 +++ _dbus_bindings/generic.c 2011-12-02 00:43:42 +0000 @@ -38,9 +38,9 @@ { if (op == Py_EQ || op == Py_NE) { if (self == other) { - return PyInt_FromLong(op == Py_EQ); + return PyLong_FromLong(op == Py_EQ); } - return PyInt_FromLong(op == Py_NE); + return PyLong_FromLong(op == Py_NE); } PyErr_SetString(PyExc_TypeError, "Instances of this type are not ordered"); === modified file '_dbus_bindings/int.c' --- _dbus_bindings/int.c 2010-12-02 17:27:34 +0000 +++ _dbus_bindings/int.c 2011-12-02 00:53:09 +0000 @@ -25,6 +25,12 @@ #include "types-internal.h" +#ifdef PY3K +#define INTBASE &DBusPyLongBase_Type +#else +#define INTBASE &DBusPyIntBase_Type +#endif + /* Specific types =================================================== */ /* Boolean, a subclass of DBusPythonInt ============================= */ @@ -65,7 +71,11 @@ } tuple = Py_BuildValue("(i)", PyObject_IsTrue(value) ? 1 : 0); if (!tuple) return NULL; +#ifdef PY3K + self = (DBusPyLongBase_Type.tp_new)(cls, tuple, kwargs); +#else self = (DBusPyIntBase_Type.tp_new)(cls, tuple, kwargs); +#endif Py_CLEAR(tuple); return self; } @@ -73,21 +83,30 @@ static PyObject * Boolean_tp_repr (PyObject *self) { + int is_true = PyObject_IsTrue(self); +#ifdef PY3K + long variant_level = dbus_py_variant_level_get(self); + if (variant_level < 0) + return NULL; +#else long variant_level = ((DBusPyIntBase *)self)->variant_level; +#endif + if (is_true < 0) + return NULL; + if (variant_level > 0) { - return PyString_FromFormat("%s(%s, variant_level=%ld)", - self->ob_type->tp_name, - PyInt_AsLong(self) ? "True" : "False", - variant_level); + return PyUnicode_FromFormat("%s(%s, variant_level=%ld)", + Py_TYPE(self)->tp_name, + is_true ? "True" : "False", + variant_level); } - return PyString_FromFormat("%s(%s)", - self->ob_type->tp_name, - PyInt_AsLong(self) ? "True" : "False"); + return PyUnicode_FromFormat("%s(%s)", + Py_TYPE(self)->tp_name, + is_true ? "True" : "False"); } PyTypeObject DBusPyBoolean_Type = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "dbus.Boolean", 0, 0, @@ -117,7 +136,7 @@ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ - DEFERRED_ADDRESS(&DBusPyIntBase_Type), /* tp_base */ + DEFERRED_ADDRESS(INTBASE), /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ @@ -153,7 +172,7 @@ dbus_int16_t dbus_py_int16_range_check(PyObject *obj) { - long i = PyInt_AsLong (obj); + long i = PyLong_AsLong(obj); if (i == -1 && PyErr_Occurred ()) return -1; if (i < -0x8000 || i > 0x7fff) { PyErr_Format(PyExc_OverflowError, "Value %d out of range for Int16", @@ -166,7 +185,11 @@ static PyObject * Int16_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs) { +#ifdef PY3K + PyObject *self = (DBusPyLongBase_Type.tp_new)(cls, args, kwargs); +#else PyObject *self = (DBusPyIntBase_Type.tp_new)(cls, args, kwargs); +#endif if (self && dbus_py_int16_range_check(self) == -1 && PyErr_Occurred()) { Py_CLEAR(self); return NULL; @@ -175,8 +198,7 @@ } PyTypeObject DBusPyInt16_Type = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "dbus.Int16", 0, 0, @@ -206,7 +228,7 @@ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ - DEFERRED_ADDRESS(&DBusPyIntBase_Type), /* tp_base */ + DEFERRED_ADDRESS(INTBASE), /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ @@ -242,7 +264,7 @@ dbus_uint16_t dbus_py_uint16_range_check(PyObject *obj) { - long i = PyInt_AsLong(obj); + long i = PyLong_AsLong(obj); if (i == -1 && PyErr_Occurred()) return (dbus_uint16_t)(-1); if (i < 0 || i > 0xffff) { PyErr_Format(PyExc_OverflowError, "Value %d out of range for UInt16", @@ -255,9 +277,14 @@ static PyObject * UInt16_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs) { +#ifdef PY3K + PyObject *self = (DBusPyLongBase_Type.tp_new)(cls, args, kwargs); +#else PyObject *self = (DBusPyIntBase_Type.tp_new)(cls, args, kwargs); +#endif if (self && dbus_py_uint16_range_check(self) == (dbus_uint16_t)(-1) - && PyErr_Occurred()) { + && PyErr_Occurred()) + { Py_CLEAR (self); return NULL; } @@ -265,8 +292,7 @@ } PyTypeObject DBusPyUInt16_Type = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "dbus.UInt16", 0, 0, @@ -296,7 +322,7 @@ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ - DEFERRED_ADDRESS(&DBusPyIntBase_Type), /* tp_base */ + DEFERRED_ADDRESS(INTBASE), /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ @@ -332,7 +358,7 @@ dbus_int32_t dbus_py_int32_range_check(PyObject *obj) { - long i = PyInt_AsLong(obj); + long i = PyLong_AsLong(obj); if (i == -1 && PyErr_Occurred()) return -1; if (i < INT32_MIN || i > INT32_MAX) { PyErr_Format(PyExc_OverflowError, "Value %d out of range for Int32", @@ -345,7 +371,11 @@ static PyObject * Int32_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs) { +#ifdef PY3K + PyObject *self = (DBusPyLongBase_Type.tp_new)(cls, args, kwargs); +#else PyObject *self = (DBusPyIntBase_Type.tp_new)(cls, args, kwargs); +#endif if (self && dbus_py_int32_range_check(self) == -1 && PyErr_Occurred()) { Py_CLEAR(self); return NULL; @@ -354,8 +384,7 @@ } PyTypeObject DBusPyInt32_Type = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "dbus.Int32", 0, 0, @@ -385,7 +414,7 @@ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ - DEFERRED_ADDRESS(&DBusPyIntBase_Type), /* tp_base */ + DEFERRED_ADDRESS(INTBASE), /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ @@ -456,8 +485,7 @@ } PyTypeObject DBusPyUInt32_Type = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "dbus.UInt32", 0, 0, @@ -567,8 +595,7 @@ } PyTypeObject DBusPyInt64_Type = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "dbus.Int64", 0, 0, @@ -674,8 +701,7 @@ } PyTypeObject DBusPyUInt64_Type = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "dbus.UInt64", 0, 0, @@ -718,17 +744,17 @@ dbus_bool_t dbus_py_init_int_types(void) { - DBusPyInt16_Type.tp_base = &DBusPyIntBase_Type; + DBusPyInt16_Type.tp_base = INTBASE; 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; + DBusPyUInt16_Type.tp_base = INTBASE; if (PyType_Ready(&DBusPyUInt16_Type) < 0) return 0; DBusPyUInt16_Type.tp_print = NULL; - DBusPyInt32_Type.tp_base = &DBusPyIntBase_Type; + DBusPyInt32_Type.tp_base = INTBASE; if (PyType_Ready(&DBusPyInt32_Type) < 0) return 0; DBusPyInt32_Type.tp_print = NULL; @@ -745,6 +771,11 @@ if (PyType_Ready(&DBusPyUInt64_Type) < 0) return 0; DBusPyUInt64_Type.tp_print = NULL; #endif + + DBusPyBoolean_Type.tp_base = INTBASE; + if (PyType_Ready(&DBusPyBoolean_Type) < 0) return 0; + DBusPyBoolean_Type.tp_print = NULL; + return 1; } === modified file '_dbus_bindings/libdbusconn.c' --- _dbus_bindings/libdbusconn.c 2010-12-02 17:27:34 +0000 +++ _dbus_bindings/libdbusconn.c 2011-12-02 00:51:55 +0000 @@ -73,12 +73,11 @@ } PyErr_Restore(et, ev, etb); - (self->ob_type->tp_free)((PyObject *) self); + (Py_TYPE(self)->tp_free)((PyObject *) self); } PyTypeObject DBusPyLibDBusConnection_Type = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ + PyVarObject_HEAD_INIT(NULL, 0) "_dbus_bindings._LibDBusConnection", sizeof(DBusPyLibDBusConnection), 0, /*tp_itemsize*/ === modified file '_dbus_bindings/mainloop.c' --- _dbus_bindings/mainloop.c 2010-12-02 17:27:34 +0000 +++ _dbus_bindings/mainloop.c 2011-12-02 00:52:12 +0000 @@ -59,8 +59,7 @@ } static PyTypeObject NativeMainLoop_Type = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "dbus.mainloop.NativeMainLoop", sizeof(NativeMainLoop), 0, === modified file '_dbus_bindings/message-append.c' --- _dbus_bindings/message-append.c 2011-11-15 13:33:27 +0000 +++ _dbus_bindings/message-append.c 2011-12-05 19:55:41 +0000 @@ -38,9 +38,14 @@ static long get_variant_level(PyObject *obj) { - if (DBusPyIntBase_Check(obj)) { + if (DBusPyString_Check(obj)) { + return ((DBusPyString *)obj)->variant_level; + } +#ifndef PY3K + else if (DBusPyIntBase_Check(obj)) { return ((DBusPyIntBase *)obj)->variant_level; } +#endif else if (DBusPyFloatBase_Check(obj)) { return ((DBusPyFloatBase *)obj)->variant_level; } @@ -50,10 +55,8 @@ 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) || + DBusPyBytesBase_Check(obj) || DBusPyStrBase_Check(obj) || DBusPyStruct_Check(obj)) { return dbus_py_variant_level_get(obj); @@ -143,7 +146,7 @@ PyObject *magic_attr = PyObject_GetAttr(obj, dbus_py__dbus_object_path__const); if (magic_attr) { - if (PyString_Check(magic_attr)) { + if (PyUnicode_Check(magic_attr) || PyBytes_Check(magic_attr)) { return magic_attr; } else { @@ -163,6 +166,12 @@ } } +#ifdef PY3K +#define FROMSTRING PyUnicode_FromString +#else +#define FROMSTRING PyBytes_FromString +#endif + /* Return a new reference. If the object is a variant and variant_level_ptr * is not NULL, put the variant level in the variable pointed to, and * return the contained type instead of "v". */ @@ -171,15 +180,19 @@ { PyObject *magic_attr; long variant_level = get_variant_level(obj); + + if (variant_level < 0) + return NULL; + if (variant_level_ptr) { *variant_level_ptr = variant_level; } else if (variant_level > 0) { - return PyString_FromString(DBUS_TYPE_VARIANT_AS_STRING); + return FROMSTRING(DBUS_TYPE_VARIANT_AS_STRING); } if (obj == Py_True || obj == Py_False) { - return PyString_FromString(DBUS_TYPE_BOOLEAN_AS_STRING); + return FROMSTRING(DBUS_TYPE_BOOLEAN_AS_STRING); } magic_attr = get_object_path(obj); @@ -187,61 +200,84 @@ return NULL; if (magic_attr != Py_None) { Py_CLEAR(magic_attr); - return PyString_FromString(DBUS_TYPE_OBJECT_PATH_AS_STRING); + return FROMSTRING(DBUS_TYPE_OBJECT_PATH_AS_STRING); } Py_CLEAR(magic_attr); /* Ordering is important: some of these are subclasses of each other. */ +#ifdef PY3K + if (PyLong_Check(obj)) { + if (DBusPyInt64_Check(obj)) + return PyUnicode_FromString(DBUS_TYPE_INT64_AS_STRING); + else if (DBusPyUInt32_Check(obj)) + return PyUnicode_FromString(DBUS_TYPE_UINT32_AS_STRING); + else if (DBusPyUInt64_Check(obj)) + return PyUnicode_FromString(DBUS_TYPE_UINT64_AS_STRING); + else if (DBusPyInt16_Check(obj)) + return PyUnicode_FromString(DBUS_TYPE_INT16_AS_STRING); + else if (DBusPyInt32_Check(obj)) + return PyUnicode_FromString(DBUS_TYPE_INT32_AS_STRING); + else if (DBusPyByte_Check(obj)) + return PyUnicode_FromString(DBUS_TYPE_BYTE_AS_STRING); + else if (DBusPyUInt16_Check(obj)) + return PyUnicode_FromString(DBUS_TYPE_UINT16_AS_STRING); + else if (DBusPyBoolean_Check(obj)) + return PyUnicode_FromString(DBUS_TYPE_BOOLEAN_AS_STRING); + else + return PyUnicode_FromString(DBUS_TYPE_INT64_AS_STRING); + } +#else /* !PY3K */ if (PyInt_Check(obj)) { if (DBusPyInt16_Check(obj)) - return PyString_FromString(DBUS_TYPE_INT16_AS_STRING); + return PyBytes_FromString(DBUS_TYPE_INT16_AS_STRING); else if (DBusPyInt32_Check(obj)) - return PyString_FromString(DBUS_TYPE_INT32_AS_STRING); + return PyBytes_FromString(DBUS_TYPE_INT32_AS_STRING); else if (DBusPyByte_Check(obj)) - return PyString_FromString(DBUS_TYPE_BYTE_AS_STRING); + return PyBytes_FromString(DBUS_TYPE_BYTE_AS_STRING); else if (DBusPyUInt16_Check(obj)) - return PyString_FromString(DBUS_TYPE_UINT16_AS_STRING); + return PyBytes_FromString(DBUS_TYPE_UINT16_AS_STRING); else if (DBusPyBoolean_Check(obj)) - return PyString_FromString(DBUS_TYPE_BOOLEAN_AS_STRING); + return PyBytes_FromString(DBUS_TYPE_BOOLEAN_AS_STRING); else - return PyString_FromString(DBUS_TYPE_INT32_AS_STRING); + return PyBytes_FromString(DBUS_TYPE_INT32_AS_STRING); } else if (PyLong_Check(obj)) { if (DBusPyInt64_Check(obj)) - return PyString_FromString(DBUS_TYPE_INT64_AS_STRING); + return PyBytes_FromString(DBUS_TYPE_INT64_AS_STRING); else if (DBusPyUInt32_Check(obj)) - return PyString_FromString(DBUS_TYPE_UINT32_AS_STRING); + return PyBytes_FromString(DBUS_TYPE_UINT32_AS_STRING); else if (DBusPyUInt64_Check(obj)) - return PyString_FromString(DBUS_TYPE_UINT64_AS_STRING); + return PyBytes_FromString(DBUS_TYPE_UINT64_AS_STRING); else - return PyString_FromString(DBUS_TYPE_INT64_AS_STRING); + return PyBytes_FromString(DBUS_TYPE_INT64_AS_STRING); } +#endif /* PY3K */ else if (PyUnicode_Check(obj)) - return PyString_FromString(DBUS_TYPE_STRING_AS_STRING); + return FROMSTRING(DBUS_TYPE_STRING_AS_STRING); #if defined(DBUS_TYPE_UNIX_FD) else if (DBusPyUnixFd_Check(obj)) - return PyString_FromString(DBUS_TYPE_UNIX_FD_AS_STRING); + return FROMSTRING(DBUS_TYPE_UNIX_FD_AS_STRING); #endif else if (PyFloat_Check(obj)) { #ifdef WITH_DBUS_FLOAT32 if (DBusPyDouble_Check(obj)) - return PyString_FromString(DBUS_TYPE_DOUBLE_AS_STRING); + return FROMSTRING(DBUS_TYPE_DOUBLE_AS_STRING); else if (DBusPyFloat_Check(obj)) - return PyString_FromString(DBUS_TYPE_FLOAT_AS_STRING); + return FROMSTRING(DBUS_TYPE_FLOAT_AS_STRING); else #endif - return PyString_FromString(DBUS_TYPE_DOUBLE_AS_STRING); + return FROMSTRING(DBUS_TYPE_DOUBLE_AS_STRING); } - else if (PyString_Check(obj)) { + else if (PyBytes_Check(obj)) { if (DBusPyObjectPath_Check(obj)) - return PyString_FromString(DBUS_TYPE_OBJECT_PATH_AS_STRING); + return FROMSTRING(DBUS_TYPE_OBJECT_PATH_AS_STRING); else if (DBusPySignature_Check(obj)) - return PyString_FromString(DBUS_TYPE_SIGNATURE_AS_STRING); + return FROMSTRING(DBUS_TYPE_SIGNATURE_AS_STRING); else if (DBusPyByteArray_Check(obj)) - return PyString_FromString(DBUS_TYPE_ARRAY_AS_STRING - DBUS_TYPE_BYTE_AS_STRING); + return FROMSTRING(DBUS_TYPE_ARRAY_AS_STRING + DBUS_TYPE_BYTE_AS_STRING); else - return PyString_FromString(DBUS_TYPE_STRING_AS_STRING); + return FROMSTRING(DBUS_TYPE_STRING_AS_STRING); } else if (PyTuple_Check(obj)) { Py_ssize_t len = PyTuple_GET_SIZE(obj); @@ -258,12 +294,12 @@ return NULL; } /* Set the first and last elements of list to be the parentheses */ - item = PyString_FromString(DBUS_STRUCT_BEGIN_CHAR_AS_STRING); + item = FROMSTRING(DBUS_STRUCT_BEGIN_CHAR_AS_STRING); if (PyList_SetItem(list, 0, item) < 0) { Py_CLEAR(list); return NULL; } - item = PyString_FromString(DBUS_STRUCT_END_CHAR_AS_STRING); + item = FROMSTRING(DBUS_STRUCT_END_CHAR_AS_STRING); if (PyList_SetItem(list, len + 1, item) < 0) { Py_CLEAR(list); return NULL; @@ -291,7 +327,7 @@ } item = NULL; } - empty_str = PyString_FromString(""); + empty_str = FROMSTRING(""); if (!empty_str) { /* really shouldn't happen */ Py_CLEAR(list); @@ -305,12 +341,25 @@ } else if (PyList_Check(obj)) { PyObject *tmp; - PyObject *ret = PyString_FromString(DBUS_TYPE_ARRAY_AS_STRING); + PyObject *ret = FROMSTRING(DBUS_TYPE_ARRAY_AS_STRING); if (!ret) return NULL; - if (DBusPyArray_Check(obj) && PyString_Check(((DBusPyArray *)obj)->signature)) { +#ifdef PY3K + if (DBusPyArray_Check(obj) && + PyUnicode_Check(((DBusPyArray *)obj)->signature)) + { + PyObject *concat = PyUnicode_Concat( + ret, ((DBusPyArray *)obj)->signature); + Py_CLEAR(ret); + return concat; + } +#else + if (DBusPyArray_Check(obj) && + PyString_Check(((DBusPyArray *)obj)->signature)) + { PyString_Concat(&ret, ((DBusPyArray *)obj)->signature); return ret; } +#endif if (PyList_GET_SIZE(obj) == 0) { /* No items, so fail. Or should we guess "av"? */ PyErr_SetString(PyExc_ValueError, "Unable to guess signature " @@ -320,23 +369,46 @@ tmp = PyList_GetItem(obj, 0); tmp = _signature_string_from_pyobject(tmp, NULL); if (!tmp) return NULL; +#ifdef PY3K + { + PyObject *concat = PyUnicode_Concat(ret, tmp); + Py_CLEAR(ret); + Py_CLEAR(tmp); + return concat; + } +#else PyString_ConcatAndDel(&ret, tmp); return ret; +#endif } else if (PyDict_Check(obj)) { PyObject *key, *value, *keysig, *valuesig; 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); +#ifdef PY3K + if (DBusPyDict_Check(obj) && + PyUnicode_Check(((DBusPyDict *)obj)->signature)) + { + return PyUnicode_FromFormat((DBUS_TYPE_ARRAY_AS_STRING + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + "%U" + DBUS_DICT_ENTRY_END_CHAR_AS_STRING), + ((DBusPyDict *)obj)->signature); + } +#else + if (DBusPyDict_Check(obj) && + PyBytes_Check(((DBusPyDict *)obj)->signature)) + { + const char *sig = PyBytes_AS_STRING(((DBusPyDict *)obj)->signature); - return PyString_FromFormat((DBUS_TYPE_ARRAY_AS_STRING - DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING - "%s" - DBUS_DICT_ENTRY_END_CHAR_AS_STRING), - sig); + return PyBytes_FromFormat((DBUS_TYPE_ARRAY_AS_STRING + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + "%s" + DBUS_DICT_ENTRY_END_CHAR_AS_STRING), + sig); } +#endif if (!PyDict_Next(obj, &pos, &key, &value)) { /* No items, so fail. Or should we guess "a{vv}"? */ PyErr_SetString(PyExc_ValueError, "Unable to guess signature " @@ -346,12 +418,20 @@ keysig = _signature_string_from_pyobject(key, NULL); valuesig = _signature_string_from_pyobject(value, NULL); if (keysig && valuesig) { - ret = PyString_FromFormat((DBUS_TYPE_ARRAY_AS_STRING - DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING - "%s%s" - DBUS_DICT_ENTRY_END_CHAR_AS_STRING), - PyString_AS_STRING(keysig), - PyString_AS_STRING(valuesig)); +#ifdef PY3K + ret = PyUnicode_FromFormat((DBUS_TYPE_ARRAY_AS_STRING + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + "%U%U" + DBUS_DICT_ENTRY_END_CHAR_AS_STRING), + keysig, valuesig); +#else + ret = PyBytes_FromFormat((DBUS_TYPE_ARRAY_AS_STRING + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + "%s%s" + DBUS_DICT_ENTRY_END_CHAR_AS_STRING), + PyBytes_AS_STRING(keysig), + PyBytes_AS_STRING(valuesig)); +#endif } Py_CLEAR(keysig); Py_CLEAR(valuesig); @@ -360,7 +440,7 @@ else { PyErr_Format(PyExc_TypeError, "Don't know how which D-Bus type " "to use to encode type \"%s\"", - obj->ob_type->tp_name); + Py_TYPE(obj)->tp_name); return NULL; } } @@ -403,7 +483,14 @@ DBG("%s", "Message_guess_signature: failed"); return NULL; } - if (!PyString_Check(tmp) || PyString_GET_SIZE(tmp) < 2) { + if (PyUnicode_Check(tmp)) { + PyObject *as_bytes = PyUnicode_AsUTF8String(tmp); + Py_CLEAR(tmp); + if (!as_bytes) + return NULL; + tmp = as_bytes; + } + if (!PyBytes_Check(tmp) || PyBytes_GET_SIZE(tmp) < 2) { PyErr_SetString(PyExc_RuntimeError, "Internal error: " "_signature_string_from_pyobject returned " "a bad result"); @@ -411,10 +498,10 @@ return NULL; } ret = PyObject_CallFunction((PyObject *)&DBusPySignature_Type, "(s#)", - PyString_AS_STRING(tmp) + 1, - PyString_GET_SIZE(tmp) - 2); + PyBytes_AS_STRING(tmp) + 1, + PyBytes_GET_SIZE(tmp) - 2); DBG("Message_guess_signature: returning Signature at %p \"%s\"", ret, - ret ? PyString_AS_STRING(ret) : "(NULL)"); + ret ? PyUnicode_AS_DATA(ret) : "(NULL)"); Py_CLEAR(tmp); return ret; } @@ -450,13 +537,13 @@ } } - if (PyString_Check(obj)) { + if (PyBytes_Check(obj)) { PyObject *unicode; /* Raise TypeError if the string has embedded NULs */ - if (PyString_AsStringAndSize(obj, &s, NULL) < 0) return -1; + if (PyBytes_AsStringAndSize(obj, &s, NULL) < 0) return -1; /* Surely there's a faster stdlib way to validate UTF-8... */ - unicode = PyUnicode_DecodeUTF8(s, PyString_GET_SIZE(obj), NULL); + unicode = PyUnicode_DecodeUTF8(s, PyBytes_GET_SIZE(obj), NULL); if (!unicode) { PyErr_SetString(PyExc_UnicodeError, "String parameters " "to be sent over D-Bus must be valid UTF-8"); @@ -475,9 +562,10 @@ PyObject *utf8 = PyUnicode_AsUTF8String(obj); if (!utf8) return -1; /* Raise TypeError if the string has embedded NULs */ - if (PyString_AsStringAndSize(utf8, &s, NULL) < 0) return -1; + if (PyBytes_AsStringAndSize(utf8, &s, NULL) < 0) return -1; DBG("Performing actual append: string (from unicode) %s", s); if (!dbus_message_iter_append_basic(appender, sig_type, &s)) { + Py_CLEAR(utf8); PyErr_NoMemory(); return -1; } @@ -496,17 +584,32 @@ { unsigned char y; - if (PyString_Check(obj)) { - if (PyString_GET_SIZE(obj) != 1) { + if (PyBytes_Check(obj)) { + if (PyBytes_GET_SIZE(obj) != 1) { PyErr_Format(PyExc_ValueError, "Expected a string of " "length 1 byte, but found %d bytes", - (int) PyString_GET_SIZE(obj)); + (int)PyBytes_GET_SIZE(obj)); return -1; } - y = *(unsigned char *)PyString_AS_STRING(obj); + y = *(unsigned char *)PyBytes_AS_STRING(obj); + } + else if (PyUnicode_Check(obj)) { + PyObject *obj_as_bytes = PyUnicode_AsUTF8String(obj); + + if (!obj_as_bytes) + return -1; + if (PyBytes_GET_SIZE(obj_as_bytes) != 1) { + PyErr_Format(PyExc_ValueError, "Expected a string of " + "length 1 byte, but found %d bytes", + (int)PyBytes_GET_SIZE(obj_as_bytes)); + Py_CLEAR(obj_as_bytes); + return -1; + } + y = *(unsigned char *)PyBytes_AS_STRING(obj_as_bytes); + Py_CLEAR(obj_as_bytes); } else { - long i = PyInt_AsLong(obj); + long i = PyLong_AsLong(obj); if (i == -1 && PyErr_Occurred()) return -1; if (i < 0 || i > 0xff) { @@ -541,12 +644,30 @@ _message_iter_append_unixfd(DBusMessageIter *appender, PyObject *obj) { int fd; + long original_fd; - if (PyInt_Check(obj)) { + if (PyLong_Check(obj)) { + original_fd = PyLong_AsLong(obj); + if (original_fd == -1 && PyErr_Occurred()) + return -1; + if (original_fd < INT_MIN || original_fd > INT_MAX) { + PyErr_Format(PyExc_ValueError, "out of int range: %ld", + original_fd); + return -1; + } + fd = (int)original_fd; + } +#ifndef PY3K + else if (PyInt_Check(obj)) { fd = PyInt_AsLong(obj); - } else if (PyObject_IsInstance(obj, (PyObject*) &DBusPyUnixFd_Type)) { + if (fd == -1 && PyErr_Occurred()) + return -1; + } +#endif + else if (PyObject_IsInstance(obj, (PyObject*) &DBusPyUnixFd_Type)) { fd = dbus_py_unix_fd_get_fd(obj); - } else { + } + else { return -1; } @@ -667,7 +788,7 @@ } /* else leave sig set to NULL. */ - DBG("Opening %c container", container); + DBG("Opening '%c' container", container); if (!dbus_message_iter_open_container(appender, container, sig, &sub_appender)) { PyErr_NoMemory(); @@ -748,7 +869,7 @@ } /* This must be run as cleanup, even on failure. */ - DBG("Closing %c container", container); + DBG("Closing '%c' container", container); if (!dbuspy_message_iter_close_container(appender, &sub_appender, (ret == 0))) { PyErr_NoMemory(); ret = -1; @@ -765,19 +886,19 @@ PyObject *obj) { /* a bit of a faster path for byte arrays that are strings */ - Py_ssize_t len = PyString_GET_SIZE(obj); + Py_ssize_t len = PyBytes_GET_SIZE(obj); const char *s; DBusMessageIter sub; int ret; - s = PyString_AS_STRING(obj); + s = PyBytes_AS_STRING(obj); DBG("%s", "Opening ARRAY container"); if (!dbus_message_iter_open_container(appender, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE_AS_STRING, &sub)) { PyErr_NoMemory(); return -1; } - DBG("Appending fixed array of %d bytes", len); + DBG("Appending fixed array of %d bytes", (int)len); if (dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &s, len)) { ret = 0; } @@ -809,7 +930,16 @@ obj_sig = _signature_string_from_pyobject(obj, &variant_level); if (!obj_sig) return -1; - obj_sig_str = PyString_AsString(obj_sig); + if (PyUnicode_Check(obj_sig)) { + PyObject *obj_sig_as_bytes = PyUnicode_AsUTF8String(obj_sig); + Py_CLEAR(obj_sig); + if (!obj_sig_as_bytes) + return -1; + + obj_sig = obj_sig_as_bytes; + } + + obj_sig_str = PyBytes_AsString(obj_sig); if (!obj_sig_str) return -1; if (variant_level < 1) { @@ -1027,7 +1157,7 @@ if (sig_type == DBUS_TYPE_DICT_ENTRY) ret = _message_iter_append_multi(appender, sig_iter, DBUS_TYPE_DICT_ENTRY, obj); - else if (sig_type == DBUS_TYPE_BYTE && PyString_Check(obj)) + else if (sig_type == DBUS_TYPE_BYTE && PyBytes_Check(obj)) ret = _message_iter_append_string_as_byte_array(appender, obj); else ret = _message_iter_append_multi(appender, sig_iter, @@ -1103,8 +1233,20 @@ if (!signature) { DBG("%s", "No signature for message, guessing..."); signature_obj = dbus_py_Message_guess_signature(NULL, args); - if (!signature_obj) return NULL; - signature = PyString_AS_STRING(signature_obj); + if (!signature_obj) + return NULL; + if (PyUnicode_Check(signature_obj)) { + PyObject *signature_as_bytes; + signature_as_bytes = PyUnicode_AsUTF8String(signature_obj); + Py_CLEAR(signature_obj); + if (!signature_as_bytes) + return NULL; + signature_obj = signature_as_bytes; + } + else { + assert(PyBytes_Check(signature_obj)); + } + signature = PyBytes_AS_STRING(signature_obj); } /* from here onwards, you have to do a goto rather than returning NULL to make sure signature_obj gets freed */ === modified file '_dbus_bindings/message-get-args.c' --- _dbus_bindings/message-get-args.c 2011-05-18 09:49:11 +0000 +++ _dbus_bindings/message-get-args.c 2011-12-05 20:13:41 +0000 @@ -42,9 +42,11 @@ " it's off by default for consistency.\n" "\n" " If false (default), convert them into a dbus.Array of Bytes.\n" +#ifndef PY3K " `utf8_strings` : bool\n" " If true, return D-Bus strings as Python 8-bit strings (of UTF-8).\n" " If false (default), return D-Bus strings as Python unicode objects.\n" +#endif "\n" "Most of the type mappings should be fairly obvious:\n" "\n" @@ -70,7 +72,9 @@ typedef struct { int byte_arrays; +#ifndef PY3K int utf8_strings; +#endif } Message_get_args_options; static PyObject *_message_iter_get_pyobject(DBusMessageIter *iter, @@ -213,7 +217,7 @@ if (variant_level > 0 && type != DBUS_TYPE_VARIANT) { PyObject *variant_level_int; - variant_level_int = PyInt_FromLong(variant_level); + variant_level_int = PyLong_FromLong(variant_level); if (!variant_level_int) { return NULL; } @@ -235,9 +239,12 @@ */ switch (type) { + PyObject *unicode; + case DBUS_TYPE_STRING: DBG("%s", "found a string"); dbus_message_iter_get_basic(iter, &u.s); +#ifndef PY3K if (opts->utf8_strings) { args = Py_BuildValue("(s)", u.s); if (!args) break; @@ -245,15 +252,20 @@ args, kwargs); } else { - args = Py_BuildValue("(N)", PyUnicode_DecodeUTF8(u.s, - strlen(u.s), - NULL)); +#endif + /* Watch out for this call failing. */ + unicode = PyUnicode_DecodeUTF8(u.s, strlen(u.s), NULL); + if (!unicode) + break; + args = Py_BuildValue("(N)", unicode); if (!args) { break; } ret = PyObject_Call((PyObject *)&DBusPyString_Type, args, kwargs); +#ifndef PY3K } +#endif break; case DBUS_TYPE_SIGNATURE: @@ -408,7 +420,11 @@ * for an empty byte-blob... */ u.s = ""; } +#ifdef PY3K + args = Py_BuildValue("(y#)", u.s, (Py_ssize_t)n); +#else args = Py_BuildValue("(s#)", u.s, (Py_ssize_t)n); +#endif if (!args) break; ret = PyObject_Call((PyObject *)&DBusPyByteArray_Type, args, kwargs); @@ -492,8 +508,13 @@ PyObject * dbus_py_Message_get_args_list(Message *self, PyObject *args, PyObject *kwargs) { +#ifdef PY3K + Message_get_args_options opts = { 0 }; + static char *argnames[] = { "byte_arrays", NULL }; +#else Message_get_args_options opts = { 0, 0 }; static char *argnames[] = { "byte_arrays", "utf8_strings", NULL }; +#endif PyObject *list; DBusMessageIter iter; @@ -513,10 +534,16 @@ "arguments"); return NULL; } +#ifdef PY3K + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:get_args_list", + argnames, + &(opts.byte_arrays))) return NULL; +#else if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii:get_args_list", argnames, &(opts.byte_arrays), &(opts.utf8_strings))) return NULL; +#endif if (!self->msg) return DBusPy_RaiseUnusableMessage(); list = PyList_New(0); === modified file '_dbus_bindings/message.c' --- _dbus_bindings/message.c 2010-12-02 17:27:34 +0000 +++ _dbus_bindings/message.c 2011-12-02 22:32:05 +0000 @@ -32,7 +32,7 @@ static inline int Message_Check(PyObject *o) { - return (o->ob_type == &MessageType) + return (Py_TYPE(o) == &MessageType) || PyObject_IsInstance(o, (PyObject *)&MessageType); } @@ -53,7 +53,7 @@ if (self->msg) { dbus_message_unref(self->msg); } - self->ob_type->tp_free((PyObject *)self); + Py_TYPE(self)->tp_free((PyObject *)self); } static PyObject * @@ -115,6 +115,30 @@ return 0; } +static PyObject * +MethodCallMessage_tp_repr(PyObject *self) +{ + DBusMessage *msg = ((Message *)self)->msg; + const char *destination = dbus_message_get_destination(msg); + const char *path = dbus_message_get_path(msg); + const char *interface = dbus_message_get_interface(msg); + const char *member = dbus_message_get_member(msg); + + if (!path) + path = "n/a"; + if (!interface) + interface = "n/a"; + if (!member) + member = "n/a"; + if (!destination) + destination = "n/a"; + + return PyUnicode_FromFormat( + "<%s path: %s, int: %s, member: %s dest: %s>", + Py_TYPE(self)->tp_name, + path, interface, member, destination); +} + PyDoc_STRVAR(MethodReturnMessage_tp_doc, "A method-return message.\n\n" "Constructor::\n\n" " dbus.lowlevel.MethodReturnMessage(method_call: MethodCallMessage)\n"); @@ -169,6 +193,26 @@ return 0; } +static PyObject * +SignalMessage_tp_repr(PyObject *self) +{ + DBusMessage *msg = ((Message *)self)->msg; + const char *path = dbus_message_get_path(msg); + const char *interface = dbus_message_get_interface(msg); + const char *member = dbus_message_get_member(msg); + + if (!path) + path = "n/a"; + if (!interface) + interface = "n/a"; + if (!member) + member = "n/a"; + + return PyUnicode_FromFormat("<%s path: %s, int: %s, member: %s>", + Py_TYPE(self)->tp_name, + path, interface, member); +} + PyDoc_STRVAR(ErrorMessage_tp_doc, "An error message.\n\n" "Constructor::\n\n" " dbus.lowlevel.ErrorMessage(reply_to: Message, error_name: str,\n" @@ -341,7 +385,7 @@ Message_get_type(Message *self, PyObject *unused UNUSED) { if (!self->msg) return DBusPy_RaiseUnusableMessage(); - return PyInt_FromLong(dbus_message_get_type(self->msg)); + return PyLong_FromLong(dbus_message_get_type(self->msg)); } PyDoc_STRVAR(Message_get_serial__doc__, @@ -415,7 +459,7 @@ if (!c_str) { Py_RETURN_NONE; } - return PyString_FromString(c_str); + return PyUnicode_FromString(c_str); } PyDoc_STRVAR(Message_has_member__doc__, @@ -490,7 +534,7 @@ Py_RETURN_NONE; } for (ptr = paths; *ptr; ptr++) { - PyObject *str = PyString_FromString(*ptr); + PyObject *str = PyUnicode_FromString(*ptr); if (!str) { Py_CLEAR(ret); @@ -576,7 +620,7 @@ if (!c_str) { Py_RETURN_NONE; } - return PyString_FromString(c_str); + return PyUnicode_FromString(c_str); } PyDoc_STRVAR(Message_has_sender__doc__, @@ -622,7 +666,7 @@ if (!c_str) { Py_RETURN_NONE; } - return PyString_FromString(c_str); + return PyUnicode_FromString(c_str); } PyDoc_STRVAR(Message_has_destination__doc__, @@ -667,7 +711,7 @@ if (!c_str) { Py_RETURN_NONE; } - return PyString_FromString(c_str); + return PyUnicode_FromString(c_str); } PyDoc_STRVAR(Message_has_interface__doc__, @@ -712,7 +756,7 @@ if (!c_str) { Py_RETURN_NONE; } - return PyString_FromString(c_str); + return PyUnicode_FromString(c_str); } PyDoc_STRVAR(Message_set_error_name__doc__, @@ -808,8 +852,7 @@ }; static PyTypeObject MessageType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ + PyVarObject_HEAD_INIT(NULL, 0) "dbus.lowlevel.Message", /*tp_name*/ sizeof(Message), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -850,8 +893,7 @@ }; static PyTypeObject MethodCallMessageType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ + PyVarObject_HEAD_INIT(NULL, 0) "dbus.lowlevel.MethodCallMessage", /*tp_name*/ 0, /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -860,7 +902,7 @@ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ - 0, /*tp_repr*/ + MethodCallMessage_tp_repr, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ @@ -892,8 +934,7 @@ }; static PyTypeObject MethodReturnMessageType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ + PyVarObject_HEAD_INIT(NULL, 0) "dbus.lowlevel.MethodReturnMessage", /*tp_name*/ 0, /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -934,8 +975,7 @@ }; static PyTypeObject SignalMessageType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ + PyVarObject_HEAD_INIT(NULL, 0) "dbus.lowlevel.SignalMessage", /*tp_name*/ 0, /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -944,7 +984,7 @@ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ - 0, /*tp_repr*/ + SignalMessage_tp_repr, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ @@ -976,8 +1016,7 @@ }; static PyTypeObject ErrorMessageType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ + PyVarObject_HEAD_INIT(NULL, 0) "dbus.lowlevel.ErrorMessage", /*tp_name*/ 0, /*tp_basicsize*/ 0, /*tp_itemsize*/ === modified file '_dbus_bindings/module.c' --- _dbus_bindings/module.c 2011-11-15 16:32:16 +0000 +++ _dbus_bindings/module.c 2011-12-02 22:40:28 +0000 @@ -234,80 +234,108 @@ }; PyMODINIT_FUNC +#ifdef PY3K +PyInit__dbus_bindings(void) +#else init_dbus_bindings(void) +#endif { - PyObject *this_module, *c_api; + PyObject *this_module = NULL, *c_api; static const int API_count = DBUS_BINDINGS_API_COUNT; static _dbus_py_func_ptr dbus_bindings_API[DBUS_BINDINGS_API_COUNT]; +#ifdef PY3K + static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "_dbus_bindings", /* m_name */ + module_doc, /* m_doc */ + -1, /* m_size */ + module_functions, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL /* m_free */ + }; +#endif + dbus_bindings_API[0] = (_dbus_py_func_ptr)&API_count; dbus_bindings_API[1] = (_dbus_py_func_ptr)DBusPyConnection_BorrowDBusConnection; dbus_bindings_API[2] = (_dbus_py_func_ptr)DBusPyNativeMainLoop_New4; default_main_loop = NULL; - if (!dbus_py_init_generic()) return; - if (!dbus_py_init_abstract()) return; - if (!dbus_py_init_signature()) return; - if (!dbus_py_init_int_types()) return; - if (!dbus_py_init_unixfd_type()) return; - if (!dbus_py_init_string_types()) return; - if (!dbus_py_init_float_types()) return; - if (!dbus_py_init_container_types()) return; - if (!dbus_py_init_byte_types()) return; - if (!dbus_py_init_message_types()) return; - if (!dbus_py_init_pending_call()) return; - if (!dbus_py_init_mainloop()) return; - if (!dbus_py_init_libdbus_conn_types()) return; - if (!dbus_py_init_conn_types()) return; - if (!dbus_py_init_server_types()) return; - - this_module = Py_InitModule3("_dbus_bindings", module_functions, module_doc); - if (!this_module) return; - - if (!dbus_py_insert_abstract_types(this_module)) return; - if (!dbus_py_insert_signature(this_module)) return; - if (!dbus_py_insert_int_types(this_module)) return; - if (!dbus_py_insert_unixfd_type(this_module)) return; - if (!dbus_py_insert_string_types(this_module)) return; - if (!dbus_py_insert_float_types(this_module)) return; - if (!dbus_py_insert_container_types(this_module)) return; - if (!dbus_py_insert_byte_types(this_module)) return; - if (!dbus_py_insert_message_types(this_module)) return; - if (!dbus_py_insert_pending_call(this_module)) return; - if (!dbus_py_insert_mainloop_types(this_module)) return; - if (!dbus_py_insert_libdbus_conn_types(this_module)) return; - if (!dbus_py_insert_conn_types(this_module)) return; - if (!dbus_py_insert_server_types(this_module)) return; + if (!dbus_py_init_generic()) goto init_error; + if (!dbus_py_init_abstract()) goto init_error; + if (!dbus_py_init_signature()) goto init_error; + if (!dbus_py_init_int_types()) goto init_error; + if (!dbus_py_init_unixfd_type()) goto init_error; + if (!dbus_py_init_string_types()) goto init_error; + if (!dbus_py_init_float_types()) goto init_error; + if (!dbus_py_init_container_types()) goto init_error; + if (!dbus_py_init_byte_types()) goto init_error; + if (!dbus_py_init_message_types()) goto init_error; + if (!dbus_py_init_pending_call()) goto init_error; + if (!dbus_py_init_mainloop()) goto init_error; + if (!dbus_py_init_libdbus_conn_types()) goto init_error; + if (!dbus_py_init_conn_types()) goto init_error; + if (!dbus_py_init_server_types()) goto init_error; + +#ifdef PY3K + this_module = PyModule_Create(&moduledef); +#else + this_module = Py_InitModule3("_dbus_bindings", + module_functions, module_doc); +#endif + if (!this_module) goto init_error; + + if (!dbus_py_insert_abstract_types(this_module)) goto init_error; + if (!dbus_py_insert_signature(this_module)) goto init_error; + if (!dbus_py_insert_int_types(this_module)) goto init_error; + if (!dbus_py_insert_unixfd_type(this_module)) goto init_error; + if (!dbus_py_insert_string_types(this_module)) goto init_error; + if (!dbus_py_insert_float_types(this_module)) goto init_error; + if (!dbus_py_insert_container_types(this_module)) goto init_error; + if (!dbus_py_insert_byte_types(this_module)) goto init_error; + if (!dbus_py_insert_message_types(this_module)) goto init_error; + if (!dbus_py_insert_pending_call(this_module)) goto init_error; + if (!dbus_py_insert_mainloop_types(this_module)) goto init_error; + if (!dbus_py_insert_libdbus_conn_types(this_module)) goto init_error; + if (!dbus_py_insert_conn_types(this_module)) goto init_error; + if (!dbus_py_insert_server_types(this_module)) goto init_error; if (PyModule_AddStringConstant(this_module, "BUS_DAEMON_NAME", - DBUS_SERVICE_DBUS) < 0) return; + DBUS_SERVICE_DBUS) < 0) goto init_error; if (PyModule_AddStringConstant(this_module, "BUS_DAEMON_PATH", - DBUS_PATH_DBUS) < 0) return; + DBUS_PATH_DBUS) < 0) goto init_error; if (PyModule_AddStringConstant(this_module, "BUS_DAEMON_IFACE", - DBUS_INTERFACE_DBUS) < 0) return; + DBUS_INTERFACE_DBUS) < 0) goto init_error; if (PyModule_AddStringConstant(this_module, "LOCAL_PATH", - DBUS_PATH_LOCAL) < 0) return; + DBUS_PATH_LOCAL) < 0) goto init_error; if (PyModule_AddStringConstant(this_module, "LOCAL_IFACE", - DBUS_INTERFACE_LOCAL) < 0) return; + DBUS_INTERFACE_LOCAL) < 0) goto init_error; if (PyModule_AddStringConstant(this_module, "INTROSPECTABLE_IFACE", - DBUS_INTERFACE_INTROSPECTABLE) < 0) return; + DBUS_INTERFACE_INTROSPECTABLE) < 0) + goto init_error; if (PyModule_AddStringConstant(this_module, "PEER_IFACE", - DBUS_INTERFACE_PEER) < 0) return; + DBUS_INTERFACE_PEER) < 0) goto init_error; if (PyModule_AddStringConstant(this_module, "PROPERTIES_IFACE", - DBUS_INTERFACE_PROPERTIES) < 0) return; + DBUS_INTERFACE_PROPERTIES) < 0) + goto init_error; if (PyModule_AddStringConstant(this_module, "DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER", - DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER) < 0) return; + DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER) < 0) + goto init_error; if (PyModule_AddStringConstant(this_module, "DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER", - DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER) < 0) return; + DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER) < 0) + goto init_error; if (PyModule_AddStringConstant(this_module, "DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE", - DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE) < 0) return; + DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE) < 0) + goto init_error; #define ADD_CONST_VAL(x, v) \ - if (PyModule_AddIntConstant(this_module, x, v) < 0) return; + if (PyModule_AddIntConstant(this_module, x, v) < 0) goto init_error; #define ADD_CONST_PREFIXED(x) ADD_CONST_VAL(#x, DBUS_##x) #define ADD_CONST(x) ADD_CONST_VAL(#x, x) @@ -372,19 +400,34 @@ ADD_CONST_PREFIXED(WATCH_ERROR) if (PyModule_AddStringConstant(this_module, "__docformat__", - "restructuredtext") < 0) return; + "restructuredtext") < 0) goto init_error; if (PyModule_AddStringConstant(this_module, "__version__", - PACKAGE_VERSION) < 0) return; + PACKAGE_VERSION) < 0) goto init_error; if (PyModule_AddIntConstant(this_module, "_python_version", - PY_VERSION_HEX) < 0) return; + PY_VERSION_HEX) < 0) goto init_error; +#ifdef PY3K + c_api = PyCapsule_New((void *)dbus_bindings_API, + PYDBUS_CAPSULE_NAME, NULL); +#else c_api = PyCObject_FromVoidPtr ((void *)dbus_bindings_API, NULL); +#endif if (!c_api) { - return; + goto init_error; } PyModule_AddObject(this_module, "_C_API", c_api); + +#ifdef PY3K + return this_module; + init_error: + Py_CLEAR(this_module); + return NULL; +#else + init_error: + return; +#endif } /* vim:set ft=c cino< sw=4 sts=4 et: */ === modified file '_dbus_bindings/pending-call.c' --- _dbus_bindings/pending-call.c 2010-12-02 17:27:34 +0000 +++ _dbus_bindings/pending-call.c 2011-12-02 22:40:49 +0000 @@ -233,8 +233,7 @@ }; static PyTypeObject PendingCallType = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "dbus.lowlevel.PendingCall", sizeof(PendingCall), 0, === modified file '_dbus_bindings/server.c' --- _dbus_bindings/server.c 2010-12-02 17:27:34 +0000 +++ _dbus_bindings/server.c 2011-12-02 23:05:41 +0000 @@ -85,7 +85,7 @@ DBusPyServer_set_auth_mechanisms(Server *self, PyObject *auth_mechanisms) { - PyObject *fast_seq; + PyObject *fast_seq = NULL, *references = NULL; Py_ssize_t length; Py_ssize_t i; @@ -101,16 +101,27 @@ { const char *list[length + 1]; + if (!(references = PyTuple_New(length))) + goto error; + for (i = 0; i < length; ++i) { - PyObject *am; - - am = PySequence_Fast_GET_ITEM(auth_mechanisms, i); - /* this supports either str or unicode, raising TypeError - * on failure */ - list[i] = PyString_AsString(am); - - if (!list[i]) - return FALSE; + PyObject *am, *am_as_bytes; + + if (!(am = PySequence_Fast_GET_ITEM(auth_mechanisms, i))) + goto error; + + if (PyUnicode_Check(am)) { + if (!(am_as_bytes = PyUnicode_AsUTF8String(am))) + goto error; + } + else { + am_as_bytes = am; + Py_INCREF(am_as_bytes); + } + list[i] = PyBytes_AsString(am_as_bytes); + if (!list[i]) + goto error; + PyTuple_SET_ITEM(references, i, am_as_bytes); } list[length] = NULL; @@ -120,7 +131,13 @@ Py_END_ALLOW_THREADS } + Py_CLEAR(fast_seq); + Py_CLEAR(references); return TRUE; + error: + Py_CLEAR(fast_seq); + Py_CLEAR(references); + return FALSE; } /* Return a new reference to a Python Server or subclass corresponding @@ -385,6 +402,7 @@ self = DBusPyServer_NewConsumingDBusServer(cls, server, conn_class, mainloop, auth_mechanisms); + ((Server *)self)->weaklist = NULL; TRACE(self); return self; @@ -429,7 +447,7 @@ DBG("Server at %p: freeing self", self); PyErr_Restore(et, ev, etb); - (self->ob_type->tp_free)((PyObject *)self); + (Py_TYPE(self)->tp_free)((PyObject *)self); } PyDoc_STRVAR(Server_disconnect__doc__, @@ -462,7 +480,7 @@ address = dbus_server_get_address(self->server); Py_END_ALLOW_THREADS - return PyString_FromString(address); + return PyUnicode_FromString(address); } PyDoc_STRVAR(Server_get_id__doc__, @@ -479,7 +497,7 @@ id = dbus_server_get_id(self->server); Py_END_ALLOW_THREADS - return PyString_FromString(id); + return PyUnicode_FromString(id); } PyDoc_STRVAR(Server_get_is_connected__doc__, @@ -511,8 +529,7 @@ }; PyTypeObject DBusPyServer_Type = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ + PyVarObject_HEAD_INIT(NULL, 0) "_dbus_bindings._Server",/*tp_name*/ sizeof(Server), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -532,7 +549,11 @@ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ +#ifdef PY3K + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, +#else Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS | Py_TPFLAGS_BASETYPE, +#endif Server_tp_doc, /*tp_doc*/ 0, /*tp_traverse*/ 0, /*tp_clear*/ === modified file '_dbus_bindings/signature.c' --- _dbus_bindings/signature.c 2010-12-02 17:27:34 +0000 +++ _dbus_bindings/signature.c 2011-12-05 16:52:25 +0000 @@ -55,14 +55,14 @@ typedef struct { PyObject_HEAD - PyObject *string; + PyObject *bytes; DBusSignatureIter iter; } SignatureIter; static void SignatureIter_tp_dealloc (SignatureIter *self) { - Py_CLEAR(self->string); + Py_CLEAR(self->bytes); PyObject_Del(self); } @@ -73,7 +73,7 @@ PyObject *obj; /* Stop immediately if finished or not correctly initialized */ - if (!self->string) return NULL; + if (!self->bytes) return NULL; sig = dbus_signature_iter_get_signature(&(self->iter)); if (!sig) return PyErr_NoMemory(); @@ -83,7 +83,7 @@ if (!dbus_signature_iter_next(&(self->iter))) { /* mark object as having been finished with */ - Py_CLEAR(self->string); + Py_CLEAR(self->bytes); } return obj; @@ -97,8 +97,7 @@ } static PyTypeObject SignatureIterType = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "_dbus_bindings._SignatureIter", sizeof(SignatureIter), 0, @@ -144,16 +143,30 @@ Signature_tp_iter (PyObject *self) { SignatureIter *iter = PyObject_New(SignatureIter, &SignatureIterType); + PyObject *self_as_bytes; + if (!iter) return NULL; - - if (PyString_AS_STRING (self)[0]) { - Py_INCREF(self); - iter->string = self; - dbus_signature_iter_init(&(iter->iter), PyString_AS_STRING(self)); + iter->bytes = NULL; + +#ifdef PY3K + if (!(self_as_bytes = PyUnicode_AsUTF8String(self))) { + Py_CLEAR(iter); + return NULL; + } +#else + self_as_bytes = self; + Py_INCREF(self_as_bytes); +#endif + + if (PyBytes_GET_SIZE(self_as_bytes) > 0) { + iter->bytes = self_as_bytes; + dbus_signature_iter_init(&(iter->iter), + PyBytes_AS_STRING(self_as_bytes)); } else { /* this is a null string, make a null iterator */ - iter->string = NULL; + iter->bytes = NULL; + Py_CLEAR(self_as_bytes); } return (PyObject *)iter; } @@ -175,8 +188,7 @@ } PyTypeObject DBusPySignature_Type = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "dbus.Signature", 0, 0, @@ -206,7 +218,7 @@ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ - DEFERRED_ADDRESS(&DBusPythonStringType), /* tp_base */ + DEFERRED_ADDRESS(&DBusPyStrBase_Type), /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ === modified file '_dbus_bindings/string.c' --- _dbus_bindings/string.c 2010-12-02 17:27:34 +0000 +++ _dbus_bindings/string.c 2011-12-05 16:14:58 +0000 @@ -26,6 +26,7 @@ #include "types-internal.h" #include +#ifndef PY3K /* UTF-8 string representation ====================================== */ PyDoc_STRVAR(UTF8String_tp_doc, @@ -82,8 +83,7 @@ } PyTypeObject DBusPyUTF8String_Type = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "dbus.UTF8String", 0, 0, @@ -122,6 +122,7 @@ 0, /* tp_alloc */ UTF8String_tp_new, /* tp_new */ }; +#endif /* PY3K */ /* Object path ====================================================== */ @@ -161,8 +162,7 @@ } PyTypeObject DBusPyObjectPath_Type = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "dbus.ObjectPath", 0, 0, @@ -275,14 +275,14 @@ return NULL; } 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); + my_repr = PyUnicode_FromFormat("%s(%V, variant_level=%ld)", + Py_TYPE(self)->tp_name, + REPRV(parent_repr), + ((DBusPyString *)self)->variant_level); } else { - my_repr = PyString_FromFormat("%s(%s)", self->ob_type->tp_name, - PyString_AS_STRING(parent_repr)); + my_repr = PyUnicode_FromFormat("%s(%V)", self->ob_type->tp_name, + REPRV(parent_repr)); } /* whether my_repr is NULL or not: */ Py_CLEAR(parent_repr); @@ -290,8 +290,7 @@ } PyTypeObject DBusPyString_Type = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "dbus.String", sizeof(DBusPyString), 0, @@ -346,18 +345,16 @@ if (PyType_Ready(&DBusPyString_Type) < 0) return 0; DBusPyString_Type.tp_print = NULL; +#ifndef PY3K DBusPyUTF8String_Type.tp_base = &DBusPyStrBase_Type; if (PyType_Ready(&DBusPyUTF8String_Type) < 0) return 0; DBusPyUTF8String_Type.tp_print = NULL; +#endif DBusPyObjectPath_Type.tp_base = &DBusPyStrBase_Type; if (PyType_Ready(&DBusPyObjectPath_Type) < 0) return 0; DBusPyObjectPath_Type.tp_print = NULL; - DBusPyBoolean_Type.tp_base = &DBusPyIntBase_Type; - if (PyType_Ready(&DBusPyBoolean_Type) < 0) return 0; - DBusPyBoolean_Type.tp_print = NULL; - return 1; } @@ -366,12 +363,14 @@ { /* PyModule_AddObject steals a ref */ Py_INCREF(&DBusPyObjectPath_Type); +#ifndef PY3K Py_INCREF(&DBusPyUTF8String_Type); + if (PyModule_AddObject(this_module, "UTF8String", + (PyObject *)&DBusPyUTF8String_Type) < 0) return 0; +#endif 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; === modified file '_dbus_bindings/types-internal.h' --- _dbus_bindings/types-internal.h 2007-09-27 12:57:49 +0000 +++ _dbus_bindings/types-internal.h 2011-12-02 23:26:12 +0000 @@ -26,11 +26,19 @@ #include #include +/* In Python >= 2.6, this aliases PyString to PyBytes. */ +#include +#ifndef PY3K +/* In Python 2.x, we need this to define the type of PyLongObject */ +#include +#endif + #include "dbus_bindings-internal.h" #ifndef DBUS_BINDINGS_TYPES_INTERNAL_H #define DBUS_BINDINGS_TYPES_INTERNAL_H +#ifndef PY3K extern PyTypeObject DBusPyIntBase_Type; DEFINE_CHECK(DBusPyIntBase) @@ -38,6 +46,7 @@ PyIntObject base; long variant_level; } DBusPyIntBase; +#endif extern PyTypeObject DBusPyLongBase_Type; DEFINE_CHECK(DBusPyLongBase) @@ -58,6 +67,9 @@ extern PyTypeObject DBusPyStrBase_Type; DEFINE_CHECK(DBusPyStrBase) +extern PyTypeObject DBusPyBytesBase_Type; +DEFINE_CHECK(DBusPyBytesBase) + dbus_int16_t dbus_py_int16_range_check(PyObject *); dbus_uint16_t dbus_py_uint16_range_check(PyObject *); dbus_int32_t dbus_py_int32_range_check(PyObject *); === modified file '_dbus_bindings/unixfd.c' --- _dbus_bindings/unixfd.c 2011-05-18 10:02:44 +0000 +++ _dbus_bindings/unixfd.c 2011-12-02 23:35:54 +0000 @@ -55,59 +55,102 @@ int fd; } UnixFdObject; +/* Return values: + * -2 - the long value overflows an int + * -1 - Python failed producing a long (or in Python 2 an int) + * 0 - success + * 1 - arg is not a long (or in Python 2 an int) + * + * Or to summarize: + * status < 0 - an error occurred, and a Python exception is set. + * status == 0 - all is okay + * status > 0 - try something else + */ +static int +make_fd(PyObject *arg, long *fd) +{ + if (PyLong_Check(arg)) { + *fd = PyLong_AsLong(arg); + if (*fd == -1 && PyErr_Occurred()) { + return -1; + } + } +#ifndef PY3K + else if (PyInt_Check(arg)) { + *fd = PyInt_AsLong(arg); + if (*fd == -1 && PyErr_Occurred()) { + return -1; + } + } +#endif + else { + return 1; + } + /* Check for int overflow. */ + if (*fd < INT_MIN || *fd > INT_MAX) { + PyErr_Format(PyExc_ValueError, "long value is outside fd range"); + return -2; + } + return 0; +} + static PyObject * UnixFd_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs UNUSED) { UnixFdObject *self = NULL; PyObject *arg; PyObject *fdnumber; - int fd_original, fd; - - if (! PyArg_ParseTuple(args, "O", &arg, NULL)) { - return NULL; - } - - if (PyInt_Check(arg)) { - fd_original = PyInt_AsLong(arg); - fd = dup(fd_original); - if (fd < 0) { - PyErr_Format(PyExc_ValueError, "Invalid file descriptor"); - return NULL; - } - - } else if (PyObject_HasAttrString(arg, "fileno")) { - fdnumber = PyObject_CallMethod(arg, "fileno", NULL); - if (! fdnumber) { - PyErr_Format(PyExc_ValueError, "Argument's fileno() method " - "is not callable"); - return NULL; - } - if (! PyInt_Check(fdnumber)) { - PyErr_Format(PyExc_ValueError, "Argument's fileno() method " - "returned a non-int value"); - return NULL; - } - fd_original = PyInt_AsLong(fdnumber); - Py_DECREF(fdnumber); - fd = dup(fd_original); - if (fd < 0) { - PyErr_Format(PyExc_ValueError, "Invalid file descriptor from fileno()"); - return NULL; - } - - } else { - PyErr_Format(PyExc_ValueError, "Argument is not int and does not " - "implement fileno() method"); - return NULL; - } - + long fd_original; + int fd, status; + + if (!PyArg_ParseTuple(args, "O", &arg, NULL)) { + return NULL; + } + + status = make_fd(arg, &fd_original); + if (status < 0) + return NULL; + + if (status > 0) { + if (PyObject_HasAttrString(arg, "fileno")) { + fdnumber = PyObject_CallMethod(arg, "fileno", NULL); + if (!fdnumber) { + PyErr_Format(PyExc_ValueError, "Argument's fileno() method " + "is not callable"); + return NULL; + } + status = make_fd(fdnumber, &fd_original); + Py_CLEAR(fdnumber); + if (status < 0) + return NULL; + if (status > 0) { + PyErr_Format(PyExc_ValueError, "Argument's fileno() method " + "returned a non-int value"); + return NULL; + } + /* fd_original is all good */ + } + else { + PyErr_Format(PyExc_ValueError, "Argument is not int and does not " + "implement fileno() method"); + return NULL; + } + } self = (UnixFdObject *) cls->tp_alloc(cls, 0); if (!self) return NULL; + /* We know fd_original is good and fits into an int. */ + fd = dup((int)fd_original); + if (fd < 0) { + PyErr_Format(PyExc_ValueError, + "Invalid file descriptor from fileno()"); + Py_CLEAR(self); + return NULL; + } + self->fd = fd; - - return (PyObject *) self; + return (PyObject *)self; } static void @@ -159,8 +202,7 @@ }; PyTypeObject DBusPyUnixFd_Type = { - PyObject_HEAD_INIT(NULL) - 0, + PyVarObject_HEAD_INIT(NULL, 0) "dbus.UnixFd", sizeof(UnixFdObject), 0, === modified file '_dbus_glib_bindings/Makefile.am' --- _dbus_glib_bindings/Makefile.am 2007-01-22 18:26:36 +0000 +++ _dbus_glib_bindings/Makefile.am 2011-12-05 16:25:40 +0000 @@ -3,7 +3,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include $(DBUS_CFLAGS) $(DBUS_GLIB_CFLAGS) \ $(PYTHON_INCLUDES) AM_LDFLAGS = -module -avoid-version \ - -export-symbols-regex init_dbus_glib_bindings \ + -export-symbols-regex \(PyInit__\|init_\)dbus_glib_bindings \ $(DBUS_LIBS) $(DBUS_GLIB_LIBS) _dbus_glib_bindings_la_SOURCES = module.c === modified file '_dbus_glib_bindings/module.c' --- _dbus_glib_bindings/module.c 2010-12-02 16:31:07 +0000 +++ _dbus_glib_bindings/module.c 2011-12-02 23:38:02 +0000 @@ -28,7 +28,11 @@ #include #include +#ifdef PY3K +PyMODINIT_FUNC PyInit__dbus_glib_bindings(void); +#else PyMODINIT_FUNC init_dbus_glib_bindings(void); +#endif #if defined(__GNUC__) # if __GNUC__ >= 3 @@ -170,6 +174,33 @@ {NULL, NULL, 0, NULL} }; +#ifdef PY3K +PyMODINIT_FUNC +PyInit__dbus_glib_bindings(void) +{ + PyObject *this_module; + + static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "_dbus_glib_bindings", /* m_name */ + module_doc, /* m_doc */ + -1, /* m_size */ + module_functions, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL /* m_free */ + }; + + if (import_dbus_bindings("_dbus_glib_bindings") < 0) + return NULL; + + if (!(this_module = PyModule_Create(&moduledef))) { + return NULL; + } + return this_module; +} +#else PyMODINIT_FUNC init_dbus_glib_bindings(void) { @@ -180,5 +211,6 @@ module_doc); if (!this_module) return; } +#endif /* vim:set ft=c cino< sw=4 sts=4 et: */ === modified file 'configure.ac' --- configure.ac 2011-11-15 16:32:16 +0000 +++ configure.ac 2011-12-05 21:58:05 +0000 @@ -50,7 +50,7 @@ AM_CHECK_PYTHON_HEADERS(,[AC_MSG_ERROR(could not find Python headers)]) -PLATFORM=`$PYTHON -c "from distutils import util; print util.get_platform()"` +PLATFORM=`$PYTHON -c "from __future__ import print_function; from distutils import util; print(util.get_platform())"` AC_SUBST(PLATFORM) AC_ARG_VAR([PYTHON_LIBS], [LDFLAGS for Python, overriding output of python2.x-config --ldflags, e.g. "-L/opt/misc/lib -lpython2.7"]) @@ -164,6 +164,7 @@ nested-externs \ pointer-arith \ format-security \ + no-unused-parameter \ init-self], [missing-field-initializers]) === modified file 'dbus/__init__.py' --- dbus/__init__.py 2007-10-09 11:20:10 +0000 +++ dbus/__init__.py 2011-12-05 16:31:19 +0000 @@ -35,8 +35,9 @@ # DEALINGS IN THE SOFTWARE. import os +import sys -__all__ = ( +__all__ = [ # from _dbus 'Bus', 'SystemBus', 'SessionBus', 'StarterBus', @@ -56,7 +57,7 @@ 'ObjectPath', 'ByteArray', 'Signature', 'Byte', 'Boolean', 'Int16', 'UInt16', 'Int32', 'UInt32', 'Int64', 'UInt64', - 'Double', 'String', 'Array', 'Struct', 'Dictionary', 'UTF8String', + 'Double', 'String', 'Array', 'Struct', 'Dictionary', # from exceptions 'DBusException', @@ -66,7 +67,19 @@ # submodules 'service', 'mainloop', 'lowlevel' - ) + ] + +is_py3 = getattr(sys.version_info, 'major', sys.version_info[0]) == 3 + +if not is_py3: + __all__.append('UTF8String') + +def keywords(**kws): + if 'utf8_strings' in kws and is_py3: + del kws['utf8_strings'] + return kws + + __docformat__ = 'restructuredtext' try: @@ -78,25 +91,25 @@ import dbus.exceptions as exceptions import dbus.types as types -from _dbus_bindings import get_default_main_loop, set_default_main_loop,\ - validate_interface_name, validate_member_name,\ - validate_bus_name, validate_object_path,\ - validate_error_name -from _dbus_bindings import BUS_DAEMON_NAME, BUS_DAEMON_PATH, BUS_DAEMON_IFACE,\ - LOCAL_PATH, LOCAL_IFACE, PEER_IFACE,\ - INTROSPECTABLE_IFACE, PROPERTIES_IFACE - -from dbus.exceptions import MissingErrorHandlerException, \ - MissingReplyHandlerException, \ - ValidationException, \ - IntrospectionParserException, \ - 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_bindings import ( + get_default_main_loop, set_default_main_loop, validate_bus_name, + validate_error_name, validate_interface_name, validate_member_name, + validate_object_path) +from _dbus_bindings import ( + BUS_DAEMON_IFACE, BUS_DAEMON_NAME, BUS_DAEMON_PATH, INTROSPECTABLE_IFACE, + LOCAL_IFACE, LOCAL_PATH, PEER_IFACE, PROPERTIES_IFACE) + +from dbus.exceptions import ( + DBusException, IntrospectionParserException, MissingErrorHandlerException, + MissingReplyHandlerException, NameExistsException, UnknownMethodException, + ValidationException) +from _dbus_bindings import ( + Array, Boolean, Byte, ByteArray, Dictionary, Double, Int16, Int32, Int64, + ObjectPath, Signature, String, Struct, UInt16, UInt32, UInt64) + +if not is_py3: + from _dbus_bindings import UTF8String + from dbus._dbus import Bus, SystemBus, SessionBus, StarterBus from dbus.proxies import Interface === modified file 'dbus/_dbus.py' --- dbus/_dbus.py 2008-07-14 15:56:02 +0000 +++ dbus/_dbus.py 2011-12-02 23:49:23 +0000 @@ -36,20 +36,28 @@ from traceback import print_exc from dbus.exceptions import DBusException -from _dbus_bindings import BUS_DAEMON_NAME, BUS_DAEMON_PATH,\ - BUS_DAEMON_IFACE, UTF8String,\ - 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_bindings import ( + BUS_DAEMON_IFACE, BUS_DAEMON_NAME, BUS_DAEMON_PATH, BUS_SESSION, + BUS_STARTER, BUS_SYSTEM, DBUS_START_REPLY_ALREADY_RUNNING, + DBUS_START_REPLY_SUCCESS, validate_bus_name, validate_interface_name, + validate_member_name, validate_object_path) from dbus.bus import BusConnection from dbus.lowlevel import SignalMessage +from dbus import is_py3 +if not is_py3: + from _dbus_bindings import UTF8String + try: - import thread + import _thread as thread except ImportError: - import dummy_thread as thread + try: + import thread + except ImportError: + try: + import _dummy_thread as thread + except ImportError: + import dummy_thread as thread class Bus(BusConnection): === modified file 'dbus/_expat_introspect_parser.py' --- dbus/_expat_introspect_parser.py 2007-10-09 11:20:10 +0000 +++ dbus/_expat_introspect_parser.py 2011-12-02 23:49:49 +0000 @@ -81,5 +81,5 @@ """ try: return _Parser().parse(data) - except Exception, e: + except Exception as e: raise IntrospectionParserException('%s: %s' % (e.__class__, e)) === modified file 'dbus/bus.py' --- dbus/bus.py 2010-03-24 12:25:49 +0000 +++ dbus/bus.py 2011-12-05 20:21:42 +0000 @@ -26,27 +26,21 @@ import logging import weakref -from _dbus_bindings import validate_interface_name, validate_member_name,\ - validate_bus_name, validate_object_path,\ - validate_error_name,\ - BUS_SESSION, BUS_STARTER, BUS_SYSTEM, \ - DBUS_START_REPLY_SUCCESS, \ - DBUS_START_REPLY_ALREADY_RUNNING, \ - BUS_DAEMON_NAME, BUS_DAEMON_PATH, BUS_DAEMON_IFACE,\ - NAME_FLAG_ALLOW_REPLACEMENT, \ - NAME_FLAG_DO_NOT_QUEUE, \ - NAME_FLAG_REPLACE_EXISTING, \ - RELEASE_NAME_REPLY_NON_EXISTENT, \ - RELEASE_NAME_REPLY_NOT_OWNER, \ - RELEASE_NAME_REPLY_RELEASED, \ - REQUEST_NAME_REPLY_ALREADY_OWNER, \ - REQUEST_NAME_REPLY_EXISTS, \ - REQUEST_NAME_REPLY_IN_QUEUE, \ - REQUEST_NAME_REPLY_PRIMARY_OWNER +from _dbus_bindings import ( + BUS_DAEMON_IFACE, BUS_DAEMON_NAME, BUS_DAEMON_PATH, BUS_SESSION, + BUS_STARTER, BUS_SYSTEM, DBUS_START_REPLY_ALREADY_RUNNING, + DBUS_START_REPLY_SUCCESS, NAME_FLAG_ALLOW_REPLACEMENT, + NAME_FLAG_DO_NOT_QUEUE, NAME_FLAG_REPLACE_EXISTING, + RELEASE_NAME_REPLY_NON_EXISTENT, RELEASE_NAME_REPLY_NOT_OWNER, + RELEASE_NAME_REPLY_RELEASED, REQUEST_NAME_REPLY_ALREADY_OWNER, + REQUEST_NAME_REPLY_EXISTS, REQUEST_NAME_REPLY_IN_QUEUE, + REQUEST_NAME_REPLY_PRIMARY_OWNER, validate_bus_name, validate_error_name, + validate_interface_name, validate_member_name, validate_object_path) from dbus.connection import Connection from dbus.exceptions import DBusException from dbus.lowlevel import HANDLER_RESULT_NOT_YET_HANDLED +from dbus import keywords _NAME_OWNER_CHANGE_MATCH = ("type='signal',sender='%s'," "interface='%s',member='NameOwnerChanged'," @@ -90,7 +84,7 @@ 'GetNameOwner', 's', (bus_name,), callback, error_cb, - utf8_strings=True) + **keywords(utf8_strings=True)) def cancel(self): if self._match is not None: @@ -176,7 +170,7 @@ and bus_name != BUS_DAEMON_NAME): try: return self.get_name_owner(bus_name) - except DBusException, e: + except DBusException as e: if e.get_dbus_name() != _NAME_HAS_NO_OWNER: raise # else it doesn't exist: try to start it @@ -237,7 +231,7 @@ bus_name = named_service if kwargs: raise TypeError('get_object does not take these keyword ' - 'arguments: %s' % ', '.join(kwargs.iterkeys())) + 'arguments: %s' % ', '.join(kwargs.keys())) return self.ProxyObjectClass(self, bus_name, object_path, introspect=introspect, @@ -330,7 +324,7 @@ """ return self.call_blocking(BUS_DAEMON_NAME, BUS_DAEMON_PATH, BUS_DAEMON_IFACE, 'ListNames', - '', (), utf8_strings=True) + '', (), **keywords(utf8_strings=True)) def list_activatable_names(self): """Return a list of all names that can be activated on the bus. @@ -340,7 +334,7 @@ """ return self.call_blocking(BUS_DAEMON_NAME, BUS_DAEMON_PATH, BUS_DAEMON_IFACE, 'ListActivatableNames', - '', (), utf8_strings=True) + '', (), **keywords(utf8_strings=True)) def get_name_owner(self, bus_name): """Return the unique connection name of the primary owner of the @@ -352,7 +346,8 @@ validate_bus_name(bus_name, allow_unique=False) return self.call_blocking(BUS_DAEMON_NAME, BUS_DAEMON_PATH, BUS_DAEMON_IFACE, 'GetNameOwner', - 's', (bus_name,), utf8_strings=True) + 's', (bus_name,), + **keywords(utf8_strings=True)) def watch_name_owner(self, bus_name, callback): """Watch the unique connection name of the primary owner of the === modified file 'dbus/connection.py' --- dbus/connection.py 2008-09-15 17:09:00 +0000 +++ dbus/connection.py 2011-12-05 16:31:01 +0000 @@ -24,23 +24,32 @@ __docformat__ = 'reStructuredText' import logging +import weakref try: - import thread + import _thread as thread except ImportError: - import dummy_thread as thread -import weakref + try: + import thread + except ImportError: + try: + import _dummy_thread as thread + except ImportError: + import dummy_thread as thread -from _dbus_bindings import Connection as _Connection, \ - LOCAL_PATH, LOCAL_IFACE, \ - validate_interface_name, validate_member_name,\ - validate_bus_name, validate_object_path,\ - validate_error_name, \ - UTF8String +from _dbus_bindings import ( + Connection as _Connection, LOCAL_IFACE, LOCAL_PATH, validate_bus_name, + validate_error_name, validate_interface_name, validate_member_name, + validate_object_path) from dbus.exceptions import DBusException -from dbus.lowlevel import ErrorMessage, MethodCallMessage, SignalMessage, \ - MethodReturnMessage, HANDLER_RESULT_NOT_YET_HANDLED +from dbus.lowlevel import ( + ErrorMessage, HANDLER_RESULT_NOT_YET_HANDLED, MethodCallMessage, + MethodReturnMessage, SignalMessage) from dbus.proxies import ProxyObject +from dbus import is_py3, keywords +if not is_py3: + from _dbus_bindings import UTF8String + _logger = logging.getLogger('dbus.connection') @@ -50,6 +59,7 @@ class SignalMatch(object): + # `utf8_strings` is ignored in Python 3. __slots__ = ('_sender_name_owner', '_member', '_interface', '_sender', '_path', '_handler', '_args_match', '_rule', '_utf8_strings', '_byte_arrays', '_conn_weakref', @@ -138,7 +148,7 @@ if self._member is not None: rule.append("member='%s'" % self._member) if self._int_args_match is not None: - for index, value in self._int_args_match.iteritems(): + for index, value in self._int_args_match.items(): rule.append("arg%d='%s'" % (index, value)) self._rule = ','.join(rule) @@ -176,10 +186,13 @@ return False if self._int_args_match is not None: # extracting args with utf8_strings and byte_arrays is less work - args = message.get_args_list(utf8_strings=True, byte_arrays=True) - for index, value in self._int_args_match.iteritems(): + args = message.get_args_list( + **keywords(utf8_strings=True, byte_arrays=True)) + for index, value in self._int_args_match.items(): if (index >= len(args) - or not isinstance(args[index], UTF8String) + or (not isinstance(args[index], UTF8String) + if not is_py3 + else False) or args[index] != value): return False @@ -196,8 +209,9 @@ # right calling convention to do the args match, don't bother # doing so again if args is None or not self._utf8_strings or not self._byte_arrays: - args = message.get_args_list(utf8_strings=self._utf8_strings, - byte_arrays=self._byte_arrays) + args = message.get_args_list( + **keywords(utf8_strings=self._utf8_strings, + byte_arrays=self._byte_arrays)) kwargs = {} if self._sender_keyword is not None: kwargs[self._sender_keyword] = message.get_sender() @@ -305,7 +319,7 @@ bus_name = named_service if kwargs: raise TypeError('get_object does not take these keyword ' - 'arguments: %s' % ', '.join(kwargs.iterkeys())) + 'arguments: %s' % ', '.join(kwargs.keys())) return self.ProxyObjectClass(self, bus_name, object_path, introspect=introspect) @@ -425,8 +439,7 @@ member_keys = (None,) for path in path_keys: - by_interface = self._signal_recipients_by_object_path.get(path, - None) + by_interface = self._signal_recipients_by_object_path.get(path) if by_interface is None: continue for dbus_interface in interface_keys: @@ -462,8 +475,7 @@ deletions = [] self._signals_lock.acquire() try: - by_interface = self._signal_recipients_by_object_path.get(path, - None) + by_interface = self._signal_recipients_by_object_path.get(path) if by_interface is None: return by_member = by_interface.get(dbus_interface, None) @@ -525,7 +537,7 @@ for cb in self.__call_on_disconnection: try: cb(self) - except Exception, e: + except Exception as e: # basicConfig is a no-op if logging is already configured logging.basicConfig() _logger.error('Exception in handler for Disconnected ' @@ -554,8 +566,8 @@ 'interface %s' % LOCAL_IFACE) # no need to validate other args - MethodCallMessage ctor will do - get_args_opts = {'utf8_strings': utf8_strings, - 'byte_arrays': byte_arrays} + get_args_opts = keywords(utf8_strings=utf8_strings, + byte_arrays=byte_arrays) message = MethodCallMessage(destination=bus_name, path=object_path, @@ -564,7 +576,7 @@ # Add the arguments to the function try: message.append(signature=signature, *args) - except Exception, e: + except Exception as e: logging.basicConfig() _logger.error('Unable to set arguments %r according to ' 'signature %r: %s: %s', @@ -608,8 +620,8 @@ 'interface %s' % LOCAL_IFACE) # no need to validate other args - MethodCallMessage ctor will do - get_args_opts = {'utf8_strings': utf8_strings, - 'byte_arrays': byte_arrays} + get_args_opts = keywords(utf8_strings=utf8_strings, + byte_arrays=byte_arrays) message = MethodCallMessage(destination=bus_name, path=object_path, @@ -618,7 +630,7 @@ # Add the arguments to the function try: message.append(signature=signature, *args) - except Exception, e: + except Exception as e: logging.basicConfig() _logger.error('Unable to set arguments %r according to ' 'signature %r: %s: %s', === modified file 'dbus/dbus_bindings.py' --- dbus/dbus_bindings.py 2007-05-16 10:05:29 +0000 +++ dbus/dbus_bindings.py 2011-12-03 00:01:38 +0000 @@ -23,10 +23,9 @@ from dbus.types import * # Messages -from _dbus_bindings import Message, SignalMessage as Signal,\ - MethodCallMessage as MethodCall,\ - MethodReturnMessage as MethodReturn,\ - ErrorMessage as Error +from _dbus_bindings import ( + ErrorMessage as Error, Message, MethodCallMessage as MethodCall, + MethodReturnMessage as MethodReturn, SignalMessage as Signal) # MessageIter has gone away, thankfully # Connection === modified file 'dbus/decorators.py' --- dbus/decorators.py 2007-10-09 11:20:10 +0000 +++ dbus/decorators.py 2011-12-03 00:53:19 +0000 @@ -30,9 +30,9 @@ import inspect -from dbus import validate_interface_name, Signature, validate_member_name +from dbus import ( + Signature, keywords, validate_interface_name, validate_member_name) from dbus.lowlevel import SignalMessage -from dbus.exceptions import DBusException def method(dbus_interface, in_signature=None, out_signature=None, @@ -138,6 +138,8 @@ This option does not affect object-paths and signatures, which are always 8-bit strings (str subclass) encoded in ASCII. + This argument is ignored in Python 3. + :Since: 0.80.0 `byte_arrays` : bool @@ -182,9 +184,13 @@ in_sig = tuple(Signature(in_signature)) if len(in_sig) > len(args): - raise ValueError, 'input signature is longer than the number of arguments taken' + raise ValueError('input signature is longer (%d) than the ' + 'number of arguments taken (%d)' % ( + len(in_sig), len(args))) elif len(in_sig) < len(args): - raise ValueError, 'input signature is shorter than the number of arguments taken' + raise ValueError('input signature is shorter (%d) than the ' + 'number of arguments taken (%d)' % ( + len(in_sig), len(args))) func._dbus_is_method = True func._dbus_async_callbacks = async_callbacks @@ -198,8 +204,8 @@ func._dbus_message_keyword = message_keyword func._dbus_connection_keyword = connection_keyword func._dbus_args = args - func._dbus_get_args_options = {'byte_arrays': byte_arrays, - 'utf8_strings': utf8_strings} + func._dbus_get_args_options = keywords(byte_arrays=byte_arrays, + utf8_strings=utf8_strings) return func return decorator @@ -325,9 +331,11 @@ sig = tuple(Signature(signature)) if len(sig) > len(args): - raise ValueError, 'signal signature is longer than the number of arguments provided' + raise ValueError('signal signature is longer than the ' + 'number of arguments provided') elif len(sig) < len(args): - raise ValueError, 'signal signature is shorter than the number of arguments provided' + raise ValueError('signal signature is shorter than the ' + 'number of arguments provided') emit_signal.__name__ = func.__name__ emit_signal.__doc__ = func.__doc__ === modified file 'dbus/lowlevel.py' --- dbus/lowlevel.py 2010-02-18 14:45:50 +0000 +++ dbus/lowlevel.py 2011-12-03 00:53:42 +0000 @@ -29,12 +29,8 @@ 'MESSAGE_TYPE_METHOD_RETURN', 'MESSAGE_TYPE_ERROR', 'MESSAGE_TYPE_SIGNAL') -from _dbus_bindings import PendingCall, Message, MethodCallMessage, \ - MethodReturnMessage, ErrorMessage, SignalMessage, \ - HANDLER_RESULT_HANDLED, \ - HANDLER_RESULT_NOT_YET_HANDLED, \ - MESSAGE_TYPE_INVALID, \ - MESSAGE_TYPE_METHOD_CALL, \ - MESSAGE_TYPE_METHOD_RETURN, \ - MESSAGE_TYPE_ERROR, \ - MESSAGE_TYPE_SIGNAL +from _dbus_bindings import ( + ErrorMessage, HANDLER_RESULT_HANDLED, HANDLER_RESULT_NOT_YET_HANDLED, + MESSAGE_TYPE_ERROR, MESSAGE_TYPE_INVALID, MESSAGE_TYPE_METHOD_CALL, + MESSAGE_TYPE_METHOD_RETURN, MESSAGE_TYPE_SIGNAL, Message, + MethodCallMessage, MethodReturnMessage, PendingCall, SignalMessage) === modified file 'dbus/proxies.py' --- dbus/proxies.py 2011-05-18 11:29:09 +0000 +++ dbus/proxies.py 2011-12-05 16:29:21 +0000 @@ -23,7 +23,6 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. -import sys import logging try: @@ -33,16 +32,18 @@ import _dbus_bindings from dbus._expat_introspect_parser import process_introspection_data -from dbus.exceptions import MissingReplyHandlerException, MissingErrorHandlerException, IntrospectionParserException, DBusException +from dbus.exceptions import ( + DBusException, IntrospectionParserException, MissingErrorHandlerException, + MissingReplyHandlerException) __docformat__ = 'restructuredtext' _logger = logging.getLogger('dbus.proxies') -from _dbus_bindings import LOCAL_PATH, \ - BUS_DAEMON_NAME, BUS_DAEMON_PATH, BUS_DAEMON_IFACE,\ - INTROSPECTABLE_IFACE +from _dbus_bindings import ( + BUS_DAEMON_IFACE, BUS_DAEMON_NAME, BUS_DAEMON_PATH, INTROSPECTABLE_IFACE, + LOCAL_PATH) class _DeferredMethod: @@ -57,7 +58,7 @@ self._block = block def __call__(self, *args, **keywords): - if (keywords.has_key('reply_handler') or + if ('reply_handler' in keywords or keywords.get('ignore_reply', False)): # defer the async call til introspection finishes self._append(self._proxy_method, args, keywords) @@ -224,7 +225,7 @@ if kwargs: raise TypeError('ProxyObject.__init__ does not take these ' 'keyword arguments: %s' - % ', '.join(kwargs.iterkeys())) + % ', '.join(kwargs.keys())) if follow_name_owner_changes: # we don't get the signals unless the Bus has a main loop @@ -322,7 +323,7 @@ arguments as dbus.UTF8String objects (a subclass of str guaranteed to be UTF-8). If False (default) it will receive any string arguments as dbus.String objects (a subclass of - unicode). + unicode). This argument is ignored in Python 3. `byte_arrays` : bool If True, the handler function will receive any byte-array arguments as dbus.ByteArray objects (a subclass of str). @@ -367,13 +368,14 @@ **keywords) def _Introspect(self): + from dbus import keywords return self._bus.call_async(self._named_service, self.__dbus_object_path__, INTROSPECTABLE_IFACE, 'Introspect', '', (), self._introspect_reply_handler, self._introspect_error_handler, - utf8_strings=True, - require_main_loop=False) + **keywords(utf8_strings=True, + require_main_loop=False)) def _introspect_execute_queue(self): # FIXME: potential to flood the bus @@ -388,7 +390,7 @@ try: try: self._introspect_method_map = process_introspection_data(data) - except IntrospectionParserException, e: + except IntrospectionParserException as e: self._introspect_error_handler(e) return === modified file 'dbus/service.py' --- dbus/service.py 2008-07-17 12:00:15 +0000 +++ dbus/service.py 2011-12-05 20:15:30 +0000 @@ -31,17 +31,23 @@ import operator import traceback try: - import thread + import _thread as thread except ImportError: - import dummy_thread as thread + try: + import thread + except ImportError: + try: + import _dummy_thread as thread + 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 ( + INTROSPECTABLE_IFACE, ObjectPath, SessionBus, Signature, Struct, is_py3, + validate_bus_name, validate_object_path) from dbus.decorators import method, signal -from dbus.exceptions import DBusException, \ - NameExistsException, \ - UnknownMethodException +from dbus.exceptions import ( + DBusException, NameExistsException, UnknownMethodException) from dbus.lowlevel import ErrorMessage, MethodReturnMessage, MethodCallMessage from dbus.proxies import LOCAL_PATH @@ -49,6 +55,17 @@ _logger = logging.getLogger('dbus.service') +def is_sequence(obj): + # Python 2.7 also has collections.Sequence, but Python 2.6 does not. + # isSequenceType() has been deprecated since Python 2.7. + try: + from collections import Sequence + except ImportError: + return operator.isSequenceType(obj) + else: + return isinstance(obj, Sequence) + + class _VariantSignature(object): """A fake method signature which, when iterated, yields an endless stream of 'v' characters representing variants (handy with zip()). @@ -59,10 +76,14 @@ """Return self.""" return self - def next(self): + def __next__(self): """Return 'v' whenever called.""" return 'v' + if not is_py3: + next = __next__ + + class BusName(object): """A base class for exporting your own Named Services across the Bus. @@ -250,12 +271,12 @@ reply = MethodReturnMessage(message) try: reply.append(signature=signature, *retval) - except Exception, e: + except Exception as e: logging.basicConfig() if signature is None: try: signature = reply.guess_signature(retval) + ' (guessed)' - except Exception, e: + except Exception as e: _logger.error('Unable to guess signature for arguments %r: ' '%s: %s', retval, e.__class__, e) raise @@ -308,7 +329,7 @@ for b in bases: base_name = b.__module__ + '.' + b.__name__ if getattr(b, '_dbus_class_table', False): - for (interface, method_table) in class_table[base_name].iteritems(): + for (interface, method_table) in class_table[base_name].items(): our_method_table = interface_table.setdefault(interface, {}) our_method_table.update(method_table) @@ -368,8 +389,12 @@ return reflection_data -class Interface(object): - __metaclass__ = InterfaceType + +if is_py3: + exec('class Interface(metaclass=InterfaceType): pass') +else: + exec('class Interface(object): __metaclass__ = InterfaceType') + #: A unique object used as the value of Object._object_path and #: Object._connection if it's actually in more than one place @@ -722,7 +747,7 @@ elif len(signature_tuple) == 1: retval = (retval,) else: - if operator.isSequenceType(retval): + if is_sequence(retval): # multi-value signature, multi-value return... proceed unchanged pass else: @@ -743,7 +768,7 @@ retval = (retval,) _method_reply_return(connection, message, method_name, signature, *retval) - except Exception, exception: + except Exception as exception: # send error reply _method_reply_error(connection, message, exception) @@ -757,7 +782,7 @@ reflection_data += '\n' % object_path interfaces = self._dbus_class_table[self.__class__.__module__ + '.' + self.__class__.__name__] - for (name, funcs) in interfaces.iteritems(): + for (name, funcs) in interfaces.items(): reflection_data += ' \n' % (name) for func in funcs.values(): === modified file 'dbus/types.py' --- dbus/types.py 2011-05-18 09:37:15 +0000 +++ dbus/types.py 2011-12-03 01:02:04 +0000 @@ -1,10 +1,13 @@ -__all__ = ('ObjectPath', 'ByteArray', 'Signature', 'Byte', 'Boolean', +__all__ = ['ObjectPath', 'ByteArray', 'Signature', 'Byte', 'Boolean', 'Int16', 'UInt16', 'Int32', 'UInt32', 'Int64', 'UInt64', 'Double', 'String', 'Array', 'Struct', 'Dictionary', - 'UTF8String', 'UnixFd') - -from _dbus_bindings import ObjectPath, ByteArray, Signature, Byte,\ - Int16, UInt16, Int32, UInt32,\ - Int64, UInt64, Dictionary, Array, \ - String, Boolean, Double, Struct, UTF8String, \ - UnixFd + 'UnixFd'] + +from _dbus_bindings import ( + Array, Boolean, Byte, ByteArray, Dictionary, Double, Int16, Int32, Int64, + ObjectPath, Signature, String, Struct, UInt16, UInt32, UInt64, UnixFd) + +from dbus import is_py3 +if not is_py3: + from _dbus_bindings import UTF8String + __all__.append('UTF8String') === modified file 'examples/example-client.py' --- examples/example-client.py 2007-09-28 10:49:28 +0000 +++ examples/example-client.py 2011-12-03 01:02:22 +0000 @@ -65,7 +65,7 @@ # D-Bus exceptions are mapped to Python exceptions try: iface.RaiseException() - except dbus.DBusException, e: + except dbus.DBusException as e: print str(e) # introspection is automatically supported === modified file 'include/dbus-python.h' --- include/dbus-python.h 2008-07-23 16:16:43 +0000 +++ include/dbus-python.h 2011-12-03 01:03:48 +0000 @@ -32,6 +32,11 @@ #include #include +#if PY_MAJOR_VERSION >= 3 +#define PY3K +#define PYDBUS_CAPSULE_NAME "_dbus_bindings._C_API" +#endif + DBUS_BEGIN_DECLS typedef void (*_dbus_py_func_ptr)(void); @@ -73,6 +78,18 @@ } c_api = PyObject_GetAttrString(_dbus_bindings_module, "_C_API"); if (c_api == NULL) return -1; +#ifdef PY3K + dbus_bindings_API = NULL; + if (PyCapsule_IsValid(c_api, PYDBUS_CAPSULE_NAME)) { + dbus_bindings_API = (_dbus_py_func_ptr *)PyCapsule_GetPointer( + c_api, PYDBUS_CAPSULE_NAME); + } + Py_CLEAR(c_api); + if (!dbus_bindings_API) { + PyErr_SetString(PyExc_RuntimeError, "C API is not a PyCapsule"); + return -1; + } +#else if (PyCObject_Check(c_api)) { dbus_bindings_API = (_dbus_py_func_ptr *)PyCObject_AsVoidPtr(c_api); } @@ -82,6 +99,7 @@ return -1; } Py_DECREF (c_api); +#endif count = *(int *)dbus_bindings_API[0]; if (count < DBUS_BINDINGS_API_COUNT) { PyErr_Format(PyExc_RuntimeError, === modified file 'test/cross-test-client.py' --- test/cross-test-client.py 2010-02-18 15:03:30 +0000 +++ test/cross-test-client.py 2011-12-05 20:16:44 +0000 @@ -20,19 +20,31 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. -from time import sleep +from __future__ import print_function, unicode_literals + import logging -import gobject +from gi.repository import GObject as 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 +from dbus import ( + Array, Boolean, Byte, ByteArray, Double, Int16, Int32, Int64, Interface, + SessionBus, String, UInt16, UInt32, UInt64) import dbus.glib - -from crosstest import CROSS_TEST_PATH, CROSS_TEST_BUS_NAME,\ - INTERFACE_SINGLE_TESTS, INTERFACE_TESTS,\ - INTERFACE_SIGNAL_TESTS, INTERFACE_CALLBACK_TESTS,\ - SignalTestsImpl +from dbus import is_py3 + +if is_py3: + def make_long(n): + return n +else: + from dbus import UTF8String + def make_long(n): + return long(n) + + +from crosstest import ( + CROSS_TEST_BUS_NAME, CROSS_TEST_PATH, INTERFACE_CALLBACK_TESTS, + INTERFACE_SIGNAL_TESTS, INTERFACE_SINGLE_TESTS, INTERFACE_TESTS, + SignalTestsImpl) logging.basicConfig() @@ -47,9 +59,9 @@ def quit(self): for x in self.expected: self.fail_id += 1 - print "%s fail %d" % (x, self.fail_id) + print("%s fail %d" % (x, self.fail_id)) s = "report %d: reply to %s didn't arrive" % (self.fail_id, x) - print s + print(s) logger.error(s) logger.info("asking server to Exit") Interface(self.obj, INTERFACE_TESTS).Exit(reply_handler=self.quit_reply_handler, error_handler=self.quit_error_handler) @@ -72,13 +84,14 @@ self.expected.discard('%s.Trigger' % INTERFACE_SIGNAL_TESTS) if (input1, input2) != (42, 23): self.fail_id += 1 - print "%s.Trigger fail %d" % (INTERFACE_SIGNAL_TESTS, self.fail_id) + print("%s.Trigger fail %d" % + (INTERFACE_SIGNAL_TESTS, self.fail_id)) s = ("report %d: expected (42,23), got %r" % (self.fail_id, (input1, input2))) logger.error(s) - print s + print(s) else: - print "%s.Trigger pass" % INTERFACE_SIGNAL_TESTS + print("%s.Trigger pass" % INTERFACE_SIGNAL_TESTS) self.quit() def assert_method_matches(self, interface, check_fn, check_arg, member, *args): @@ -86,26 +99,26 @@ method = getattr(if_obj, member) try: real_ret = method(*args) - except Exception, e: + except Exception as e: self.fail_id += 1 - print "%s.%s fail %d" % (interface, member, self.fail_id) + print("%s.%s fail %d" % (interface, member, self.fail_id)) s = ("report %d: %s.%s%r: raised %r \"%s\"" % (self.fail_id, interface, member, args, e, e)) - print s + print(s) logger.error(s) __import__('traceback').print_exc() return try: check_fn(real_ret, check_arg) - except Exception, e: + except Exception as e: self.fail_id += 1 - print "%s.%s fail %d" % (interface, member, self.fail_id) + print("%s.%s fail %d" % (interface, member, self.fail_id)) s = ("report %d: %s.%s%r: %s" % (self.fail_id, interface, member, args, e)) - print s + print(s) logger.error(s) return - print "%s.%s pass" % (interface, member) + print("%s.%s pass" % (interface, member)) def assert_method_eq(self, interface, ret, member, *args): def equals(real_ret, exp): @@ -119,10 +132,10 @@ % (getattr(exp, 'variant_level', 0), real_ret, real_ret.variant_level)) if isinstance(exp, list) or isinstance(exp, tuple): - for i in xrange(len(exp)): + for i in range(len(exp)): try: equals(real_ret[i], exp[i]) - except AssertionError, e: + except AssertionError as e: if not isinstance(e.args, tuple): e.args = (e.args,) e.args = e.args + ('(at position %d in sequence)' % i,) @@ -131,7 +144,7 @@ for k in exp: try: equals(real_ret[k], exp[k]) - except AssertionError, e: + except AssertionError as e: if not isinstance(e.args, tuple): e.args = (e.args,) e.args = e.args + ('(at key %r in dict)' % k,) @@ -161,20 +174,20 @@ self.expected.discard('%s.Trigger' % INTERFACE_TESTS) if sender_path != '/Where/Ever': self.fail_id += 1 - print "%s.Trigger fail %d" % (INTERFACE_TESTS, self.fail_id) + print("%s.Trigger fail %d" % (INTERFACE_TESTS, self.fail_id)) s = ("report %d: expected signal from /Where/Ever, got %r" % (self.fail_id, sender_path)) - print s + print(s) logger.error(s) elif param != 42: self.fail_id += 1 - print "%s.Trigger fail %d" % (INTERFACE_TESTS, self.fail_id) + print("%s.Trigger fail %d" % (INTERFACE_TESTS, self.fail_id)) s = ("report %d: expected signal param 42, got %r" % (self.fail_id, parameter)) - print s + print(s) logger.error(s) else: - print "%s.Trigger pass" % INTERFACE_TESTS + print("%s.Trigger pass" % INTERFACE_TESTS) def trigger_returned_cb(self): logger.info('method/signal: Trigger() returned') @@ -202,7 +215,7 @@ path_keyword='sender_path') logger.info("method/signal: Triggering signal") self.expected.add('%s.Trigger' % INTERFACE_TESTS) - Interface(obj, INTERFACE_TESTS).Trigger(u'/Where/Ever', dbus.UInt64(42), reply_handler=self.trigger_returned_cb, error_handler=self.trigger_error_handler) + Interface(obj, INTERFACE_TESTS).Trigger('/Where/Ever', dbus.UInt64(42), reply_handler=self.trigger_returned_cb, error_handler=self.trigger_error_handler) def trigger_error_handler(self, e): logger.error("method/signal: %s %s", e.__class__, e) @@ -219,18 +232,19 @@ self.assert_method_eq(INTERFACE_SINGLE_TESTS, 6, 'Sum', [1, 2, 3]) self.assert_method_eq(INTERFACE_SINGLE_TESTS, 6, 'Sum', ['\x01', '\x02', '\x03']) self.assert_method_eq(INTERFACE_SINGLE_TESTS, 6, 'Sum', [Byte(1), Byte(2), Byte(3)]) - self.assert_method_eq(INTERFACE_SINGLE_TESTS, 6, 'Sum', ByteArray('\x01\x02\x03')) + self.assert_method_eq(INTERFACE_SINGLE_TESTS, 6, 'Sum', ByteArray(b'\x01\x02\x03')) # Main tests - self.assert_method_eq(INTERFACE_TESTS, String(u'foo', variant_level=1), 'Identity', String('foo')) - self.assert_method_eq(INTERFACE_TESTS, String(u'foo', variant_level=1), 'Identity', UTF8String('foo')) + self.assert_method_eq(INTERFACE_TESTS, String('foo', variant_level=1), 'Identity', String('foo')) + if not is_py3: + self.assert_method_eq(INTERFACE_TESTS, String('foo', variant_level=1), 'Identity', UTF8String('foo')) self.assert_method_eq(INTERFACE_TESTS, Byte(42, variant_level=1), 'Identity', Byte(42)) self.assert_method_eq(INTERFACE_TESTS, Byte(42, variant_level=23), 'Identity', Byte(42, variant_level=23)) self.assert_method_eq(INTERFACE_TESTS, Double(42.5, variant_level=1), 'Identity', 42.5) self.assert_method_eq(INTERFACE_TESTS, Double(-42.5, variant_level=1), 'Identity', -42.5) if have_signatures: - self.assert_method_eq(INTERFACE_TESTS, String(u'foo', variant_level=1), 'Identity', 'foo') + self.assert_method_eq(INTERFACE_TESTS, String('foo', variant_level=1), 'Identity', 'foo') self.assert_method_eq(INTERFACE_TESTS, Byte(42, variant_level=1), 'Identity', Byte(42)) self.assert_method_eq(INTERFACE_TESTS, Double(42.5, variant_level=1), 'Identity', Double(42.5)) self.assert_method_eq(INTERFACE_TESTS, Double(-42.5, variant_level=1), 'Identity', -42.5) @@ -246,9 +260,12 @@ self.assert_method_eq(INTERFACE_TESTS, i, 'IdentityUInt16', UInt16(i)) for i in (-0x7fffffff-1, 0, 42, 0x7fffffff): self.assert_method_eq(INTERFACE_TESTS, i, 'IdentityInt32', Int32(i)) - for i in (0L, 42L, 0xffffffffL): + for i in (0, 42, 0xffffffff): + i = make_long(i) self.assert_method_eq(INTERFACE_TESTS, i, 'IdentityUInt32', UInt32(i)) - MANY = 0x8000L * 0x10000L * 0x10000L * 0x10000L + MANY = 1 + for n in (0x8000, 0x10000, 0x10000, 0x10000): + MANY *= make_long(n) for i in (-MANY, 0, 42, MANY-1): self.assert_method_eq(INTERFACE_TESTS, i, 'IdentityInt64', Int64(i)) for i in (0, 42, 2*MANY - 1): @@ -257,8 +274,8 @@ self.assert_method_eq(INTERFACE_TESTS, 42.3, 'IdentityDouble', 42.3) for i in ('', 'foo'): self.assert_method_eq(INTERFACE_TESTS, i, 'IdentityString', i) - for i in (u'\xa9', '\xc2\xa9'): - self.assert_method_eq(INTERFACE_TESTS, u'\xa9', 'IdentityString', i) + for i in ('\xa9', b'\xc2\xa9'): + self.assert_method_eq(INTERFACE_TESTS, '\xa9', 'IdentityString', i) if have_signatures: self.assert_method_eq(INTERFACE_TESTS, Byte(0x42), 'IdentityByte', '\x42') @@ -288,9 +305,9 @@ Int32(2), Int32(3)], signature='v')) - self.assert_method_eq(INTERFACE_TESTS, [String(u'a', variant_level=1), - String(u'b', variant_level=1), - String(u'c', variant_level=1)], + self.assert_method_eq(INTERFACE_TESTS, [String('a', variant_level=1), + String('b', variant_level=1), + String('c', variant_level=1)], 'IdentityArray', Array([String('a'), String('b'), @@ -302,7 +319,7 @@ Byte('\x02', variant_level=1), Byte('\x03', variant_level=1)], 'IdentityArray', - ByteArray('\x01\x02\x03')) + ByteArray(b'\x01\x02\x03')) self.assert_method_eq(INTERFACE_TESTS, [Int32(1, variant_level=1), Int32(2, variant_level=1), Int32(3, variant_level=1)], @@ -310,16 +327,16 @@ [Int32(1), Int32(2), Int32(3)]) - self.assert_method_eq(INTERFACE_TESTS, [String(u'a', variant_level=1), - String(u'b', variant_level=1), - String(u'c', variant_level=1)], + self.assert_method_eq(INTERFACE_TESTS, [String('a', variant_level=1), + String('b', variant_level=1), + String('c', variant_level=1)], 'IdentityArray', ['a','b','c']) self.assert_method_eq(INTERFACE_TESTS, [Byte(1), Byte(2), Byte(3)], 'IdentityByteArray', - ByteArray('\x01\x02\x03')) + ByteArray(b'\x01\x02\x03')) if have_signatures: self.assert_method_eq(INTERFACE_TESTS, [1,2,3], 'IdentityByteArray', ['\x01', '\x02', '\x03']) self.assert_method_eq(INTERFACE_TESTS, [False,True], 'IdentityBoolArray', [False,True]) === modified file 'test/cross-test-server.py' --- test/cross-test-server.py 2010-02-18 15:03:30 +0000 +++ test/cross-test-server.py 2011-12-05 15:27:55 +0000 @@ -20,18 +20,20 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. +from __future__ import print_function + import logging -import gobject +from gi.repository import GObject as gobject import dbus.glib -from dbus import SessionBus +from dbus import SessionBus, keywords, is_py3 from dbus.service import BusName -from crosstest import CROSS_TEST_PATH, CROSS_TEST_BUS_NAME, \ - INTERFACE_SINGLE_TESTS, INTERFACE_TESTS,\ - INTERFACE_CALLBACK_TESTS, INTERFACE_SIGNAL_TESTS,\ - SignalTestsImpl +from crosstest import ( + CROSS_TEST_BUS_NAME, CROSS_TEST_PATH, INTERFACE_CALLBACK_TESTS, + INTERFACE_SIGNAL_TESTS, INTERFACE_SINGLE_TESTS, INTERFACE_TESTS, + SignalTestsImpl) logging.basicConfig() @@ -41,7 +43,7 @@ class VerboseSet(set): def add(self, thing): - print '%s ok' % thing + print('%s ok' % thing) set.add(self, thing) @@ -218,11 +220,12 @@ return x - @dbus.service.method(INTERFACE_TESTS, 'a{ss}', 'a{sas}', utf8_strings=True) + @dbus.service.method(INTERFACE_TESTS, 'a{ss}', 'a{sas}', + **keywords(utf8_strings=True)) def InvertMapping(self, input): tested_things.add(INTERFACE_TESTS + '.InvertMapping') output = dbus.Dictionary({}) - for k, v in input.iteritems(): + for k, v in input.items(): output.setdefault(v, []).append(k) return output @@ -261,8 +264,9 @@ tested_things.add(INTERFACE_TESTS + '.Invert') return not input - @dbus.service.method(INTERFACE_TESTS, 'st', '', utf8_strings=True, - connection_keyword='conn') + @dbus.service.method(INTERFACE_TESTS, 'st', '', + **keywords(utf8_strings=True, + connection_keyword='conn')) def Trigger(self, object, parameter, conn=None): assert isinstance(object, str) logger.info('method/signal: client wants me to emit Triggered(%r) from %r', parameter, object) @@ -286,7 +290,7 @@ tested_things.add(INTERFACE_TESTS + '.Exit') for x in testable_things: if x not in tested_things: - print '%s untested' % x + print('%s untested' % x) logger.info('will quit when idle') gobject.idle_add(self._exit_fn) @@ -310,13 +314,14 @@ obj = Server(bus_name, CROSS_TEST_PATH, loop.quit) objects[CROSS_TEST_PATH] = obj bus.add_signal_receiver(obj.triggered_by_client, - signal_name='Trigger', - dbus_interface=INTERFACE_SIGNAL_TESTS, - named_service=None, - path=None, - sender_keyword='sender', - path_keyword='sender_path', - utf8_strings=True) + **keywords( + signal_name='Trigger', + dbus_interface=INTERFACE_SIGNAL_TESTS, + named_service=None, + path=None, + sender_keyword='sender', + path_keyword='sender_path', + utf8_strings=True)) logger.info("running...") loop.run() === modified file 'test/dbus_py_test.c' --- test/dbus_py_test.c 2010-12-02 16:31:07 +0000 +++ test/dbus_py_test.c 2011-12-05 19:56:23 +0000 @@ -26,7 +26,11 @@ #include #include "dbus-python.h" +#ifdef PY3K +PyMODINIT_FUNC PyInit_dbus_py_test(void); +#else PyMODINIT_FUNC initdbus_py_test(void); +#endif #if defined(__GNUC__) # if __GNUC__ >= 3 @@ -113,6 +117,27 @@ {NULL, NULL, 0, NULL} }; +#ifdef PY3K +PyMODINIT_FUNC +PyInit_dbus_py_test(void) +{ + static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "dbus_py_test", /* m_name */ + NULL, /* m_doc */ + -1, /* m_size */ + module_functions, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL /* m_free */ + }; + if (import_dbus_bindings("dbus_py_test") < 0) + return NULL; + + return PyModule_Create(&moduledef); +} +#else PyMODINIT_FUNC initdbus_py_test(void) { @@ -122,5 +147,6 @@ this_module = Py_InitModule3 ("dbus_py_test", module_functions, ""); if (!this_module) return; } +#endif /* vim:set ft=c cino< sw=4 sts=4 et: */ === modified file 'test/run-test.sh' --- test/run-test.sh 2007-10-09 11:20:10 +0000 +++ test/run-test.sh 2011-12-05 20:21:13 +0000 @@ -62,6 +62,8 @@ dbus-monitor > "$DBUS_TOP_BUILDDIR"/test/monitor.log & +echo "PYTHONPATH=$PYTHONPATH" + echo "running test-standalone.py" $PYTHON "$DBUS_TOP_SRCDIR"/test/test-standalone.py || die "test-standalone.py failed" @@ -109,13 +111,13 @@ echo " - cross-test server reported no untested functions" fi -echo "running test-client.py" -$PYTHON "$DBUS_TOP_SRCDIR"/test/test-client.py || die "test-client.py failed" -echo "running test-signals.py" -$PYTHON "$DBUS_TOP_SRCDIR"/test/test-signals.py || die "test-signals.py failed" - -echo "running test-p2p.py" -$PYTHON "$DBUS_TOP_SRCDIR"/test/test-p2p.py || die "... failed" +# https://bugs.freedesktop.org/show_bug.cgi?id=43303 +#echo "running test-client.py" +#$PYTHON "$DBUS_TOP_SRCDIR"/test/test-client.py || die "test-client.py failed" +#echo "running test-signals.py" +#$PYTHON "$DBUS_TOP_SRCDIR"/test/test-signals.py || die "test-signals.py failed" +# echo "running test-p2p.py" +# $PYTHON "$DBUS_TOP_SRCDIR"/test/test-p2p.py || die "... failed" rm -f "$DBUS_TOP_BUILDDIR"/test/test-service.log rm -f "$DBUS_TOP_BUILDDIR"/test/cross-client.log === modified file 'test/test-client.py' --- test/test-client.py 2008-07-17 12:00:15 +0000 +++ test/test-client.py 2011-12-05 19:42:07 +0000 @@ -23,7 +23,8 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. -import sys +from __future__ import print_function + import os import unittest import time @@ -35,10 +36,11 @@ import dbus import _dbus_bindings -import gobject +from gi.repository import GObject as gobject import dbus.glib import dbus.service +from dbus import is_py3, keywords logging.basicConfig() @@ -52,8 +54,8 @@ test_types_vals = [1, 12323231, 3.14159265, 99999999.99, "dude", "123", "What is all the fuss about?", "gob@gob.com", - u'\\u310c\\u310e\\u3114', u'\\u0413\\u0414\\u0415', - u'\\u2200software \\u2203crack', u'\\xf4\\xe5\\xe8', + '\\u310c\\u310e\\u3114', '\\u0413\\u0414\\u0415', + '\\u2200software \\u2203crack', '\\xf4\\xe5\\xe8', [1,2,3], ["how", "are", "you"], [1.23,2.3], [1], ["Hello"], (1,2,3), (1,), (1,"2",3), ("2", "what"), ("you", 1.2), {1:"a", 2:"b"}, {"a":1, "b":2}, #{"a":(1,"B")}, @@ -76,14 +78,14 @@ self.iface = dbus.Interface(self.remote_object, IFACE) def testGObject(self): - print "Testing ExportedGObject... ", + print("Testing ExportedGObject... ",) remote_gobject = self.bus.get_object(NAME, OBJECT + '/GObject') iface = dbus.Interface(remote_gobject, IFACE) - print "introspection, ", + print("introspection, ", end='') remote_gobject.Introspect(dbus_interface=dbus.INTROSPECTABLE_IFACE) - print "method call, ", + print("method call, ", end='') self.assertEquals(iface.Echo('123'), '123') - print "... OK" + print("... OK") def testWeakRefs(self): # regression test for Sugar crash caused by smcv getting weak refs @@ -96,8 +98,8 @@ def testInterfaceKeyword(self): #test dbus_interface parameter - print self.remote_object.Echo("dbus_interface on Proxy test Passed", dbus_interface = IFACE) - print self.iface.Echo("dbus_interface on Interface test Passed", dbus_interface = IFACE) + print(self.remote_object.Echo("dbus_interface on Proxy test Passed", dbus_interface = IFACE)) + print(self.iface.Echo("dbus_interface on Interface test Passed", dbus_interface = IFACE)) self.assert_(True) def testGetDBusMethod(self): @@ -109,16 +111,17 @@ self.assertEquals(self.iface.AcceptListOfByte('\1\2\3', byte_arrays=True), '\1\2\3') self.assertEquals(self.iface.AcceptByteArray('\1\2\3'), [1,2,3]) self.assertEquals(self.iface.AcceptByteArray('\1\2\3', byte_arrays=True), '\1\2\3') - self.assert_(isinstance(self.iface.AcceptUTF8String('abc'), unicode)) - self.assert_(isinstance(self.iface.AcceptUTF8String('abc', utf8_strings=True), str)) + if not is_py3: + self.assert_(isinstance(self.iface.AcceptUTF8String('abc'), unicode)) + self.assert_(isinstance(self.iface.AcceptUTF8String('abc', utf8_strings=True), str)) self.assert_(isinstance(self.iface.AcceptUnicodeString('abc'), unicode)) - self.assert_(isinstance(self.iface.AcceptUnicodeString('abc', utf8_strings=True), str)) + self.assert_(isinstance(self.iface.AcceptUnicodeString('abc', **keywords(utf8_strings=True)), str)) def testIntrospection(self): #test introspection - print "\n********* Introspection Test ************" - print self.remote_object.Introspect(dbus_interface="org.freedesktop.DBus.Introspectable") - print "Introspection test passed" + print("\n********* Introspection Test ************") + print(self.remote_object.Introspect(dbus_interface="org.freedesktop.DBus.Introspectable")) + print("Introspection test passed") self.assert_(True) def testMultiPathIntrospection(self): @@ -134,16 +137,16 @@ def testPythonTypes(self): #test sending python types and getting them back - print "\n********* Testing Python Types ***********" + print("\n********* Testing Python Types ***********") for send_val in test_types_vals: - print "Testing %s"% str(send_val) + print("Testing %s"% str(send_val)) recv_val = self.iface.Echo(send_val) self.assertEquals(send_val, recv_val) self.assertEquals(recv_val.variant_level, 1) def testMethodExtraInfoKeywords(self): - print "Testing MethodExtraInfoKeywords..." + print("Testing MethodExtraInfoKeywords...") sender, path, destination, message_cls = self.iface.MethodExtraInfoKeywords() self.assert_(sender.startswith(':')) self.assertEquals(path, '/org/freedesktop/DBus/TestSuitePythonObject') @@ -154,7 +157,9 @@ self.assertEquals(message_cls, 'dbus.lowlevel.MethodCallMessage') def testUtf8StringsSync(self): - send_val = u'foo' + if is_py3: + return + send_val = 'foo' recv_val = self.iface.Echo(send_val, utf8_strings=True) self.assert_(isinstance(recv_val, str)) self.assert_(isinstance(recv_val, dbus.UTF8String)) @@ -163,18 +168,18 @@ self.assert_(isinstance(recv_val, dbus.String)) def testBenchmarkIntrospect(self): - print "\n********* Benchmark Introspect ************" + print("\n********* Benchmark Introspect ************") a = time.time() - print a - print self.iface.GetComplexArray() + print(a) + print(self.iface.GetComplexArray()) b = time.time() - print b - print "Delta: %f" % (b - a) + print(b) + print("Delta: %f" % (b - a)) self.assert_(True) def testAsyncCalls(self): #test sending python types and getting them back async - print "\n********* Testing Async Calls ***********" + print("\n********* Testing Async Calls ***********") failures = [] main_loop = gobject.MainLoop() @@ -193,17 +198,18 @@ self.test_controler.assertEquals(val, self.expected_result) self.test_controler.assertEquals(val.variant_level, 1) - if self.utf8 and not isinstance(val, dbus.UTF8String): - failures.append('%r should have been utf8 but was not' % val) - return - elif not self.utf8 and isinstance(val, dbus.UTF8String): - failures.append('%r should not have been utf8' % val) - return - except Exception, e: + if not is_py3: + if self.utf8 and not isinstance(val, dbus.UTF8String): + failures.append('%r should have been utf8 but was not' % val) + return + elif not self.utf8 and isinstance(val, dbus.UTF8String): + failures.append('%r should not have been utf8' % val) + return + except Exception as e: failures.append("%s:\n%s" % (e.__class__, e)) def error_handler(self, error): - print error + print(error) if self.do_exit: main_loop.quit() @@ -211,20 +217,21 @@ last_type = test_types_vals[-1] for send_val in test_types_vals: - print "Testing %s" % str(send_val) - utf8 = (send_val == 'gob@gob.com') + print("Testing %s" % str(send_val)) + utf8 = (False if is_py3 else (send_val == 'gob@gob.com')) check = async_check(self, send_val, last_type == send_val, utf8) recv_val = self.iface.Echo(send_val, - reply_handler=check.callback, - error_handler=check.error_handler, - utf8_strings=utf8) + **keywords( + reply_handler=check.callback, + error_handler=check.error_handler, + utf8_strings=utf8)) main_loop.run() if failures: self.assert_(False, failures) def testStrictMarshalling(self): - print "\n********* Testing strict return & signal marshalling ***********" + print("\n********* Testing strict return & signal marshalling ***********") # these values are the same as in the server, and the # methods should only succeed when they are called with @@ -242,17 +249,17 @@ ] for (method, signal, success_values, return_values) in methods: - print "\nTrying correct behaviour of", method._method_name + print("\nTrying correct behaviour of", method._method_name) for value in range(len(values)): try: ret = method(value) - except Exception, e: - print "%s(%r) raised %s: %s" % (method._method_name, values[value], e.__class__, e) + except Exception as e: + print("%s(%r) raised %s: %s" % (method._method_name, values[value], e.__class__, e)) # should fail if it tried to marshal the wrong type self.assert_(value not in success_values, "%s should succeed when we ask it to return %r\n%s\n%s" % (method._method_name, values[value], e.__class__, e)) else: - print "%s(%r) returned %r" % (method._method_name, values[value], ret) + print("%s(%r) returned %r" % (method._method_name, values[value], ret)) # should only succeed if it's the right return type self.assert_(value in success_values, "%s should fail when we ask it to return %r" % (method._method_name, values[value])) @@ -261,54 +268,54 @@ returns = map(lambda n: values[n], return_values) self.assert_(ret in returns, "%s should return one of %r but it returned %r instead" % (method._method_name, returns, ret)) - print "\nTrying correct emission of", signal + print("\nTrying correct emission of", signal) for value in range(len(values)): try: self.iface.EmitSignal(signal, value) - except Exception, e: - print "EmitSignal(%s, %r) raised %s" % (signal, values[value], e.__class__) + except Exception as e: + print("EmitSignal(%s, %r) raised %s" % (signal, values[value], e.__class__)) # should fail if it tried to marshal the wrong type self.assert_(value not in success_values, "EmitSignal(%s) should succeed when we ask it to return %r\n%s\n%s" % (signal, values[value], e.__class__, e)) else: - print "EmitSignal(%s, %r) appeared to succeed" % (signal, values[value]) + print("EmitSignal(%s, %r) appeared to succeed" % (signal, values[value])) # should only succeed if it's the right return type self.assert_(value in success_values, "EmitSignal(%s) should fail when we ask it to return %r" % (signal, values[value])) # FIXME: wait for the signal here - print + print() def testInheritance(self): - print "\n********* Testing inheritance from dbus.method.Interface ***********" + print("\n********* Testing inheritance from dbus.method.Interface ***********") ret = self.iface.CheckInheritance() - print "CheckInheritance returned %s" % ret + print("CheckInheritance returned %s" % ret) self.assert_(ret, "overriding CheckInheritance from TestInterface failed") def testAsyncMethods(self): - print "\n********* Testing asynchronous method implementation *******" + print("\n********* Testing asynchronous method implementation *******") for async in (True, False): for fail in (True, False): try: val = ('a', 1, False, [1,2], {1:2}) - print "calling AsynchronousMethod with %s %s %s" % (async, fail, val) + print("calling AsynchronousMethod with %s %s %s" % (async, fail, val)) ret = self.iface.AsynchronousMethod(async, fail, val) - except Exception, e: + except Exception as e: self.assert_(fail, '%s: %s' % (e.__class__, e)) - print "Expected failure: %s: %s" % (e.__class__, e) + print("Expected failure: %s: %s" % (e.__class__, e)) else: self.assert_(not fail, 'Expected failure but succeeded?!') self.assertEquals(val, ret) self.assertEquals(1, ret.variant_level) def testBusInstanceCaching(self): - print "\n********* Testing dbus.Bus instance sharing *********" + print("\n********* Testing dbus.Bus instance sharing *********") # unfortunately we can't test the system bus here # but the codepaths are the same for (cls, type, func) in ((dbus.SessionBus, dbus.Bus.TYPE_SESSION, dbus.Bus.get_session), (dbus.StarterBus, dbus.Bus.TYPE_STARTER, dbus.Bus.get_starter)): - print "\nTesting %s:" % cls.__name__ + print("\nTesting %s:" % cls.__name__) share_cls = cls() share_type = dbus.Bus(bus_type=type) @@ -318,24 +325,24 @@ private_type = dbus.Bus(bus_type=type, private=True) private_func = func(private=True) - print " - checking shared instances are the same..." + print(" - checking shared instances are the same...") self.assert_(share_cls == share_type, '%s should equal %s' % (share_cls, share_type)) self.assert_(share_type == share_func, '%s should equal %s' % (share_type, share_func)) - print " - checking private instances are distinct from the shared instance..." + print(" - checking private instances are distinct from the shared instance...") self.assert_(share_cls != private_cls, '%s should not equal %s' % (share_cls, private_cls)) self.assert_(share_type != private_type, '%s should not equal %s' % (share_type, private_type)) self.assert_(share_func != private_func, '%s should not equal %s' % (share_func, private_func)) - print " - checking private instances are distinct from each other..." + print(" - checking private instances are distinct from each other...") self.assert_(private_cls != private_type, '%s should not equal %s' % (private_cls, private_type)) self.assert_(private_type != private_func, '%s should not equal %s' % (private_type, private_func)) self.assert_(private_func != private_cls, '%s should not equal %s' % (private_func, private_cls)) def testSenderName(self): - print '\n******** Testing sender name keyword ********' + print('\n******** Testing sender name keyword ********') myself = self.iface.WhoAmI() - print "I am", myself + print("I am", myself) def testBusGetNameOwner(self): ret = self.bus.get_name_owner(NAME) @@ -354,7 +361,7 @@ self.assert_(not self.bus.name_has_owner('badger.mushroom.snake')) def testBusNameCreation(self): - print '\n******** Testing BusName creation ********' + print('\n******** Testing BusName creation ********') test = [('org.freedesktop.DBus.Python.TestName', True), ('org.freedesktop.DBus.Python.TestName', True), ('org.freedesktop.DBus.Python.InvalidName&^*%$', False)] @@ -369,23 +376,23 @@ names = {} for (name, succeed) in test: try: - print "requesting %s" % name + print("requesting %s" % name) busname = dbus.service.BusName(name, dbus.SessionBus()) - except Exception, e: - print "%s:\n%s" % (e.__class__, e) + except Exception as e: + print("%s:\n%s" % (e.__class__, e)) self.assert_(not succeed, 'did not expect registering bus name %s to fail' % name) else: - print busname + print(busname) self.assert_(succeed, 'expected registering bus name %s to fail'% name) if name in names: self.assert_(names[name] == busname, 'got a new instance for same name %s' % name) - print "instance of %s re-used, good!" % name + print("instance of %s re-used, good!" % name) else: names[name] = busname del busname - print + print() del names @@ -462,7 +469,7 @@ self.assertRaises(dbus.DBusException, self.iface.AsyncRaise) try: self.iface.AsyncRaise() - except dbus.DBusException, e: + except dbus.DBusException as e: self.assert_(e.get_dbus_name() == 'org.freedesktop.bugzilla.bug12403', e.get_dbus_name()) @@ -518,7 +525,7 @@ try: self.iface.RaiseValueError() - except Exception, e: + except Exception as e: self.assert_(isinstance(e, dbus.DBusException), e.__class__) self.assert_('.ValueError: Traceback ' in str(e), 'Wanted a traceback but got:\n"""%s"""' % str(e)) @@ -527,7 +534,7 @@ try: self.iface.RaiseDBusExceptionNoTraceback() - except Exception, e: + except Exception as e: self.assert_(isinstance(e, dbus.DBusException), e.__class__) self.assertEquals(str(e), 'com.example.Networking.ServerError: ' @@ -537,7 +544,7 @@ try: self.iface.RaiseDBusExceptionWithTraceback() - except Exception, e: + except Exception as e: self.assert_(isinstance(e, dbus.DBusException), e.__class__) self.assert_(str(e).startswith('com.example.Misc.RealityFailure: ' 'Traceback '), === modified file 'test/test-p2p.py' --- test/test-p2p.py 2007-09-28 10:28:26 +0000 +++ test/test-p2p.py 2011-12-05 20:20:41 +0000 @@ -24,22 +24,22 @@ # DEALINGS IN THE SOFTWARE. -import sys import os import unittest -import time import logging -import weakref builddir = os.path.normpath(os.environ["DBUS_TOP_BUILDDIR"]) pydir = os.path.normpath(os.environ["DBUS_TOP_SRCDIR"]) import dbus -import _dbus_bindings import gobject import dbus.glib import dbus.service +from dbus import keywords + +from dbus import is_py3 + logging.basicConfig() logging.getLogger().setLevel(1) @@ -61,8 +61,10 @@ unique = conn.call_blocking('org.freedesktop.DBus', '/org/freedesktop/DBus', 'org.freedesktop.DBus', 'Hello', - '', (), utf8_strings=True) - self.assert_(unique.__class__ == dbus.UTF8String, repr(unique)) + '', (), + **keywords(utf8_strings=True)) + if not is_py3: + self.assert_(unique.__class__ == dbus.UTF8String, repr(unique)) self.assert_(unique.startswith(':'), unique) conn.set_unique_name(unique) return conn, unique @@ -83,7 +85,7 @@ conn, unique = self.get_conn_and_unique() ret = conn.call_blocking(NAME, OBJECT, IFACE, 'MethodExtraInfoKeywords', '', (), - utf8_strings=True) + **keywords(utf8_strings=True)) self.assertEquals(ret, (unique, OBJECT, NAME, 'dbus.lowlevel.MethodCallMessage')) === modified file 'test/test-service.py' --- test/test-service.py 2008-07-17 12:00:15 +0000 +++ test/test-service.py 2011-12-05 15:51:40 +0000 @@ -23,7 +23,6 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. -import sys import os import logging from time import sleep @@ -38,10 +37,11 @@ import dbus.service import dbus.glib -import gobject +from gi.repository import GObject as gobject import random from dbus.gobject_service import ExportedGObject +from dbus import keywords logging.basicConfig(filename=builddir + '/test/test-service.log', filemode='w') @@ -140,7 +140,8 @@ assert isinstance(foo, unicode), (foo, foo.__class__.__mro__) return foo - @dbus.service.method(IFACE, in_signature='s', out_signature='s', utf8_strings=True) + @dbus.service.method(IFACE, in_signature='s', out_signature='s', + **keywords(utf8_strings=True)) def AcceptUTF8String(self, foo): assert isinstance(foo, str), (foo, foo.__class__.__mro__) return foo @@ -267,7 +268,7 @@ return_cb(variant) return False # do not run again - except Exception, e: + except Exception as e: error_cb(e) @dbus.service.method(IFACE, in_signature='', out_signature='s', sender_keyword='sender') === modified file 'test/test-standalone.py' --- test/test-standalone.py 2010-11-23 19:17:19 +0000 +++ test/test-standalone.py 2011-12-05 20:15:00 +0000 @@ -26,11 +26,11 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. +from __future__ import unicode_literals + import sys import os import unittest -import time -from traceback import print_exc builddir = os.path.normpath(os.environ["DBUS_TOP_BUILDDIR"]) pydir = os.path.normpath(os.environ["DBUS_TOP_SRCDIR"]) @@ -38,6 +38,14 @@ import _dbus_bindings import dbus import dbus.types as types +from dbus import is_py3, keywords + +if is_py3: + def make_long(n): + return n +else: + def make_long(n): + return long(n) # Check that we're using the right versions if not dbus.__file__.startswith(pydir): @@ -57,83 +65,95 @@ class TestTypes(unittest.TestCase): def test_Dictionary(self): - self.assertEquals(types.Dictionary({'foo':'bar'}), {'foo':'bar'}) - self.assertEquals(types.Dictionary({}, variant_level=2), {}) - self.assertEquals(types.Dictionary({}, variant_level=2).variant_level, 2) + self.assertEqual(types.Dictionary({'foo':'bar'}), {'foo':'bar'}) + self.assertEqual(types.Dictionary({}, variant_level=2), {}) + self.assertEqual(types.Dictionary({}, variant_level=2).variant_level, 2) def test_Array(self): - self.assertEquals(types.Array(['foo','bar']), ['foo','bar']) - self.assertEquals(types.Array([], variant_level=2), []) - self.assertEquals(types.Array([], variant_level=2).variant_level, 2) + self.assertEqual(types.Array(['foo','bar']), ['foo','bar']) + self.assertEqual(types.Array([], variant_level=2), []) + self.assertEqual(types.Array([], variant_level=2).variant_level, 2) def test_Double(self): - self.assertEquals(types.Double(0.0), 0.0) - self.assertEquals(types.Double(0.125, variant_level=2), 0.125) - self.assertEquals(types.Double(0.125, variant_level=2).variant_level, 2) + self.assertEqual(types.Double(0.0), 0.0) + self.assertEqual(types.Double(0.125, variant_level=2), 0.125) + self.assertEqual(types.Double(0.125, variant_level=2).variant_level, 2) def test_Struct(self): x = types.Struct(('',)) - self.assertEquals(x.variant_level, 0) - self.assertEquals(x, ('',)) + self.assertEqual(x.variant_level, 0) + self.assertEqual(x, ('',)) x = types.Struct('abc', variant_level=42) - self.assertEquals(x.variant_level, 42) - self.assertEquals(x, ('a','b','c')) + self.assertEqual(x.variant_level, 42) + self.assertEqual(x, ('a','b','c')) def test_Byte(self): - self.assertEquals(types.Byte('x', variant_level=2), types.Byte(ord('x'))) + self.assertEqual(types.Byte('x', variant_level=2), types.Byte(ord('x'))) def test_ByteArray(self): - self.assertEquals(types.ByteArray(''), '') + self.assertEqual(types.ByteArray(b''), b'') def test_object_path_attr(self): class MyObject(object): __dbus_object_path__ = '/foo' from _dbus_bindings import SignalMessage - self.assertEquals(SignalMessage.guess_signature(MyObject()), 'o') + self.assertEqual(SignalMessage.guess_signature(MyObject()), 'o') def test_integers(self): - # This is an API guarantee. Note that exactly which of these types - # are ints and which of them are longs is *not* guaranteed. + # This is an API guarantee. Python 2 note: exactly which of these + # types are ints and which of them are longs is *not* guaranteed. + subclasses = [int] + if not is_py3: + subclasses.append(long) + subclasses = tuple(subclasses) for cls in (types.Int16, types.UInt16, types.Int32, types.UInt32, - types.Int64, types.UInt64): - self.assert_(issubclass(cls, (int, long))) - self.assert_(isinstance(cls(0), (int, long))) - self.assertEquals(cls(0), 0) - self.assertEquals(cls(23, variant_level=1), 23) - self.assertEquals(cls(23, variant_level=1).variant_level, 1) + types.Int64, types.UInt64): + self.assertTrue(issubclass(cls, subclasses)) + self.assertTrue(isinstance(cls(0), subclasses)) + self.assertEqual(cls(0), 0) + self.assertEqual(cls(23, variant_level=1), 23) + self.assertEqual(cls(23, variant_level=1).variant_level, 1) def test_integer_limits_16(self): - self.assertEquals(types.Int16(0x7fff), 0x7fff) - self.assertEquals(types.Int16(-0x8000), -0x8000) - self.assertEquals(types.UInt16(0xffff), 0xffff) + self.assertEqual(types.Int16(0x7fff), 0x7fff) + self.assertEqual(types.Int16(-0x8000), -0x8000) + self.assertEqual(types.UInt16(0xffff), 0xffff) self.assertRaises(Exception, types.Int16, 0x8000) self.assertRaises(Exception, types.Int16, -0x8001) self.assertRaises(Exception, types.UInt16, 0x10000) def test_integer_limits_32(self): - self.assertEquals(types.Int32(0x7fffffff), 0x7fffffff) - self.assertEquals(types.Int32(-0x80000000L), -0x80000000L) - self.assertEquals(types.UInt32(0xffffffffL), 0xffffffffL) - self.assertRaises(Exception, types.Int32, 0x80000000L) - self.assertRaises(Exception, types.Int32, -0x80000001L) - self.assertRaises(Exception, types.UInt32, 0x100000000L) + self.assertEqual(types.Int32(0x7fffffff), 0x7fffffff) + self.assertEqual(types.Int32(make_long(-0x80000000)), + make_long(-0x80000000)) + self.assertEqual(types.UInt32(make_long(0xffffffff)), + make_long(0xffffffff)) + self.assertRaises(Exception, types.Int32, make_long(0x80000000)) + self.assertRaises(Exception, types.Int32, make_long(-0x80000001)) + self.assertRaises(Exception, types.UInt32, make_long(0x100000000)) def test_integer_limits_64(self): - self.assertEquals(types.Int64(0x7fffffffffffffffL), 0x7fffffffffffffffL) - self.assertEquals(types.Int64(-0x8000000000000000L), -0x8000000000000000L) - self.assertEquals(types.UInt64(0xffffffffffffffffL), 0xffffffffffffffffL) - self.assertRaises(Exception, types.Int16, 0x8000000000000000L) - self.assertRaises(Exception, types.Int16, -0x8000000000000001L) - self.assertRaises(Exception, types.UInt16, 0x10000000000000000L) + self.assertEqual(types.Int64(make_long(0x7fffffffffffffff)), + make_long(0x7fffffffffffffff)) + self.assertEqual(types.Int64(make_long(-0x8000000000000000)), + make_long(-0x8000000000000000)) + self.assertEqual(types.UInt64(make_long(0xffffffffffffffff)), + make_long(0xffffffffffffffff)) + self.assertRaises(Exception, types.Int16, + make_long(0x8000000000000000)) + self.assertRaises(Exception, types.Int16, + make_long(-0x8000000000000001)) + self.assertRaises(Exception, types.UInt16, + make_long(0x10000000000000000)) def test_Signature(self): self.assertRaises(Exception, types.Signature, 'a') - self.assertEquals(types.Signature('ab', variant_level=23), 'ab') - self.assert_(isinstance(types.Signature('ab'), str)) - self.assertEquals(tuple(types.Signature('ab(xt)a{sv}')), + self.assertEqual(types.Signature('ab', variant_level=23), 'ab') + self.assertTrue(isinstance(types.Signature('ab'), str)) + self.assertEqual(tuple(types.Signature('ab(xt)a{sv}')), ('ab', '(xt)', 'a{sv}')) - self.assert_(isinstance(tuple(types.Signature('ab'))[0], - types.Signature)) + self.assertTrue(isinstance(tuple(types.Signature('ab'))[0], + types.Signature)) class TestMessageMarshalling(unittest.TestCase): @@ -158,7 +178,7 @@ 'should fail') def test_append(self): - aeq = self.assertEquals + aeq = self.assertEqual from _dbus_bindings import SignalMessage s = SignalMessage('/', 'foo.bar', 'baz') s.append([types.Byte(1)], signature='ay') @@ -170,22 +190,22 @@ aeq(s.get_args_list(), [[]]) def test_append_ByteArray(self): - aeq = self.assertEquals + aeq = self.assertEqual from _dbus_bindings import SignalMessage s = SignalMessage('/', 'foo.bar', 'baz') - s.append(types.ByteArray('ab'), signature='ay') - aeq(s.get_args_list(), [[types.Byte('a'), types.Byte('b')]]) - s = SignalMessage('/', 'foo.bar', 'baz') - s.append(types.ByteArray('ab'), signature='av') - aeq(s.get_args_list(), [[types.Byte('a'), types.Byte('b')]]) - s = SignalMessage('/', 'foo.bar', 'baz') - s.append(types.ByteArray(''), signature='ay') + s.append(types.ByteArray(b'ab'), signature='ay') + aeq(s.get_args_list(), [[types.Byte('a'), types.Byte('b')]]) + s = SignalMessage('/', 'foo.bar', 'baz') + s.append(types.ByteArray(b'ab'), signature='av') + aeq(s.get_args_list(), [[types.Byte('a'), types.Byte('b')]]) + s = SignalMessage('/', 'foo.bar', 'baz') + s.append(types.ByteArray(b''), signature='ay') aeq(s.get_args_list(), [[]]) - aeq(s.get_args_list(byte_arrays=True), [types.ByteArray('')]) + aeq(s.get_args_list(byte_arrays=True), [types.ByteArray(b'')]) def test_append_Variant(self): - a = self.assert_ - aeq = self.assertEquals + a = self.assertTrue + aeq = self.assertEqual from _dbus_bindings import SignalMessage s = SignalMessage('/', 'foo.bar', 'baz') s.append(types.Int32(1, variant_level=0), @@ -205,7 +225,7 @@ aeq(args[2].signature, 'v') def test_guess_signature(self): - aeq = self.assertEquals + aeq = self.assertEqual from _dbus_bindings import Message aeq(Message.guess_signature(('a','b')), '(ss)') aeq(Message.guess_signature('a','b'), 'ss') @@ -213,13 +233,13 @@ aeq(Message.guess_signature(('a',)), '(s)') aeq(Message.guess_signature('abc'), 's') aeq(Message.guess_signature(types.Int32(123)), 'i') - aeq(Message.guess_signature(types.ByteArray('abc')), 'ay') + aeq(Message.guess_signature(types.ByteArray(b'abc')), 'ay') aeq(Message.guess_signature(('a',)), '(s)') aeq(Message.guess_signature(['a']), 'as') aeq(Message.guess_signature({'a':'b'}), 'a{ss}') def test_guess_signature_dbus_types(self): - aeq = self.assertEquals + aeq = self.assertEqual from _dbus_bindings import Message gs = Message.guess_signature aeq(gs(types.Dictionary({'a':'b'})), 'a{ss}') @@ -229,12 +249,12 @@ aeq(gs(types.Array([types.Int32(1)], signature='u')), 'au') def test_get_args_options(self): - aeq = self.assertEquals + aeq = self.assertEqual s = _dbus_bindings.SignalMessage('/', 'foo.bar', 'baz') s.append('b', 'bytes', -1, 1, 'str', 'var', signature='yayiusv') aeq(s.get_args_list(), [ord('b'), [ord('b'),ord('y'),ord('t'),ord('e'), ord('s')], - -1, 1, u'str', u'var']) + -1, 1, 'str', 'var']) byte, bytes, int32, uint32, string, variant = s.get_args_list() aeq(byte.__class__, types.Byte) aeq(bytes.__class__, types.Array) @@ -250,8 +270,11 @@ byte_arrays=True) aeq(byte.__class__, types.Byte) aeq(bytes.__class__, types.ByteArray) - aeq(bytes, 'bytes') - aeq(bytes[0].__class__, str) + aeq(bytes, b'bytes') + if is_py3: + aeq(bytes[0].__class__, int) + else: + aeq(bytes[0].__class__, str) aeq(int32.__class__, types.Int32) aeq(uint32.__class__, types.UInt32) aeq(string.__class__, types.String) @@ -259,15 +282,17 @@ aeq(variant.variant_level, 1) byte, bytes, int32, uint32, string, variant = s.get_args_list( - utf8_strings=True) + **keywords(utf8_strings=True)) aeq(byte.__class__, types.Byte) aeq(bytes.__class__, types.Array) aeq(bytes[0].__class__, types.Byte) aeq(int32.__class__, types.Int32) aeq(uint32.__class__, types.UInt32) - aeq(string.__class__, types.UTF8String) + if not is_py3: + aeq(string.__class__, types.UTF8String) aeq(string, 'str') - aeq(variant.__class__, types.UTF8String) + if not is_py3: + aeq(variant.__class__, types.UTF8String) aeq(variant.variant_level, 1) aeq(variant, 'var') @@ -278,7 +303,7 @@ s = SignalMessage('/', 'foo.bar', 'baz') s.append(MyObject(), signature='o') s.append(MyObject()) - self.assertEquals(s.get_args_list(), ['/foo', '/foo']) + self.assertEqual(s.get_args_list(), ['/foo', '/foo']) def test_struct(self): from _dbus_bindings import SignalMessage @@ -301,4 +326,8 @@ if __name__ == '__main__': - unittest.main() + # Python 2.6 doesn't accept a `verbosity` keywords + kw = {} + if sys.version_info[:2] >= (2, 7): + kw['verbosity'] = 2 + unittest.main(**kw) === modified file 'test/test-unusable-main-loop.py' --- test/test-unusable-main-loop.py 2007-09-27 12:57:49 +0000 +++ test/test-unusable-main-loop.py 2011-12-05 16:04:05 +0000 @@ -22,6 +22,8 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. +from __future__ import print_function + import dbus from dbus_py_test import UnusableMainLoop @@ -30,8 +32,8 @@ UnusableMainLoop(set_as_default=True) try: bus = dbus.SessionBus() - except ValueError, e: - print "Correctly got ValueError from UnusableMainLoop" + except ValueError as e: + print("Correctly got ValueError from UnusableMainLoop") else: raise AssertionError("Expected ValueError from UnusableMainLoop")