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 # Permission is hereby granted, free of charge, to any person
9 # obtaining a copy of this software and associated documentation
10 # files (the "Software"), to deal in the Software without
11 # restriction, including without limitation the rights to use, copy,
12 # modify, merge, publish, distribute, sublicense, and/or sell copies
13 # of the Software, and to permit persons to whom the Software is
14 # furnished to do so, subject to the following conditions:
16 # The above copyright notice and this permission notice shall be
17 # included in all copies or substantial portions of the Software.
19 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23 # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 # DEALINGS IN THE SOFTWARE.
28 from __future__
import generators
30 __all__
= ('Bus', 'SystemBus', 'SessionBus', 'StarterBus')
31 __docformat__
= 'reStructuredText'
36 from traceback
import print_exc
38 from dbus
.exceptions
import DBusException
39 from _dbus_bindings
import BUS_DAEMON_NAME
, BUS_DAEMON_PATH
,\
40 BUS_DAEMON_IFACE
, UTF8String
,\
41 validate_member_name
, validate_interface_name
,\
42 validate_bus_name
, validate_object_path
,\
43 BUS_SESSION
, BUS_SYSTEM
, BUS_STARTER
,\
44 DBUS_START_REPLY_SUCCESS
, \
45 DBUS_START_REPLY_ALREADY_RUNNING
46 from dbus
.bus
import BusConnection
47 from dbus
.lowlevel
import SignalMessage
52 import dummy_thread
as thread
55 class Bus(BusConnection
):
56 """A connection to one of three possible standard buses, the SESSION,
57 SYSTEM, or STARTER bus. This class manages shared connections to those
60 If you're trying to subclass `Bus`, you may be better off subclassing
61 `BusConnection`, which doesn't have all this magic.
64 _shared_instances
= {}
66 def __new__(cls
, bus_type
=BusConnection
.TYPE_SESSION
, private
=False,
68 """Constructor, returning an existing instance where appropriate.
70 The returned instance is actually always an instance of `SessionBus`,
71 `SystemBus` or `StarterBus`.
74 `bus_type` : cls.TYPE_SESSION, cls.TYPE_SYSTEM or cls.TYPE_STARTER
75 Connect to the appropriate bus
77 If true, never return an existing shared instance, but instead
78 return a private connection.
79 :Deprecated: since 0.82.3. Use dbus.bus.BusConnection for
81 `mainloop` : dbus.mainloop.NativeMainLoop
82 The main loop to use. The default is to use the default
83 main loop if one has been set up, or raise an exception
85 :Changed: in dbus-python 0.80:
86 converted from a wrapper around a Connection to a Connection
89 if (not private
and bus_type
in cls
._shared
_instances
):
90 return cls
._shared
_instances
[bus_type
]
92 # this is a bit odd, but we create instances of the subtypes
93 # so we can return the shared instances if someone tries to
94 # construct one of them (otherwise we'd eg try and return an
95 # instance of Bus from __new__ in SessionBus). why are there
96 # three ways to construct this class? we just don't know.
97 if bus_type
== BUS_SESSION
:
99 elif bus_type
== BUS_SYSTEM
:
101 elif bus_type
== BUS_STARTER
:
102 subclass
= StarterBus
104 raise ValueError('invalid bus_type %s' % bus_type
)
106 bus
= BusConnection
.__new
__(subclass
, bus_type
, mainloop
=mainloop
)
108 bus
._bus
_type
= bus_type
111 cls
._shared
_instances
[bus_type
] = bus
117 if self
.__class
__._shared
_instances
.get(t
) is self
:
118 del self
.__class
__._shared
_instances
[t
]
119 super(Bus
, self
).close()
121 def get_connection(self
):
122 """Return self, for backwards compatibility with earlier dbus-python
123 versions where Bus was not a subclass of Connection.
125 :Deprecated: since 0.80.0
128 _connection
= property(get_connection
, None, None,
129 """self._connection == self, for backwards
130 compatibility with earlier dbus-python versions
131 where Bus was not a subclass of Connection.""")
133 def get_session(private
=False):
134 """Static method that returns a connection to the session bus.
138 If true, do not return a shared connection.
140 return SessionBus(private
=private
)
142 get_session
= staticmethod(get_session
)
144 def get_system(private
=False):
145 """Static method that returns a connection to the system bus.
149 If true, do not return a shared connection.
151 return SystemBus(private
=private
)
153 get_system
= staticmethod(get_system
)
156 def get_starter(private
=False):
157 """Static method that returns a connection to the starter bus.
161 If true, do not return a shared connection.
163 return StarterBus(private
=private
)
165 get_starter
= staticmethod(get_starter
)
168 if self
._bus
_type
== BUS_SESSION
:
170 elif self
._bus
_type
== BUS_SYSTEM
:
172 elif self
._bus
_type
== BUS_STARTER
:
175 name
= 'unknown bus type'
177 return '<%s.%s (%s) at %#x>' % (self
.__class
__.__module
__,
178 self
.__class
__.__name
__,
183 # FIXME: Drop the subclasses here? I can't think why we'd ever want
185 class SystemBus(Bus
):
186 """The system-wide message bus."""
187 def __new__(cls
, private
=False, mainloop
=None):
188 """Return a connection to the system bus.
192 If true, never return an existing shared instance, but instead
193 return a private connection.
194 `mainloop` : dbus.mainloop.NativeMainLoop
195 The main loop to use. The default is to use the default
196 main loop if one has been set up, or raise an exception
199 return Bus
.__new
__(cls
, Bus
.TYPE_SYSTEM
, mainloop
=mainloop
,
202 class SessionBus(Bus
):
203 """The session (current login) message bus."""
204 def __new__(cls
, private
=False, mainloop
=None):
205 """Return a connection to the session bus.
209 If true, never return an existing shared instance, but instead
210 return a private connection.
211 `mainloop` : dbus.mainloop.NativeMainLoop
212 The main loop to use. The default is to use the default
213 main loop if one has been set up, or raise an exception
216 return Bus
.__new
__(cls
, Bus
.TYPE_SESSION
, private
=private
,
219 class StarterBus(Bus
):
220 """The bus that activated this process (only valid if
221 this process was launched by DBus activation).
223 def __new__(cls
, private
=False, mainloop
=None):
224 """Return a connection to the bus that activated this process.
228 If true, never return an existing shared instance, but instead
229 return a private connection.
230 `mainloop` : dbus.mainloop.NativeMainLoop
231 The main loop to use. The default is to use the default
232 main loop if one has been set up, or raise an exception
235 return Bus
.__new
__(cls
, Bus
.TYPE_STARTER
, private
=private
,
239 if 'DBUS_PYTHON_NO_DEPRECATED' not in os
.environ
:
241 class _DBusBindingsEmulation
:
242 """A partial emulation of the dbus_bindings module."""
244 return '_DBusBindingsEmulation()'
246 return '_DBusBindingsEmulation()'
247 def __getattr__(self
, attr
):
249 import dbus
.dbus_bindings
as m
251 return getattr(m
, attr
)
253 dbus_bindings
= _DBusBindingsEmulation()
254 """Deprecated, don't use."""