comparison frontends/src/quick_frontend/quick_contact_list.py @ 2065:f3167c873e7b

quick frontend (contact list): better handling of cache with full jid: - get_cache has a new argument "bare_default" - value of resource is returned if full jid is used. None is returned if not found and bare_default is False, bare jid value is returned if not found and bare_default is True
author Goffi <goffi@goffi.org>
date Fri, 09 Sep 2016 23:54:33 +0200
parents 748e539c5feb
children e8cb9cc09485
comparison
equal deleted inserted replaced
2064:ee9621d92cb9 2065:f3167c873e7b
202 self.host.bridge.getContacts(self.profile, callback=self._gotContacts) 202 self.host.bridge.getContacts(self.profile, callback=self._gotContacts)
203 203
204 def fill(self): 204 def fill(self):
205 handler.fill(self.profile) 205 handler.fill(self.profile)
206 206
207 def getCache(self, entity, name=None): 207 def getCache(self, entity, name=None, bare_default=False):
208 """Return a cache value for a contact 208 """Return a cache value for a contact
209 209
210 @param entity(jid.JID): entity of the contact from who we want data (resource is used if given) 210 @param entity(jid.JID): entity of the contact from who we want data (resource is used if given)
211 if a resource specific information is requested: 211 if a resource specific information is requested:
212 - if no resource is given (bare jid), the main resource is used, according to priority 212 - if no resource is given (bare jid), the main resource is used, according to priority
213 - if resource is given, it is used 213 - if resource is given, it is used
214 @param name(unicode): name the data to get, or None to get everything 214 @param name(unicode): name the data to get, or None to get everything
215 @param bare_default(bool): if True and entity is a full jid, the value of bare jid
216 will be returned if not value is found for the requested resource.
217 If False, None is returned if no value is found for the requested resource.
215 @return: full cache if no name is given, or value of "name", or None 218 @return: full cache if no name is given, or value of "name", or None
216 """ 219 """
217 # FIXME: resource handling need to be reworked 220 # FIXME: resource handling need to be reworked
218 try: 221 try:
219 cache = self._cache[entity.bare] 222 cache = self._cache[entity.bare]
225 return cache 228 return cache
226 229
227 if name in ('status', C.PRESENCE_STATUSES, C.PRESENCE_PRIORITY, C.PRESENCE_SHOW): 230 if name in ('status', C.PRESENCE_STATUSES, C.PRESENCE_PRIORITY, C.PRESENCE_SHOW):
228 # these data are related to the resource 231 # these data are related to the resource
229 if not entity.resource: 232 if not entity.resource:
230 try: 233 main_resource = cache[C.CONTACT_MAIN_RESOURCE]
231 main_resource = cache[C.CONTACT_MAIN_RESOURCE] 234 if main_resource is None:
232 except KeyError:
233 # we ignore presence info if we don't have any resource in cache 235 # we ignore presence info if we don't have any resource in cache
234 # FIXME: to be checked 236 # FIXME: to be checked
235 return 237 return
236 cache = cache[C.CONTACT_RESOURCES].setdefault(main_resource, {}) 238 cache = cache[C.CONTACT_RESOURCES].setdefault(main_resource, {})
237 else: 239 else:
240 if name == 'status': # XXX: we get the first status for 'status' key 242 if name == 'status': # XXX: we get the first status for 'status' key
241 # TODO: manage main language for statuses 243 # TODO: manage main language for statuses
242 return cache[C.PRESENCE_STATUSES].get(C.PRESENCE_STATUSES_DEFAULT, '') 244 return cache[C.PRESENCE_STATUSES].get(C.PRESENCE_STATUSES_DEFAULT, '')
243 245
244 elif entity.resource: 246 elif entity.resource:
245 # if we have a resource, we first check if the value is not available for the resource
246 # and we fallback to main cache if not found
247 try: 247 try:
248 return cache[C.CONTACT_RESOURCES][entity.resource][name] 248 return cache[C.CONTACT_RESOURCES][entity.resource][name]
249 except KeyError: 249 except KeyError:
250 pass 250 if not bare_default:
251 return None
251 252
252 try: 253 try:
253 return cache[name] 254 return cache[name]
254 except KeyError: 255 except KeyError:
255 return None 256 return None
345 you may move your contact from its actual group(s) to the default one. 346 you may move your contact from its actual group(s) to the default one.
346 347
347 None value for 'groups' has a different meaning than [None] which is for the default group. 348 None value for 'groups' has a different meaning than [None] which is for the default group.
348 349
349 @param entity (jid.JID): entity to add or replace 350 @param entity (jid.JID): entity to add or replace
351 if entity is a full jid, attributes will be cached in for the full jid only
350 @param groups (list): list of groups or None to ignore the groups membership. 352 @param groups (list): list of groups or None to ignore the groups membership.
351 @param attributes (dict): attibutes of the added jid or to update 353 @param attributes (dict): attibutes of the added jid or to update
354 if attribute value is None, it will be removed
352 @param in_roster (bool): True if contact is from roster 355 @param in_roster (bool): True if contact is from roster
353 """ 356 """
354 if attributes is None: 357 if attributes is None:
355 attributes = {} 358 attributes = {}
356 359
359 362
360 if in_roster: 363 if in_roster:
361 self._roster.add(entity_bare) 364 self._roster.add(entity_bare)
362 365
363 cache = self._cache.setdefault(entity_bare, {C.CONTACT_RESOURCES: {}, 366 cache = self._cache.setdefault(entity_bare, {C.CONTACT_RESOURCES: {},
367 C.CONTACT_MAIN_RESOURCE: None,
364 C.CONTACT_SELECTED: set()}) 368 C.CONTACT_SELECTED: set()})
365 369
366 assert not C.CONTACT_DATA_FORBIDDEN.intersection(attributes) # we don't want forbidden data in attributes 370 assert not C.CONTACT_DATA_FORBIDDEN.intersection(attributes) # we don't want forbidden data in attributes
367 371
368 # we set groups and fill self._groups accordingly 372 # we set groups and fill self._groups accordingly
385 else: 389 else:
386 self._specials.add(entity) 390 self._specials.add(entity)
387 cache[C.CONTACT_MAIN_RESOURCE] = None 391 cache[C.CONTACT_MAIN_RESOURCE] = None
388 392
389 # now the attributes we keep in cache 393 # now the attributes we keep in cache
394 # XXX: if entity is a full jid, we store the value for the resource only
395 cache_attr = cache[C.CONTACT_RESOURCES].setdefault(entity.resource, {}) if entity.resource else cache
390 for attribute, value in attributes.iteritems(): 396 for attribute, value in attributes.iteritems():
391 if attribute == 'avatar' and entity.resource: 397 if value is None:
392 # FIXME: Q&D hack to workaround avatar issue. 398 cache_attr[attribute].pop(value, None)
393 # TODO: Need to refactor avatar handling in backend and here 399 else:
394 cache[C.CONTACT_RESOURCES].setdefault(entity.resource, {})[attribute] = value 400 cache_attr[attribute] = value
395 cache[attribute] = value
396 401
397 # we can update the display 402 # we can update the display
398 self.update([entity], update_type, self.profile) 403 self.update([entity], update_type, self.profile)
399 404
400 def entityToShow(self, entity, check_resource=False): 405 def entityToShow(self, entity, check_resource=False):