From 770f4d345641b383464c131ecf9d6bbbbb2fdad6 Mon Sep 17 00:00:00 2001 From: davemds Date: Thu, 9 May 2013 20:17:58 +0200 Subject: [PATCH] Python-EFL: add documentation for the dbus main loop integration --- doc/dbus/dbus.rst | 199 ++++++++++++++++++++++++++++++++++++++++++++++ doc/index.rst | 7 ++ 2 files changed, 206 insertions(+) create mode 100644 doc/dbus/dbus.rst diff --git a/doc/dbus/dbus.rst b/doc/dbus/dbus.rst new file mode 100644 index 0000000..bd7ed7c --- /dev/null +++ b/doc/dbus/dbus.rst @@ -0,0 +1,199 @@ +Ecore DBus Mainloop integration +=============================== + + +How to use the main loop +----------------------------- + +Python-EFL provide the necessary main loop integration to let +python-dbus use the Ecore main loop to perform async stuff. The only +function you need to use from the efl is: DBusEcoreMainLoop() + +The function returns a NativeMainLoop to attach the Ecore main loop to D-Bus +from within Python. In practice you just need to pass the NativeMainLoop +as the 'mainloop' param when you connect to a bus. + +This is how you connect to a dbus bus: + +.. code-block:: python + + import dbus + from efl import ecore + from efl.dbus_mainloop import DBusEcoreMainLoop + + # connect to the session bus + bus = dbus.SessionBus(mainloop=DBusEcoreMainLoop()) + # or to the system bus + bus = dbus.SystemBus(mainloop=DBusEcoreMainLoop()) + +Once you have your bus connected you can just normally use all the python-dbus +functionality. This is the reason why you will not find any docs about dbus +here (except for some basic examples). + +It's therefore highly suggested to read the official python-dbus tutorial and +to use the python-dbus reference, you will find all the links in the bottom +of the page. + + +Proxy objects +------------- + +In the dbus world to interact with an object you need to know: + +- the name of the service, ex: `org.enlightenment.FileManager` +- the path to the object you are intrested, ex: `/org/enlightenment/FileManager` +- the interface to interact with, ex: `org.enlightenment.FileManager` + +.. code-block:: python + + obj = bus.get_object(named_service, object_path) + iface = dbus.Interface(obj, iface_name) + +then, on the iface object, you can call methods, connect to signals and access +properties. + + +Calling methods +--------------- + +There are at least two way to call methods on a remote object, the first +example show how to do it the simple way, while the second show a much more +complex but much powerfull async way. Note: using the sync way can make your +app lag or halt forever if the remote keep too much time to respond. + +Both the examples use the ``OpenDirectory(s)`` method of the Enlightenment +file manager to open a new window in the `/tmp` directory. + +.. code-block:: python + + # synchronous call + + obj = bus.get_object('org.enlightenment.FileManager', + '/org/enlightenment/FileManager') + iface = dbus.Interface(obj, 'org.enlightenment.FileManager') + # directly + iface.OpenDirectory('/tmp') + # or using a method object + meth = iface.get_dbus_method('OpenDirectory') + meth('/tmp') + + +.. code-block:: python + + # asynchronous call + + def reply_handler(*params): + print("Method return: " + str(params)) + + def error_handler(*params): + print("Method error") + + + obj = bus.get_object('org.enlightenment.FileManager', + '/org/enlightenment/FileManager') + iface = dbus.Interface(obj, 'org.enlightenment.FileManager') + iface.OpenDirectory('/tmp', + reply_handler=reply_handler, + error_handler=error_handler) + + ecore.main_loop_begin() + + +Accessing properties +-------------------- + +To access properties you need to use the standard **org.freedesktop.DBus.Properties** +interface that all the objects provide. Methods on this iterface are: + +- Get(s interface, s propname) → (v value) +- GetAll(s interface) → (a{sv} props) +- Set(s interface, s propname, v value) + +The example show how to get the value of the `DaemonVersion` prop of `UDisks` + +.. code-block:: python + + + bus = dbus.SystemBus(mainloop=DBusEcoreMainLoop()) + obj = bus.get_object('org.freedesktop.UDisks', + '/org/freedesktop/UDisks') + props_iface = dbus.Interface(obj, 'org.freedesktop.DBus.Properties') + value = props_iface.Get('org.freedesktop.UDisks', 'DaemonVersion') + + + + +Connecting signals +------------------ + +.. literalinclude:: ../../examples/dbus/test_signal_simple.py + + +Introspection +------------- + +To get information for a given proxy object you need to use the ``Introspect()`` +method on the **org.freedesktop.DBus.Introspectable** interface. +The introspection will return an XML string that describe all the interfaces +available on the object, with all the methods, properties and signals info. + +.. code-block:: python + + bus = dbus.SessionBus(mainloop=DBusEcoreMainLoop()) + obj = bus.get_object('org.enlightenment.FileManager', + '/org/enlightenment/FileManager') + iface = dbus.Interface(obj, 'org.freedesktop.DBus.Introspectable') + xml_string = iface.Introspect() + +This other example show how to do recursive introspection on a given service, +starting from the root object path ``/`` + +.. code-block:: python + + import dbus + import xml.etree.ElementTree as ElementTree + from efl import ecore + from efl.dbus_mainloop import DBusEcoreMainLoop + + def recursive_introspect(bus, named_service, object_path): + print('Introspecting obj "%s" on service "%s"' % \ + (object_path, named_service)) + + # introspect + obj = bus.get_object(named_service, object_path) + iface = dbus.Interface(obj, 'org.freedesktop.DBus.Introspectable') + xml_string = iface.Introspect() + + # parse + for xml_node in ElementTree.fromstring(xml_string): + # found an interface + if xml_node.tag == 'interface': + print(' Found interface: ' + xml_node.attrib['name']) + + for child in xml_node: + if child.tag == 'property': + print(' Found property: ' + child.attrib['name']) + + if child.tag == 'method': + print(' Found method: ' + child.attrib['name']) + + if child.tag == 'signal': + print(' Found signal: ' + child.attrib['name']) + + # found another node, introspect it... + if xml_node.tag == 'node': + if object_path == '/': + object_path = '' + new_path = '/'.join((object_path, xml_node.attrib['name'])) + recursive_introspect(bus, named_service, new_path) + + bus = dbus.SystemBus(mainloop=DBusEcoreMainLoop()) + recursive_introspect(bus, 'org.freedesktop.UDisks', '/') + + +References +---------- + +- `dbus tutorial `_ +- `python-dbus tutorial `_ +- `python-dbus reference `_ diff --git a/doc/index.rst b/doc/index.rst index 3828cbb..f023e8a 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -36,6 +36,13 @@ Elementary .. toctree:: elementary/elementary :maxdepth: 3 + +DBus integration +------------------------ + +.. toctree:: dbus/dbus + + Acknowledgements ----------------