core, plugin XEP-0115: discovery refactoring:

- hashing algorithm of XEP-0115 has been including in core
    - our own hash is still calculated by XEP-0115 and can be regenerated with XEP_0115.recalculateHash
    - old discovery methods have been removed. Now the following methods are used:
        - hasFeature: tell if a feature is available for an entity
        - getDiscoInfos: self explaining
        - getDiscoItems: self explaining
        - findServiceEntities: return all available items of an entity which given (category, type)
        - findFeaturesSet: search for a set of features in entity + entity's items
      all these methods are asynchronous, and manage cache automatically
    - XEP-0115 manage in a better way hashes, and now use a trigger for presence instead of monkey patch
    - new FeatureNotFound exception, when we want to do something which is not available
    - refactored client initialisation sequence, removed client.initialized Deferred
    - added constant APP_URL
    - test_plugin_xep_0033.py has been temporarly deactivated, the time to adapt it
    - lot of cleaning
This commit is contained in:
Goffi 2014-03-28 18:07:22 +01:00
commit 95678d7967

View file

@ -32,6 +32,7 @@ from sat.core.constants import Const as C
from sat.memory.sqlite import SqliteStorage
from sat.memory.persistent import PersistentDict
from sat.memory.params import Params
from sat.memory.disco import Discovery
class Sessions(object):
@ -115,8 +116,7 @@ class Memory(object):
self._entities_cache = {} # XXX: keep presence/last resource/other data in cache
# /!\ an entity is not necessarily in roster
self.subscriptions = {}
self.server_features = {} # used to store discovery's informations
self.server_identities = {}
self.disco = Discovery(host)
self.config = self.parseMainConf()
self.__fixLocalDir()
database_file = os.path.expanduser(os.path.join(self.getConfig('', 'local_dir'), C.SAVEFILE_DATABASE))
@ -280,93 +280,6 @@ class Memory(object):
assert profile != C.PROF_KEY_NONE
return self.storage.getHistory(jid.JID(from_jid), jid.JID(to_jid), limit, between, profile)
def addServerFeature(self, feature, jid_, profile):
"""Add a feature discovered from server
@param feature: string of the feature
@param jid_: the jid of the target server
@param profile: which profile asked this server?"""
if profile not in self.server_features:
self.server_features[profile] = {}
features = self.server_features[profile].setdefault(jid_, [])
features.append(feature)
def addServerIdentity(self, category, type_, entity, jid_, profile):
"""Add an identity discovered from server
@param feature: string of the feature
@param jid_: the jid of the target server
@param profile: which profile asked this server?"""
if not profile in self.server_identities:
self.server_identities[profile] = {}
identities = self.server_identities[profile].setdefault(jid_, {})
if (category, type_) not in identities:
identities[(category, type_)] = set()
identities[(category, type_)].add(entity)
def getServerServiceEntities(self, category, type_, jid_=None, profile=None):
"""Return all available entities of a server for the service (category, type_)
@param category: identity's category
@param type_: identitiy's type
@param jid_: the jid of the target server (None for profile's server)
@param profile: which profile is asking this server?
@return: a set of entities or None if no cached data were found
"""
if jid_ is None:
jid_ = self.host.getClientHostJid(profile)
if profile in self.server_identities and jid_ in self.server_identities[profile]:
return self.server_identities[profile][jid_].get((category, type_), set())
else:
return None
def getServerServiceEntity(self, category, type_, jid_=None, profile=None):
"""Helper method to get first available entity of a server for the service (category, type_)
@param category: identity's category
@param type_: identitiy's type
@param jid_: the jid of the target server (None for profile's server)
@param profile: which profile is asking this server?
@return: the first found entity or None if no cached data were found
"""
entities = self.getServerServiceEntities(category, type_, jid_, profile)
if entities is None:
warning(_("Entities (%(category)s/%(type)s) of %(server)s not available, maybe they haven't been asked yet?")
% {"category": category, "type": type_, "server": jid_})
return None
else:
return list(entities)[0] if entities else None
def getAllServerIdentities(self, jid_, profile):
"""Helper method to get all identities of a server
@param jid_: the jid of the target server (None for profile's server)
@param profile: which profile is asking this server?
@return: a set of entities or None if no cached data were found
"""
if jid_ is None:
jid_ = self.host.getClientHostJid(profile)
if jid_ not in self.server_identities[profile]:
return None
entities = set()
for set_ in self.server_identities[profile][jid_].values():
entities.update(set_)
return entities
def hasServerFeature(self, feature, jid_=None, profile_key=C.PROF_KEY_NONE):
"""Tell if the specified server has the required feature
@param feature: requested feature
@param jid_: the jid of the target server (None for profile's server)
@param profile_key: %(doc_profile_key)s
"""
profile = self.getProfileName(profile_key)
if not profile:
error(_('Trying find server feature for a non-existant profile'))
return None
assert profile in self.server_features
if jid_ is None:
jid_ = self.host.getClientHostJid(profile)
if jid_ in self.server_features[profile]:
return feature in self.server_features[profile][jid_]
else:
warning(_("Features of %s not available, maybe they haven't been asked yet?") % jid_)
return None
def _getLastResource(self, jid_s, profile_key):
jid_ = jid.JID(jid_s)
return self.getLastResource(jid_, profile_key) or ""
@ -484,8 +397,9 @@ class Memory(object):
def getEntityData(self, entity_jid, keys_list, profile_key):
"""Get a list of cached values for entity
@param entity_jid: JID of the entity
@param keys_list: list of keys to get, empty list for everything
@param keys_list (iterable): list of keys to get, empty list for everything
@param profile_key: %(doc_profile_key)s
@return: dict withs values for each key in keys_list.
if there is no value of a given key, resulting dict will
@ -504,6 +418,20 @@ class Memory(object):
ret[key] = entity_data[key]
return ret
def getEntityDatum(self, entity_jid, key, profile_key):
"""Get a datum from entity
@param entity_jid: JID of the entity
@param keys: key to get
@param profile_key: %(doc_profile_key)s
@return: requested value
@raise: exceptions.UnknownEntityError if entity is not in cache
@raise: KeyError if there is no value for this key and this entity
"""
return self.getEntityData(entity_jid, (key,), profile_key)[key]
def delEntityCache(self, entity_jid, delete_all_resources=True, profile_key=C.PROF_KEY_NONE):
"""Remove cached data for entity
@param entity_jid: JID of the entity to delete