Convert _BusDaemonMixin and _MethodCallMixin into base classes BusConnection and...
[dbus-python-phuang.git] / dbus / bus.py
blobe5356d2d85b5b6a304f8db98dcb39b7250ea680f
1 # Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/>
3 # Licensed under the Academic Free License version 2.1
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU Lesser General Public License as published
7 # by the Free Software Foundation; either version 2.1 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 from _dbus_bindings import validate_interface_name, validate_member_name,\
20 validate_bus_name, validate_object_path,\
21 validate_error_name,\
22 DBusException, \
23 BUS_DAEMON_NAME, BUS_DAEMON_PATH, BUS_DAEMON_IFACE
24 from dbus.connection import Connection
27 class BusConnection(Connection):
28 """This mixin provides simple blocking wrappers for various methods on
29 the org.freedesktop.DBus bus-daemon object, to reduce the amount of C
30 code we need.
31 """
33 def activate_name_owner(self, bus_name):
34 if (bus_name is not None and bus_name[:1] != ':'
35 and bus_name != BUS_DAEMON_NAME):
36 try:
37 return self.get_name_owner(bus_name)
38 except DBusException, e:
39 # FIXME: detect whether it's NameHasNoOwner, but properly
40 #if not str(e).startswith('org.freedesktop.DBus.Error.NameHasNoOwner:'):
41 # raise
42 # it might not exist: try to start it
43 self.start_service_by_name(bus_name)
44 return self.get_name_owner(bus_name)
45 else:
46 # already unique
47 return bus_name
49 def get_unix_user(self, bus_name):
50 """Get the numeric uid of the process owning the given bus name.
52 :Parameters:
53 `bus_name` : str
54 A bus name, either unique or well-known
55 :Returns: a `dbus.UInt32`
56 """
57 validate_bus_name(bus_name)
58 return self.call_blocking(BUS_DAEMON_NAME, BUS_DAEMON_PATH,
59 BUS_DAEMON_IFACE, 'GetConnectionUnixUser',
60 's', (bus_name,))
62 def start_service_by_name(self, bus_name, flags=0):
63 """Start a service which will implement the given bus name on this Bus.
65 :Parameters:
66 `bus_name` : str
67 The well-known bus name to be activated.
68 `flags` : dbus.UInt32
69 Flags to pass to StartServiceByName (currently none are
70 defined)
72 :Returns: A tuple of 2 elements. The first is always True, the
73 second is either START_REPLY_SUCCESS or
74 START_REPLY_ALREADY_RUNNING.
76 :Raises DBusException: if the service could not be started.
77 """
78 validate_bus_name(bus_name)
79 return (True, self.call_blocking(BUS_DAEMON_NAME, BUS_DAEMON_PATH,
80 BUS_DAEMON_IFACE,
81 'StartServiceByName',
82 'su', (bus_name, flags)))
84 # XXX: it might be nice to signal IN_QUEUE, EXISTS by exception,
85 # but this would not be backwards-compatible
86 def request_name(self, name, flags=0):
87 """Request a bus name.
89 :Parameters:
90 `name` : str
91 The well-known name to be requested
92 `flags` : dbus.UInt32
93 A bitwise-OR of 0 or more of the flags
94 `DBUS_NAME_FLAG_ALLOW_REPLACEMENT`,
95 `DBUS_NAME_FLAG_REPLACE_EXISTING`
96 and `DBUS_NAME_FLAG_DO_NOT_QUEUE`
97 :Returns: `DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER`,
98 `DBUS_REQUEST_NAME_REPLY_IN_QUEUE`,
99 `DBUS_REQUEST_NAME_REPLY_EXISTS` or
100 `DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER`
101 :Raises DBusException: if the bus daemon cannot be contacted or
102 returns an error.
104 validate_bus_name(name, allow_unique=False)
105 return self.call_blocking(BUS_DAEMON_NAME, BUS_DAEMON_PATH,
106 BUS_DAEMON_IFACE, 'RequestName',
107 'su', (name, flags))
109 def release_name(self, name):
110 """Release a bus name.
112 :Parameters:
113 `name` : str
114 The well-known name to be released
115 :Returns: `DBUS_RELEASE_NAME_REPLY_RELEASED`,
116 `DBUS_RELEASE_NAME_REPLY_NON_EXISTENT`
117 or `DBUS_RELEASE_NAME_REPLY_NOT_OWNER`
118 :Raises DBusException: if the bus daemon cannot be contacted or
119 returns an error.
121 validate_bus_name(name, allow_unique=False)
122 return self.call_blocking(BUS_DAEMON_NAME, BUS_DAEMON_PATH,
123 BUS_DAEMON_IFACE, 'ReleaseName',
124 's', (name,))
126 def list_names(self):
127 """Return a list of all currently-owned names on the bus.
129 :Returns: a dbus.Array of dbus.UTF8String
131 return self.call_blocking(BUS_DAEMON_NAME, BUS_DAEMON_PATH,
132 BUS_DAEMON_IFACE, 'ListNames',
133 '', (), utf8_strings=True)
135 def list_activatable_names(self):
136 """Return a list of all names that can be activated on the bus.
138 :Returns: a dbus.Array of dbus.UTF8String
140 return self.call_blocking(BUS_DAEMON_NAME, BUS_DAEMON_PATH,
141 BUS_DAEMON_IFACE, 'ListNames',
142 '', (), utf8_strings=True)
144 def get_name_owner(self, bus_name):
145 """Return the unique connection name of the primary owner of the
146 given name.
148 :Raises DBusException: if the `bus_name` has no owner
150 validate_bus_name(bus_name, allow_unique=False)
151 return self.call_blocking(BUS_DAEMON_NAME, BUS_DAEMON_PATH,
152 BUS_DAEMON_IFACE, 'GetNameOwner',
153 's', (bus_name,), utf8_strings=True)
155 def name_has_owner(self, bus_name):
156 """Return True iff the given bus name has an owner on this bus.
158 :Parameters:
159 `name` : str
160 The bus name to look up
161 :Returns: a `bool`
163 return bool(self.call_blocking(BUS_DAEMON_NAME, BUS_DAEMON_PATH,
164 BUS_DAEMON_IFACE, 'NameHasOwner',
165 's', (bus_name,)))
167 def add_match_string(self, rule):
168 """Arrange for this application to receive messages on the bus that
169 match the given rule. This version will block.
171 :Parameters:
172 `rule` : str
173 The match rule
174 :Raises: `DBusException` on error.
176 self.call_blocking(BUS_DAEMON_NAME, BUS_DAEMON_PATH,
177 BUS_DAEMON_IFACE, 'AddMatch', 's', (rule,))
179 # FIXME: add an async success/error handler capability?
180 # (and the same for remove_...)
181 def add_match_string_non_blocking(self, rule):
182 """Arrange for this application to receive messages on the bus that
183 match the given rule. This version will not block, but any errors
184 will be ignored.
187 :Parameters:
188 `rule` : str
189 The match rule
190 :Raises: `DBusException` on error.
192 self.call_async(BUS_DAEMON_NAME, BUS_DAEMON_PATH,
193 BUS_DAEMON_IFACE, 'AddMatch', 's', (rule,),
194 None, None)
196 def remove_match_string(self, rule):
197 """Arrange for this application to receive messages on the bus that
198 match the given rule. This version will block.
200 :Parameters:
201 `rule` : str
202 The match rule
203 :Raises: `DBusException` on error.
205 self.call_blocking(BUS_DAEMON_NAME, BUS_DAEMON_PATH,
206 BUS_DAEMON_IFACE, 'RemoveMatch', 's', (rule,))
208 def remove_match_string_non_blocking(self, rule):
209 """Arrange for this application to receive messages on the bus that
210 match the given rule. This version will not block, but any errors
211 will be ignored.
214 :Parameters:
215 `rule` : str
216 The match rule
217 :Raises: `DBusException` on error.
219 self.call_async(BUS_DAEMON_NAME, BUS_DAEMON_PATH,
220 BUS_DAEMON_IFACE, 'RemoveMatch', 's', (rule,),
221 None, None)