diff sat/plugins/plugin_xep_0060.py @ 2807:0b7ce5daee9b

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.
author Goffi <goffi@goffi.org>
date Sat, 23 Feb 2019 18:59:00 +0100
parents ae127e14b040
children cd391ea847cb
line wrap: on
line diff
--- a/sat/plugins/plugin_xep_0060.py	Wed Feb 20 19:42:35 2019 +0100
+++ b/sat/plugins/plugin_xep_0060.py	Sat Feb 23 18:59:00 2019 +0100
@@ -24,6 +24,7 @@
 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 @@
 
         #  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 @@
             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 @@
             )
 
         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 @@
     ):
         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 @@
 
         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 @@
         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 @@
             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: