* python/dbus_bindings.pyx.in (send_with_reply_handlers): New send

method for doing async calls
(_pending_call_notification): New C function for handling pendning call
callbacks
(set_notify): New method for setting pending call notification

* python/dbus.py: new version tuple "version" is set at (0, 40, 0)
Async capabilities added to remote method calls
(Sender): class removed
(RemoteService): class removed
(ObjectTree): class removed for now
(RemoteObject): Renamed to ProxyObject
(RemoteMethod): Renamed to ProxyMethod
(method): Decorator added for decorating python methods as dbus methods
(signal): Decorator added for decorating python methods as signal emitters
(ObjectType): Metaclass added for generating introspection data and the
method callback vtable
(Interface): Wrapper class added to wrap objects in a dbus interface
(Object): Uses ObjectType as its metaclass and exports Introspect
of the org.freedesktop.DBus.Introspectable interface
(ValidationException, UnknownMethodException): new exceptions

* python/examples/*: Modified to fit with the new bindings
This commit is contained in:
John (J5) Palmieri 2005-04-25 22:54:28 +00:00
parent 64f3d8f67d
commit 8d40569d8a
8 changed files with 459 additions and 234 deletions

View file

@ -1,3 +1,29 @@
2005-04-25 John (J5) Palmieri <johnp@redhat.com>
* python/dbus_bindings.pyx.in (send_with_reply_handlers): New send
method for doing async calls
(_pending_call_notification): New C function for handling pendning call
callbacks
(set_notify): New method for setting pending call notification
* python/dbus.py: new version tuple "version" is set at (0, 40, 0)
Async capabilities added to remote method calls
(Sender): class removed
(RemoteService): class removed
(ObjectTree): class removed for now
(RemoteObject): Renamed to ProxyObject
(RemoteMethod): Renamed to ProxyMethod
(method): Decorator added for decorating python methods as dbus methods
(signal): Decorator added for decorating python methods as signal emitters
(ObjectType): Metaclass added for generating introspection data and the
method callback vtable
(Interface): Wrapper class added to wrap objects in a dbus interface
(Object): Uses ObjectType as its metaclass and exports Introspect
of the org.freedesktop.DBus.Introspectable interface
(ValidationException, UnknownMethodException): new exceptions
* python/examples/*: Modified to fit with the new bindings
2005-04-23 Havoc Pennington <hp@redhat.com>
* dbus/dbus-message.c (dbus_message_append_args): fix doc comment,

View file

@ -42,6 +42,11 @@ print(dbus_object.ListServices())
"""
import dbus_bindings
import re
import inspect
version = (0, 40, 0)
_threads_initialized = 0
def init_gthreads ():
@ -50,13 +55,51 @@ def init_gthreads ():
dbus_bindings.init_gthreads ()
_threads_initialized = 1
class Sender:
def __init__(self, interface, signal_name, service, path, message):
self.interface = interface
self.signal_name = signal_name
self.service = service
self.path = path
self.message = message
def _validate_interface_or_name(value):
elements = value.split('.')
if len(elements) <= 1:
raise ValidationException("%s must contain at least two elements seperated by a period ('.')"%(value))
validate = re.compile('[A-Za-z][\w_]*')
for element in elements:
if not validate.match(element):
raise ValidationException("Element %s of %s has invalid characters"%(element ,value))
#Decorators
def method(dbus_interface):
_validate_interface_or_name(dbus_interface)
def decorator(func):
func._dbus_is_method = True
func._dbus_interface = dbus_interface
func._dbus_args = inspect.getargspec(func)[0]
func._dbus_args.pop(0)
return func
return decorator
def signal(dbus_interface):
_validate_interface_or_name(dbus_interface)
def decorator(func):
def emit_signal(self, *args, **keywords):
func(self, *args, **keywords)
message = dbus_bindings.Signal(self._object_path, dbus_interface, func.__name__)
iter = message.get_iter(True)
for arg in args:
iter.append(arg)
self._connection.send(message)
emit_signal._dbus_is_signal = True
emit_signal._dbus_interface = dbus_interface
emit_signal.__name__ = func.__name__
emit_signal._dbus_args = inspect.getargspec(func)[0]
emit_signal._dbus_args.pop(0)
return emit_signal
return decorator
class Bus:
"""A connection to a DBus daemon.
@ -85,50 +128,62 @@ class Bus:
def get_connection(self):
return self._connection
def get_service(self, service_name="org.freedesktop.Broadcast"):
"""Get one of the RemoteServices connected to this Bus. service_name
is just a string of the form 'com.widgetcorp.MyService'
"""
return RemoteService(self, service_name)
def get_session():
"""Static method that returns the session bus"""
return SessionBus()
def add_signal_receiver(self, handler_function, signal_name=None, interface=None, service=None, path=None, expand_args=True):
match_rule = self._get_match_rule(signal_name, interface, service, path)
get_session = staticmethod(get_session)
def get_system():
"""Static method that returns the system bus"""
return SystemBus()
get_system = staticmethod(get_system)
def get_starter():
"""Static method that returns the starter bus"""
return StarterBus()
get_starter = staticmethod(get_starter)
def get_object(self, named_service, object_path):
"""Get a proxy object to call over the bus"""
return ProxyObject(self, named_service, object_path)
def add_signal_receiver(self, handler_function, signal_name=None, dbus_interface=None, named_service=None, path=None):
match_rule = self._get_match_rule(signal_name, dbus_interface, named_service, path)
if (not self._match_rule_to_receivers.has_key(match_rule)):
self._match_rule_to_receivers[match_rule] = {handler_function: True}
self._match_rule_to_receivers[match_rule][handler_function] = expand_args
self._match_rule_to_receivers[match_rule] = [handler_function]
else:
self._match_rule_to_receivers[match_rule].append(handler_function)
dbus_bindings.bus_add_match(self._connection, match_rule)
def remove_signal_receiver(self, handler_function, signal_name=None, interface=None, service=None, path=None):
match_rule = self._get_match_rule(signal_name, interface, service, path)
def remove_signal_receiver(self, handler_function, signal_name=None, dbus_interface=None, named_service=None, path=None):
match_rule = self._get_match_rule(signal_name, dbus_interface, named_service, path)
if self._match_rule_to_receivers.has_key(match_rule):
if self._match_rule_to_receivers[match_rule].__contains__(handler_function):
self._match_rule_to_receivers[match_rule].pop(handler_function)
dbus_bindings.bus_remove_match(self._connection, match_rule)
def get_connection(self):
"""Get the dbus_bindings.Connection object associated with this Bus"""
return self._connection
def get_unix_user(self, service_name):
"""Get the unix user for the given service_name on this Bus"""
return dbus_bindings.bus_get_unix_user(self._connection, service_name)
def get_unix_user(self, named_service):
"""Get the unix user for the given named_service on this Bus"""
return dbus_bindings.bus_get_unix_user(self._connection, named_service)
def _get_match_rule(self, signal_name, interface, service, path):
def _get_match_rule(self, signal_name, dbus_interface, named_service, path):
match_rule = "type='signal'"
if (interface):
match_rule = match_rule + ",interface='%s'" % (interface)
if (service):
if (service[0] != ':' and service != "org.freedesktop.DBus"):
bus_service = self.get_service("org.freedesktop.DBus")
bus_object = bus_service.get_object('/org/freedesktop/DBus',
'org.freedesktop.DBus')
service = bus_object.GetNameOwner(service)
if (dbus_interface):
match_rule = match_rule + ",interface='%s'" % (dbus_interface)
if (named_service):
if (named_service[0] != ':' and named_service != "org.freedesktop.DBus"):
bus_object = self.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus')
named_service = bus_object.GetNameOwner(named_service, dbus_interface='org.freedesktop.DBus')
match_rule = match_rule + ",sender='%s'" % (service)
match_rule = match_rule + ",sender='%s'" % (named_service)
if (path):
match_rule = match_rule + ",path='%s'" % (path)
if (signal_name):
@ -139,28 +194,22 @@ class Bus:
if (message.get_type() != dbus_bindings.MESSAGE_TYPE_SIGNAL):
return dbus_bindings.HANDLER_RESULT_NOT_YET_HANDLED
interface = message.get_interface()
service = message.get_sender()
dbus_interface = message.get_interface()
named_service = message.get_sender()
path = message.get_path()
signal_name = message.get_member()
match_rule = self._get_match_rule(signal_name, interface, service, path)
match_rule = self._get_match_rule(signal_name, dbus_interface, named_service, path)
if (self._match_rule_to_receivers.has_key(match_rule)):
receivers = self._match_rule_to_receivers[match_rule]
sender = Sender(interface, signal_name, service, path, message)
arg = [sender]
for receiver in receivers.iterkeys():
if receivers[receiver]:
args = [sender]
args.extend(message.get_args_list())
receiver(*args)
else:
receiver(*arg)
for receiver in receivers:
args = message.get_args_list()
receiver(*args)
def start_service_by_name(self, service):
return dbus_bindings.bus_start_service_by_name(self._connection, service)
def start_service_by_name(self, named_service):
return dbus_bindings.bus_start_service_by_name(self._connection, named_service)
class SystemBus(Bus):
"""The system-wide message bus
@ -182,59 +231,116 @@ class StarterBus(Bus):
Bus.__init__(self, Bus.TYPE_STARTER)
class RemoteObject:
"""A remote Object.
class Interface:
"""An inteface into a remote object
A RemoteObject is provided by a RemoteService on a particular Bus. RemoteObjects
have member functions, and can be called like normal Python objects.
An Interface can be used to wrap ProxyObjects
so that calls can be routed to their correct
dbus interface
"""
def __init__(self, service, object_path, interface):
self._service = service
self._object_path = object_path
self._interface = interface
def connect_to_signal(self, signal_name, handler_function):
self._service.get_bus().add_signal_receiver(handler_function,
signal_name=signal_name,
interface=self._interface,
service=self._service.get_service_name(),
path=self._object_path)
def __init__(self, object, dbus_interface):
self._obj = object
self._dbus_interface = dbus_interface
def connect_to_signal(self, signal_name, handler_function, dbus_interface = None):
if not dbus_interface:
dbus_interface = self._dbus_interface
self._obj.connect_to_signal(signal_name, handler_function, dbus_interface)
def __getattr__(self, member, **keywords):
if (keywords.has_key('dbus_interface')):
_dbus_interface = keywords['dbus_interface']
else:
_dbus_interface = self._dbus_interface
def __getattr__(self, member):
if member == '__call__':
return object.__call__
else:
return RemoteMethod(self._service.get_bus().get_connection(),
self._service.get_service_name(),
self._object_path, self._interface, member)
return self._obj.__getattr__(member, dbus_interface=_dbus_interface)
class ProxyObject:
"""A proxy to the remote Object.
class RemoteMethod:
"""A remote Method.
Typically a member of a RemoteObject. Calls to the
method produce messages that travel over the Bus and are routed
to a specific Service.
A ProxyObject is provided by the Bus. ProxyObjects
have member functions, and can be called like normal Python objects.
"""
def __init__(self, connection, service_name, object_path, interface, method_name):
self._connection = connection
self._service_name = service_name
def __init__(self, bus, named_service, object_path):
self._bus = bus
self._named_service = named_service
self._object_path = object_path
self._interface = interface
self._method_name = method_name
def __call__(self, *args):
message = dbus_bindings.MethodCall(self._object_path, self._interface, self._method_name)
message.set_destination(self._service_name)
def connect_to_signal(self, signal_name, handler_function, dbus_interface=None):
self._bus.add_signal_receiver(handler_function,
signal_name=signal_name,
dbus_interface=dbus_interface,
named_service=self._named_service,
path=self._object_path)
def __getattr__(self, member, **keywords):
if member == '__call__':
return object.__call__
else:
iface = None
if (keywords.has_key('dbus_interface')):
iface = keywords['dbus_interface']
return ProxyMethod(self._bus.get_connection(),
self._named_service,
self._object_path, iface, member)
class ProxyMethod:
"""A proxy Method.
Typically a member of a ProxyObject. Calls to the
method produce messages that travel over the Bus and are routed
to a specific named Service.
"""
def __init__(self, connection, named_service, object_path, dbus_interface, method_name):
self._connection = connection
self._named_service = named_service
self._object_path = object_path
self._method_name = method_name
self._dbus_interface = dbus_interface
def __call__(self, *args, **keywords):
dbus_interface = self._dbus_interface
if (keywords.has_key('dbus_interface')):
dbus_interface = keywords['dbus_interface']
reply_handler = None
if (keywords.has_key('reply_handler')):
reply_handler = keywords['reply_handler']
error_handler = None
if (keywords.has_key('error_handler')):
error_handler = keywords['error_handler']
if not(reply_handler and error_handler):
if reply_handler:
raise MissingErrorself, HandlerException()
elif error_handler:
raise MissingReplyHandlerException()
message = dbus_bindings.MethodCall(self._object_path, dbus_interface, self._method_name)
message.set_destination(self._named_service)
# Add the arguments to the function
iter = message.get_iter(True)
for arg in args:
iter.append(arg)
reply_message = self._connection.send_with_reply_and_block(message, 5000)
args_tuple = reply_message.get_args_list()
if reply_handler:
result = self._connection.send_with_reply_handlers(message, -1, reply_handler, error_handler)
args_tuple = (result,)
else:
reply_message = self._connection.send_with_reply_and_block(message, -1)
args_tuple = reply_message.get_args_list()
if len(args_tuple) == 0:
return
elif len(args_tuple) == 1:
@ -248,8 +354,8 @@ class Service:
Just inherit from Service, providing the name of your service
(e.g. org.designfu.SampleService).
"""
def __init__(self, service_name, bus=None):
self._service_name = service_name
def __init__(self, named_service, bus=None):
self._named_service = named_service
if bus == None:
# Get the default bus
@ -257,22 +363,40 @@ class Service:
else:
self._bus = bus
dbus_bindings.bus_request_name(self._bus.get_connection(), service_name)
dbus_bindings.bus_request_name(self._bus.get_connection(), named_service)
def get_bus(self):
"""Get the Bus this Service is on"""
return self._bus
def get_service_name(self):
def get_name(self):
"""Get the name of this service"""
return self._service_name
return self._named_service
def _dispatch_dbus_method_call(target_method, argument_list, message):
def _dispatch_dbus_method_call(target_methods, self, argument_list, message):
"""Calls method_to_call using argument_list, but handles
exceptions, etc, and generates a reply to the DBus Message message
"""
try:
retval = target_method(message, *argument_list)
target_method = None
dbus_interface = message.get_interface()
if dbus_interface == None:
if target_methods:
target_method = target_methods[0]
else:
for dbus_method in target_methods:
if dbus_method._dbus_interface == dbus_interface:
target_method = dbus_method
break
if target_method:
retval = target_method(self, *argument_list)
else:
if not dbus_interface:
raise UnknownMethodException('%s is not a valid method'%(message.get_member()))
else:
raise UnknownMethodException('%s is not a valid method of interface %s'%(message.get_member(), dbus_interface))
except Exception, e:
if e.__module__ == '__main__':
# FIXME: is it right to use .__name__ here?
@ -289,13 +413,77 @@ def _dispatch_dbus_method_call(target_method, argument_list, message):
return reply
def _build_method_dictionary(methods):
method_dict = {}
for method in methods:
if method_dict.has_key(method.__name__):
print ('WARNING: registering DBus Object methods, already have a method named %s' % (method.__name__))
method_dict[method.__name__] = method
return method_dict
class ObjectType(type):
def __init__(cls, name, bases, dct):
#generate out vtable
method_vtable = getattr(cls, '_dbus_method_vtable', {})
reflection_data = getattr(cls, '_dbus_reflection_data', "")
reflection_interface_method_hash = {}
reflection_interface_signal_hash = {}
for func in dct.values():
if getattr(func, '_dbus_is_method', False):
if method_vtable.has_key(func.__name__):
method_vtable[func.__name__].append(func)
else:
method_vtable[func.__name__] = [func]
#generate a hash of interfaces so we can group
#methods in the xml data
if reflection_interface_method_hash.has_key(func._dbus_interface):
reflection_interface_method_hash[func._dbus_interface].append(func)
else:
reflection_interface_method_hash[func._dbus_interface] = [func]
elif getattr(func, '_dbus_is_signal', False):
if reflection_interface_signal_hash.has_key(func._dbus_interface):
reflection_interface_signal_hash[func._dbus_interface].append(func)
else:
reflection_interface_signal_hash[func._dbus_interface] = [func]
for interface in reflection_interface_method_hash.keys():
reflection_data = reflection_data + ' <interface name="%s">\n'%(interface)
for func in reflection_interface_method_hash[interface]:
reflection_data = reflection_data + ' <method name="%s">\n'%(func.__name__)
for arg in func._dbus_args:
reflection_data = reflection_data + ' <arg name="%s" type="v" />\n'%(arg)
#reclaim some memory
func._dbus_args = None
reflection_data = reflection_data + ' </method>\n'
if reflection_interface_signal_hash.has_key(interface):
for func in reflection_interface_signal_hash[interface]:
reflection_data = reflection_data + ' <signal name="%s">\n'%(func.__name__)
for arg in func._dbus_args:
reflection_data = reflection_data + ' <arg name="%s" type="v" />\n'%(arg)
#reclaim some memory
func._dbus_args = None
reflection_data = reflection_data + ' </signal>\n'
del reflection_interface_signal_hash[interface]
reflection_data = reflection_data + ' </interface>\n'
for interface in reflection_interface_signal_hash.keys():
reflection_data = reflection_data + ' <interface name="%s">\n'%(interface)
for func in reflection_interface_signal_hash[interface]:
reflection_data = reflection_data + ' <signal name="%s">\n'%(func.__name__)
for arg in func._dbus_args:
reflection_data = reflection_data + ' <arg name="%s" type="v" />\n'%(arg)
#reclaim some memory
func._dbus_args = None
reflection_data = reflection_data + ' </signal>\n'
reflection_data = reflection_data + ' </interface>\n'
cls._dbus_reflection_data = reflection_data
cls._dbus_method_vtable = method_vtable
super(ObjectType, cls).__init__(name, bases, dct)
class Object:
"""A base class for exporting your own Objects across the Bus.
@ -304,129 +492,71 @@ class Object:
across the Bus. These will appear as member functions of your
ServiceObject.
"""
def __init__(self, object_path, service, dbus_methods=[]):
# Reversed constructor argument order. Add a temporary
# check to help people get things straightened out with minimal pain.
if type(service) == list:
raise TypeError, "dbus.Object.__init__(): the order of the 'service' and 'dbus_methods' arguments has been reversed (for consistency with dbus.ObjectTree)."
__metaclass__ = ObjectType
def __init__(self, object_path, service):
self._object_path = object_path
self._service = service
self._bus = service.get_bus()
self._connection = self._bus.get_connection()
self._method_name_to_method = _build_method_dictionary(dbus_methods)
self._connection.register_object_path(object_path, self._unregister_cb, self._message_cb)
def emit_signal(self, interface, signal_name, *args):
message = dbus_bindings.Signal(self._object_path, interface, signal_name)
iter = message.get_iter(True)
for arg in args:
iter.append(arg)
self._connection.send(message)
def _unregister_cb(self, connection):
print ("Unregister")
def _message_cb(self, connection, message):
target_method_name = message.get_member()
target_method = self._method_name_to_method[target_method_name]
target_methods = self._dbus_method_vtable[target_method_name]
args = message.get_args_list()
reply = _dispatch_dbus_method_call(target_method, args, message)
reply = _dispatch_dbus_method_call(target_methods, self, args, message)
self._connection.send(reply)
class ObjectTree:
"""An object tree allows you to register a handler for a tree of object paths.
This means that literal Python objects do not need to be created for each object
over the bus, but you can have a virtual tree of objects handled by a single
Python object. There are two ways to handle method calls on virtual objects:
@method('org.freedesktop.DBus.Introspectable')
def Introspect(self):
reflection_data = '<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">\n'
reflection_data = reflection_data + '<node name="%s">\n'%(self._object_path)
reflection_data = reflection_data + self._dbus_reflection_data
reflection_data = reflection_data + '</node>\n'
1) Pass a list of dbus_methods in to __init__. This works just like dbus.Object,
except an object_path is passed as the first argument to each method, denoting which
virtual object the call was made on. If all the objects in the tree support the same
methods, this is the best approach.
return reflection_data
2) Override object_method_called. This allows you to define the valid methods dynamically
on an object by object basis. For example, if providing an object tree that represented
a filesystem heirarchy, you'd only want an ls method on directory objects, not file objects.
"""
#Exceptions
class MissingErrorHandlerException(Exception):
def __init__(self):
Exception.__init__(self)
def __init__(self, base_path, service, dbus_methods=[]):
self._base_path = base_path
self._service = service
self._bus = service.get_bus()
self._connection = self._bus.get_connection()
self._method_name_to_method = _build_method_dictionary(dbus_methods)
self._connection.register_fallback(base_path, self._unregister_cb, self._message_cb)
def __str__(self):
return "error_handler not defined: if you define a reply_handler you must also define an error_handler"
def relative_path_to_object_path(self, relative_path):
return ObjectPath(self._base_path + relative_path)
def broadcast_signal(self, interface, signal_name, relative_path):
object_path = self.relative_path_to_object_path(relative_path)
message = dbus_bindings.Signal(object_path, interface, signal_name)
self._connection.send(message)
def object_method_called(self, message, relative_path, method_name, argument_list):
"""Override this method. Called with, object_path, the relative path of the object
under the base_path, the name of the method invoked, and a list of arguments
"""
raise NotImplementedException, "object_method_called() must be overriden"
def _unregister_cb(self, connection):
print ("Unregister")
class MissingReplyHandlerException(Exception):
def __init__(self):
Exception.__init__(self)
def _message_cb(self, connection, message):
target_object_full_path = message.get_path()
assert(self._base_path == target_object_full_path[:len(self._base_path)])
target_object_path = target_object_full_path[len(self._base_path):]
target_method_name = message.get_member()
message_args = message.get_args_list()
def __str__(self):
return "reply_handler not defined: if you define an error_handler you must also define a reply_handler"
try:
target_method = self._method_name_to_method[target_method_name]
args = [target_object_path] + message_args
except KeyError:
target_method = self.object_method_called
args = [target_object_path, target_method_name, message_args]
class ValidationException(Exception):
def __init__(self, msg=''):
self.msg = msg
Exception.__init__(self)
reply = _dispatch_dbus_method_call(target_method, args, message)
def __str__(self):
return "Error validating string: %s" % self.msg
self._connection.send(reply)
class RemoteService:
"""A remote service providing objects.
class UnknownMethodException(Exception):
def __init__(self, msg=''):
self.msg = msg
Exception.__init__(self)
A service is typically a process or application that provides
remote objects, but can also be the broadcast service that
receives signals from all applications on the Bus.
"""
def __init__(self, bus, service_name):
self._bus = bus
self._service_name = service_name
def __str__(self):
return "Unknown method: %s" % self.msg
def get_bus(self):
return self._bus
def get_service_name(self):
return self._service_name
def get_object(self, object_path, interface):
"""Get an object provided by this Service that implements a
particular interface. object_path is a string of the form
'/com/widgetcorp/MyService/MyObject1'. interface looks a lot
like a service_name (they're often the same) and is of the form,
'com.widgetcorp.MyInterface', and mostly just defines the
set of member functions that will be present in the object.
"""
return RemoteObject(self, object_path, interface)
ObjectPath = dbus_bindings.ObjectPath
ByteArray = dbus_bindings.ByteArray

View file

@ -222,6 +222,17 @@ cdef class Connection:
NULL)
return retval
def send_with_reply_handlers(self, Message message, timeout_milliseconds, reply_handler, error_handler):
retval = False
try:
(retval, pending_call) = self.send_with_reply(message, timeout_milliseconds)
if pending_call:
pending_call.set_notify(reply_handler, error_handler)
except Exception, e:
error_handler(e)
return retval
def send_with_reply(self, Message message, timeout_milliseconds):
cdef dbus_bool_t retval
cdef DBusPendingCall *cpending_call
@ -376,7 +387,34 @@ cdef class Connection:
return child_entries
cdef void _pending_call_notification(DBusPendingCall *pending_call, void *user_data):
cdef DBusMessage *dbus_message
cdef Message message
(reply_handler, error_handler) = <object>user_data
dbus_message = dbus_pending_call_steal_reply(pending_call)
message = Message(_create=0)
message._set_msg(dbus_message)
type = message.get_type()
if type == MESSAGE_TYPE_METHOD_RETURN:
args = message.get_args_list()
reply_handler(*args)
elif type == MESSAGE_TYPE_ERROR:
args = message.get_args_list()
error_handler(DBusException(args[0]))
else:
error_handler(DBusException('Unexpected Message Type: ' + message.type_to_name(type)))
dbus_message_unref(dbus_message)
dbus_pending_call_unref(pending_call)
cdef void _pending_call_free_user_data(void *data):
call_tuple = <object>data
Py_XDECREF(call_tuple)
cdef class PendingCall:
cdef DBusPendingCall *pending_call
@ -406,6 +444,13 @@ cdef class PendingCall:
def block(self):
dbus_pending_call_block(self.pending_call)
def set_notify(self, reply_handler, error_handler):
user_data = (reply_handler, error_handler)
Py_XINCREF(user_data)
dbus_pending_call_set_notify(self.pending_call, _pending_call_notification,
<void *>user_data, _pending_call_free_user_data)
cdef class Watch:
cdef DBusWatch* watch
@ -914,29 +959,34 @@ cdef class Message:
cdef DBusMessage *msg
def __init__(self, message_type=MESSAGE_TYPE_INVALID,
service=None, path=None, interface=None, method=None,
service=None, path=None, dbus_interface=None, method=None,
Message method_call=None,
name=None,
Message reply_to=None, error_name=None, error_message=None,
_create=1):
cdef char *cservice
cdef char *ciface
cdef DBusMessage *cmsg
if (service == None):
cservice = NULL
else:
ciface = NULL
if (dbus_interface != None):
ciface = dbus_interface
cservice = NULL
if (service != None):
cservice = service
if not _create:
return
if message_type == MESSAGE_TYPE_METHOD_CALL:
self.msg = dbus_message_new_method_call(cservice, path, interface, method)
self.msg = dbus_message_new_method_call(cservice, path, ciface, method)
elif message_type == MESSAGE_TYPE_METHOD_RETURN:
cmsg = method_call._get_msg()
self.msg = dbus_message_new_method_return(cmsg)
elif message_type == MESSAGE_TYPE_SIGNAL:
self.msg = dbus_message_new_signal(path, interface, name)
self.msg = dbus_message_new_signal(path, ciface, name)
elif message_type == MESSAGE_TYPE_ERROR:
cmsg = reply_to._get_msg()
self.msg = dbus_message_new_error(cmsg, error_name, error_message)
@ -1105,11 +1155,11 @@ cdef class Message:
class Signal(Message):
def __init__(self, spath, sinterface, sname):
Message.__init__(self, MESSAGE_TYPE_SIGNAL, path=spath, interface=sinterface, name=sname)
Message.__init__(self, MESSAGE_TYPE_SIGNAL, path=spath, dbus_interface=sinterface, name=sname)
class MethodCall(Message):
def __init__(self, mpath, minterface, mmethod):
Message.__init__(self, MESSAGE_TYPE_METHOD_CALL, path=mpath, interface=minterface, method=mmethod)
Message.__init__(self, MESSAGE_TYPE_METHOD_CALL, path=mpath, dbus_interface=minterface, method=mmethod)
class MethodReturn(Message):
def __init__(self, method_call):

View file

@ -3,15 +3,14 @@
import dbus
bus = dbus.SessionBus()
remote_service = bus.get_service("org.designfu.SampleService")
remote_object = remote_service.get_object("/SomeObject",
"org.designfu.SampleInterface")
remote_object = bus.get_object("org.designfu.SampleService", "/SomeObject")
iface = dbus.Interface(remote_object, "org.designfu.SampleInterface")
hello_reply_list = remote_object.HelloWorld("Hello from example-client.py!")
hello_reply_list = remote_object.HelloWorld("Hello from example-client.py!", dbus_interface = "org.designfu.SampleInterface")
hello_reply_tuple = remote_object.GetTuple()
hello_reply_tuple = iface.GetTuple()
hello_reply_dict = remote_object.GetDict()
hello_reply_dict = iface.GetDict()
print (hello_reply_list)
@ -19,3 +18,4 @@ print str(hello_reply_tuple)
print str(hello_reply_dict)
print remote_object.Introspect(dbus_interface="org.freedesktop.DBus.Introspectable")

View file

@ -5,17 +5,19 @@ import gtk
class SomeObject(dbus.Object):
def __init__(self, service):
export = [self.HelloWorld, self.GetTuple, self.GetDict]
dbus.Object.__init__(self, "/SomeObject", service, export)
dbus.Object.__init__(self, "/SomeObject", service)
def HelloWorld(self, message, hello_message):
@dbus.method("org.designfu.SampleInterface")
def HelloWorld(self, hello_message):
print (str(hello_message))
return ["Hello", " from example-service.py"]
def GetTuple(self, message):
@dbus.method("org.designfu.SampleInterface")
def GetTuple(self):
return ("Hello Tuple", " from example-service.py")
def GetDict(self, message):
@dbus.method("org.designfu.SampleInterface")
def GetDict(self):
return {"first": "Hello Dict", "second": " from example-service.py"}
session_bus = dbus.SessionBus()

View file

@ -3,13 +3,20 @@ import gtk
class TestObject(dbus.Object):
def __init__(self, service):
dbus.Object.__init__(self, "/org/designfu/TestService/object", service, [self.emitHelloSignal])
dbus.Object.__init__(self, "/org/designfu/TestService/object", service)
def emitHelloSignal(self, message):
# Emit the signal
self.emit_signal(interface="org.designfu.TestService",
signal_name="hello")
@dbus.signal('org.designfu.TestService')
def HelloSignal(self, message):
# The signal is emitted when this method exits
# You can have code here if you wish
pass
@dbus.method('org.designfu.TestService')
def emitHelloSignal(self):
#you emit signals by calling the signal's skeleton method
self.HelloSignal("Hello")
return "Signal emitted"
session_bus = dbus.SessionBus()
service = dbus.Service("org.designfu.TestService", bus=session_bus)
object = TestObject(service)

View file

@ -1,19 +1,30 @@
import gtk
import dbus
import gobject
def handle_reply(msg):
print msg
def handle_error(e):
print str(e)
def emit_signal():
#call the emitHelloSignal method async
object.emitHelloSignal(dbus_interface="org.designfu.TestService",
reply_handler = handle_reply, error_handler = handle_error)
return True
bus = dbus.SessionBus()
service = bus.get_service("org.designfu.TestService")
object = service.get_object("/org/designfu/TestService/object", "org.designfu.TestService")
object = bus.get_object("org.designfu.TestService","/org/designfu/TestService/object")
def hello_signal_handler(sender):
print ("Received signal '%s.%s' from object '%s%s'"
% (sender.interface, sender.signal_name, sender.service, sender.path))
def hello_signal_handler(hello_string):
print ("Received signal and it says: " + hello_string)
object.connect_to_signal("HelloSignal", hello_signal_handler, dbus_interface="org.designfu.TestService")
object.connect_to_signal("hello", hello_signal_handler)
gobject.timeout_add(2000, emit_signal)
# Tell the remote object to emit the signal
object.emitHelloSignal()
gtk.main()

View file

@ -5,15 +5,14 @@ import dbus
# Get a connection to the SYSTEM bus
bus = dbus.SystemBus()
# Get the service provided by the dbus-daemon named org.freedesktop.DBus
dbus_service = bus.get_service('org.freedesktop.DBus')
# Get a reference to the desktop bus' standard object, denoted
# by the path /org/freedesktop/DBus. The object /org/freedesktop/DBus
# by the path /org/freedesktop/DBus.
dbus_object = bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus')
# The object /org/freedesktop/DBus
# implements the 'org.freedesktop.DBus' interface
dbus_object = dbus_service.get_object('/org/freedesktop/DBus',
'org.freedesktop.DBus')
dbus_iface = dbus.Interface(dbus_object, 'org.freedesktop.DBus')
# One of the member functions in the org.freedesktop.DBus interface
# is ListServices(), which provides a list of all the other services
# registered on this bus. Call it, and print the list.