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
This commit is contained in:
Goffi 2016-01-05 23:20:20 +01:00
commit 9c6d0fecc4
2 changed files with 131 additions and 77 deletions

View file

@ -1408,12 +1408,8 @@ class PubSubService(XMPPHandler, IQHandlerMixin):
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

View file

@ -45,7 +45,7 @@ class RSMNotFoundError(Exception):
"""
class RSMRequest():
class RSMRequest(object):
"""
A Result Set Management request.
@ -62,28 +62,28 @@ class RSMRequest():
@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 @@ class RSMRequest():
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)
if request.max is None:
try:
after_elt = set_elt.elements(NS_RSM, 'after').next()
except StopIteration:
after = None
else:
after = unicode(after_elt)
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
# <max/> 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 @@ class RSMRequest():
@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 @@ class RSMRequest():
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 @@ class RSMResponse():
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 @@ class RSMResponse():
@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 @@ class RSMResponse():
@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 @@ class PubSubRequest(pubsub.PubSubRequest):
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 @@ class PubSubClient(pubsub.PubSubClient):
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 @@ class PubSubService(pubsub.PubSubService):
_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 <item/> 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