diff options
Diffstat (limited to 'python/_dbus.py')
| -rw-r--r-- | python/_dbus.py | 75 | 
1 files changed, 55 insertions, 20 deletions
diff --git a/python/_dbus.py b/python/_dbus.py index bb4c0428..2376f172 100644 --- a/python/_dbus.py +++ b/python/_dbus.py @@ -42,14 +42,14 @@ print(dbus_object.ListServices())  """  import dbus -  import dbus_bindings +import weakref  from proxies import *  from exceptions import *  from matchrules import * -class Bus: +class Bus(object):      """A connection to a DBus daemon.      One of three possible standard buses, the SESSION, SYSTEM, @@ -65,19 +65,54 @@ class Bus:      ProxyObjectClass = ProxyObject      START_REPLY_SUCCESS = dbus_bindings.DBUS_START_REPLY_SUCCESS -    START_REPLY_ALREADY_RUNNING = dbus_bindings.DBUS_START_REPLY_ALREADY_RUNNING  +    START_REPLY_ALREADY_RUNNING = dbus_bindings.DBUS_START_REPLY_ALREADY_RUNNING + +    _shared_instances = weakref.WeakValueDictionary() + +    def __new__(cls, bus_type=TYPE_SESSION, use_default_mainloop=True, private=False): +        if (not private and bus_type in cls._shared_instances): +            return cls._shared_instances[bus_type] + +        # this is a bit odd, but we create instances of the subtypes +        # so we can return the shared instances if someone tries to +        # construct one of them (otherwise we'd eg try and return an +        # instance of Bus from __new__ in SessionBus). why are there +        # three ways to construct this class? we just don't know. +        if bus_type == cls.TYPE_SESSION: +            subclass = SessionBus +        elif bus_type == cls.TYPE_SYSTEM: +            subclass = SystemBus +        elif bus_type == cls.TYPE_STARTER: +            subclass = StarterBus +        else: +            raise ValueError('invalid bus_type %s' % bus_type) + +        bus = object.__new__(subclass) -    def __init__(self, bus_type=TYPE_SESSION, use_default_mainloop=True, private=False): -        self._bus_type = bus_type -        self._connection = dbus_bindings.bus_get(bus_type, private) +        bus._bus_type = bus_type +        bus._bus_names = weakref.WeakValueDictionary() +        bus._match_rule_tree = SignalMatchTree() -        self._connection.add_filter(self._signal_func) -        self._match_rule_tree = SignalMatchTree() +        # FIXME: if you get a starter and a system/session bus connection +        # in the same process, it's the same underlying connection that +        # is returned by bus_get, but we initialise it twice +        bus._connection = dbus_bindings.bus_get(bus_type, private) +        bus._connection.add_filter(bus._signal_func)          if use_default_mainloop:              func = getattr(dbus, "_dbus_mainloop_setup_function", None) -            if func != None: -                func(self) +            if func: +                func(bus) + +        if not private: +            cls._shared_instances[bus_type] = bus + +        return bus + +    def __init__(self, *args, **keywords): +        # do nothing here because this can get called multiple times on the +        # same object if __new__ returns a shared instance +        pass      def close(self):          self._connection.close() @@ -87,20 +122,20 @@ class Bus:      def get_session(private=False):          """Static method that returns the session bus""" -        return SessionBus(private) +        return SessionBus(private=private)      get_session = staticmethod(get_session)      def get_system(private=False):          """Static method that returns the system bus""" -        return SystemBus(private) +        return SystemBus(private=private)      get_system = staticmethod(get_system)      def get_starter(private=False):          """Static method that returns the starter bus""" -        return StarterBus(private) +        return StarterBus(private=private)      get_starter = staticmethod(get_starter) @@ -213,24 +248,24 @@ class Bus:  class SystemBus(Bus):      """The system-wide message bus      """ -    def __init__(self, use_default_mainloop=True, private=False): -        Bus.__init__(self, Bus.TYPE_SYSTEM, use_default_mainloop, private) +    def __new__(cls, use_default_mainloop=True, private=False): +        return Bus.__new__(cls, Bus.TYPE_SYSTEM, use_default_mainloop, private)  class SessionBus(Bus):      """The session (current login) message bus      """ -    def __init__(self, use_default_mainloop=True, private=False): -        Bus.__init__(self, Bus.TYPE_SESSION, use_default_mainloop, private) +    def __new__(cls, use_default_mainloop=True, private=False): +        return Bus.__new__(cls, Bus.TYPE_SESSION, use_default_mainloop, private)  class StarterBus(Bus):      """The bus that activated this process (if      this process was launched by DBus activation)      """ -    def __init__(self, use_default_mainloop=True, private=False): -        Bus.__init__(self, Bus.TYPE_STARTER, use_default_mainloop, private) +    def __new__(cls, use_default_mainloop=True, private=False): +        return Bus.__new__(cls, Bus.TYPE_STARTER, use_default_mainloop, private)  class Interface: -    """An inteface into a remote object +    """An interface into a remote object      An Interface can be used to wrap ProxyObjects      so that calls can be routed to their correct  | 
