Git Product home page Git Product logo

txdbus's People

Contributors

arturgaspar avatar cocagne avatar dlech avatar exvito avatar geertj avatar jaakkomoller avatar kaharlichenko avatar mineo avatar mk-fg avatar oeh041 avatar pyrrvs avatar rheenen avatar rrerolle avatar varzac avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

txdbus's Issues

string vs bytes type checking/handling

Split out from #11

The way the type checking is done in the code base problematic. Take this line:

if not isinstance(var, six.string_types):
    raise MarshallingError('Required string. Received: ' + repr(var))

The problem is, on Python 2 this will always evaluate to False! For both bytes and unicode strings.

(cpy361_7) oberstet@thinkpad-t430s:~/scm/crossbario/crossbar-fabric-device-agent$ python2
Python 2.7.12 (default, Nov 19 2016, 06:48:10) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import six
>>> six.text_type
<type 'unicode'>
>>> six.binary_type
<type 'str'>
>>> type(b'hello') == six.binary_type
True
>>> type(b'hello') == six.text_type
False
>>> six.string_types
(<type 'basestring'>,)
>>> isinstance(u'hello', six.string_types)
True
>>> isinstance(b'hello', six.string_types)
True
>>> 
(cpy361_7) oberstet@thinkpad-t430s:~/scm/crossbario/crossbar-fabric-device-agent$ python
Python 3.6.1 (default, Apr  2 2017, 18:19:20) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import six
>>> six.text_type
<class 'str'>
>>> six.binary_type
<class 'bytes'>
>>> type(b'hello') == six.binary_type
True
>>> type(b'hello') == six.text_type
False
>>> six.string_types
(<class 'str'>,)
>>> isinstance(u'hello', six.string_types)
True
>>> isinstance(b'hello', six.string_types)
False
>>> 

