diff --git a/configure.ac b/configure.ac index 520ad934..00e76ab0 100644 --- a/configure.ac +++ b/configure.ac @@ -32,7 +32,6 @@ PKG_CHECK_MODULES(SHELL, gtk+-2.0 gstreamer-0.10 gstreamer-plugins-base-0.10) PYGTK_DEFSDIR=`$PKG_CONFIG --variable=defsdir pygtk-2.0` AC_SUBST(PYGTK_DEFSDIR) -# # Setup GETTEXT # ALL_LINGUAS="it ha ig yo" diff --git a/services/presence/activity.py b/services/presence/activity.py index d295ce3c..ee91bc82 100644 --- a/services/presence/activity.py +++ b/services/presence/activity.py @@ -36,6 +36,8 @@ _PROP_LOCAL = "local" _PROP_JOINED = "joined" _PROP_CUSTOM_PROPS = "custom-props" +_logger = logging.getLogger('s-p-s.activity') + class Activity(ExportedGObject): """Represents a potentially shareable activity on the network. """ @@ -359,7 +361,7 @@ class Activity(ExportedGObject): Called by the _shared_cb and _joined_cb methods. """ if not text_channel: - logging.debug("Error sharing: text channel was None, shouldn't happen") + _logger.debug("Error sharing: text channel was None, shouldn't happen") raise RuntimeError("Plugin returned invalid text channel") self._text_channel = text_channel @@ -379,14 +381,14 @@ class Activity(ExportedGObject): self._tp.disconnect(sigid) if exc: - logging.debug("Share of activity %s failed: %s" % (self._id, exc)) + _logger.debug("Share of activity %s failed: %s" % (self._id, exc)) async_err_cb(exc) else: self._handle_share_join(tp, text_channel) self.send_properties() owner.add_activity(self) async_cb(dbus.ObjectPath(self._object_path)) - logging.debug("Share of activity %s succeeded." % self._id) + _logger.debug("Share of activity %s succeeded." % self._id) def _share(self, (async_cb, async_err_cb), owner): """XXX - not documented yet @@ -394,13 +396,13 @@ class Activity(ExportedGObject): XXX - This method is called externally by the PresenceService despite the fact that this is supposed to be an internal method! """ - logging.debug("Starting share of activity %s" % self._id) + _logger.debug("Starting share of activity %s" % self._id) if self._joined: async_err_cb(RuntimeError("Already shared activity %s" % self.props.id)) return sigid = self._tp.connect('activity-shared', self._shared_cb) self._tp.share_activity(self.props.id, (sigid, owner, async_cb, async_err_cb)) - logging.debug("done with share attempt %s" % self._id) + _logger.debug("done with share attempt %s" % self._id) def _joined_cb(self, tp, activity_id, text_channel, exc, userdata): """XXX - not documented yet @@ -506,7 +508,7 @@ class Activity(ExportedGObject): if type != self._type: # Type can never be changed after first set if self._type: - logging.debug("Activity type changed by network; this is illegal") + _logger.debug("Activity type changed by network; this is illegal") else: self._type = type changed = True diff --git a/services/presence/buddy.py b/services/presence/buddy.py index 2b404e09..53999e8b 100644 --- a/services/presence/buddy.py +++ b/services/presence/buddy.py @@ -49,6 +49,9 @@ _PROP_VALID = "valid" # Will go away soon _PROP_IP4_ADDRESS = "ip4-address" +_logger = logging.getLogger('s-p-s.buddy') + + class Buddy(ExportedGObject): """Person on the network (tracks properties and shared activites) @@ -130,7 +133,7 @@ class Buddy(ExportedGObject): _ALLOWED_INIT_PROPS = [_PROP_NICK, _PROP_KEY, _PROP_ICON, _PROP_CURACT, _PROP_COLOR, _PROP_IP4_ADDRESS] for (key, value) in kwargs.items(): if key not in _ALLOWED_INIT_PROPS: - logging.debug("Invalid init property '%s'; ignoring..." % key) + _logger.debug("Invalid init property '%s'; ignoring..." % key) del kwargs[key] # Set icon after superclass init, because it sends DBus and GObject @@ -634,7 +637,7 @@ class TestOwner(GenericOwner): color = xocolor.XoColor().to_string() icon = _get_random_image() - logging.debug("pubkey is %s" % pubkey) + _logger.debug("pubkey is %s" % pubkey) GenericOwner.__init__(self, ps, bus_name, object_id, key=pubkey, nick=nick, color=color, icon=icon, registered=registered, key_hash=privkey_hash) @@ -645,13 +648,13 @@ class TestOwner(GenericOwner): def _share_reply_cb(self, actid, object_path): activity = self._ps.internal_get_activity(actid) if not activity or not object_path: - logging.debug("Couldn't find activity %s even though it was shared." % actid) + _logger.debug("Couldn't find activity %s even though it was shared." % actid) return - logging.debug("Shared activity %s (%s)." % (actid, activity.props.name)) + _logger.debug("Shared activity %s (%s)." % (actid, activity.props.name)) self._test_activities.append(activity) def _share_error_cb(self, actid, err): - logging.debug("Error sharing activity %s: %s" % (actid, str(err))) + _logger.debug("Error sharing activity %s: %s" % (actid, str(err))) def _ps_connection_status_cb(self, ps, connected): if not connected: @@ -744,7 +747,7 @@ def _hash_private_key(self): lines = f.readlines() f.close() except IOError, e: - logging.error("Error reading private key: %s" % e) + _logger.error("Error reading private key: %s" % e) return key = "" @@ -756,7 +759,7 @@ def _hash_private_key(self): continue key += l if not len(key): - logging.error("Error parsing public key.") + _logger.error("Error parsing public key.") # hash it key_hash = util._sha_data(key) @@ -768,7 +771,7 @@ def _extract_public_key(keyfile): lines = f.readlines() f.close() except IOError, e: - logging.error("Error reading public key: %s" % e) + _logger.error("Error reading public key: %s" % e) return None # Extract the public key @@ -781,7 +784,7 @@ def _extract_public_key(keyfile): key = l[len(magic):] break if not len(key): - logging.error("Error parsing public key.") + _logger.error("Error parsing public key.") return None return key @@ -793,7 +796,7 @@ def _extract_private_key(keyfile): lines = f.readlines() f.close() except IOError, e: - logging.error("Error reading private key: %s" % e) + _logger.error("Error reading private key: %s" % e) return None key = "" @@ -805,7 +808,7 @@ def _extract_private_key(keyfile): continue key += l if not len(key): - logging.error("Error parsing private key.") + _logger.error("Error parsing private key.") return None return key @@ -830,7 +833,7 @@ def _get_new_keypair(num): print "Done." pubkey = privkey = None if s != 0: - logging.error("Could not generate key pair: %d (%s)" % (s, o)) + _logger.error("Could not generate key pair: %d (%s)" % (s, o)) else: pubkey = _extract_public_key(pubkeyfile) privkey = _extract_private_key(privkeyfile) diff --git a/services/presence/presenceservice.py b/services/presence/presenceservice.py index 6b67357e..c554ce6e 100644 --- a/services/presence/presenceservice.py +++ b/services/presence/presenceservice.py @@ -40,6 +40,9 @@ _PRESENCE_INTERFACE = "org.laptop.Sugar.Presence" _PRESENCE_PATH = "/org/laptop/Sugar/Presence" +_logger = logging.getLogger('s-p-s.presenceservice') + + class NotFoundError(dbus.DBusException): def __init__(self, msg): dbus.DBusException.__init__(self, msg) @@ -101,7 +104,7 @@ class PresenceService(ExportedGObject): def _connection_disconnected_cb(self, foo=None): """Log event when D-Bus kicks us off the bus for some reason""" - logging.debug("Disconnected from session bus!!!") + _logger.debug("Disconnected from session bus!!!") def _server_status_cb(self, plugin, status, reason): # FIXME: figure out connection status when we have a salut plugin too @@ -135,10 +138,10 @@ class PresenceService(ExportedGObject): def _buddy_validity_changed_cb(self, buddy, valid): if valid: self.BuddyAppeared(buddy.object_path()) - logging.debug("New Buddy: %s (%s)" % (buddy.props.nick, buddy.props.color)) + _logger.debug("New Buddy: %s (%s)" % (buddy.props.nick, buddy.props.color)) else: self.BuddyDisappeared(buddy.object_path()) - logging.debug("Buddy left: %s (%s)" % (buddy.props.nick, buddy.props.color)) + _logger.debug("Buddy left: %s (%s)" % (buddy.props.nick, buddy.props.color)) def _contact_offline(self, tp, handle): if not self._handles_buddies[tp].has_key(handle): @@ -152,7 +155,7 @@ class PresenceService(ExportedGObject): if not buddy.handles: if buddy.props.valid: self.BuddyDisappeared(buddy.object_path()) - logging.debug("Buddy left: %s (%s)" % (buddy.props.nick, buddy.props.color)) + _logger.debug("Buddy left: %s (%s)" % (buddy.props.nick, buddy.props.color)) self._buddies.pop(key) def _get_next_object_id(self): @@ -163,21 +166,21 @@ class PresenceService(ExportedGObject): def _avatar_updated(self, tp, handle, avatar): buddy = self._handles_buddies[tp].get(handle) if buddy and not buddy.props.owner: - logging.debug("Buddy %s icon updated" % buddy.props.nick) + _logger.debug("Buddy %s icon updated" % buddy.props.nick) buddy.props.icon = avatar def _buddy_properties_changed(self, tp, handle, properties): buddy = self._handles_buddies[tp].get(handle) if buddy: buddy.set_properties(properties) - logging.debug("Buddy %s properties updated: %s" % (buddy.props.nick, properties.keys())) + _logger.debug("Buddy %s properties updated: %s" % (buddy.props.nick, properties.keys())) def _new_activity(self, activity_id, tp): try: objid = self._get_next_object_id() activity = Activity(self._bus_name, objid, tp, id=activity_id) except Exception, e: - logging.debug("Invalid activity: %s" % e) + _logger.debug("Invalid activity: %s" % e) return None activity.connect("validity-changed", self._activity_validity_changed_cb) @@ -185,7 +188,7 @@ class PresenceService(ExportedGObject): return activity def _remove_activity(self, activity): - logging.debug("remove activity %s" % activity.props.id) + _logger.debug("remove activity %s" % activity.props.id) self.ActivityDisappeared(activity.object_path()) del self._activities[activity.props.id] @@ -194,7 +197,7 @@ class PresenceService(ExportedGObject): acts = [] for act in activities: acts.append(str(act)) - logging.debug("Handle %s activities changed: %s" % (contact_handle, acts)) + _logger.debug("Handle %s activities changed: %s" % (contact_handle, acts)) buddies = self._handles_buddies[tp] buddy = buddies.get(contact_handle) @@ -202,7 +205,7 @@ class PresenceService(ExportedGObject): # We don't know this buddy # FIXME: What should we do here? # FIXME: Do we need to check if the buddy is valid or something? - logging.debug("contact_activities_changed: buddy unknown") + _logger.debug("contact_activities_changed: buddy unknown") return old_activities = set() @@ -213,7 +216,7 @@ class PresenceService(ExportedGObject): activities_joined = new_activities - old_activities for act in activities_joined: - logging.debug("Handle %s joined activity %s" % (contact_handle, act)) + _logger.debug("Handle %s joined activity %s" % (contact_handle, act)) activity = self._activities.get(act) if not activity: # new activity, can fail @@ -225,7 +228,7 @@ class PresenceService(ExportedGObject): activities_left = old_activities - new_activities for act in activities_left: - logging.debug("Handle %s left activity %s" % (contact_handle, act)) + _logger.debug("Handle %s left activity %s" % (contact_handle, act)) activity = self._activities.get(act) if not activity: continue @@ -341,10 +344,10 @@ class PresenceService(ExportedGObject): def _activity_validity_changed_cb(self, activity, valid): if valid: self.ActivityAppeared(activity.object_path()) - logging.debug("New Activity: %s (%s)" % (activity.props.name, activity.props.id)) + _logger.debug("New Activity: %s (%s)" % (activity.props.name, activity.props.id)) else: self.ActivityDisappeared(activity.object_path()) - logging.debug("Activity disappeared: %s (%s)" % (activity.props.name, activity.props.id)) + _logger.debug("Activity disappeared: %s (%s)" % (activity.props.name, activity.props.id)) def _activity_properties_changed(self, tp, act_id, props): activity = self._activities.get(act_id) @@ -364,7 +367,7 @@ def main(test_num=0, randomize=False): loop.run() except KeyboardInterrupt: ps.cleanup() - logging.debug('Ctrl+C pressed, exiting...') + _logger.debug('Ctrl+C pressed, exiting...') if __name__ == "__main__": main() diff --git a/services/presence/psutils.py b/services/presence/psutils.py index b24b1df0..4d6ae3d5 100644 --- a/services/presence/psutils.py +++ b/services/presence/psutils.py @@ -18,6 +18,9 @@ import dbus, dbus.glib, gobject import logging +_logger = logging.getLogger('s-p-s.psutils') + + def bytes_to_string(bytes): """The function converts a D-BUS byte array provided by dbus to string format. @@ -92,7 +95,7 @@ class IP4AddressMonitor(gobject.GObject): return self._addr = new_addr - logging.debug("IP4 address now '%s'" % new_addr) + _logger.debug("IP4 address now '%s'" % new_addr) self.emit('address-changed', new_addr) def _connect_to_nm(self): @@ -102,7 +105,7 @@ class IP4AddressMonitor(gobject.GObject): proxy = sys_bus.get_object(NM_SERVICE, NM_PATH) self._nm_obj = dbus.Interface(proxy, NM_IFACE) except dbus.DBusException, err: - logging.debug("Error finding NetworkManager: %s" % err) + _logger.debug("Error finding NetworkManager: %s" % err) self._nm_present = False return @@ -115,13 +118,13 @@ class IP4AddressMonitor(gobject.GObject): match = sys_bus.add_signal_receiver(self._nm_device_no_longer_active_cb, signal_name="DeviceNoLongerActive", dbus_interface=NM_IFACE, - named_service=NM_SERVICE) + bus_name=NM_SERVICE) self._matches.append(match) match = sys_bus.add_signal_receiver(self._nm_state_change_cb, signal_name="StateChange", dbus_interface=NM_IFACE, - named_service=NM_SERVICE) + bus_name=NM_SERVICE) self._matches.append(match) state = self._nm_obj.state() @@ -141,7 +144,7 @@ class IP4AddressMonitor(gobject.GObject): self._update_address(props[6]) def _device_properties_error_cb(self, err): - logging.debug("Error querying device properties: %s" % err) + _logger.debug("Error querying device properties: %s" % err) def _query_device_properties(self, device): sys_bus = dbus.SystemBus() @@ -156,7 +159,7 @@ class IP4AddressMonitor(gobject.GObject): self._query_device_properties(op) def _get_devices_error_cb(self, err): - logging.debug("Error getting NetworkManager devices: %s" % err) + _logger.debug("Error getting NetworkManager devices: %s" % err) def _query_devices(self): """Query NM for a list of network devices""" diff --git a/services/presence/server_plugin.py b/services/presence/server_plugin.py index cd03c014..d4930c9e 100644 --- a/services/presence/server_plugin.py +++ b/services/presence/server_plugin.py @@ -42,6 +42,8 @@ CONN_INTERFACE_ACTIVITY_PROPERTIES = 'org.laptop.Telepathy.ActivityProperties' _PROTOCOL = "jabber" +_logger = logging.getLogger('s-p-s.server_plugin') + class InvalidBuddyError(Exception): """(Unused) exception to indicate an invalid buddy specifier""" @@ -144,14 +146,14 @@ class ServerPlugin(gobject.GObject): self._ip4am.connect('address-changed', self._ip4_address_changed_cb) def _ip4_address_changed_cb(self, ip4am, address): - logging.debug("::: IP4 address now %s" % address) + _logger.debug("::: IP4 address now %s" % address) if address: - logging.debug("::: valid IP4 address, conn_status %s" % self._conn_status) + _logger.debug("::: valid IP4 address, conn_status %s" % self._conn_status) if self._conn_status == CONNECTION_STATUS_DISCONNECTED: - logging.debug("::: will connect") + _logger.debug("::: will connect") self.start() else: - logging.debug("::: invalid IP4 address, will disconnect") + _logger.debug("::: invalid IP4 address, will disconnect") self.cleanup() def _owner_property_changed_cb(self, owner, properties): @@ -169,7 +171,7 @@ class ServerPlugin(gobject.GObject): depending on which properties are present in the set of properties. """ - logging.debug("Owner properties changed: %s" % properties) + _logger.debug("Owner properties changed: %s" % properties) if properties.has_key("current-activity"): self._set_self_current_activity() @@ -185,7 +187,7 @@ class ServerPlugin(gobject.GObject): def _owner_icon_changed_cb(self, owner, icon): """Owner has changed their icon, forward to network""" - logging.debug("Owner icon changed to size %d" % len(str(icon))) + _logger.debug("Owner icon changed to size %d" % len(str(icon))) self._set_self_avatar(icon) def _get_account_info(self): @@ -250,7 +252,7 @@ class ServerPlugin(gobject.GObject): def _connect_error_cb(self, exception): """Handle connection failure""" - logging.debug("Connect error: %s" % exception) + _logger.debug("Connect error: %s" % exception) def _init_connection(self): """Set up our connection @@ -318,11 +320,22 @@ class ServerPlugin(gobject.GObject): # the group of contacts who may receive your presence publish = self._request_list_channel('publish') - publish_handles, local_pending, remote_pending = publish[CHANNEL_INTERFACE_GROUP].GetAllMembers() + self._publish_channel = publish + publish[CHANNEL_INTERFACE_GROUP].connect_to_signal('MembersChanged', + self._publish_members_changed_cb) + publish_handles, local_pending, remote_pending = \ + publish[CHANNEL_INTERFACE_GROUP].GetAllMembers() # the group of contacts for whom you wish to receive presence subscribe = self._request_list_channel('subscribe') - subscribe_handles = subscribe[CHANNEL_INTERFACE_GROUP].GetMembers() + self._subscribe_channel = subscribe + subscribe[CHANNEL_INTERFACE_GROUP].connect_to_signal('MembersChanged', + self._subscribe_members_changed_cb) + subscribe_handles, subscribe_lp, subscribe_rp = \ + subscribe[CHANNEL_INTERFACE_GROUP].GetAllMembers() + self._subscribe_members = set(subscribe_handles) + self._subscribe_local_pending = set(subscribe_lp) + self._subscribe_remote_pending = set(subscribe_rp) if local_pending: # accept pending subscriptions @@ -336,7 +349,7 @@ class ServerPlugin(gobject.GObject): subscribe[CHANNEL_INTERFACE_GROUP].AddMembers(not_subscribed, '') if CONN_INTERFACE_BUDDY_INFO not in self._conn.get_valid_interfaces(): - logging.debug('OLPC information not available') + _logger.debug('OLPC information not available') return False self._conn[CONN_INTERFACE_BUDDY_INFO].connect_to_signal('PropertiesChanged', @@ -362,8 +375,7 @@ class ServerPlugin(gobject.GObject): self._set_self_current_activity() self._set_self_avatar() - # Request presence for everyone on the channel - subscribe_handles = subscribe[CHANNEL_INTERFACE_GROUP].GetMembers() + # Request presence for everyone we're subscribed to self._conn[CONN_INTERFACE_PRESENCE].RequestPresence(subscribe_handles) return True @@ -394,7 +406,7 @@ class ServerPlugin(gobject.GObject): types, minw, minh, maxw, maxh, maxsize = self._conn[CONN_INTERFACE_AVATARS].GetAvatarRequirements() if not "image/jpeg" in types: - logging.debug("server does not accept JPEG format avatars.") + _logger.debug("server does not accept JPEG format avatars.") return img_data = _get_buddy_icon_at_size(icon_data, min(maxw, 96), min(maxh, 96), maxsize) @@ -414,7 +426,7 @@ class ServerPlugin(gobject.GObject): if (activity_id, handles[0]) in self._joined_activities: e = RuntimeError("Already joined activity %s" % activity_id) - logging.debug(str(e)) + _logger.debug(str(e)) self.emit(signal, activity_id, None, e, userdata) return @@ -425,7 +437,7 @@ class ServerPlugin(gobject.GObject): def _join_error_cb(self, activity_id, signal, userdata, err): e = Exception("Error joining/sharing activity %s: %s" % (activity_id, err)) - logging.debug(str(e)) + _logger.debug(str(e)) self.emit(signal, activity_id, None, e, userdata) def _internal_join_activity(self, activity_id, signal, userdata): @@ -470,7 +482,7 @@ class ServerPlugin(gobject.GObject): def _log_error_cb(self, msg, err): """Log a message (error) at debug level with prefix msg""" - logging.debug("Error %s: %s" % (msg, err)) + _logger.debug("Error %s: %s" % (msg, err)) def _set_self_olpc_properties(self): """Set color and key on our Telepathy server identity""" @@ -519,7 +531,7 @@ class ServerPlugin(gobject.GObject): # dont advertise a current activity that's not shared cur_activity = "" - logging.debug("Setting current activity to '%s' (handle %s)" % (cur_activity, cur_activity_handle)) + _logger.debug("Setting current activity to '%s' (handle %s)" % (cur_activity, cur_activity_handle)) self._conn[CONN_INTERFACE_BUDDY_INFO].SetCurrentActivity(cur_activity, cur_activity_handle, reply_handler=self._ignore_success_cb, @@ -549,17 +561,17 @@ class ServerPlugin(gobject.GObject): if status == CONNECTION_STATUS_CONNECTING: self._conn_status = status - logging.debug("status: connecting...") + _logger.debug("status: connecting...") elif status == CONNECTION_STATUS_CONNECTED: if self._connected_cb(): - logging.debug("status: connected") + _logger.debug("status: connected") self._conn_status = status else: self.cleanup() - logging.debug("status: was connected, but an error occurred") + _logger.debug("status: was connected, but an error occurred") elif status == CONNECTION_STATUS_DISCONNECTED: self.cleanup() - logging.debug("status: disconnected (reason %r)" % reason) + _logger.debug("status: disconnected (reason %r)" % reason) if reason == CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED: # FIXME: handle connection failure; retry later? pass @@ -580,7 +592,7 @@ class ServerPlugin(gobject.GObject): status -- CONNECTION_STATUS_* reason -- integer code describing the reason... """ - logging.debug("::: connection status changed to %s" % status) + _logger.debug("::: connection status changed to %s" % status) self._handle_connection_status_change(status, reason) def start(self): @@ -594,7 +606,7 @@ class ServerPlugin(gobject.GObject): otherwise initiate a connection and transfer control to _connect_reply_cb or _connect_error_cb """ - logging.debug("Starting up...") + _logger.debug("Starting up...") if self._reconnect_id > 0: gobject.source_remove(self._reconnect_id) @@ -602,10 +614,10 @@ class ServerPlugin(gobject.GObject): # Only init connection if we have a valid IP address if self._ip4am.props.address: - logging.debug("::: Have IP4 address %s, will connect" % self._ip4am.props.address) + _logger.debug("::: Have IP4 address %s, will connect" % self._ip4am.props.address) self._init_connection() else: - logging.debug("::: No IP4 address, postponing connection") + _logger.debug("::: No IP4 address, postponing connection") def cleanup(self): """If we still have a connection, disconnect it""" @@ -641,14 +653,14 @@ class ServerPlugin(gobject.GObject): def _contact_online_activities_error_cb(self, handle, err): """Handle contact's activity list being unavailable""" - logging.debug("Handle %s - Error getting activities: %s" % (handle, err)) + _logger.debug("Handle %s - Error getting activities: %s" % (handle, err)) # Don't drop the buddy if we can't get their activities, for now #self._contact_offline(handle) def _contact_online_aliases_cb(self, handle, props, aliases): """Handle contact's alias being received (do further queries)""" if not self._conn or not aliases or not len(aliases): - logging.debug("Handle %s - No aliases" % handle) + _logger.debug("Handle %s - No aliases" % handle) self._contact_offline(handle) return @@ -664,22 +676,22 @@ class ServerPlugin(gobject.GObject): def _contact_online_aliases_error_cb(self, handle, props, retry, err): """Handle failure to retrieve given user's alias/information""" if retry: - logging.debug("Handle %s - Error getting nickname (will retry): %s" % (handle, err)) + _logger.debug("Handle %s - Error getting nickname (will retry): %s" % (handle, err)) self._conn[CONN_INTERFACE_ALIASING].RequestAliases([handle], reply_handler=lambda *args: self._contact_online_aliases_cb(handle, props, *args), error_handler=lambda *args: self._contact_online_aliases_error_cb(handle, props, False, *args)) else: - logging.debug("Handle %s - Error getting nickname: %s" % (handle, err)) + _logger.debug("Handle %s - Error getting nickname: %s" % (handle, err)) self._contact_offline(handle) def _contact_online_properties_cb(self, handle, props): """Handle failure to retrieve given user's alias/information""" if not props.has_key('key'): - logging.debug("Handle %s - invalid key." % handle) + _logger.debug("Handle %s - invalid key." % handle) self._contact_offline(handle) return if not props.has_key('color'): - logging.debug("Handle %s - invalid color." % handle) + _logger.debug("Handle %s - invalid color." % handle) self._contact_offline(handle) return @@ -699,15 +711,22 @@ class ServerPlugin(gobject.GObject): def _contact_online_properties_error_cb(self, handle, tries, err): """Handle error retrieving property-set for a user (handle)""" if tries <= 3: - logging.debug("Handle %s - Error getting properties (will retry): %s" % (handle, err)) + _logger.debug("Handle %s - Error getting properties (will retry): %s" % (handle, err)) tries += 1 gobject.timeout_add(1000, self._contact_online_request_properties, handle, tries) else: - logging.debug("Handle %s - Error getting properties: %s" % (handle, err)) + _logger.debug("Handle %s - Error getting properties: %s" % (handle, err)) self._contact_offline(handle) def _contact_online(self, handle): """Handle a contact coming online""" + if (handle not in self._subscribe_members and + handle not in self._subscribe_local_pending and + handle not in self._subscribe_remote_pending): + # it's probably a channel-specific handle - can't create a Buddy + # object + return + self._online_contacts[handle] = None if handle == self._conn[CONN_INTERFACE].GetSelfHandle(): jid = self._conn[CONN_INTERFACE].InspectHandles(CONNECTION_HANDLE_TYPE_CONTACT, [handle])[0] @@ -718,6 +737,34 @@ class ServerPlugin(gobject.GObject): self._contact_online_request_properties(handle, 1) + def _subscribe_members_changed_cb(self, added, removed, local_pending, + remote_pending, actor, reason): + for handle in added: + self._subscribe_members.add(handle) + for handle in local_pending: + self._subscribe_local_pending.add(handle) + for handle in remote_pending: + self._subscribe_remote_pending.add(handle) + for handle in removed: + self._subscribe_members.discard(handle) + self._subscribe_local_pending.discard(handle) + self._subscribe_remote_pending.discard(handle) + + def _publish_members_changed_cb(self, added, removed, local_pending, + remote_pending, actor, reason): + + if local_pending: + # accept all requested subscriptions + self._publish_channel[CHANNEL_INTERFACE_GROUP].AddMembers( + local_pending, '') + + # subscribe to people who've subscribed to us, if necessary + added = list(set(added) - self._subscribe_members + - self._subscribe_remote_pending) + if added: + self._subscribe_channel[CHANNEL_INTERFACE_GROUP].AddMembers( + added, '') + def _presence_update_cb(self, presence): """Send update for online/offline status of presence""" for handle in presence: @@ -730,7 +777,7 @@ class ServerPlugin(gobject.GObject): jid = self._conn[CONN_INTERFACE].InspectHandles(CONNECTION_HANDLE_TYPE_CONTACT, [handle])[0] olstr = "ONLINE" if not online: olstr = "OFFLINE" - logging.debug("Handle %s (%s) was %s, status now '%s'." % (handle, jid, olstr, status)) + _logger.debug("Handle %s (%s) was %s, status now '%s'." % (handle, jid, olstr, status)) if not online and status in ["available", "away", "brb", "busy", "dnd", "xa"]: self._contact_online(handle) elif status in ["offline", "invisible"]: @@ -753,12 +800,12 @@ class ServerPlugin(gobject.GObject): return if not self._online_contacts.has_key(handle): - logging.debug("Handle %s unknown." % handle) + _logger.debug("Handle %s unknown." % handle) return jid = self._online_contacts[handle] if not jid: - logging.debug("Handle %s not valid yet..." % handle) + _logger.debug("Handle %s not valid yet..." % handle) return icon = self._icon_cache.get_icon(jid, new_avatar_token) @@ -814,7 +861,7 @@ class ServerPlugin(gobject.GObject): if not len(activity) or not util.validate_activity_id(activity): activity = None prop = {'current-activity': activity} - logging.debug("Handle %s: current activity now %s" % (handle, activity)) + _logger.debug("Handle %s: current activity now %s" % (handle, activity)) self._buddy_properties_changed_cb(handle, prop) def _new_channel_cb(self, object_path, channel_type, handle_type, handle, suppress_handler): diff --git a/services/presence/sugar-presence-service b/services/presence/sugar-presence-service index 1680fea5..6ab871ca 100755 --- a/services/presence/sugar-presence-service +++ b/services/presence/sugar-presence-service @@ -24,8 +24,12 @@ import os from sugar import logger from sugar import env + +_logger = logging.getLogger('s-p-s') + + def usage(): - logging.debug("Usage: sugar-presence-service [] [randomize]") + _logger.debug("Usage: sugar-presence-service [] [randomize]") sys.path.append(env.get_service_path('presence')) @@ -35,9 +39,9 @@ if len(sys.argv) in [2, 3]: try: test_num = int(sys.argv[1]) except ValueError: - logging.debug("Bad test user number.") + _logger.debug("Bad test user number.") if test_num < 1 or test_num > 10: - logging.debug("Bad test user number.") + _logger.debug("Bad test user number.") if len(sys.argv) == 3 and sys.argv[2] == "randomize": randomize = True @@ -54,6 +58,6 @@ else: import presenceservice -logging.info('Starting presence service...') +_logger.info('Starting presence service...') presenceservice.main(test_num, randomize) diff --git a/shell/view/clipboardicon.py b/shell/view/clipboardicon.py index fb370fb9..fc609f6b 100644 --- a/shell/view/clipboardicon.py +++ b/shell/view/clipboardicon.py @@ -106,16 +106,6 @@ class ClipboardIcon(CanvasIcon): else: self.props.xo_color = XoColor("#000000,#FFFFFF") - if activity and percent == 100: - # FIXME: restrict based on file type rather than activity once - # we have a better type registry - # restrict auto-open to a specific set of activities - allowed = ["org.laptop.AbiWordActivity", - "org.laptop.sugar.Xbook", - "org.vpri.EtoysActivity"] - if activity in allowed: - self._open_file() - def _open_file(self): if self._percent < 100: return diff --git a/sugar/activity/activity.py b/sugar/activity/activity.py index 421d7ba2..3dba4c71 100644 --- a/sugar/activity/activity.py +++ b/sugar/activity/activity.py @@ -28,6 +28,7 @@ import gtk, gobject from sugar.presence import presenceservice from sugar.activity.activityservice import ActivityService +from sugar.activity import bundleregistry from sugar.graphics.window import Window from sugar.graphics.toolbox import Toolbox from sugar.graphics.toolbutton import ToolButton @@ -200,13 +201,15 @@ class Activity(Window, gtk.Container): if handle.object_id: self.jobject = datastore.get(handle.object_id) + self.jobject.object_id = '' + del self.jobject['ctime'] + del self.jobject['mtime'] elif create_jobject: logging.debug('Creating a jobject.') self.jobject = datastore.create() self.jobject['title'] = '%s %s' % (get_bundle_name(), 'Activity') self.jobject['activity'] = self.get_service_name() - self.jobject['date'] = str(time.time()) - self.jobject['icon'] = '' + self.jobject['icon'] = self._get_icon() self.jobject['keep'] = '0' self.jobject['buddies'] = '' self.jobject['preview'] = '' @@ -329,6 +332,10 @@ class Activity(Window, gtk.Container): raise self.destroy() + def _get_icon(self): + registry = bundleregistry.get_registry() + return registry.get_bundle(self.get_service_name()).get_icon() + def get_bundle_name(): """Return the bundle name for the current process' bundle """ diff --git a/sugar/datastore/datastore.py b/sugar/datastore/datastore.py index 99fd230d..9d656707 100644 --- a/sugar/datastore/datastore.py +++ b/sugar/datastore/datastore.py @@ -39,6 +39,9 @@ class DSObject(gobject.GObject): self.metadata[key] = value self.emit('updated') + def __delitem__(self, key): + del self.metadata[key] + def get_metadata(self): return self._metadata diff --git a/sugar/datastore/dbus_helpers.py b/sugar/datastore/dbus_helpers.py index 33aa9a6e..fa054915 100644 --- a/sugar/datastore/dbus_helpers.py +++ b/sugar/datastore/dbus_helpers.py @@ -40,7 +40,7 @@ def create(properties, filename): return object_id def update(uid, properties, filename, reply_handler=None, error_handler=None): - logging.debug('dbus_helpers.update') + logging.debug('dbus_helpers.update: %s, %s' % (uid, filename)) if reply_handler and error_handler: _data_store.update(uid, dbus.Dictionary(properties), filename, reply_handler=reply_handler, diff --git a/sugar/graphics/canvasicon.py b/sugar/graphics/canvasicon.py index 14f83519..ec141d0c 100644 --- a/sugar/graphics/canvasicon.py +++ b/sugar/graphics/canvasicon.py @@ -123,7 +123,7 @@ class _IconCache: del self._icons[evict_key] def get_handle(self, name, fill_color, stroke_color): - if name == None: + if not name: return None if name[0:6] == "theme:": diff --git a/sugar/presence/presenceservice.py b/sugar/presence/presenceservice.py index 621a2894..1bc9a579 100644 --- a/sugar/presence/presenceservice.py +++ b/sugar/presence/presenceservice.py @@ -36,6 +36,8 @@ DBUS_SERVICE = "org.laptop.Sugar.Presence" DBUS_INTERFACE = "org.laptop.Sugar.Presence" DBUS_PATH = "/org/laptop/Sugar/Presence" +_logger = logging.getLogger('sugar.presence.presenceservice') + class PresenceService(gobject.GObject): """UI-side interface to the dbus presence service @@ -116,7 +118,7 @@ class PresenceService(gobject.GObject): DBUS_INTERFACE ) except dbus.exceptions.DBusException, err: - logging.error( + _logger.error( """Failure retrieving %r interface from the D-BUS service %r %r: %s""", DBUS_INTERFACE, DBUS_SERVICE, DBUS_PATH, err ) @@ -247,7 +249,7 @@ class PresenceService(gobject.GObject): try: resp = self._ps.GetActivities() except dbus.exceptions.DBusException, err: - logging.warn( + _logger.warn( """Unable to retrieve activity list from presence service: %s""" % err ) @@ -269,7 +271,7 @@ class PresenceService(gobject.GObject): try: act_op = self._ps.GetActivityById(activity_id) except dbus.exceptions.DBusException, err: - logging.warn( + _logger.warn( """Unable to retrieve activity handle for %r from presence service: %s""" % (activity_id, err) ) @@ -285,7 +287,7 @@ class PresenceService(gobject.GObject): try: resp = self._ps.GetBuddies() except dbus.exceptions.DBusException, err: - logging.warn( + _logger.warn( """Unable to retrieve buddy-list from presence service: %s""" % err ) @@ -308,7 +310,7 @@ class PresenceService(gobject.GObject): try: buddy_op = self._ps.GetBuddyByPublicKey(dbus.ByteArray(key)) except dbus.exceptions.DBusException, err: - logging.warn( + _logger.warn( """Unable to retrieve buddy handle for %r from presence service: %s""" % key, err ) @@ -320,7 +322,7 @@ class PresenceService(gobject.GObject): try: owner_op = self._ps.GetOwner() except dbus.exceptions.DBusException, err: - logging.warn( + _logger.warn( """Unable to retrieve local user/owner from presence service: %s""" % err ) @@ -335,7 +337,7 @@ class PresenceService(gobject.GObject): def _share_activity_error_cb(self, activity, err): """Notify with GObject event of unsuccessful sharing of activity""" - logging.debug("Error sharing activity %s: %s" % (activity.get_id(), err)) + _logger.debug("Error sharing activity %s: %s" % (activity.get_id(), err)) self.emit("activity-shared", False, None, err) def share_activity(self, activity, properties={}):