dbus.connection: Release signals lock before calling _clean_up_signal_match().
[dbus-python-phuang.git] / dbus / _dbus.py
blob3b96201adf49f0bb16ec358ee7746dc8def3c7c5
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 SignalMessage,\
43 HANDLER_RESULT_NOT_YET_HANDLED,\
44 HANDLER_RESULT_HANDLED
45 from dbus.bus import BusConnection
47 try:
48 import thread
49 except ImportError:
50 import dummy_thread as thread
53 class Bus(BusConnection):
54 """A connection to one of three possible standard buses, the SESSION,
55 SYSTEM, or STARTER bus. This class manages shared connections to those
56 buses.
58 If you're trying to subclass `Bus`, you may be better off subclassing
59 `BusConnection`, which doesn't have all this magic.
60 """
62 _shared_instances = {}
64 def __new__(cls, bus_type=BusConnection.TYPE_SESSION, private=False,
65 mainloop=None):
66 """Constructor, returning an existing instance where appropriate.
68 The returned instance is actually always an instance of `SessionBus`,
69 `SystemBus` or `StarterBus`.
71 :Parameters:
72 `bus_type` : cls.TYPE_SESSION, cls.TYPE_SYSTEM or cls.TYPE_STARTER
73 Connect to the appropriate bus
74 `private` : bool
75 If true, never return an existing shared instance, but instead
76 return a private connection
77 `mainloop` : dbus.mainloop.NativeMainLoop
78 The main loop to use. The default is to use the default
79 main loop if one has been set up, or raise an exception
80 if none has been.
81 :ToDo:
82 - There is currently no way to connect this class to a custom
83 address.
84 - Some of this functionality should be available on
85 peer-to-peer D-Bus connections too.
86 :Changed: in dbus-python 0.80:
87 converted from a wrapper around a Connection to a Connection
88 subclass.
89 """
90 if (not private and bus_type in cls._shared_instances):
91 return cls._shared_instances[bus_type]
93 # this is a bit odd, but we create instances of the subtypes
94 # so we can return the shared instances if someone tries to
95 # construct one of them (otherwise we'd eg try and return an
96 # instance of Bus from __new__ in SessionBus). why are there
97 # three ways to construct this class? we just don't know.
98 if bus_type == BUS_SESSION:
99 subclass = SessionBus
100 elif bus_type == BUS_SYSTEM:
101 subclass = SystemBus
102 elif bus_type == BUS_STARTER:
103 subclass = StarterBus
104 else:
105 raise ValueError('invalid bus_type %s' % bus_type)
107 bus = BusConnection.__new__(subclass, bus_type, mainloop=mainloop)
109 bus._bus_type = bus_type
111 if not private:
112 cls._shared_instances[bus_type] = bus
114 return bus
116 def close(self):
117 t = self._bus_type
118 if self.__class__._shared_instances[t] is self:
119 del self.__class__._shared_instances[t]
120 super(Bus, self).close()
122 def get_connection(self):
123 """(Deprecated - in new code, just use self)
125 Return self, for backwards compatibility with earlier dbus-python
126 versions where Bus was not a subclass of Connection.
128 return self
129 _connection = property(get_connection, None, None,
130 """self._connection == self, for backwards
131 compatibility with earlier dbus-python versions
132 where Bus was not a subclass of Connection.""")
134 def get_session(private=False):
135 """Static method that returns a connection to the session bus.
137 :Parameters:
138 `private` : bool
139 If true, do not return a shared connection.
141 return SessionBus(private=private)
143 get_session = staticmethod(get_session)
145 def get_system(private=False):
146 """Static method that returns a connection to the system bus.
148 :Parameters:
149 `private` : bool
150 If true, do not return a shared connection.
152 return SystemBus(private=private)
154 get_system = staticmethod(get_system)
157 def get_starter(private=False):
158 """Static method that returns a connection to the starter bus.
160 :Parameters:
161 `private` : bool
162 If true, do not return a shared connection.
164 return StarterBus(private=private)
166 get_starter = staticmethod(get_starter)
168 def __repr__(self):
169 if self._bus_type == BUS_SESSION:
170 name = 'SESSION'
171 elif self._bus_type == BUS_SYSTEM:
172 name = 'SYSTEM'
173 elif self._bus_type == BUS_STARTER:
174 name = 'STARTER'
175 else:
176 raise AssertionError('Unable to represent unknown bus type.')
178 return '<dbus.Bus on %s at %#x>' % (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."""