1 from decorators import *
6 """A base class for exporting your own Named Services across the Bus
8 def __init__(self, named_service, bus=None):
9 self._named_service = named_service
17 dbus_bindings.bus_request_name(self._bus.get_connection(), named_service)
20 """Get the Bus this Service is on"""
24 """Get the name of this service"""
25 return self._named_service
27 def _dispatch_dbus_method_call(target_methods, self, argument_list, message):
28 """Calls method_to_call using argument_list, but handles
29 exceptions, etc, and generates a reply to the DBus Message message
34 dbus_interface = message.get_interface()
35 if dbus_interface == None:
37 target_method = target_methods[0]
39 for dbus_method in target_methods:
40 if dbus_method._dbus_interface == dbus_interface:
41 target_method = dbus_method
45 retval = target_method(self, *argument_list)
47 if not dbus_interface:
48 raise UnknownMethodException('%s is not a valid method'%(message.get_member()))
50 raise UnknownMethodException('%s is not a valid method of interface %s'%(message.get_member(), dbus_interface))
52 if e.__module__ == '__main__':
53 # FIXME: is it right to use .__name__ here?
54 error_name = e.__class__.__name__
56 error_name = e.__module__ + '.' + str(e.__class__.__name__)
57 error_contents = str(e)
58 reply = dbus_bindings.Error(message, error_name, error_contents)
60 reply = dbus_bindings.MethodReturn(message)
62 iter = reply.get_iter(append=True)
67 class ObjectType(type):
68 def __init__(cls, name, bases, dct):
71 method_vtable = getattr(cls, '_dbus_method_vtable', {})
72 reflection_data = getattr(cls, '_dbus_reflection_data', "")
74 reflection_interface_method_hash = {}
75 reflection_interface_signal_hash = {}
77 for func in dct.values():
78 if getattr(func, '_dbus_is_method', False):
79 if method_vtable.has_key(func.__name__):
80 method_vtable[func.__name__].append(func)
82 method_vtable[func.__name__] = [func]
84 #generate a hash of interfaces so we can group
85 #methods in the xml data
86 if reflection_interface_method_hash.has_key(func._dbus_interface):
87 reflection_interface_method_hash[func._dbus_interface].append(func)
89 reflection_interface_method_hash[func._dbus_interface] = [func]
91 elif getattr(func, '_dbus_is_signal', False):
92 if reflection_interface_signal_hash.has_key(func._dbus_interface):
93 reflection_interface_signal_hash[func._dbus_interface].append(func)
95 reflection_interface_signal_hash[func._dbus_interface] = [func]
97 for interface in reflection_interface_method_hash.keys():
98 reflection_data = reflection_data + ' <interface name="%s">\n'%(interface)
99 for func in reflection_interface_method_hash[interface]:
100 reflection_data = reflection_data + cls._reflect_on_method(func)
102 if reflection_interface_signal_hash.has_key(interface):
103 for func in reflection_interface_signal_hash[interface]:
104 reflection_data = reflection_data + cls._reflect_on_signal(func)
106 del reflection_interface_signal_hash[interface]
108 reflection_data = reflection_data + ' </interface>\n'
110 for interface in reflection_interface_signal_hash.keys():
111 reflection_data = reflection_data + ' <interface name="%s">\n'%(interface)
113 for func in reflection_interface_signal_hash[interface]:
114 reflection_data = reflection_data + cls._reflect_on_signal(func)
116 reflection_data = reflection_data + ' </interface>\n'
118 cls._dbus_reflection_data = reflection_data
119 cls._dbus_method_vtable = method_vtable
121 super(ObjectType, cls).__init__(name, bases, dct)
123 #reflections on methods and signals may look like similar code but may in fact
124 #diverge in the future so keep them seperate
125 def _reflect_on_method(cls, func):
126 reflection_data = ' <method name="%s">\n'%(func.__name__)
127 for arg in func._dbus_args:
128 reflection_data = reflection_data + ' <arg name="%s" type="v" />\n'%(arg)
131 func._dbus_args = None
132 reflection_data = reflection_data + ' </method>\n'
134 return reflection_data
136 def _reflect_on_signal(cls, func):
137 reflection_data = ' <signal name="%s">\n'%(func.__name__)
138 for arg in func._dbus_args:
139 reflection_data = reflection_data + ' <arg name="%s" type="v" />\n'%(arg)
141 func._dbus_args = None
142 reflection_data = reflection_data + ' </signal>\n'
144 return reflection_data
147 """A base class for exporting your own Objects across the Bus.
149 Just inherit from Object and provide a list of methods to share
152 __metaclass__ = ObjectType
154 def __init__(self, bus_name, object_path):
155 self._object_path = object_path
156 self._name = bus_name
157 self._bus = name.get_bus()
159 self._connection = self._bus.get_connection()
161 self._connection.register_object_path(object_path, self._unregister_cb, self._message_cb)
163 def _unregister_cb(self, connection):
166 def _message_cb(self, connection, message):
167 target_method_name = message.get_member()
168 target_methods = self._dbus_method_vtable[target_method_name]
169 args = message.get_args_list()
171 reply = _dispatch_dbus_method_call(target_methods, self, args, message)
173 self._connection.send(reply)
175 @method('org.freedesktop.DBus.Introspectable')
176 def Introspect(self):
177 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'
178 reflection_data = reflection_data + '<node name="%s">\n'%(self._object_path)
179 reflection_data = reflection_data + self._dbus_reflection_data
180 reflection_data = reflection_data + '</node>\n'
182 return reflection_data