Mercurial > libervia-backend
comparison src/tmp/wokkel/rsm.py @ 1773:6e867caf4621
plugin XEP-0060, tmp(wokkel.rsm): small refactoring:
- don't use getRSMResponse anymore: rsm.PubSubClient use a different signature which return items and RSMResponse, this is better than the previous method as if the requested don't call getRSMResponse, there is no memory leak anymore.
- use RSMResponse directly instead of using ext_data, as other extension (like MAM) will be probably be managed with an other workflow
- don't do a useless deep copy of pubsub.PubSubRequest._parameters on each instance anymore
- RSMResponse.parse do now manage parsing of <set/> element directly
author | Goffi <goffi@goffi.org> |
---|---|
date | Tue, 05 Jan 2016 23:20:22 +0100 |
parents | b77dc676a4df |
children | 4beb613d277c |
comparison
equal
deleted
inserted
replaced
1772:666ab06a9d81 | 1773:6e867caf4621 |
---|---|
84 | 84 |
85 @classmethod | 85 @classmethod |
86 def fromElement(cls, element): | 86 def fromElement(cls, element): |
87 """Parse the given request element. | 87 """Parse the given request element. |
88 | 88 |
89 @param element: request containing a set element. | 89 @param element: request containing a set element, or set element itself. |
90 @type element: L{domish.Element} | 90 @type element: L{domish.Element} |
91 | 91 |
92 @return: RSMRequest instance. | 92 @return: RSMRequest instance. |
93 @rtype: L{RSMRequest} | 93 @rtype: L{RSMRequest} |
94 """ | 94 """ |
95 try: | 95 |
96 set_elt = element.elements(NS_RSM, 'set').next() | 96 if element.name == 'set' and element.uri == NS_RSM: |
97 except StopIteration: | 97 set_elt = element |
98 raise RSMNotFoundError() | 98 else: |
99 try: | |
100 set_elt = element.elements(NS_RSM, 'set').next() | |
101 except StopIteration: | |
102 raise RSMNotFoundError() | |
99 | 103 |
100 try: | 104 try: |
101 before_elt = set_elt.elements(NS_RSM, 'before').next() | 105 before_elt = set_elt.elements(NS_RSM, 'before').next() |
102 except StopIteration: | 106 except StopIteration: |
103 before = None | 107 before = None |
318 @ivar rsm: RSM request instance. | 322 @ivar rsm: RSM request instance. |
319 @type rsm: L{RSMRequest} | 323 @type rsm: L{RSMRequest} |
320 """ | 324 """ |
321 | 325 |
322 rsm = None | 326 rsm = None |
323 | 327 _parameters = copy.deepcopy(pubsub.PubSubRequest._parameters) |
324 def __init__(self, verb=None): | 328 _parameters['items'].append('rsm') |
325 super(PubSubRequest, self).__init__(verb) | |
326 self._parameters = copy.deepcopy(pubsub.PubSubRequest._parameters) | |
327 self._parameters['items'].append('rsm') | |
328 | 329 |
329 def _parse_rsm(self, verbElement): | 330 def _parse_rsm(self, verbElement): |
330 try: | 331 try: |
331 self.rsm = RSMRequest.fromElement(verbElement.parent) | 332 self.rsm = RSMRequest.fromElement(verbElement.parent) |
332 except RSMNotFoundError: | 333 except RSMNotFoundError: |
338 | 339 |
339 | 340 |
340 class PubSubClient(pubsub.PubSubClient): | 341 class PubSubClient(pubsub.PubSubClient): |
341 """PubSubClient extension to handle RSM.""" | 342 """PubSubClient extension to handle RSM.""" |
342 | 343 |
343 _rsm_responses = {} | 344 _request_class = PubSubRequest |
344 | 345 |
345 def items(self, service, nodeIdentifier, maxItems=None, itemIdentifiers=None, | 346 def items(self, service, nodeIdentifier, maxItems=None, itemIdentifiers=None, |
346 subscriptionIdentifier=None, sender=None, ext_data=None): | 347 subscriptionIdentifier=None, sender=None, rsm_request=None): |
347 """ | 348 """ |
348 Retrieve previously published items from a publish subscribe node. | 349 Retrieve previously published items from a publish subscribe node. |
349 | 350 |
350 @param service: The publish subscribe service that keeps the node. | 351 @param service: The publish subscribe service that keeps the node. |
351 @type service: L{JID<twisted.words.protocols.jabber.jid.JID>} | 352 @type service: L{JID<twisted.words.protocols.jabber.jid.JID>} |
365 @type subscriptionIdentifier: C{unicode} | 366 @type subscriptionIdentifier: C{unicode} |
366 | 367 |
367 @param ext_data: extension data. | 368 @param ext_data: extension data. |
368 @type ext_data: L{dict} | 369 @type ext_data: L{dict} |
369 | 370 |
370 @return: a Deferred that fires a C{list} of L{domish.Element}. | 371 @return: a Deferred that fires a C{list} of C{tuple} of L{domish.Element}, L{RSMResponse}. |
371 @rtype: L{defer.Deferred} | 372 @rtype: L{defer.Deferred} |
372 """ | 373 """ |
373 request = PubSubRequest('items') # that's a rsm.PubSubRequest instance | 374 # XXX: we have to copy initial method instead of calling it, |
375 # as original cb remove all non item elements | |
376 request = self._request_class('items') | |
374 request.recipient = service | 377 request.recipient = service |
375 request.nodeIdentifier = nodeIdentifier | 378 request.nodeIdentifier = nodeIdentifier |
376 if maxItems is not None: | 379 if maxItems: |
377 request.maxItems = str(int(maxItems)) | 380 request.maxItems = str(int(maxItems)) |
378 request.subscriptionIdentifier = subscriptionIdentifier | 381 request.subscriptionIdentifier = subscriptionIdentifier |
379 request.sender = sender | 382 request.sender = sender |
380 request.itemIdentifiers = itemIdentifiers | 383 request.itemIdentifiers = itemIdentifiers |
381 if ext_data and 'rsm' in ext_data: | 384 request.rsm = rsm_request |
382 request.rsm = ext_data['rsm'] | |
383 | 385 |
384 def cb(iq): | 386 def cb(iq): |
385 items = [] | 387 items = [] |
386 if iq.pubsub.items: | 388 pubsub_elt = iq.pubsub |
387 for element in iq.pubsub.items.elements(pubsub.NS_PUBSUB, 'item'): | 389 for element in pubsub_elt.items.elements(pubsub.NS_PUBSUB, 'item'): |
388 items.append(element) | 390 items.append(element) |
389 | 391 |
390 if request.rsm: | 392 try: |
391 try: | 393 rsm_response = RSMResponse.parse(pubsub_elt) |
392 response = RSMResponse.fromElement(iq.pubsub) | 394 except RSMNotFoundError: |
393 if response is not None: | 395 rsm_response = None |
394 self._rsm_responses[ext_data['id']] = response | 396 return (items, rsm_response) |
395 except RSMNotFoundError: # target pubsub server doesn't support RSM | |
396 pass | |
397 return items | |
398 | 397 |
399 d = request.send(self.xmlstream) | 398 d = request.send(self.xmlstream) |
400 d.addCallback(cb) | 399 d.addCallback(cb) |
401 return d | 400 return d |
402 | |
403 def getRSMResponse(self, id_): | |
404 """Post-retrieve the RSM response data after items retrieval is done. | |
405 | |
406 @param id_: extension data ID | |
407 @type id_: C{unicode} | |
408 | |
409 @return: dict representation of the RSM response. | |
410 @rtype: C{dict} of C{unicode} | |
411 """ | |
412 # This method exists to not modify the return value of self.items. | |
413 if id_ not in self._rsm_responses: | |
414 return {} | |
415 result = self._rsm_responses[id_].toDict() | |
416 del self._rsm_responses[id_] | |
417 return result | |
418 | 401 |
419 | 402 |
420 class PubSubService(pubsub.PubSubService): | 403 class PubSubService(pubsub.PubSubService): |
421 """PubSubService extension to handle RSM.""" | 404 """PubSubService extension to handle RSM.""" |
422 | 405 |