Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/sugar/presence
diff options
context:
space:
mode:
authorMike C. Fletcher <mcfletch@raistlin.(none)>2007-04-22 04:23:19 (GMT)
committer Mike C. Fletcher <mcfletch@raistlin.(none)>2007-04-22 04:23:19 (GMT)
commita7af5b06cd66eabbb6f412f0debc57ad89de06cb (patch)
tree8bb14cf4cd9893f0d99dc3ac78e62cd06b3b5cb0 /sugar/presence
parenta0ee487a401f63805d760c4a2003c2c434864b70 (diff)
Try to avoid Sugar's shell just crashing and leaving a blank X server
when the PresenceService isn't available on the back-end for whatever reason, whether mis-configuration, corrupted installation, unexpected circumstances, or what have you. This patch makes as few changes as possible to the code, simply replacing the _ps member with a property that re-attempts connection on each access until an attempt is successful.
Diffstat (limited to 'sugar/presence')
-rw-r--r--sugar/presence/presenceservice.py95
1 files changed, 85 insertions, 10 deletions
diff --git a/sugar/presence/presenceservice.py b/sugar/presence/presenceservice.py
index e61c8d7..3d731b6 100644
--- a/sugar/presence/presenceservice.py
+++ b/sugar/presence/presenceservice.py
@@ -132,18 +132,64 @@ class PresenceService(gobject.GObject):
def __init__(self):
- """Initialise the service and connect to events"""
+ """Initialise the service and attempt to connect to events
+ """
gobject.GObject.__init__(self)
self._objcache = ObjectCache()
- self._bus = dbus.SessionBus()
- self._ps = dbus.Interface(self._bus.get_object(DBUS_SERVICE,
- DBUS_PATH), DBUS_INTERFACE)
- self._ps.connect_to_signal('BuddyAppeared', self._buddy_appeared_cb)
- self._ps.connect_to_signal('BuddyDisappeared', self._buddy_disappeared_cb)
- self._ps.connect_to_signal('ActivityAppeared', self._activity_appeared_cb)
- self._ps.connect_to_signal('ActivityDisappeared', self._activity_disappeared_cb)
- self._ps.connect_to_signal('ActivityInvitation', self._activity_invitation_cb)
- self._ps.connect_to_signal('PrivateInvitation', self._private_invitation_cb)
+ # attempt to load the interface to the service...
+ self._get_ps()
+
+ _bus_ = None
+ def _get_bus( self ):
+ """Retrieve dbus session-bus or create new"""
+ if not self._bus_:
+ self._bus_ = dbus.SessionBus()
+ return self._bus_
+ _bus = property(
+ _get_bus, None, None,
+ """DBUS SessionBus object for user-local communications"""
+ )
+ _ps_ = None
+ def _get_ps( self ):
+ """Retrieve dbus interface to PresenceService
+
+ Also registers for updates from various dbus events on the
+ interface.
+
+ If unable to retrieve the interface, we will temporarily
+ return an _OfflineInterface object to allow the calling
+ code to continue functioning as though it had accessed a
+ real presence service.
+
+ If successful, caches the presence service interface
+ for use by other methods and returns that interface
+ """
+ if not self._ps_:
+ try:
+ ps = dbus.Interface(
+ self._bus.get_object(DBUS_SERVICE,DBUS_PATH),
+ DBUS_INTERFACE
+ )
+ except dbus.exceptions.DBusException, err:
+ logging.error(
+ """Failure retrieving %r interface from the D-BUS service %r %r: %s""",
+ DBUS_INTERFACE, DBUS_SERVICE, DBUS_PATH, err
+ )
+ return _OfflineInterface()
+ else:
+ self._ps_ = ps
+ ps.connect_to_signal('BuddyAppeared', self._buddy_appeared_cb)
+ ps.connect_to_signal('BuddyDisappeared', self._buddy_disappeared_cb)
+ ps.connect_to_signal('ActivityAppeared', self._activity_appeared_cb)
+ ps.connect_to_signal('ActivityDisappeared', self._activity_disappeared_cb)
+ ps.connect_to_signal('ActivityInvitation', self._activity_invitation_cb)
+ ps.connect_to_signal('PrivateInvitation', self._private_invitation_cb)
+ return self._ps_
+
+ _ps = property(
+ _get_ps, None, None,
+ """DBUS interface to the PresenceService (services/presence/presenceservice)"""
+ )
def _new_object(self, object_path):
"""Turn new object path into (cached) Buddy/Activity instance
@@ -350,6 +396,35 @@ class PresenceService(gobject.GObject):
return bus_name, object_path
+class _OfflineInterface( object ):
+ """Offline-presence-service interface
+
+ Used to mimic the behaviour of a real PresenceService sufficiently
+ to avoid crashing client code that expects the given interface.
+
+ XXX we could likely return a "MockOwner" object reasonably
+ easily, but would it be worth it?
+ """
+ def raiseException( self, *args, **named ):
+ """Raise dbus.exceptions.DBusException"""
+ raise dbus.exceptions.DBusException(
+ """PresenceService Interface not available"""
+ )
+ GetActivities = raiseException
+ GetActivityById = raiseException
+ GetBuddies = raiseException
+ GetBuddyByPublicKey = raiseException
+ GetOwner = raiseException
+ GetPreferredConnection = raiseException
+ def ShareActivity(
+ self, actid, atype, name, properties,
+ reply_handler, error_handler,
+ ):
+ """Pretend to share and fail..."""
+ exc = IOError(
+ """Unable to share activity as PresenceService is not currenly available"""
+ )
+ return error_handler( exc )
class _MockPresenceService(gobject.GObject):
"""Test fixture allowing testing of items that use PresenceService