The reason is, that on Python 2, both str (bytes) and unicode derive of basestring (https://pythonhosted.org/six/#six.string_types, https://docs.python.org/2/library/functions.html#basestring).

The right way to check is via six.text_type and six.binary_type. See above.

Missing 1.1.0 release

Hello

I noticed that you updated to version 1.1.0 on PyPI, but not in the git repository. Can you add a release tag for this? This is important for us because we build from source.

Thanks!
Brecht

ValueError is raised when annotated functions are used

When a method is called with annotated variables, then the following error message is returned:

org.txdbus.PythonException.ValueError: Function has keyword-only arguments or annotations, use getfullargspec() API which can support them

This is because getargspec does not support the new signature formats of keyword-only arguments and annotations. This issue is easily fixed:

In file txdbus/objects.py line 488 replace

    def _set_method_flags(self, method_obj):
        """
        Sets the \"_dbusCaller\" boolean on the \"dbus_*\" methods. This
        is a one-time operation used to flag each method with a boolean
        indicating whether or not they accept the \"dbusCaller\" keyword
        argument
        """
        args = inspect.getargspec(method_obj)[0]
        needs_caller = False

        if len(args) >= 1 and args[-1] == 'dbusCaller':
            needs_caller = True

        method_obj.__func__._dbusCaller = needs_caller

by:

    def _set_method_flags(self, method_obj):
        """
        Sets the \"_dbusCaller\" boolean on the \"dbus_*\" methods. This
        is a one-time operation used to flag each method with a boolean
        indicating whether or not they accept the \"dbusCaller\" keyword
        argument
        """
        try:
            args = inspect.getfullargspec(method_obj)[0]
        except AttributeError:
            args = inspect.getargspec(method_obj)[0]
        needs_caller = False

        if len(args) >= 1 and args[-1] == 'dbusCaller':
            needs_caller = True

        method_obj.__func__._dbusCaller = needs_caller

This maintains backwards compatibility with python2 and supports the new signatures introduced in python3.

missing early dbus signals

The example code in doc/examples/avahi_browse fails to notice some of the early dbus signals.

When I first start avahi_browse and then avahi_publish, everything works fine.
The browser correctly receives the ItemNew signal sent by the Avahi server.

When I first start avahi_publish and then avahi_browse, then the browser does not recognize the ItemNew signal.
The ItemNew signal is however sent by the Avahi server, as one can detect by monitoring the system bus.

I suspect a race condition here: When a new ServiceBrowser is created by calling ServiceBrowserNew, ItemNew is sent by Avahi before we can set the callback via

self.browser.notifyOnSignal('ItemNew', self.new_service)

So, in general, how do I catch all of the signals of a remote object after creating that object?

publishing an Object on a session-bus

I wrote two scripts which publish one object each on a session-bus with bus name "de.test.objectbus".
When I execute one of the scripts the objects are perfectly published and I can execute all of the remote methods specified by the interfaces. The interfaces have different names and the object have different object-paths.

My question: Is it possible to publish an remote object on a session-bus which has already been created with the reactor running? Or do I have to publish all objects on that bus before I start the reactor?

dbus auth protocol compatiblity issues

I am running on a centos 5 system and python 2.6.8 (python26) and dbus authentication does not work smoothly. In particular mechanism EXTERNAL never succeeds. It appears the root cause is the client and server not being in sync early in the auth sequence, and EXTERNAL being first in the order gets discarded.

After brief investigation it appears the ClientAuthenticator implementation might not be ideal. It might benefit from sending an empty AUTH which should give a server response listing mechanisms, and get client and server in sync right away.

The dbus server on this centos 5 system rejects the first auth attempt from txdbus which by default tries EXTERNAL. Seeing errors returned like "Not currently in an auth conversation" is a key diagnostic.

I got it to work by adding a second EXTERNAL after the first in the 'preference' member variable. Not a preferred solution, but it is diagnostic.

variant ('v') type does not handle {1: True, 2:False}

At least, in python2 (where isinstance(True, int) is True) If I try to serialize {1: True, 2:False} as DBUS's variant, it is really serialized as {1: 1, 2:0}.

And also txdbus allows mix of types in such dicts., for example, {1:'s', 'd': True}

Method interface, is it not complete, how to put async callback?

Hi

Browsing to the code, it looks like Method interface is not complete. In ur code u have implemented
Method('exampleMethod', arguments='s', returns='s' )
So it takes arguments and returns only...
But the original package is

http://dbus.freedesktop.org/doc/dbus-python/api/dbus.decorators-module.html

We have decorators which takes many additional param.
For example I need async_callback to be added and I would implement what would happen if the remote call lead to error.
In normal python package, I do

<
@method(MY_INTFACE, in_signature='', out_signature='', async_callbacks=('async_cb', 'async_eb'))
def DoSomething(self, async_cb, async_eb):
"""Do Something"""
d = self.remote.doSomething()
return self.add_callbacks(d, async_cb, async_eb)
/>

How can I achieve similar thing in tx_dbus.

class MyObj (objects.DBusObject):

iface = DBusInterface('org.example.MyIFace',
                      Method('exampleMethod', arguments='s', returns='s' )) --> Here I cant add async_callback param which I can pass 

Roundtrip tests between different Py versions

Split out from #11

I only have sketchy knowledge about dbus and stuff, haven't looked deeply enough into the txdbus codebase, but are the unit tests actually talk to a real dbus? and if so, are there tests that

  • roundtrip Py2 -> dbus -> Py2 (and Py3 -> dbus -> Py3) - eg both a proc implemented in Py and called from Py
  • roundtrip Py2 -> dbus -> Py3 (and Py3 -> dbus -> Py2)

What I meant with round-tripping is between different Python versions.

Like have a procedure implemented in Python 3, exposed via Dbus, and being called from Python 2.

Where the procedure name is a fancy Unicode name, and/or the procedure takes an Unicode argument (and the test actually uses non-US-ASCII characters) and/or the procedure takes a binary argument (and the test actually uses a binary value which isn't valid UTF8).

Simplify/eliminate callRemote

I was thinking it may be better to eliminate the use of callRemote in txdbus. This would mean that D-Bus remote objects are first-class Python objects, which makes RPC interfaces much simpler, and don't need any glue to talk over the D-Bus.

How I've implemented this in my own code is with something like this:

class DBusRemoteWrapperMethod(object):
    """
    Wrapper for methods for interface.callRemote
    """
    def __init__(self, obj, methname):
        self._obj = obj
        self._methname = methname


    def __call__(self, *args, **kwargs):
        return self._obj.callRemote(self._methname, *args, **kwargs)


class DBusRemoteWrapper(object):
    """
    Wrapper for interfaces that makes everything a callRemote.

    """
    def __init__(self, obj):
        self._obj = obj

    def __getattr__(self, name):
        return DBusRemoteWrapperMethod(self._obj, name)

# (setup reactor here, omitted for simplicity)

@defer.inlineCallbacks
def main():
    conn = yield client.connect(reactor, 'session')
    obj = yield conn.getRemoteObject(DBUS_SERVICE, DBUS_PATH)

    # Add callRemote wrapper
    api = DBusRemoteWrapper(obj)

    # Now we can execute methods directly on the DBus object as if it was
    # a normal Python class...
    yield api.my_method()
    result = yield api.do_other_things('bar', 123)

There's a some limitations to my implementation as it stands:

  • Members are generated dynamically, and it does not check or expose the org.freedesktop.DBus.Introspection interface in order to be smart about this (and populate things like __all__.
  • This doesn't support wrapping org.freedesktop.DBus.Properties to Python properties.
  • This doesn't support handling other interfaces of the object.

There's one major limitation to my implementation as it stands is that it can't handle org.freedesktop.DBus.Properties interface wrapping to a Python property. This would require a little bit more glue in order to handle this.

With o.fd.DB.Properties implementation, it would allow even more interaction like a normal Python object:

api.MyProperty = 6
while api.BottleCount > 0:
  api.BottleCount -= 1

This would make txdbus work a little more like python-dbus, and other RPC mechanisms like Python's XMLRPC module in the standard library (ServiceProxy).

When some function returns struct, result is wrapped to extra list.

Suppose this:

...
Method('structMethod', arguments='(si)', returns='(is)')
...
def dbus_structMethod(self, arg):
        print 'swapping and returning swapped struct'
        return (arg[1], arg[0])

When I call it:

res = yield qwe.callRemote('structMethod', ('x', 69))

I expect [69, 'x'] in res, but actually I see [[69, 'x']]

Port to txaio?

Note: opening a new issue to avoid polluting the other one, which is about Python 3 after all.

Over at #11 (comment), you mentioned you'd be interested in having txdbus work with both twisted and asyncio.

How about porting txdbus to txaio?

That would achieve compatibility with asyncio and twisted.

setting invalid properties to connman service causes txdbus client to disconnect (cleanly)

I'm trying to call SetProperty of a connman service, and it works fine if params are ok, when I use invalid params txdbus client apparently disconnects cleanly

I've defined a custom datatype:

class VariantList(list):
    dbusSignature = 'a(v)'

here is the debug log:

2017-05-22T18:06:38+0200 [twisted.internet.defer#critical] Unhandled error in Deferred:
2017-05-22T18:06:38+0200 [twisted.internet.defer#critical] (debug:  C: Deferred was created:
	 C:  File "/root/venv/bin/twistd", line 18, in <module>
	 C:    run()
	 C:  File "/root/venv/local/lib/python2.7/site-packages/twisted/scripts/twistd.py", line 29, in run
	 C:    app.run(runApp, ServerOptions)
	 C:  File "/root/venv/local/lib/python2.7/site-packages/twisted/application/app.py", line 643, in run
	 C:    runApp(config)
	 C:  File "/root/venv/local/lib/python2.7/site-packages/twisted/scripts/twistd.py", line 25, in runApp
	 C:    _SomeApplicationRunner(config).run()
	 C:  File "/root/venv/local/lib/python2.7/site-packages/twisted/application/app.py", line 378, in run
	 C:    self.postApplication()
	 C:  File "/root/venv/local/lib/python2.7/site-packages/twisted/scripts/_twistd_unix.py", line 222, in postApplication
	 C:    self.startReactor(None, self.oldstdout, self.oldstderr)
	 C:  File "/root/venv/local/lib/python2.7/site-packages/twisted/application/app.py", line 390, in startReactor
	 C:    self.config, oldstdout, oldstderr, self.profiler, reactor)
	 C:  File "/root/venv/local/lib/python2.7/site-packages/twisted/application/app.py", line 311, in runReactorWithLogging
	 C:    reactor.run()
	 C:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/base.py", line 1194, in run
	 C:    self.mainLoop()
	 C:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/base.py", line 1203, in mainLoop
	 C:    self.runUntilCurrent()
	 C:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/base.py", line 825, in runUntilCurrent
	 C:    call.func(*call.args, **call.kw)
	 C:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 1274, in unwindGenerator
	 C:    return _inlineCallbacks(None, gen, Deferred())
	 I: First Invoker was:
	 I:  File "/root/venv/bin/twistd", line 18, in <module>
	 I:    run()
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/scripts/twistd.py", line 29, in run
	 I:    app.run(runApp, ServerOptions)
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/application/app.py", line 643, in run
	 I:    runApp(config)
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/scripts/twistd.py", line 25, in runApp
	 I:    _SomeApplicationRunner(config).run()
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/application/app.py", line 378, in run
	 I:    self.postApplication()
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/scripts/_twistd_unix.py", line 222, in postApplication
	 I:    self.startReactor(None, self.oldstdout, self.oldstderr)
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/application/app.py", line 390, in startReactor
	 I:    self.config, oldstdout, oldstderr, self.profiler, reactor)
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/application/app.py", line 311, in runReactorWithLogging
	 I:    reactor.run()
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/base.py", line 1194, in run
	 I:    self.mainLoop()
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/base.py", line 1206, in mainLoop
	 I:    self.doIteration(t)
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/epollreactor.py", line 396, in doPoll
	 I:    log.callWithLogger(selectable, _drdw, selectable, fd, event)
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/python/log.py", line 101, in callWithLogger
	 I:    return callWithContext({"system": lp}, func, *args, **kw)
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/python/log.py", line 84, in callWithContext
	 I:    return context.call({ILogContext: newCtx}, func, *args, **kw)
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/python/context.py", line 118, in callWithContext
	 I:    return self.currentContext().callWithContext(ctx, func, *args, **kw)
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/python/context.py", line 81, in callWithContext
	 I:    return func(*args,**kw)
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/posixbase.py", line 610, in _doReadOrWrite
	 I:    self._disconnectSelectable(selectable, why, inRead)
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/posixbase.py", line 252, in _disconnectSelectable
	 I:    selectable.readConnectionLost(f)
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/tcp.py", line 273, in readConnectionLost
	 I:    self.connectionLost(reason)
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/tcp.py", line 479, in connectionLost
	 I:    self._commonConnection.connectionLost(self, reason)
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/tcp.py", line 293, in connectionLost
	 I:    protocol.connectionLost(reason)
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/endpoints.py", line 129, in connectionLost
	 I:    return self._wrappedProtocol.connectionLost(reason)
	 I:  File "/root/venv/local/lib/python2.7/site-packages/txdbus/client.py", line 105, in connectionLost
	 I:    d.errback(reason)
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 434, in errback
	 I:    self._startRunCallbacks(fail)
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 501, in _startRunCallbacks
	 I:    self._runCallbacks()
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 588, in _runCallbacks
	 I:    current.result = callback(current.result, *args, **kw)
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 1184, in gotResult
	 I:    _inlineCallbacks(r, g, deferred)
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 1174, in _inlineCallbacks
	 I:    deferred.errback()
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 434, in errback
	 I:    self._startRunCallbacks(fail)
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 501, in _startRunCallbacks
	 I:    self._runCallbacks()
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 588, in _runCallbacks
	 I:    current.result = callback(current.result, *args, **kw)
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 1184, in gotResult
	 I:    _inlineCallbacks(r, g, deferred)
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 1174, in _inlineCallbacks
	 I:    deferred.errback()
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 434, in errback
	 I:    self._startRunCallbacks(fail)
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 501, in _startRunCallbacks
	 I:    self._runCallbacks()
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 588, in _runCallbacks
	 I:    current.result = callback(current.result, *args, **kw)
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 1184, in gotResult
	 I:    _inlineCallbacks(r, g, deferred)
	 I:  File "/root/venv/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 1174, in _inlineCallbacks
	 I:    deferred.errback()
	)

Traceback (most recent call last):
Failure: twisted.internet.error.ConnectionDone: Connection was closed cleanly.
2017-05-22T18:06:38+0200 [txdbus.client.DBusClientFactory#info] Stopping factory <txdbus.client.DBusClientFactory instance at 0x7f87a0690368>

and the dbus monitor output:

method call sender=:1.35 -> dest=net.connman serial=37 path=/net/connman/service/ethernet_080027b88135_cable; interface=org.freedesktop.DBus.Introspectable; member=Introspect
method return sender=:1.2 -> dest=:1.35 reply_serial=37
   string "<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node><interface name="org.freedesktop.DBus.Introspectable"><method name="Introspect"><arg name="xml" type="s" direction="out"/>
</method></interface><interface name="net.connman.Service"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
<annotation name="org.freedesktop.DBus.Deprecated" value="true"/></method><method name="SetProperty"><arg name="name" type="s" direction="in"/>
<arg name="value" type="v" direction="in"/>
</method><method name="ClearProperty"><arg name="name" type="s" direction="in"/>
</method><method name="Connect"></method><method name="Disconnect"></method><method name="Remove"></method><method name="MoveBefore"><arg name="service" type="o" direction="in"/>
</method><method name="MoveAfter"><arg name="service" type="o" direction="in"/>
</method><method name="ResetCounters"></method><signal name="PropertyChanged"><arg name="name" type="s"/>
<arg name="value" type="v"/>
</signal>
</interface></node>"
method call sender=:1.35 -> dest=net.connman serial=38 path=/net/connman/service/ethernet_080027b88135_cable; interface=net.connman.Service; member=SetProperty
   string "Domains.Configuration"
   variant       array [
         struct {
            variant                string "n"
         }
      ]
signal sender=:1.2 -> dest=(null destination) serial=683 path=/net/connman/service/ethernet_080027b88135_cable; interface=net.connman.Service; member=PropertyChanged
   string "Domains.Configuration"
   variant       array [
      ]
signal sender=:1.2 -> dest=(null destination) serial=684 path=/net/connman/service/ethernet_080027b88135_cable; interface=net.connman.Service; member=PropertyChanged
   string "Domains"
   variant       array [
      ]
method return sender=:1.2 -> dest=:1.35 reply_serial=38
method call sender=:1.35 -> dest=net.connman serial=39 path=/net/connman/service/ethernet_080027b88135_cable; interface=org.freedesktop.DBus.Introspectable; member=Introspect
method return sender=:1.2 -> dest=:1.35 reply_serial=39
   string "<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node><interface name="org.freedesktop.DBus.Introspectable"><method name="Introspect"><arg name="xml" type="s" direction="out"/>
</method></interface><interface name="net.connman.Service"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
<annotation name="org.freedesktop.DBus.Deprecated" value="true"/></method><method name="SetProperty"><arg name="name" type="s" direction="in"/>
<arg name="value" type="v" direction="in"/>
</method><method name="ClearProperty"><arg name="name" type="s" direction="in"/>
</method><method name="Connect"></method><method name="Disconnect"></method><method name="Remove"></method><method name="MoveBefore"><arg name="service" type="o" direction="in"/>
</method><method name="MoveAfter"><arg name="service" type="o" direction="in"/>
</method><method name="ResetCounters"></method><signal name="PropertyChanged"><arg name="name" type="s"/>
<arg name="value" type="v"/>
</signal>
</interface></node>"

Add txdbus.__version__

For logs, crash reports and version specific workarounds it would be nice to have the "standard" txdbus.__version__ variable. Could get it from $ pip3 show txdbus | grep Version but it is less pretty.

txdbus will not install if twisted pip installed at the same time

This is most common in a requirements file, from chris| on #twisted irc:

"before installing, pip runs egg_info on all packages and txdbus decides it is a good thing to just SystemExit() the setup if twisted is not there, even if it is not even needed"

Ideally twisted would be declared as a dependency correctly in the setup() call.

Cheers!

Create a new release on PyPI: 1.1.0

Latest release on PyPI is lacking the latest improvements, including Python 3 support and support for UNIX_FD function/method arguments, probably among others.

See #11 (comment) and #24 (comment).

Per those discussions, this should move forward once #61 is fixed which, in turn, declares #11 ready for release -- for the time being. :)

Not sure about the release numbering policy, any pointers?

Add support for `bytes`?

Sorry if this is stupid question, but could not bytes be added to the following tuple of supported types?

if isinstance(var, (list, tuple, bytearray)):

Currently this raises txdbus.error.MarshallingError: List, Tuple, Bytearray, or Dictionary required for DBus array if bytes are used.

UInt64 can't handle 2**64 - 1

Attempting to construct a UInt64(2 ** 64 - 1) fails with an OverflowError. I think Int64 and UInt64 should be be based on long, not int, as the latter is only guaranteed to fit 32 bits, signed. Even on x86_64 the signedness prevents its use for UInt64.

DBus service hang when you mix big and small endian dbus clients

I have several dbus client programs that connect to the same dbus server(implemented with txdbus). These client programs are written in different programming languages and I noticed java client uses big endian, and all others use little endian.

Using both big and little endian dbus clients to the same txdbus server at the same time cuases dbus service hang, and I resolved the issue as follow;

diff --git a/txdbus/protocol.py b/txdbus/protocol.py
index 946b652..db92340 100644
--- a/txdbus/protocol.py
+++ b/txdbus/protocol.py
@@ -112,6 +112,8 @@ class BasicDBusProtocol(protocol.Protocol):
             if self._nextMsgLen == 0 and buffer_len >= 16:
                 if self._buffer[:1] != b'l':
                     self._endian = '>'
+                else:
+                    self._endian = '<'

                 body_len = struct.unpack(self._endian + 'I', self._buffer[4:8]  )[0]
                 harr_len = struct.unpack(self._endian + 'I', self._buffer[12:16])[0]

Please review it and apply to upstream..
Thanks,

Py 3 does not have a long type

split out from #11

(cpy361_7) oberstet@thinkpad-t430s:~/scm/3rdparty/txdbus$ flake8 --select=F821 --show-source .
./txdbus/test/test_marshal.py:39:20: F821 undefined name 'long'
            self.t(long(1),'x')
                   ^

here:

(cpy361_7) oberstet@thinkpad-t430s:~/scm/crossbario/crossbario-organize/fibu$ python
Python 3.6.1 (default, Apr  2 2017, 18:19:20) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import six
>>> six.integer_types
(<class 'int'>,)
>>> 
(cpy361_7) oberstet@thinkpad-t430s:~/scm/crossbario/crossbario-organize/fibu$ python2
Python 2.7.12 (default, Nov 19 2016, 06:48:10) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import six
>>> six.integer_types
(<type 'int'>, <type 'long'>)
>>> 
KeyboardInterrupt
>>> 

Python 3 support

It would be good if at least parts of txdbus would work on Python 3.x. It makes integrating txdbus into my "gruvi" project easier. And I'd expect it'd be useful for the asyncio folks as well (And hopefully at some point Twisted will support Python 3 as well.)

I'm happy to contribute patches. However, the best way to support both Python 2.x and 3.x (which is generally accepted now in the Python community), is to have a single-source project that supports 2.6, 2.7 and 3.3+ (3.2 is possible as well but 3.3+ is easier).

So the question is... are you currently supporting Python 2.5 and if so are you willing to give up on that?

Add code linter to CI infrastructure

See #11 from #11 (comment) onwards.

I'd start with running a linter on CI but not failing on errors. From there, individual issues / PRs can be created and addressed with a somewhat narrow-focus (example: one issue fixes E111 indentation not a multiple of 4, etc.)

Once we get the "good enough" results (up to discussion?), then maybe linter failures could prevent PR merges.

Thoughts welcome.

Native test (ocasionally) fails

This is kinda hard to reproduce, since this test only fails sometimes (I'm guessing race condition or something alike).

It's txdbus.test.test_client_against_native_bus.SignalTester.test_shared_signal.

The easiest way to reproduce is running trial -u txdbus, which will run all tests in a loop, forever, until failure (it eventually fails).

Confirm integer marhsalling/unmarshalling

Creating this ticket as a follow-up of a not 100% clear matter identified in #65 (comment).

Facts:

  • DBus has several int types, singed/unsigned, from 8- to 64- bit wide.
  • Python 3 unified Python int and longs into a common int. In either case, these are arbitrariliy long and may not fit in a 64-bit wide representation.
  • With #11 and associated tickets some changes have been made which may affect this.

What I'm trying to account for:

  • This code appropriately marshals/unmarshals whichever ints (or longs, in Python 2) into the appropriate DBus types or "fails" in a documented way (i.e.: when marshalling a value that does not fit the destination DBus type).

Maybe this is all correct, maybe not. Just leaving this here for future reference and to be checked by someone (me, who knows?) in the future.

Plan:

  • Ensure tests exist for all combinations of DBus integer types and valid/invalid Python integers for each of those.

Test test_get_all_properties fails with given PYTHONHASHSEED

While exploring tox and testing in general, I found out that one particular test was failing unpredictably on my dev system, under Python 2.7.

I found a way of reproducing it by passing in a particular value for PYTHONHASHSEED.

I run the test with trial txdbus.test.test_client_against_native_bus.InterfaceTester.test_get_all_properties which will only run if a DBUS session is up. So, on my dev VM with no GUI, I actually run dbus-run-session trial txdbus.test.test_client_against_native_bus.InterfaceTester.test_get_all_properties. This runs successfully most of the time.

To force a failure, I need to set PYTHONHASHSEED to 3475844530 by running PYTHONHASHSEED=3475844530 dbus-run-session trial txdbus.test.test_client_against_native_bus.InterfaceTester.test_get_all_properties which consistently fails for me.

Taking a quick peek at the test itself, in txdbus/test/client_tests.py...

    def test_get_all_properties(self):

        def got_object(ro):
            return ro.callRemote('GetAll', '')

        def got_reply(reply):
            self.assertEquals(reply, {'common'   : 'common1',
                                      'prop1'    : 'foobar',
                                      'prop2'    : 5,
                                      'prop_if1' : 'pif1',
                                      'pwrite'   : 'orig'})

        return self.proxy_chain(got_object, got_reply)

...it is calling the GetAll method with an empty interface argument. Not being familiar with DBUS specifics, the behavior seems to be returning a "merged" result of two interfaces in TestClass at around line 1388: these are org.txdbus.trial.IFace1 and org.txdbus.trial.IFace2.

Given that both interfaces expose/declare a property named common, respectively supported by the common1 and common2 attributes in the class, it seems that for most cases of the test run, common1's value is returned, but for the particular PYTHONHASHSEED mentioned above, common2's value is returned and the test fails.

Questions on my mind at that point:

  1. First things first: what's the specification for the behaviour of GetAll when an empty interface argument is passed in? Is it supposed to merge/combine the existing interfaces? If so how?
  2. If GetAll should return a merged/combined list of all existing interfaces, and assuming that somehow order is important when facing overlapping names, then the current implementation needs fixing.
  3. If, otherwise, no such speficification for GetAll exists -- and, say, the result may be arbitrary (again, I have no idea) -- then the test may need to be adapted to account for that possibility.

Then I skimmed through https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-properties which apparently states that:

An empty string may be provided for the interface name; in this case, if there are multiple properties on an object with the same name, the results are undefined (picking one by according to an arbitrary deterministic rule, or returning an error, are the reasonable possibilities).

So, it seems 3. above is the case -- unless txdbus wants to be stricter in this scenario, of course. :)

Python2.7 tests fail

Running tox -e py27 passes, but there's lots of test failures. Looks like the script that runs the tests returns 0, even if tests failed:

$ tox -e py27
GLOB sdist-make: /home/hugo/workspace/Forks/txdbus/setup.py
py27 inst-nodeps: /home/hugo/workspace/Forks/txdbus/.tox/dist/txdbus-1.0.12.zip
py27 installed: appdirs==1.4.3,attrs==17.2.0,Automat==0.6.0,constantly==15.1.0,incremental==17.5.0,packaging==16.8,pyparsing==2.2.0,six==1.10.0,Twisted==17.1.0,txdbus==1.0.12,zope.interface==4.4.1
py27 runtests: PYTHONHASHSEED='61129722'
py27 runtests: commands[0] | python runtests.py
Internal bus tests are currently broken... skipping
.....................................EEEEEEEE.........................EUnhandled error in Deferred:

E..Unhandled Error
Traceback (most recent call last):
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/python/log.py", line 103, in callWithLogger
    return callWithContext({"system": lp}, func, *args, **kw)
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/python/log.py", line 86, in callWithContext
    return context.call({ILogContext: newCtx}, func, *args, **kw)
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/python/context.py", line 122, in callWithContext
    return self.currentContext().callWithContext(ctx, func, *args, **kw)
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/python/context.py", line 85, in callWithContext
    return func(*args,**kw)
--- <exception caught here> ---
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/posixbase.py", line 597, in _doReadOrWrite
    why = selectable.doRead()
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/unix.py", line 193, in doRead
    return self._dataReceived(data)
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/tcp.py", line 214, in _dataReceived
    rval = self.protocol.dataReceived(data)
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/endpoints.py", line 119, in dataReceived
    return self._wrappedProtocol.dataReceived(data)
  File "/home/hugo/workspace/Forks/txdbus/txdbus/test/test_authentication.py", line 387, in dataReceived
    self.gotMessage(line)
  File "/home/hugo/workspace/Forks/txdbus/txdbus/test/test_authentication.py", line 531, in recv1
    self.send('AUTH DBUS_COOKIE_SHA1 ' + binascii.hexlify(get_username()))
exceptions.TypeError: b2a_hex() argument 1 must be string or buffer, not None

FE........................................................................................
======================================================================
ERROR: test_launchd_address (txdbus.test.test_endpoints.EndpointsTester)
test_launchd_address
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/defer.py", line 150, in maybeDeferred
    result = f(*args, **kw)
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/utils.py", line 201, in runWithWarningsSuppressed
    reraise(exc_info[1], exc_info[2])
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/utils.py", line 197, in runWithWarningsSuppressed
    result = f(*a, **kw)
  File "/home/hugo/workspace/Forks/txdbus/txdbus/test/test_endpoints.py", line 13, in setUp
    self.pre_ses = os.environ['DBUS_SESSION_BUS_ADDRESS']
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/UserDict.py", line 40, in __getitem__
    raise KeyError(key)
KeyError: 'DBUS_SESSION_BUS_ADDRESS'

======================================================================
ERROR: test_multiple_addresses (txdbus.test.test_endpoints.EndpointsTester)
test_multiple_addresses
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/defer.py", line 150, in maybeDeferred
    result = f(*args, **kw)
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/utils.py", line 201, in runWithWarningsSuppressed
    reraise(exc_info[1], exc_info[2])
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/utils.py", line 197, in runWithWarningsSuppressed
    result = f(*a, **kw)
  File "/home/hugo/workspace/Forks/txdbus/txdbus/test/test_endpoints.py", line 13, in setUp
    self.pre_ses = os.environ['DBUS_SESSION_BUS_ADDRESS']
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/UserDict.py", line 40, in __getitem__
    raise KeyError(key)
KeyError: 'DBUS_SESSION_BUS_ADDRESS'

======================================================================
ERROR: test_no_session (txdbus.test.test_endpoints.EndpointsTester)
test_no_session
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/defer.py", line 150, in maybeDeferred
    result = f(*args, **kw)
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/utils.py", line 201, in runWithWarningsSuppressed
    reraise(exc_info[1], exc_info[2])
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/utils.py", line 197, in runWithWarningsSuppressed
    result = f(*a, **kw)
  File "/home/hugo/workspace/Forks/txdbus/txdbus/test/test_endpoints.py", line 13, in setUp
    self.pre_ses = os.environ['DBUS_SESSION_BUS_ADDRESS']
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/UserDict.py", line 40, in __getitem__
    raise KeyError(key)
KeyError: 'DBUS_SESSION_BUS_ADDRESS'

======================================================================
ERROR: test_nonce_tcp_address (txdbus.test.test_endpoints.EndpointsTester)
test_nonce_tcp_address
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/defer.py", line 150, in maybeDeferred
    result = f(*args, **kw)
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/utils.py", line 201, in runWithWarningsSuppressed
    reraise(exc_info[1], exc_info[2])
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/utils.py", line 197, in runWithWarningsSuppressed
    result = f(*a, **kw)
  File "/home/hugo/workspace/Forks/txdbus/txdbus/test/test_endpoints.py", line 13, in setUp
    self.pre_ses = os.environ['DBUS_SESSION_BUS_ADDRESS']
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/UserDict.py", line 40, in __getitem__
    raise KeyError(key)
KeyError: 'DBUS_SESSION_BUS_ADDRESS'

======================================================================
ERROR: test_session (txdbus.test.test_endpoints.EndpointsTester)
test_session
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/defer.py", line 150, in maybeDeferred
    result = f(*args, **kw)
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/utils.py", line 201, in runWithWarningsSuppressed
    reraise(exc_info[1], exc_info[2])
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/utils.py", line 197, in runWithWarningsSuppressed
    result = f(*a, **kw)
  File "/home/hugo/workspace/Forks/txdbus/txdbus/test/test_endpoints.py", line 13, in setUp
    self.pre_ses = os.environ['DBUS_SESSION_BUS_ADDRESS']
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/UserDict.py", line 40, in __getitem__
    raise KeyError(key)
KeyError: 'DBUS_SESSION_BUS_ADDRESS'

======================================================================
ERROR: test_system (txdbus.test.test_endpoints.EndpointsTester)
test_system
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/defer.py", line 150, in maybeDeferred
    result = f(*args, **kw)
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/utils.py", line 201, in runWithWarningsSuppressed
    reraise(exc_info[1], exc_info[2])
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/utils.py", line 197, in runWithWarningsSuppressed
    result = f(*a, **kw)
  File "/home/hugo/workspace/Forks/txdbus/txdbus/test/test_endpoints.py", line 13, in setUp
    self.pre_ses = os.environ['DBUS_SESSION_BUS_ADDRESS']
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/UserDict.py", line 40, in __getitem__
    raise KeyError(key)
KeyError: 'DBUS_SESSION_BUS_ADDRESS'

======================================================================
ERROR: test_tcp_address (txdbus.test.test_endpoints.EndpointsTester)
test_tcp_address
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/defer.py", line 150, in maybeDeferred
    result = f(*args, **kw)
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/utils.py", line 201, in runWithWarningsSuppressed
    reraise(exc_info[1], exc_info[2])
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/utils.py", line 197, in runWithWarningsSuppressed
    result = f(*a, **kw)
  File "/home/hugo/workspace/Forks/txdbus/txdbus/test/test_endpoints.py", line 13, in setUp
    self.pre_ses = os.environ['DBUS_SESSION_BUS_ADDRESS']
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/UserDict.py", line 40, in __getitem__
    raise KeyError(key)
KeyError: 'DBUS_SESSION_BUS_ADDRESS'

======================================================================
ERROR: test_unix_address (txdbus.test.test_endpoints.EndpointsTester)
test_unix_address
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/defer.py", line 150, in maybeDeferred
    result = f(*args, **kw)
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/utils.py", line 201, in runWithWarningsSuppressed
    reraise(exc_info[1], exc_info[2])
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/utils.py", line 197, in runWithWarningsSuppressed
    result = f(*a, **kw)
  File "/home/hugo/workspace/Forks/txdbus/txdbus/test/test_endpoints.py", line 13, in setUp
    self.pre_ses = os.environ['DBUS_SESSION_BUS_ADDRESS']
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/UserDict.py", line 40, in __getitem__
    raise KeyError(key)
KeyError: 'DBUS_SESSION_BUS_ADDRESS'

======================================================================
ERROR: test_cancel (txdbus.test.test_authentication.ServerObjectTester)
test_cancel
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/defer.py", line 150, in maybeDeferred
    result = f(*args, **kw)
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/utils.py", line 201, in runWithWarningsSuppressed
    reraise(exc_info[1], exc_info[2])
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/utils.py", line 197, in runWithWarningsSuppressed
    result = f(*a, **kw)
  File "/home/hugo/workspace/Forks/txdbus/txdbus/test/test_authentication.py", line 662, in test_cancel
    return self.conn.test_cancel()
  File "/home/hugo/workspace/Forks/txdbus/txdbus/test/test_authentication.py", line 541, in test_cancel
    self.send('AUTH DBUS_COOKIE_SHA1 '+ binascii.hexlify(get_username()))
TypeError: b2a_hex() argument 1 must be string or buffer, not None

======================================================================
ERROR: test_max_rejects (txdbus.test.test_authentication.ServerObjectTester)
test_max_rejects
----------------------------------------------------------------------
FailTest: Connection unexpectedly dropped

======================================================================
ERROR: test_retry (txdbus.test.test_authentication.ServerObjectTester)
test_retry
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/posixbase.py", line 597, in _doReadOrWrite
    why = selectable.doRead()
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/unix.py", line 193, in doRead
    return self._dataReceived(data)
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/tcp.py", line 214, in _dataReceived
    rval = self.protocol.dataReceived(data)
  File "/home/hugo/workspace/Forks/txdbus/.tox/py27/lib/python2.7/site-packages/twisted/internet/endpoints.py", line 119, in dataReceived
    return self._wrappedProtocol.dataReceived(data)
  File "/home/hugo/workspace/Forks/txdbus/txdbus/test/test_authentication.py", line 387, in dataReceived
    self.gotMessage(line)
  File "/home/hugo/workspace/Forks/txdbus/txdbus/test/test_authentication.py", line 531, in recv1
    self.send('AUTH DBUS_COOKIE_SHA1 ' + binascii.hexlify(get_username()))
TypeError: b2a_hex() argument 1 must be string or buffer, not None

======================================================================
FAIL: test_retry (txdbus.test.test_authentication.ServerObjectTester)
test_retry
----------------------------------------------------------------------
FailTest: Connection unexpectedly dropped

----------------------------------------------------------------------
Ran 163 tests in 0.073s

FAILED (failures=1, errors=11)
_____________________________________________________________________________________ summary _____________________________________________________________________________________
  py27: commands succeeded
  congratulations :)

Also reproduced here.

TooManyOpenFiles

Hello,

if I try to stress the dbus Interface, I get an error, too many open files.
Maybe I'm doing something wrong.
After 1024 requests, the server stops.
I have attached the error as an example.

toomanyopenfiles.zip

deferToThread() usable with inline callbacks?

I exported two object with one blocking method each. I would like to use the threads.deferToThread() method from twisted, in order to make the blocking methods non-blocking. I don't understand, how to use this method together with inline callbacks. Does a solution for this problem exist?

Main example is not Py2/3 safe

Split out from #11

Looking at the example on the frontpage, I'm a bit puzzled that none of the arguments there is using explicit b'..' or u'...'. So the arguments will be bytes on Py2 and unicode on Py3. Are the arguments auto-coerced under the hood?

Take

    notifier = yield con.getRemoteObject('org.freedesktop.Notifications',
                                         '/org/freedesktop/Notifications')

Does getRemoteObject take bytes or strings? If the latter, then the example code should read:

    notifier = yield con.getRemoteObject(u'org.freedesktop.Notifications',
                                         u'/org/freedesktop/Notifications')

This code then works on both Python 2 and 3.

Sometime introspection doesnt work for remote object

Hi,

Is it mandatory to specify "Method" in interface explicitly?

=== Not working===
I tried following to call a remote method I wrote "ActivateConnection", passed the argument using following piece of code:

Note I have not specified interface here

dialer_iface = DBusInterface(DIALUP_INTFACE)
self.dobj= yield self.mdmModel.bus.getRemoteObject(DIALUP_SERVICE, DIALUP_OBJECT,dialer_iface)
self.path = yield self.dobj.callRemote('ActivateConnection',self.mdmModel.device_opath,
timeout=80)
--> This gives an error that Remote Object doesnt have ActivateConnection in any of interfaces --->

=== working===
Then I tried explicitly specifying the method in interface

dialer_iface = DBusInterface(DIALUP_INTFACE,
Method('ActivateConnection', 'o',returns=''))
self.dobj= yield self.mdmModel.bus.getRemoteObject(DIALUP_SERVICE, DIALUP_OBJECT,dialer_iface)
self.path = yield self.dobj.callRemote('ActivateConnection',self.mdmModel.device_opath,
timeout=80)

It works fine.. here, am I missing something?

  • Also do you have API documentation for all public API ?
  • Since from tutorial its tough to find all API definition and corresponding options

is this repository still maintained?

Hello,

and first of all thanks for your work!

This repository has not seen any update for 2 years, is it still maintained? Do you have any plan to update it?

If not, could be nice to specify it in the README and/or archive the repos.

Thanks!

Introspection does not handle well exported objects with a common prefix in path

The introspection of txdbus does not handle correctly objects whose path has a prefix in common.

Just having any parts in common causes every entry to be duplicated in the generated XML.

Example:

from twisted.internet import reactor, defer

from txdbus import client
from txdbus.objects import DBusObject


@defer.inlineCallbacks
def main():
    conn = yield client.connect(reactor)
    conn.exportObject(DBusObject('/org/example/ObjPath'))
    conn.exportObject(DBusObject('/org/example/ObjPath2'))

    yield conn.requestBusName('org.example')


reactor.callWhenRunning(main)
reactor.run()

Introspection XML for path /:

<node name="/">
<node name="org"/>
<node name="org"/>
</node>

Introspection XML for path /org/:

<node name="/org/">
<node name="example"/>
<node name="example"/>
</node>

Having one object whose path is "under" another object's path excludes the former from the introspection.

from twisted.internet import reactor, defer

from txdbus import client
from txdbus.objects import DBusObject


@defer.inlineCallbacks
def main():
    conn = yield client.connect(reactor)
    conn.exportObject(DBusObject('/org/example/ObjPath'))
    conn.exportObject(DBusObject('/org/example/ObjPath/more_path'))
    yield conn.requestBusName('org.example')


reactor.callWhenRunning(main)
reactor.run()

Introspection XML for path /org/example/ObjPath: (Snipped for brevity; the issue is that it should have had a <node name="more_path"/> under the root element.)

<node name="/org/example/ObjPath">
  <interface name="org.freedesktop.DBus.Properties">
    [...]
  </interface>
  <interface name="org.freedesktop.DBus.Introspectable">
    [...]
  </interface>
  <interface name="org.freedesktop.DBus.Peer">
    [...]
  </interface>
  <interface name="org.freedesktop.DBus.ObjectManager">
    [...]
  </interface>
</node>

If fixes are welcome, I can make a pull request.

DBus connection leak on multiple "client.connect()" calls without "disconnect()"

It seems calling client.connect() creates a new connection to DBus, and I have to call disconnct() to prevent DBus connection leaking in my program. My program is a daemon process and uses @defer.inlineCallbacks pattern to call dbus method calls.

Not sure it's possible, but it would be convenient if the connection is reused if client.connect() is called multiple times.

Support of 'h' -- sending/receiving of file descriptors

When implementing, we should return file objects os.fdopen(received_fd) in order not to lost FD on, say, exception. If someone wants to use file with another parameters, please use .fileno().

One thing. CLOEXEC. https://sourceware.org/bugzilla/show_bug.cgi?id=12539 . This should be set by default as I think.

Also, suppose code:

with open(...) as f:
    # suppose f.fileno() = 42
    yield xxx.callRemote(f)
# (B)
f2 = open(...)
# f2.fileno() == 42 too

Due to #20 in some situations, we may go to point (B) while message is not sent actually (just buffered in twisted). But file f already closed. And more over, another file may be opened under the same descriptor. So, we should guarantee to wait for sendmsg() syscall in ANY cases.

Works in Eclipse but not in Terminal

There is a good chance I am missing something here as I am new to Twisted and TxDBus but I am truly stumped. I am writing a program that can connect with Spotify onmy desktop and control it from a remote computer.

I've been testing it in Eclipse and everything has been working great but when I run the same module in Terminal I get an error saying,

File "/usr/local/lib/python2.7/dist-packages/txdbus/client.py", line 653, in connect eplist = endpoints.getDBusEndpoints(reactor, busAddress) File "/usr/local/lib/python2.7/dist-packages/txdbus/endpoints.py", line 48, in getDBusEndpoints raise Exception('DBus Session environment variable not set') exceptions.Exception: DBus Session environment variable not set

I went to the source to try and figure things out. I noticed in endpoints.getDBusEndPoints() that I can pass it the actual Bus address from os.environ instead of it trying to find it. So I did just that. I opened terminal, ran python, typed

import os os.environ.get("DBUS_SESSION_BUS_ADDRESS", None)

and it returned

unix:abstract=/tmp/dbus-viyOLeetrg

Then in my code I replaced,

cli = yield client.connect(reactor, 'session')

with

cli = yield client.connect(reactor, 'unix:abstract=/tmp/dbus-viyOLeetrg')

It worked perfectly again in Eclipse but not in Terminal. Although this time in Terminal it didn't throw that error like it did before.

I'm sorry if this isn't a bug and I am missing something but it feels like a bug to me.

Thanks for your time,
Snortoise

Matching rules are never removed from the bus

DBusClientConnection's delMatch should remove rules from the bus by calling RemoveMatch with the original rule string. Otherwise, they can keep accumulating until the bus refuses to add any more rules.

How to handle DBus structure on the receiver side

In the Tx DBus Tutorial it's described how one could send a structure using dbusOrder class variable. I would like to have convenient way of unmarshalling such structure on the receiving side. As of now I presumably invented the wheel with the from_marshalled method:

class SensorDescription(object):
    dbusOrder = ['name', 'parameter', 'type']
    def __init__(self, sensor = None):
        if sensor != None:
            self.name = sensor.name
            self.parameter = sensor.parameter
            self.type = sensor.type

    @classmethod
    def from_marshalled(cls, marshalled_item):
        assert isinstance(marshalled_item, list)
        assert len(marshalled_item) == len(SensorDescription.dbusOrder)
        result = cls()
        for i in range(0, len(SensorDescription.dbusOrder)):
            setattr(result, SensorDescription.dbusOrder[i], marshalled_item[i])
        return result

Does txdbus have some way of automatic structure unmarshalling? Maybe I could register my structure on the client side for unmarshalling and txdbus would do for me the same as the code in the from_marshalled class method above?

marshal.sigFromPy assumes all python ints to be 'i', which is not the case...

I have noticed several errors when I try to return a large int from a dbus method who's return signature is a variant or dictionary of variants. Python ints are C longs, and can contain larger values than will fit in 'i'. A simple size check for integers in sigFromPy would be easy to implement and solve this problem. A less elegant solution would be to change the default assignment to 'x', but that would result in larger messages in many cases.

Export simple object with integer as an argument.

I want to become familiar with txdbus, which is a native dbus implementation that uses twisted. I want to export an simple object in order to remotely call its only method with python 2.7. The example given at http://pythonhosted.org/txdbus/ works properly.

I changed the example_method a little bit. Now it takes an integer, instead of a string, like the original example method does. I took this into account when specifying the interface.

Server:

from twisted.internet import reactor, defer
from txdbus           import client, objects, error
from txdbus.interface import DBusInterface, Method
import time

class MyObj (objects.DBusObject):

    iface = DBusInterface('org.example.MyIFace',
                          Method('exampleMethod', arguments='i', returns='s'))

    dbusInterfaces = [iface]

    def __init__(self, objectPath):
        super(MyObj, self).__init__(objectPath)


    def dbus_exampleMethod(self, arg):
        time.sleep(arg)
        return 'success'


@defer.inlineCallbacks
def main():
    try:
        conn = yield client.connect(reactor)

        conn.exportObject( MyObj('/MyObjPath') )

        yield conn.requestBusName('org.example')

        print 'Object exported on bus name "org.example" with path /MyObjPath'

    except error.DBusException, e:
        print 'Failed to export object: ', e
        reactor.stop()


reactor.callWhenRunning( main )
reactor.run()

The client calls the example method exactly as in the original example client but with an integer instead of a string.

Client:

from twisted.internet import reactor, defer
from txdbus import client, error


@defer.inlineCallbacks
def main():

    try:
        cli   = yield client.connect(reactor)

        robj  = yield cli.getRemoteObject( 'org.example', '/MyObjPath' )

        reply = yield robj.callRemote('exampleMethod', 2)

        print 'Reply from server: ', reply

    except error.DBusException, e:
        print 'DBus Error:', e

    reactor.stop()


reactor.callWhenRunning(main)
reactor.run()

Executing both the server and the client yields the error message:

Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/twisted/internet/defer.py", line 1184, in gotResult
    _inlineCallbacks(r, g, deferred)
  File "/usr/local/lib/python2.7/dist-packages/twisted/internet/defer.py", line 1128, in _inlineCallbacks
    result = g.send(result)
  File "tx_example_client.py", line 16, in main
    reply = yield robj.callRemote('exampleMethod', 'Hello World!')
  File "/usr/local/lib/python2.7/dist-packages/txdbus/objects.py", line 284, in callRemote
    returnSignature  = m.sigOut )
--- <exception caught here> ---
  File "/usr/local/lib/python2.7/dist-packages/txdbus/client.py", line 519, in callRemote
    autoStart    = autoStart )
  File "/usr/local/lib/python2.7/dist-packages/txdbus/message.py", line 190, in __init__
    self._marshal()
  File "/usr/local/lib/python2.7/dist-packages/txdbus/message.py", line 103, in _marshal
    binBody = b''.join( marshal.marshal( self.signature, self.body )[1] )
  File "/usr/local/lib/python2.7/dist-packages/txdbus/marshal.py", line 612, in marshal
    nbytes, vchunks = marshallers[ tcode ]( ct, var, startByte, lendian )
  File "/usr/local/lib/python2.7/dist-packages/txdbus/marshal.py", line 405, in marshal_int32
    return 4, [ struct.pack( lendian and '<i' or '>i', var) ]
struct.error: cannot convert argument to integer

What am I doing wrong? It would be great if someone could help me with this issue. It would be the coolest, if someone could explain to me what the error means.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.