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'
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
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
56 If you're trying to subclass `Bus`, you may be better off subclassing
57 `BusConnection`, which doesn't have all this magic.
60 _shared_instances
= {}
62 def __new__(cls
, bus_type
=BusConnection
.TYPE_SESSION
, private
=False,
64 """Constructor, returning an existing instance where appropriate.
66 The returned instance is actually always an instance of `SessionBus`,
67 `SystemBus` or `StarterBus`.
70 `bus_type` : cls.TYPE_SESSION, cls.TYPE_SYSTEM or cls.TYPE_STARTER
71 Connect to the appropriate bus
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
80 - There is currently no way to connect this class to a custom
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
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
:
98 elif bus_type
== BUS_SYSTEM
:
100 elif bus_type
== BUS_STARTER
:
101 subclass
= StarterBus
103 raise ValueError('invalid bus_type %s' % bus_type
)
105 bus
= BusConnection
.__new
__(subclass
, bus_type
, mainloop
=mainloop
)
107 bus
._bus
_type
= bus_type
110 cls
._shared
_instances
[bus_type
] = bus
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
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.
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.
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.
160 If true, do not return a shared connection.
162 return StarterBus(private
=private
)
164 get_starter
= staticmethod(get_starter
)
167 if self
._bus
_type
== BUS_SESSION
:
169 elif self
._bus
_type
== BUS_SYSTEM
:
171 elif self
._bus
_type
== BUS_STARTER
:
174 name
= 'unknown bus type'
176 return '<%s.%s (%s) at %#x>' % (self
.__class
__.__module
__,
177 self
.__class
__.__name
__,
182 # FIXME: Drop the subclasses here? I can't think why we'd ever want
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.
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
198 return Bus
.__new
__(cls
, Bus
.TYPE_SYSTEM
, mainloop
=mainloop
,
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.
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
215 return Bus
.__new
__(cls
, Bus
.TYPE_SESSION
, private
=private
,
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.
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
234 return Bus
.__new
__(cls
, Bus
.TYPE_STARTER
, private
=private
,
238 if 'DBUS_PYTHON_NO_DEPRECATED' not in os
.environ
:
240 class _DBusBindingsEmulation
:
241 """A partial emulation of the dbus_bindings module."""
243 return '_DBusBindingsEmulation()'
245 return '_DBusBindingsEmulation()'
246 def __getattr__(self
, attr
):
248 import dbus
.dbus_bindings
as m
250 return getattr(m
, attr
)
252 dbus_bindings
= _DBusBindingsEmulation()
253 """Deprecated, don't use."""