plugin XEP-0277: blog items data are now entirely serialised before going to bridge:

So far, and for historical reasons, blog items data where serialised using a unicode: unicode dict, which was causing trouble for many types of values (timestamps, booleans, lists).
This patch changes it by serialising the whole items before going to bridge, and deserialising it when going back. This way, complex data can be used easily in items.
This impact psEvent and serItemsData* methods which are renamed transItemsData* because there are not always serialising anymore (a new argument "serialise" allows to specify it).
When editing a blog post in jp, metadata are now more easy to manipulate, specially lists like tags.
This commit is contained in:
Goffi 2019-02-23 18:59:00 +01:00
commit 512ae0b91e

View file

@ -24,6 +24,7 @@ from sat.core.log import getLogger
log = getLogger(__name__)
from sat.core import exceptions
from sat.tools import sat_defer
from sat.tools.common import data_format
from twisted.words.protocols.jabber import jid, error
from twisted.internet import reactor, defer
@ -280,7 +281,7 @@ class XEP_0060(object):
#  high level observer method
host.bridge.addSignal(
"psEvent", ".plugin", signature="ssssa{ss}s"
"psEvent", ".plugin", signature="ssssss"
) # args: category, service(jid), node, type (C.PS_ITEMS, C.PS_DELETE), data, profile
# low level observer method, used if service/node is in watching list (see psNodeWatch* methods)
@ -568,7 +569,7 @@ class XEP_0060(object):
extra.rsm_request,
extra.extra,
)
d.addCallback(self.serItemsData)
d.addCallback(self.transItemsData)
return d
def getItems(self, client, service, node, max_items=None, item_ids=None, sub_id=None,
@ -648,7 +649,7 @@ class XEP_0060(object):
)
def doSubscribe(data):
self.subscribe(service, node, profile_key=client.profile).addErrback(
self.subscribe(client, service, node).addErrback(
subscribeEb, service, node
)
return data
@ -1075,32 +1076,46 @@ class XEP_0060(object):
):
return self.rt_sessions.getResults(session_id, on_success, on_error, profile)
def serItemsData(self, items_data, item_cb=lambda item: item.toXml()):
"""Helper method to serialise result from [getItems]
def transItemsData(self, items_data, item_cb=lambda item: item.toXml(),
serialise=False):
"""Helper method to transform result from [getItems]
the items_data must be a tuple(list[domish.Element], dict[unicode, unicode])
as returned by [getItems]. metadata values are then casted to unicode and
each item is passed to items_cb
each item is passed to items_cb then optionally serialised with
data_format.serialise.
@param items_data(tuple): tuple returned by [getItems]
@param item_cb(callable): method to transform each item
@param serialise(bool): if True do a data_format.serialise
after applying item_cb
@return (tuple): a serialised form ready to go throught bridge
"""
items, metadata = items_data
if serialise:
items = [data_format.serialise(item_cb(item)) for item in items]
else:
items = [item_cb(item) for item in items]
return (
[item_cb(item) for item in items],
items,
{key: unicode(value) for key, value in metadata.iteritems()},
)
def serItemsDataD(self, items_data, item_cb):
"""Helper method to serialise result from [getItems], deferred version
def transItemsDataD(self, items_data, item_cb, serialise=False):
"""Helper method to transform result from [getItems], deferred version
the items_data must be a tuple(list[domish.Element], dict[unicode, unicode])
as returned by [getItems]. metadata values are then casted to unicode and
each item is passed to items_cb
An errback is added to item_cb, and when it is fired the value is filtered from final items
each item is passed to items_cb then optionally serialised with
data_format.serialise.
An errback is added to item_cb, and when it is fired the value is filtered from
final items
@param items_data(tuple): tuple returned by [getItems]
@param item_cb(callable): method to transform each item (must return a deferred)
@return (tuple): a deferred which fire a serialised form ready to go throught bridge
@param serialise(bool): if True do a data_format.serialise
after applying item_cb
@return (tuple): a deferred which fire a serialised form ready to go throught
bridge
"""
items, metadata = items_data
@ -1111,9 +1126,14 @@ class XEP_0060(object):
d = defer.gatherResults([item_cb(item).addErrback(eb) for item in items])
def finishSerialisation(serialised_items):
def finishSerialisation(parsed_items):
if serialise:
items = [data_format.serialise(i) for i in parsed_items if i is not None]
else:
items = [i for i in parsed_items if i is not None]
return (
[item for item in serialised_items if item is not None],
items,
{key: unicode(value) for key, value in metadata.iteritems()},
)
@ -1315,7 +1335,7 @@ class XEP_0060(object):
profile = self.host.getClient(profile_key).profile
d = self.rt_sessions.getResults(
session_id,
on_success=lambda result: ("", self.serItemsData(result)),
on_success=lambda result: ("", self.transItemsData(result)),
on_error=lambda failure: (unicode(failure.value) or UNSPECIFIED, ([], {})),
profile=profile,
)
@ -1348,14 +1368,8 @@ class XEP_0060(object):
profile_key,
)
def getFromMany(
self,
node_data,
max_item=None,
rsm_request=None,
extra=None,
profile_key=C.PROF_KEY_NONE,
):
def getFromMany(self, node_data, max_item=None, rsm_request=None, extra=None,
profile_key=C.PROF_KEY_NONE):
"""Get items from many nodes at once
@param node_data (iterable[tuple]): iterable of tuple (service, node) where: