# HG changeset patch # User Goffi # Date 1452032420 -3600 # Node ID 54f834e4034153cdf3ca6bbf2e888318829b9a1b # Parent 81f9b53ec7e47eaf76c6b9bbd711f5a7e0636cef tmp (wokkel/rsm): various improvments: - restored original tmp.wokkel.pubsub.PubSubService._toResponse_items - changed arguments order in RSMRequest.__init__ to have most common arguments first - added __str__ methods - better parsing/toElement - better handling of optional elements/attributes (count/index) - _toResponse_items handler RSM set elements without modifying original pubsub _toResponse_items - renamed parse to fromElement for coherency diff -r 81f9b53ec7e4 -r 54f834e40341 wokkel/pubsub.py --- a/wokkel/pubsub.py Sun Jan 03 18:36:41 2016 +0100 +++ b/wokkel/pubsub.py Tue Jan 05 23:20:20 2016 +0100 @@ -1408,12 +1408,8 @@ items["node"] = request.nodeIdentifier for item in result: - if isinstance(item, tuple): - # XXX: see sat_pubsub.pgsql_storage.LeafNode.getItemsById return value - item = item[0] - if item.name == 'item': - item.uri = NS_PUBSUB - items.addChild(item) + item.uri = NS_PUBSUB + items.addChild(item) return response diff -r 81f9b53ec7e4 -r 54f834e40341 wokkel/rsm.py --- a/wokkel/rsm.py Sun Jan 03 18:36:41 2016 +0100 +++ b/wokkel/rsm.py Tue Jan 05 23:20:20 2016 +0100 @@ -45,7 +45,7 @@ """ -class RSMRequest(): +class RSMRequest(object): """ A Result Set Management request. @@ -62,28 +62,28 @@ @itype before: C{unicode} """ - def __init__(self, max_=10, index=None, after=None, before=None): - max_ = int(max_) - assert max_ >= 0 - self.max = max_ + def __init__(self, max_=10, after=None, before=None, index=None): + self.max = int(max_) if index is not None: assert after is None and before is None index = int(index) - assert index >= 0 self.index = index if after is not None: assert before is None - assert isinstance(after, unicode) + assert isinstance(after, basestring) self.after = after if before is not None: - assert isinstance(before, unicode) + assert isinstance(before, basestring) self.before = before + def __str__(self): + return "RSM Request: max={0.max} after={0.after} before={0.before} index={0.index}".format(self) + @classmethod - def parse(cls, element): + def fromElement(cls, element): """Parse the given request element. @param element: request containing a set element. @@ -97,17 +97,43 @@ except StopIteration: raise RSMNotFoundError() - request = RSMRequest() - for elt in set_elt.elements(): - if elt.name in ('before', 'after'): - setattr(request, elt.name, ''.join(elt.children)) - elif elt.name in ('max', 'index'): - setattr(request, elt.name, int(''.join(elt.children))) + try: + before_elt = set_elt.elements(NS_RSM, 'before').next() + except StopIteration: + before = None + else: + before = unicode(before_elt) + + try: + after_elt = set_elt.elements(NS_RSM, 'after').next() + except StopIteration: + after = None + else: + after = unicode(after_elt) - if request.max is None: + try: + max_elt = set_elt.elements(NS_RSM, 'max').next() + except StopIteration: + # FIXME: even if it doesn't make a lot of sense without it + # element is not mandatory in XEP-0059 raise RSMError("RSM request is missing its 'max' element") + else: + try: + max_ = int(unicode(max_elt)) + except ValueError: + raise RSMError("bad value for 'max' element") - return request + try: + index_elt = set_elt.elements(NS_RSM, 'index').next() + except StopIteration: + index = None + else: + try: + index = int(unicode(index_elt)) + except ValueError: + raise RSMError("bad value for 'index' element") + + return RSMRequest(max_, after, before, index) def toElement(self): """ @@ -116,19 +142,19 @@ @rtype: L{domish.Element} """ set_elt = domish.Element((NS_RSM, 'set')) - set_elt.addElement('max').addContent(unicode(self.max)) + set_elt.addElement('max', content=unicode(self.max)) if self.index is not None: - set_elt.addElement('index').addContent(unicode(self.index)) + set_elt.addElement('index', content=unicode(self.index)) if self.before is not None: if self.before == '': # request the last page set_elt.addElement('before') else: - set_elt.addElement('before').addContent(self.before) + set_elt.addElement('before', content=self.before) if self.after is not None: - set_elt.addElement('after').addContent(self.after) + set_elt.addElement('after', content=self.after) return set_elt @@ -150,38 +176,45 @@ return set_elt -class RSMResponse(): +class RSMResponse(object): """ A Result Set Management response. - @ivar count: total number of items. - @itype count: C{int} - - @ivar index: starting index of the returned page. - @itype index: C{int} - @ivar first: ID of the first element of the returned page. @itype first: C{unicode} @ivar last: ID of the last element of the returned page. @itype last: C{unicode} + + @ivar index: starting index of the returned page. + @itype index: C{int} + + @ivar count: total number of items. + @itype count: C{int} + """ - def __init__(self, count=0, index=None, first=None, last=None): - assert isinstance(count, int) and count >= 0 - self.count = count - if index is not None: - assert isinstance(index, int) and index >= 0 - assert isinstance(first, unicode) - assert isinstance(last, unicode) - else: - assert first is None and last is None - self.index = index + def __init__(self, first=None, last=None, index=None, count=None): + if first is None: + assert last is None and index is None + if last is None: + assert first is None self.first = first self.last = last + if count is not None: + self.count = int(count) + else: + self.count = None + if index is not None: + self.index = int(index) + else: + self.index = None + + def __str__(self): + return "RSM Request: first={0.first} last={0.last} index={0.index} count={0.count}".format(self) @classmethod - def parse(cls, element): + def fromElement(cls, element): """Parse the given response element. @param element: response element. @@ -195,19 +228,43 @@ except StopIteration: raise RSMNotFoundError() - response = RSMResponse() - for elt in list(set_elt.elements()): - if elt.name in ('first', 'last'): - setattr(response, elt.name, ''.join(elt.children)) - if elt.name == 'first': - response.index = int(elt.getAttribute("index")) - elif elt.name == 'count': - response.count = int(''.join(elt.children)) + try: + first_elt = set_elt.elements(NS_RSM, 'first').next() + except StopIteration: + first = None + index = None + else: + first = unicode(first_elt) + try: + index = int(first_elt['index']) + except KeyError: + index = None + except ValueError: + raise RSMError("bad index in RSM response") - if response.count is None: - raise RSMError("RSM response is missing its 'count' element") + try: + last_elt = set_elt.elements(NS_RSM, 'last').next() + except StopIteration: + if first is not None: + raise RSMError("RSM response is missing its 'last' element") + else: + last = None + else: + if first is None: + raise RSMError("RSM response is missing its 'first' element") + last = unicode(last_elt) - return response + try: + count_elt = set_elt.elements(NS_RSM, 'count').next() + except StopIteration: + count = None + else: + try: + count = int(unicode(count_elt)) + except ValueError: + raise RSMError("invalid count in RSM response") + + return RSMResponse(first, last, index, count) def toElement(self): """ @@ -216,14 +273,15 @@ @rtype: L{domish.Element} """ set_elt = domish.Element((NS_RSM, 'set')) - set_elt.addElement('count').addContent(unicode(self.count)) + if self.first is not None: + first_elt = set_elt.addElement('first', content=self.first) + if self.index is not None: + first_elt['index'] = unicode(self.index) - if self.index is not None: - first_elt = set_elt.addElement('first') - first_elt.addContent(self.first) - first_elt['index'] = unicode(self.index) + set_elt.addElement('last', content=self.last) - set_elt.addElement('last').addContent(self.last) + if self.count is not None: + set_elt.addElement('count', content=unicode(self.count)) return set_elt @@ -247,7 +305,7 @@ @rtype: C{dict} binding C{unicode} to C{unicode} """ result = {} - for attr in ('count', 'index', 'first', 'last'): + for attr in ('first', 'last', 'index', 'count'): value = getattr(self, attr) if value is not None: result[attr] = unicode(value) @@ -270,7 +328,7 @@ def _parse_rsm(self, verbElement): try: - self.rsm = RSMRequest.parse(verbElement.parent) + self.rsm = RSMRequest.fromElement(verbElement.parent) except RSMNotFoundError: self.rsm = None @@ -331,7 +389,7 @@ if request.rsm: try: - response = RSMResponse.parse(iq.pubsub) + response = RSMResponse.fromElement(iq.pubsub) if response is not None: self._rsm_responses[ext_data['id']] = response except RSMNotFoundError: # target pubsub server doesn't support RSM @@ -364,15 +422,18 @@ _request_class = PubSubRequest - def _toResponse_items(self, result, resource, request): - response = pubsub.PubSubService._toResponse_items(self, result, - resource, request) - for item in result: - if isinstance(item, tuple): - # XXX: see sat_pubsub.pgsql_storage.LeafNode.getItemsById return value - item = item[0] - if item.name == "set": - response.addChild(item) + def _toResponse_items(self, elts, resource, request): + # default method only manage elements + # but we need to add RSM set element + rsm_elt = None + for idx, elt in enumerate(reversed(elts)): + if elt.name == "set" and elt.uri == NS_RSM: + rsm_elt = elts.pop(-1-idx) break + response = pubsub.PubSubService._toResponse_items(self, elts, + resource, request) + if rsm_elt is not None: + response.addChild(rsm_elt) + return response