Mercurial > libervia-backend
comparison src/memory/disco.py @ 973:4a8903021fda
core (disco): findFeaturesSet and findServiceEntities don't use inlineCallbacks anymore, that allow a better error management (no more anonying debugger raise when discoInfo fails in debug mode)
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 02 Apr 2014 12:31:23 +0200 |
parents | 723f28cd15c7 |
children | 301b342c697a |
comparison
equal
deleted
inserted
replaced
972:07b817f5a197 | 973:4a8903021fda |
---|---|
19 | 19 |
20 from sat.core.i18n import _ | 20 from sat.core.i18n import _ |
21 from sat.core import exceptions | 21 from sat.core import exceptions |
22 from logging import debug, info, warning, error | 22 from logging import debug, info, warning, error |
23 from twisted.words.protocols.jabber import jid | 23 from twisted.words.protocols.jabber import jid |
24 from twisted.words.protocols.jabber.error import StanzaError | |
24 from twisted.internet import defer | 25 from twisted.internet import defer |
25 from sat.core.constants import Const as C | 26 from sat.core.constants import Const as C |
26 from wokkel import disco | 27 from wokkel import disco |
27 from base64 import b64encode | 28 from base64 import b64encode |
28 from hashlib import sha1 | 29 from hashlib import sha1 |
65 @param feature: feature namespace | 66 @param feature: feature namespace |
66 @param jid_: jid of the target, or None for profile's server | 67 @param jid_: jid of the target, or None for profile's server |
67 @param profile_key: %(doc_profile_key)s | 68 @param profile_key: %(doc_profile_key)s |
68 @return: a Deferred which fire a boolean (True if feature is available) | 69 @return: a Deferred which fire a boolean (True if feature is available) |
69 """ | 70 """ |
70 disco_info = yield self.getInfos(jid_, profile_key) | 71 disco_infos = yield self.getInfos(jid_, profile_key) |
71 defer.returnValue(feature in disco_info.features) | 72 defer.returnValue(feature in disco_infos.features) |
72 | 73 |
73 @defer.inlineCallbacks | 74 @defer.inlineCallbacks |
74 def checkFeature(self, feature, jid_=None, profile_key=C.PROF_KEY_NONE): | 75 def checkFeature(self, feature, jid_=None, profile_key=C.PROF_KEY_NONE): |
75 """Like hasFeature, but raise an exception is feature is not Found | 76 """Like hasFeature, but raise an exception is feature is not Found |
76 | 77 |
79 @param profile_key: %(doc_profile_key)s | 80 @param profile_key: %(doc_profile_key)s |
80 @return: None if feature is found | 81 @return: None if feature is found |
81 | 82 |
82 @raise: exceptions.FeatureNotFound | 83 @raise: exceptions.FeatureNotFound |
83 """ | 84 """ |
84 disco_info = yield self.getInfos(jid_, profile_key) | 85 disco_infos = yield self.getInfos(jid_, profile_key) |
85 if not feature in disco_info.features: | 86 if not feature in disco_infos.features: |
86 raise exceptions.FeatureNotFound | 87 raise exceptions.FeatureNotFound |
87 defer.returnValue(feature in disco_info) | 88 defer.returnValue(feature in disco_infos) |
88 | 89 |
89 @defer.inlineCallbacks | |
90 def getInfos(self, jid_=None, profile_key=C.PROF_KEY_NONE): | 90 def getInfos(self, jid_=None, profile_key=C.PROF_KEY_NONE): |
91 """get disco infos from jid_, filling capability hash if needed | 91 """get disco infos from jid_, filling capability hash if needed |
92 | 92 |
93 @param jid_: jid of the target, or None for profile's server | 93 @param jid_: jid of the target, or None for profile's server |
94 @param profile_key: %(doc_profile_key)s | 94 @param profile_key: %(doc_profile_key)s |
97 client = self.host.getClient(profile_key) | 97 client = self.host.getClient(profile_key) |
98 if jid_ is None: | 98 if jid_ is None: |
99 jid_ = jid.JID(client.jid.host) | 99 jid_ = jid.JID(client.jid.host) |
100 try: | 100 try: |
101 cap_hash = self.host.memory.getEntityData(jid_, [C.ENTITY_CAP_HASH], client.profile)[C.ENTITY_CAP_HASH] | 101 cap_hash = self.host.memory.getEntityData(jid_, [C.ENTITY_CAP_HASH], client.profile)[C.ENTITY_CAP_HASH] |
102 disco_info = self.hashes[cap_hash] | 102 disco_infos = self.hashes[cap_hash] |
103 return defer.succeed(disco_infos) | |
103 except KeyError: | 104 except KeyError: |
104 # capability hash is not available, we'll compute one | 105 # capability hash is not available, we'll compute one |
105 disco_info = yield client.disco.requestInfo(jid_) | 106 def infosCb(disco_infos): |
106 cap_hash = self.generateHash(disco_info) | 107 cap_hash = self.generateHash(disco_infos) |
107 self.hashes[cap_hash] = disco_info | 108 self.hashes[cap_hash] = disco_infos |
108 yield self.host.memory.updateEntityData(jid_, C.ENTITY_CAP_HASH, cap_hash, client.profile) | 109 self.host.memory.updateEntityData(jid_, C.ENTITY_CAP_HASH, cap_hash, client.profile) |
109 defer.returnValue(disco_info) | 110 return disco_infos |
111 d = client.disco.requestInfo(jid_) | |
112 d.addCallback(infosCb) | |
113 return d | |
110 | 114 |
111 @defer.inlineCallbacks | 115 @defer.inlineCallbacks |
112 def getItems(self, jid_=None, profile_key=C.PROF_KEY_NONE): | 116 def getItems(self, jid_=None, profile_key=C.PROF_KEY_NONE): |
113 """get disco items from jid_, cache them for our own server | 117 """get disco items from jid_, cache them for our own server |
114 | 118 |
131 items = yield client.disco.requestItems(jid_) | 135 items = yield client.disco.requestItems(jid_) |
132 | 136 |
133 defer.returnValue(items) | 137 defer.returnValue(items) |
134 | 138 |
135 | 139 |
136 @defer.inlineCallbacks | 140 def _infosEb(self, failure, entity_jid): |
141 failure.trap(StanzaError) | |
142 warning(_("Error while requesting [%(jid)s]: %(error)s") % {'jid': entity_jid.full(), | |
143 'error': failure.getErrorMessage()}) | |
144 | |
137 def findServiceEntities(self, category, type_, jid_=None, profile_key=C.PROF_KEY_NONE): | 145 def findServiceEntities(self, category, type_, jid_=None, profile_key=C.PROF_KEY_NONE): |
138 """Return all available items of an entity which correspond to (category, type_) | 146 """Return all available items of an entity which correspond to (category, type_) |
139 | 147 |
140 @param category: identity's category | 148 @param category: identity's category |
141 @param type_: identitiy's type | 149 @param type_: identitiy's type |
142 @param jid_: the jid of the target server (None for profile's server) | 150 @param jid_: the jid of the target server (None for profile's server) |
143 @param profile_key: %(doc_profile_key)s | 151 @param profile_key: %(doc_profile_key)s |
144 @return: a set of entities or None if no cached data were found | 152 @return: a set of entities or None if no cached data were found |
145 """ | 153 """ |
146 found_identities = set() | 154 found_entities = set() |
147 items = yield self.getItems(jid_, profile_key) | 155 |
148 for item in items: | 156 def infosCb(infos, entity_jid): |
149 infos = yield self.getInfos(item.entity, profile_key) | |
150 if (category, type_) in infos.identities: | 157 if (category, type_) in infos.identities: |
151 found_identities.add(item.entity) | 158 found_entities.add(entity_jid) |
152 | 159 |
153 defer.returnValue(found_identities) | 160 def gotItems(items): |
154 | 161 defers_list = [] |
155 @defer.inlineCallbacks | 162 for item in items: |
163 info_d = self.getInfos(item.entity, profile_key) | |
164 info_d.addCallbacks(infosCb, self._infosEb, [item.entity], None, [item.entity]) | |
165 defers_list.append(info_d) | |
166 return defer.DeferredList(defers_list) | |
167 | |
168 d = self.getItems(jid_, profile_key) | |
169 d.addCallback(gotItems) | |
170 d.addCallback(lambda dummy: found_entities) | |
171 return d | |
172 | |
156 def findFeaturesSet(self, features, category=None, type_=None, jid_=None, profile_key=C.PROF_KEY_NONE): | 173 def findFeaturesSet(self, features, category=None, type_=None, jid_=None, profile_key=C.PROF_KEY_NONE): |
157 """Return entities (including jid_ and its items) offering features | 174 """Return entities (including jid_ and its items) offering features |
158 | 175 |
159 @param features: iterable of features which must be present | 176 @param features: iterable of features which must be present |
160 @param category: if not None, accept only this category | 177 @param category: if not None, accept only this category |
167 if jid_ is None: | 184 if jid_ is None: |
168 jid_ = jid.JID(client.jid.host) | 185 jid_ = jid.JID(client.jid.host) |
169 features = set(features) | 186 features = set(features) |
170 found_entities = set() | 187 found_entities = set() |
171 | 188 |
172 items = yield self.getItems(jid_, profile_key) | 189 def infosCb(infos, entity): |
173 for entity in [jid_] + [item.entity for item in items]: | |
174 infos = yield self.getInfos(entity, profile_key) | |
175 if category is not None or type_ is not None: | 190 if category is not None or type_ is not None: |
176 categories = set() | 191 categories = set() |
177 types = set() | 192 types = set() |
178 for identity in infos.identities: | 193 for identity in infos.identities: |
179 id_cat, id_type = identity | 194 id_cat, id_type = identity |
180 categories.add(id_cat) | 195 categories.add(id_cat) |
181 types.add(id_type) | 196 types.add(id_type) |
182 if category is not None and category not in categories: | 197 if category is not None and category not in categories: |
183 continue | 198 return |
184 if type_ is not None and type_ not in types: | 199 if type_ is not None and type_ not in types: |
185 continue | 200 return |
186 if features.issubset(infos.features): | 201 if features.issubset(infos.features): |
187 found_entities.add(entity) | 202 found_entities.add(entity) |
188 | 203 |
189 defer.returnValue(found_entities) | 204 def gotItems(items): |
205 defer_list = [] | |
206 for entity in [jid_] + [item.entity for item in items]: | |
207 infos_d = self.getInfos(entity, profile_key) | |
208 infos_d.addCallbacks(infosCb, self._infosEb, [entity], None, [entity]) | |
209 defer_list.append(infos_d) | |
210 return defer.DeferredList(defer_list) | |
211 | |
212 d = self.getItems(jid_, profile_key) | |
213 d.addCallback(gotItems) | |
214 d.addCallback(lambda dummy: found_entities) | |
215 return d | |
190 | 216 |
191 def generateHash(self, services): | 217 def generateHash(self, services): |
192 """ Generate a unique hash for given service | 218 """ Generate a unique hash for given service |
193 | 219 |
194 hash algorithm is the one described in XEP-0115 | 220 hash algorithm is the one described in XEP-0115 |