0

I have a top class and classes that extend the top class, but almost all methods from the child classes are from the top class (using inheritance, without reimplementation), so I don't have the methods in the child classes, how could I export them with dbus for each child class (with the name of each child class as part of dbus path)?

I will show a example code for clarify, my class structure is:

Window (main class)
  |--WindowOne (child class)
  |--WindowTwo
  |--WindowThree

My interface for dbus is com.example.MyInterface and I would like to access each child class using: com.example.MyInterface.WindowOne, and for each child class I would like to access the methods, inclusive the inherited methods from the main class, like com.example.MyInterface.WindowOne.show and com.example.MyInterface.WindowOne.destroy.

In this code, I extend the child class 'WindowOne' with the 'Window' class, the methods show() and destroy() in the 'Window' are not re-implemented in 'WindowOne', but in this code I put the method show() to explain the problem, the way I get the code to work was this, I re-declare the method show() in child class, but this seems bad.

The big question maybe is: There is some way to use the decorator: @dbus.service.method('com.example.MyInterface.WindowOne') for classes (child classes in this case)?

The test source code:

# interface imports
from gi.repository import Gtk

# dbus imports  
import dbus
import dbus.service
from dbus.mainloop.glib import DBusGMainLoop

# Main window class
class Window(dbus.service.Object):
    def __init__(self, gladeFilePath, name):
        # ... inicialization
        self.name = name
        self.busName = dbus.service.BusName('com.example.MyInterface.', bus=dbus.SessionBus())
        dbus.service.Object.__init__(self, self.busName, '/com/example/MyInterface/' + self.name)

    def show(self):
        self.window.show_all()

    def destroy(self):
        Gtk.main_quit()


# Child window class
class WindowOne(Window):
    def __init__(self, gladeFilePath):
        Window.__init__(self, gladeFilePath, "WindowOne")

    @dbus.service.method('com.example.MyInterface.WindowOne')
    def show(self):
        self.window.show_all()


if __name__ == "__main__":
    DBusGMainLoop(set_as_default=True)

    gladeFilePath = "/etc/interface.glade"
    windowOne = WindowOne(gladeFilePath)

    Gtk.main()
Rapid
  • 1,442
  • 1
  • 13
  • 25
Juliao
  • 127
  • 3
  • 12
  • I'm not so good with decorators and dbus, but why don't you decorate the `__init__`-function and use the `name` supplied to it? – deinonychusaur Dec 08 '12 at 15:59
  • Maybe I don't understood what you meant, but I tried to change the line in `__init__` to: `self.busName = dbus.service.BusName('com.example.MyInterface.' + self.name, bus=dbus.SessionBus())`, bus this just change the name bus, the exported methods need to have the proper decorator, with the full name like `com.example.MyInterface.WindowOne`and self.name don't work inside a decorator :( – Juliao Dec 10 '12 at 10:40
  • I figured out another problem that I don't realized before, the object `com.example.MyInterface.WindowOne` will just be available if one object of this class is instanced, but this will just happen for the default window, so the others windows will still unavailable in dbus. I will think in a better solution, any help will be welcome. Thanks. – Juliao Dec 10 '12 at 11:14
  • I'm not sure if your code is self-contained in the example, so I'm a bit uncertain of how to go about it, but at any rate `self.busName = dbus.service.BusName('com.example.MyInterface.{0}'.format(self.__class__.__name__), bus=dbus.SessionBus())` attaches the class name after the dot. I'm not sure if that fixes your problem though – deinonychusaur Dec 10 '12 at 22:21
  • I tried something like this, but using the member `self.name` that I passed to main class, but was not sufficient because I figured out another problem, the static decorator cannot help with a dinamically generated interface path, so I opened a proper question at: http://stackoverflow.com/questions/13810613/how-dynamically-export-methods-to-dbus-using-python-without-static-decorator – Juliao Dec 10 '12 at 22:53

1 Answers1

0

After some experimentation, I realize something essential, that I don't find before in documentation: The path for exported methods don't need to have the same path of exported object! Clarifing: If the method is not reimplemented in the child class (WindowOne), I don't need to export it in the child class using @dbus.service.method('com.example.MyInterface.WindowOne') , for example, I just need to export the method in the main class (Window) using: @dbus.service.method('com.example.MyInterface.Window')

So I just need to use a fixed path when export the method of the top class Window, see in the fixed code below.

# interface imports
from gi.repository import Gtk

# dbus imports  
import dbus
import dbus.service
from dbus.mainloop.glib import DBusGMainLoop

# Main window class
class Window(dbus.service.Object):
    def __init__(self, gladeFilePath, name):
        # ... inicialization
        self.name = name
        self.busName = dbus.service.BusName('com.example.MyInterface.', bus=dbus.SessionBus())
        dbus.service.Object.__init__(self, self.busName, '/com/example/MyInterface/' + self.name)

    @dbus.service.method('com.example.MyInterface.Window')
    def show(self):
        self.window.show_all()

    @dbus.service.method('com.example.MyInterface.Window')
    def destroy(self):
        Gtk.main_quit()

    @dbus.service.method('com.example.MyInterface.Window')
    def update(self, data):
        # top class 'update' method


# Child window class
class WindowOne(Window):
    def __init__(self, gladeFilePath):
        Window.__init__(self, gladeFilePath, "WindowOne")

    @dbus.service.method('com.example.MyInterface.WindowOne')
    def update(self, data):
        # reimplementation of top class 'update' method


if __name__ == "__main__":
    DBusGMainLoop(set_as_default=True)

    gladeFilePath = "/etc/interface.glade"
    windowOne = WindowOne(gladeFilePath)

    Gtk.main()

In the code for call the bus method, I just use like below:

bus = dbus.SessionBus()
dbusWindowOne = bus.get_object('com.example.MyInterface', '/com/example/MyInterface/WindowOne')
showWindowOne = dbusWindowOne.get_dbus_method('show', 'com.example.MyInterface.Window')
updateWindowOne = dbusWindowOne.get_dbus_method('update', 'com.example.MyInterface.WindowOne')

The method show is called in the top class Window, but is executed in the object WindowOne that is a child class.

And the method update is called in the child class WindowOne, because it is reimplementing the top class method.

Juliao
  • 127
  • 3
  • 12