diff options
Diffstat (limited to 'sleekxmpp/roster')
-rw-r--r-- | sleekxmpp/roster/item.py | 23 | ||||
-rw-r--r-- | sleekxmpp/roster/multi.py | 19 | ||||
-rw-r--r-- | sleekxmpp/roster/single.py | 62 |
3 files changed, 90 insertions, 14 deletions
diff --git a/sleekxmpp/roster/item.py b/sleekxmpp/roster/item.py index 6f956b31..9cb278a4 100644 --- a/sleekxmpp/roster/item.py +++ b/sleekxmpp/roster/item.py @@ -134,17 +134,22 @@ class RosterItem(object): 'subscription': 'none', 'name': '', 'groups': []} + self._db_state = {} self.load() - def set_backend(self, db=None): + def set_backend(self, db=None, save=True): """ Set the datastore interface object for the roster item. Arguments: - db -- The new datastore interface. + db -- The new datastore interface. + save -- If True, save the existing state to the new + backend datastore. Defaults to True. """ self.db = db + if save: + self.save() self.load() def load(self): @@ -167,16 +172,25 @@ class RosterItem(object): return self._state return None - def save(self): + def save(self, remove=False): """ Save the item's state information to an external datastore, if one has been provided. + + Arguments: + remove -- If True, expunge the item from the datastore. """ self['subscription'] = self._subscription() + if remove: + self._state['removed'] = True if self.db: self.db.save(self.owner, self.jid, self._state, self._db_state) + # Finally, remove the in-memory copy if needed. + if remove: + del self.xmpp.roster[self.owner][self.jid] + def __getitem__(self, key): """Return a state field's value.""" if key in self._state: @@ -482,3 +496,6 @@ class RosterItem(object): a roster reset request. """ self.resources = {} + + def __repr__(self): + return repr(self._state) diff --git a/sleekxmpp/roster/multi.py b/sleekxmpp/roster/multi.py index ee56f2a8..6a60778b 100644 --- a/sleekxmpp/roster/multi.py +++ b/sleekxmpp/roster/multi.py @@ -9,7 +9,6 @@ from sleekxmpp.xmlstream import JID from sleekxmpp.roster import RosterNode - class Roster(object): """ @@ -68,6 +67,8 @@ class Roster(object): """ if isinstance(key, JID): key = key.bare + if key is None: + key = self.xmpp.boundjid.bare if key not in self._rosters: self.add(key) self._rosters[key].auto_authorize = self.auto_authorize @@ -94,18 +95,23 @@ class Roster(object): if node not in self._rosters: self._rosters[node] = RosterNode(self.xmpp, node, self.db) - def set_backend(self, db=None): + def set_backend(self, db=None, save=True): """ Set the datastore interface object for the roster. Arguments: db -- The new datastore interface. + save -- If True, save the existing state to the new + backend datastore. Defaults to True. """ self.db = db - for node in self.db.entries(None, {}): + existing_entries = set(self._rosters) + new_entries = set(self.db.entries(None, {})) + + for node in existing_entries: + self._rosters[node].set_backend(db, save) + for node in new_entries - existing_entries: self.add(node) - for node in self._rosters: - self._rosters[node].set_backend(db) def reset(self): """ @@ -182,3 +188,6 @@ class Roster(object): self._auto_subscribe = value for node in self._rosters: self._rosters[node].auto_subscribe = value + + def __repr__(self): + return repr(self._rosters) diff --git a/sleekxmpp/roster/single.py b/sleekxmpp/roster/single.py index c2c7497d..518afebe 100644 --- a/sleekxmpp/roster/single.py +++ b/sleekxmpp/roster/single.py @@ -57,11 +57,28 @@ class RosterNode(object): self.auto_authorize = True self.auto_subscribe = True self.last_status = None + self._version = '' self._jids = {} if self.db: + if hasattr(self.db, 'version'): + self._version = self.db.version(self.jid) for jid in self.db.entries(self.jid): self.add(jid) + + @property + def version(self): + """Retrieve the roster's version ID.""" + if self.db and hasattr(self.db, 'version'): + self._version = self.db.version(self.jid) + return self._version + + @version.setter + def version(self, version): + """Set the roster's version ID.""" + self._version = version + if self.db and hasattr(self.db, 'set_version'): + self.db.set_version(self.jid, version) def __getitem__(self, key): """ @@ -75,6 +92,17 @@ class RosterNode(object): self.add(key, save=True) return self._jids[key] + def __delitem__(self, key): + """ + Remove a roster item from the local storage. + + To remove an item from the server, use the remove() method. + """ + if isinstance(key, JID): + key = key.bare + if key in self._jids: + del self._jids[key] + def __len__(self): """Return the number of JIDs referenced by the roster.""" return len(self._jids) @@ -101,18 +129,23 @@ class RosterNode(object): """Iterate over the roster items.""" return self._jids.__iter__() - def set_backend(self, db=None): + def set_backend(self, db=None, save=True): """ Set the datastore interface object for the roster node. Arguments: db -- The new datastore interface. + save -- If True, save the existing state to the new + backend datastore. Defaults to True. """ self.db = db - for jid in self.db.entries(self.jid): + existing_entries = set(self._jids) + new_entries = set(self.db.entries(self.jid, {})) + + for jid in existing_entries: + self._jids[jid].set_backend(db, save) + for jid in new_entries - existing_entries: self.add(jid) - for jid in self._jids: - self._jids[jid].set_backend(db) def add(self, jid, name='', groups=None, afrom=False, ato=False, pending_in=False, pending_out=False, whitelisted=False, @@ -144,6 +177,9 @@ class RosterNode(object): """ if isinstance(jid, JID): key = jid.bare + else: + key = jid + state = {'name': name, 'groups': groups or [], 'from': afrom, @@ -152,11 +188,11 @@ class RosterNode(object): 'pending_out': pending_out, 'whitelisted': whitelisted, 'subscription': 'none'} - self._jids[jid] = RosterItem(self.xmpp, jid, self.jid, + self._jids[key] = RosterItem(self.xmpp, jid, self.jid, state=state, db=self.db, roster=self) if save: - self._jids[jid].save() + self._jids[key].save() def subscribe(self, jid): """ @@ -285,3 +321,17 @@ class RosterNode(object): if not self.xmpp.sentpresence: self.xmpp.event('sent_presence') self.xmpp.sentpresence = True + + def send_last_presence(self): + if self.last_status is None: + self.send_presence() + else: + pres = self.last_status + if self.xmpp.is_component: + pres['from'] = self.jid + else: + del pres['from'] + pres.send() + + def __repr__(self): + return repr(self._jids) |