Move get_object, constants into Connection and BusConnection. Add docstrings
[dbus-python-phuang.git] / dbus / bus.py
blob45c8505bcea8f156532ea6646b7e4684884a10dd
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 __all__ = ('BusConnection',)
20 __docformat__ = 'reStructuredText'
22 from _dbus_bindings import validate_interface_name, validate_member_name,\
23 validate_bus_name, validate_object_path,\
24 validate_error_name,\
25 DBusException, \
26 BUS_SESSION, BUS_STARTER, BUS_SYSTEM, \
27 BUS_DAEMON_NAME, BUS_DAEMON_PATH, BUS_DAEMON_IFACE
28 from dbus.connection import Connection
31 class BusConnection(Connection):
32 """A connection to a D-Bus daemon that implements the
33 ``org.freedesktop.DBus`` pseudo-service.
34 """
36 TYPE_SESSION = BUS_SESSION
37 """Represents a session bus (same as the global dbus.BUS_SESSION)"""
39 TYPE_SYSTEM = BUS_SYSTEM
40 """Represents the system bus (same as the global dbus.BUS_SYSTEM)"""
42 TYPE_STARTER = BUS_STARTER
43 """Represents the bus that started this service by activation (same as
44 the global dbus.BUS_STARTER)"""
46 def activate_name_owner(self, bus_name):
47 if (bus_name is not None and bus_name[:1] != ':'
48 and bus_name != BUS_DAEMON_NAME):
49 try:
50 return self.get_name_owner(bus_name)
51 except DBusException, e:
52 # FIXME: detect whether it's NameHasNoOwner, but properly
53 #if not str(e).startswith('org.freedesktop.DBus.Error.NameHasNoOwner:'):
54 # raise
55 # it might not exist: try to start it
56 self.start_service_by_name(bus_name)
57 return self.get_name_owner(bus_name)
58 else:
59 # already unique
60 return bus_name
62 def get_object(self, named_service, object_path, introspect=True,
63 follow_name_owner_changes=False):
64 """Return a local proxy for the given remote object.
66 Method calls on the proxy are translated into method calls on the
67 remote object.
69 :Parameters:
70 `named_service` : str
71 A bus name (either the unique name or a well-known name)
72 of the application owning the object
73 `object_path` : str
74 The object path of the desired object
75 `introspect` : bool
76 If true (default), attempt to introspect the remote
77 object to find out supported methods and their signatures
78 `follow_name_owner_changes` : bool
79 If the object path is a well-known name and this parameter
80 is false (default), resolve the well-known name to the unique
81 name of its current owner and bind to that instead; if the
82 ownership of the well-known name changes in future,
83 keep communicating with the original owner.
84 This is necessary if the D-Bus API used is stateful.
86 If the object path is a well-known name and this parameter
87 is true, whenever the well-known name changes ownership in
88 future, bind to the new owner, if any.
90 If the given object path is a unique name, this parameter
91 has no effect.
93 :Returns: a `dbus.proxies.ProxyObject`
94 :Raises `DBusException`: if resolving the well-known name to a
95 unique name fails
96 """
97 if follow_name_owner_changes:
98 self._require_main_loop() # we don't get the signals otherwise
99 return self.ProxyObjectClass(self, named_service, object_path,
100 introspect=introspect,
101 follow_name_owner_changes=follow_name_owner_changes)
103 def get_unix_user(self, bus_name):
104 """Get the numeric uid of the process owning the given bus name.
106 :Parameters:
107 `bus_name` : str
108 A bus name, either unique or well-known
109 :Returns: a `dbus.UInt32`
111 validate_bus_name(bus_name)
112 return self.call_blocking(BUS_DAEMON_NAME, BUS_DAEMON_PATH,
113 BUS_DAEMON_IFACE, 'GetConnectionUnixUser',
114 's', (bus_name,))
116 def start_service_by_name(self, bus_name, flags=0):
117 """Start a service which will implement the given bus name on this Bus.
119 :Parameters:
120 `bus_name` : str
121 The well-known bus name to be activated.
122 `flags` : dbus.UInt32
123 Flags to pass to StartServiceByName (currently none are
124 defined)
126 :Returns: A tuple of 2 elements. The first is always True, the
127 second is either START_REPLY_SUCCESS or
128 START_REPLY_ALREADY_RUNNING.
130 :Raises DBusException: if the service could not be started.
132 validate_bus_name(bus_name)
133 return (True, self.call_blocking(BUS_DAEMON_NAME, BUS_DAEMON_PATH,
134 BUS_DAEMON_IFACE,
135 'StartServiceByName',
136 'su', (bus_name, flags)))
138 # XXX: it might be nice to signal IN_QUEUE, EXISTS by exception,
139 # but this would not be backwards-compatible
140 def request_name(self, name, flags=0):
141 """Request a bus name.
143 :Parameters:
144 `name` : str
145 The well-known name to be requested
146 `flags` : dbus.UInt32
147 A bitwise-OR of 0 or more of the flags
148 `DBUS_NAME_FLAG_ALLOW_REPLACEMENT`,
149 `DBUS_NAME_FLAG_REPLACE_EXISTING`
150 and `DBUS_NAME_FLAG_DO_NOT_QUEUE`
151 :Returns: `DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER`,
152 `DBUS_REQUEST_NAME_REPLY_IN_QUEUE`,
153 `DBUS_REQUEST_NAME_REPLY_EXISTS` or
154 `DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER`
155 :Raises DBusException: if the bus daemon cannot be contacted or
156 returns an error.
158 validate_bus_name(name, allow_unique=False)
159 return self.call_blocking(BUS_DAEMON_NAME, BUS_DAEMON_PATH,
160 BUS_DAEMON_IFACE, 'RequestName',
161 'su', (name, flags))
163 def release_name(self, name):
164 """Release a bus name.
166 :Parameters:
167 `name` : str
168 The well-known name to be released
169 :Returns: `DBUS_RELEASE_NAME_REPLY_RELEASED`,
170 `DBUS_RELEASE_NAME_REPLY_NON_EXISTENT`
171 or `DBUS_RELEASE_NAME_REPLY_NOT_OWNER`
172 :Raises DBusException: if the bus daemon cannot be contacted or
173 returns an error.
175 validate_bus_name(name, allow_unique=False)
176 return self.call_blocking(BUS_DAEMON_NAME, BUS_DAEMON_PATH,
177 BUS_DAEMON_IFACE, 'ReleaseName',
178 's', (name,))
180 def list_names(self):
181 """Return a list of all currently-owned names on the bus.
183 :Returns: a dbus.Array of dbus.UTF8String
185 return self.call_blocking(BUS_DAEMON_NAME, BUS_DAEMON_PATH,
186 BUS_DAEMON_IFACE, 'ListNames',
187 '', (), utf8_strings=True)
189 def list_activatable_names(self):
190 """Return a list of all names that can be activated on the bus.
192 :Returns: a dbus.Array of dbus.UTF8String
194 return self.call_blocking(BUS_DAEMON_NAME, BUS_DAEMON_PATH,
195 BUS_DAEMON_IFACE, 'ListNames',
196 '', (), utf8_strings=True)
198 def get_name_owner(self, bus_name):
199 """Return the unique connection name of the primary owner of the
200 given name.
202 :Raises DBusException: if the `bus_name` has no owner
204 validate_bus_name(bus_name, allow_unique=False)
205 return self.call_blocking(BUS_DAEMON_NAME, BUS_DAEMON_PATH,
206 BUS_DAEMON_IFACE, 'GetNameOwner',
207 's', (bus_name,), utf8_strings=True)
209 def name_has_owner(self, bus_name):
210 """Return True iff the given bus name has an owner on this bus.
212 :Parameters:
213 `name` : str
214 The bus name to look up
215 :Returns: a `bool`
217 return bool(self.call_blocking(BUS_DAEMON_NAME, BUS_DAEMON_PATH,
218 BUS_DAEMON_IFACE, 'NameHasOwner',
219 's', (bus_name,)))
221 def add_match_string(self, rule):
222 """Arrange for this application to receive messages on the bus that
223 match the given rule. This version will block.
225 :Parameters:
226 `rule` : str
227 The match rule
228 :Raises: `DBusException` on error.
230 self.call_blocking(BUS_DAEMON_NAME, BUS_DAEMON_PATH,
231 BUS_DAEMON_IFACE, 'AddMatch', 's', (rule,))
233 # FIXME: add an async success/error handler capability?
234 # (and the same for remove_...)
235 def add_match_string_non_blocking(self, rule):
236 """Arrange for this application to receive messages on the bus that
237 match the given rule. This version will not block, but any errors
238 will be ignored.
241 :Parameters:
242 `rule` : str
243 The match rule
244 :Raises: `DBusException` on error.
246 self.call_async(BUS_DAEMON_NAME, BUS_DAEMON_PATH,
247 BUS_DAEMON_IFACE, 'AddMatch', 's', (rule,),
248 None, None)
250 def remove_match_string(self, rule):
251 """Arrange for this application to receive messages on the bus that
252 match the given rule. This version will block.
254 :Parameters:
255 `rule` : str
256 The match rule
257 :Raises: `DBusException` on error.
259 self.call_blocking(BUS_DAEMON_NAME, BUS_DAEMON_PATH,
260 BUS_DAEMON_IFACE, 'RemoveMatch', 's', (rule,))
262 def remove_match_string_non_blocking(self, rule):
263 """Arrange for this application to receive messages on the bus that
264 match the given rule. This version will not block, but any errors
265 will be ignored.
268 :Parameters:
269 `rule` : str
270 The match rule
271 :Raises: `DBusException` on error.
273 self.call_async(BUS_DAEMON_NAME, BUS_DAEMON_PATH,
274 BUS_DAEMON_IFACE, 'RemoveMatch', 's', (rule,),
275 None, None)