dbus.service: Don't assume that exceptions passed to asynchronous callbacks are the...
[dbus-python-phuang.git] / dbus / _dbus.py
blobbfb62f786ee71f35841112cdbdbfb7f460db0020
1 """Implementation for dbus.Bus. Not to be imported directly."""
3 # Copyright (C) 2003, 2004, 2005, 2006 Red Hat Inc. <http://www.redhat.com/>
4 # Copyright (C) 2003 David Zeuthen
5 # Copyright (C) 2004 Rob Taylor
6 # Copyright (C) 2005, 2006 Collabora Ltd. <http://www.collabora.co.uk/>
8 # Licensed under the Academic Free License version 2.1
10 # This program is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 2 of the License, or
13 # (at your option) any later version.
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
20 # You should have received a copy of the GNU General Public License
21 # along with this program; if not, write to the Free Software
22 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 from __future__ import generators
26 __all__ = ('Bus', 'SystemBus', 'SessionBus', 'StarterBus')
27 __docformat__ = 'reStructuredText'
29 import os
30 import sys
31 import weakref
32 from traceback import print_exc
34 from dbus.exceptions import DBusException
35 from _dbus_bindings import BUS_DAEMON_NAME, BUS_DAEMON_PATH,\
36 BUS_DAEMON_IFACE, UTF8String,\
37 validate_member_name, validate_interface_name,\
38 validate_bus_name, validate_object_path,\
39 BUS_SESSION, BUS_SYSTEM, BUS_STARTER,\
40 DBUS_START_REPLY_SUCCESS, \
41 DBUS_START_REPLY_ALREADY_RUNNING
42 from dbus.bus import BusConnection
43 from dbus.lowlevel import SignalMessage
45 try:
46 import thread
47 except ImportError:
48 import dummy_thread as thread
51 class Bus(BusConnection):
52 """A connection to one of three possible standard buses, the SESSION,
53 SYSTEM, or STARTER bus. This class manages shared connections to those
54 buses.
56 If you're trying to subclass `Bus`, you may be better off subclassing
57 `BusConnection`, which doesn't have all this magic.
58 """
60 _shared_instances = {}
62 def __new__(cls, bus_type=BusConnection.TYPE_SESSION, private=False,
63 mainloop=None):
64 """Constructor, returning an existing instance where appropriate.
66 The returned instance is actually always an instance of `SessionBus`,
67 `SystemBus` or `StarterBus`.
69 :Parameters:
70 `bus_type` : cls.TYPE_SESSION, cls.TYPE_SYSTEM or cls.TYPE_STARTER
71 Connect to the appropriate bus
72 `private` : bool
73 If true, never return an existing shared instance, but instead
74 return a private connection
75 `mainloop` : dbus.mainloop.NativeMainLoop
76 The main loop to use. The default is to use the default
77 main loop if one has been set up, or raise an exception
78 if none has been.
79 :ToDo:
80 - There is currently no way to connect this class to a custom
81 address.
82 - Some of this functionality should be available on
83 peer-to-peer D-Bus connections too.
84 :Changed: in dbus-python 0.80:
85 converted from a wrapper around a Connection to a Connection
86 subclass.
87 """
88 if (not private and bus_type in cls._shared_instances):
89 return cls._shared_instances[bus_type]
91 # this is a bit odd, but we create instances of the subtypes
92 # so we can return the shared instances if someone tries to
93 # construct one of them (otherwise we'd eg try and return an
94 # instance of Bus from __new__ in SessionBus). why are there
95 # three ways to construct this class? we just don't know.
96 if bus_type == BUS_SESSION:
97 subclass = SessionBus
98 elif bus_type == BUS_SYSTEM:
99 subclass = SystemBus
100 elif bus_type == BUS_STARTER:
101 subclass = StarterBus
102 else:
103 raise ValueError('invalid bus_type %s' % bus_type)
105 bus = BusConnection.__new__(subclass, bus_type, mainloop=mainloop)
107 bus._bus_type = bus_type
109 if not private:
110 cls._shared_instances[bus_type] = bus
112 return bus
114 def close(self):
115 t = self._bus_type
116 if self.__class__._shared_instances[t] is self:
117 del self.__class__._shared_instances[t]
118 super(Bus, self).close()
120 def get_connection(self):
121 """Return self, for backwards compatibility with earlier dbus-python
122 versions where Bus was not a subclass of Connection.
124 :Deprecated: since 0.80.0
126 return self
127 _connection = property(get_connection, None, None,
128 """self._connection == self, for backwards
129 compatibility with earlier dbus-python versions
130 where Bus was not a subclass of Connection.""")
132 def get_session(private=False):
133 """Static method that returns a connection to the session bus.
135 :Parameters:
136 `private` : bool
137 If true, do not return a shared connection.
139 return SessionBus(private=private)
141 get_session = staticmethod(get_session)
143 def get_system(private=False):
144 """Static method that returns a connection to the system bus.
146 :Parameters:
147 `private` : bool
148 If true, do not return a shared connection.
150 return SystemBus(private=private)
152 get_system = staticmethod(get_system)
155 def get_starter(private=False):
156 """Static method that returns a connection to the starter bus.
158 :Parameters:
159 `private` : bool
160 If true, do not return a shared connection.
162 return StarterBus(private=private)
164 get_starter = staticmethod(get_starter)
166 def __repr__(self):
167 if self._bus_type == BUS_SESSION:
168 name = 'session'
169 elif self._bus_type == BUS_SYSTEM:
170 name = 'system'
171 elif self._bus_type == BUS_STARTER:
172 name = 'starter'
173 else:
174 name = 'unknown bus type'
176 return '<%s.%s (%s) at %#x>' % (self.__class__.__module__,
177 self.__class__.__name__,
178 name, id(self))
179 __str__ = __repr__
182 # FIXME: Drop the subclasses here? I can't think why we'd ever want
183 # polymorphism
184 class SystemBus(Bus):
185 """The system-wide message bus."""
186 def __new__(cls, private=False, mainloop=None):
187 """Return a connection to the system bus.
189 :Parameters:
190 `private` : bool
191 If true, never return an existing shared instance, but instead
192 return a private connection.
193 `mainloop` : dbus.mainloop.NativeMainLoop
194 The main loop to use. The default is to use the default
195 main loop if one has been set up, or raise an exception
196 if none has been.
198 return Bus.__new__(cls, Bus.TYPE_SYSTEM, mainloop=mainloop,
199 private=private)
201 class SessionBus(Bus):
202 """The session (current login) message bus."""
203 def __new__(cls, private=False, mainloop=None):
204 """Return a connection to the session bus.
206 :Parameters:
207 `private` : bool
208 If true, never return an existing shared instance, but instead
209 return a private connection.
210 `mainloop` : dbus.mainloop.NativeMainLoop
211 The main loop to use. The default is to use the default
212 main loop if one has been set up, or raise an exception
213 if none has been.
215 return Bus.__new__(cls, Bus.TYPE_SESSION, private=private,
216 mainloop=mainloop)
218 class StarterBus(Bus):
219 """The bus that activated this process (only valid if
220 this process was launched by DBus activation).
222 def __new__(cls, private=False, mainloop=None):
223 """Return a connection to the bus that activated this process.
225 :Parameters:
226 `private` : bool
227 If true, never return an existing shared instance, but instead
228 return a private connection.
229 `mainloop` : dbus.mainloop.NativeMainLoop
230 The main loop to use. The default is to use the default
231 main loop if one has been set up, or raise an exception
232 if none has been.
234 return Bus.__new__(cls, Bus.TYPE_STARTER, private=private,
235 mainloop=mainloop)
238 if 'DBUS_PYTHON_NO_DEPRECATED' not in os.environ:
240 class _DBusBindingsEmulation:
241 """A partial emulation of the dbus_bindings module."""
242 def __str__(self):
243 return '_DBusBindingsEmulation()'
244 def __repr__(self):
245 return '_DBusBindingsEmulation()'
246 def __getattr__(self, attr):
247 global dbus_bindings
248 import dbus.dbus_bindings as m
249 dbus_bindings = m
250 return getattr(m, attr)
252 dbus_bindings = _DBusBindingsEmulation()
253 """Deprecated, don't use."""