Mercurial > libervia-backend
comparison 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 |
comparison
equal
deleted
inserted
replaced
2806:2400cad2dace | 2807:0b7ce5daee9b |
---|---|
22 from sat.core.log import getLogger | 22 from sat.core.log import getLogger |
23 | 23 |
24 log = getLogger(__name__) | 24 log = getLogger(__name__) |
25 from sat.core import exceptions | 25 from sat.core import exceptions |
26 from sat.tools import sat_defer | 26 from sat.tools import sat_defer |
27 from sat.tools.common import data_format | |
27 | 28 |
28 from twisted.words.protocols.jabber import jid, error | 29 from twisted.words.protocols.jabber import jid, error |
29 from twisted.internet import reactor, defer | 30 from twisted.internet import reactor, defer |
30 from wokkel import disco | 31 from wokkel import disco |
31 from wokkel import data_form | 32 from wokkel import data_form |
278 async=True, | 279 async=True, |
279 ) | 280 ) |
280 | 281 |
281 # high level observer method | 282 # high level observer method |
282 host.bridge.addSignal( | 283 host.bridge.addSignal( |
283 "psEvent", ".plugin", signature="ssssa{ss}s" | 284 "psEvent", ".plugin", signature="ssssss" |
284 ) # args: category, service(jid), node, type (C.PS_ITEMS, C.PS_DELETE), data, profile | 285 ) # args: category, service(jid), node, type (C.PS_ITEMS, C.PS_DELETE), data, profile |
285 | 286 |
286 # low level observer method, used if service/node is in watching list (see psNodeWatch* methods) | 287 # low level observer method, used if service/node is in watching list (see psNodeWatch* methods) |
287 host.bridge.addSignal( | 288 host.bridge.addSignal( |
288 "psEventRaw", ".plugin", signature="sssass" | 289 "psEventRaw", ".plugin", signature="sssass" |
566 item_ids, | 567 item_ids, |
567 sub_id or None, | 568 sub_id or None, |
568 extra.rsm_request, | 569 extra.rsm_request, |
569 extra.extra, | 570 extra.extra, |
570 ) | 571 ) |
571 d.addCallback(self.serItemsData) | 572 d.addCallback(self.transItemsData) |
572 return d | 573 return d |
573 | 574 |
574 def getItems(self, client, service, node, max_items=None, item_ids=None, sub_id=None, | 575 def getItems(self, client, service, node, max_items=None, item_ids=None, sub_id=None, |
575 rsm_request=None, extra=None): | 576 rsm_request=None, extra=None): |
576 """Retrieve pubsub items from a node. | 577 """Retrieve pubsub items from a node. |
646 node, unicode(service), unicode(failure.value) | 647 node, unicode(service), unicode(failure.value) |
647 ) | 648 ) |
648 ) | 649 ) |
649 | 650 |
650 def doSubscribe(data): | 651 def doSubscribe(data): |
651 self.subscribe(service, node, profile_key=client.profile).addErrback( | 652 self.subscribe(client, service, node).addErrback( |
652 subscribeEb, service, node | 653 subscribeEb, service, node |
653 ) | 654 ) |
654 return data | 655 return data |
655 | 656 |
656 if subscribe: | 657 if subscribe: |
1073 def getRTResults( | 1074 def getRTResults( |
1074 self, session_id, on_success=None, on_error=None, profile=C.PROF_KEY_NONE | 1075 self, session_id, on_success=None, on_error=None, profile=C.PROF_KEY_NONE |
1075 ): | 1076 ): |
1076 return self.rt_sessions.getResults(session_id, on_success, on_error, profile) | 1077 return self.rt_sessions.getResults(session_id, on_success, on_error, profile) |
1077 | 1078 |
1078 def serItemsData(self, items_data, item_cb=lambda item: item.toXml()): | 1079 def transItemsData(self, items_data, item_cb=lambda item: item.toXml(), |
1079 """Helper method to serialise result from [getItems] | 1080 serialise=False): |
1081 """Helper method to transform result from [getItems] | |
1080 | 1082 |
1081 the items_data must be a tuple(list[domish.Element], dict[unicode, unicode]) | 1083 the items_data must be a tuple(list[domish.Element], dict[unicode, unicode]) |
1082 as returned by [getItems]. metadata values are then casted to unicode and | 1084 as returned by [getItems]. metadata values are then casted to unicode and |
1083 each item is passed to items_cb | 1085 each item is passed to items_cb then optionally serialised with |
1086 data_format.serialise. | |
1084 @param items_data(tuple): tuple returned by [getItems] | 1087 @param items_data(tuple): tuple returned by [getItems] |
1085 @param item_cb(callable): method to transform each item | 1088 @param item_cb(callable): method to transform each item |
1089 @param serialise(bool): if True do a data_format.serialise | |
1090 after applying item_cb | |
1086 @return (tuple): a serialised form ready to go throught bridge | 1091 @return (tuple): a serialised form ready to go throught bridge |
1087 """ | 1092 """ |
1088 items, metadata = items_data | 1093 items, metadata = items_data |
1094 if serialise: | |
1095 items = [data_format.serialise(item_cb(item)) for item in items] | |
1096 else: | |
1097 items = [item_cb(item) for item in items] | |
1098 | |
1089 return ( | 1099 return ( |
1090 [item_cb(item) for item in items], | 1100 items, |
1091 {key: unicode(value) for key, value in metadata.iteritems()}, | 1101 {key: unicode(value) for key, value in metadata.iteritems()}, |
1092 ) | 1102 ) |
1093 | 1103 |
1094 def serItemsDataD(self, items_data, item_cb): | 1104 def transItemsDataD(self, items_data, item_cb, serialise=False): |
1095 """Helper method to serialise result from [getItems], deferred version | 1105 """Helper method to transform result from [getItems], deferred version |
1096 | 1106 |
1097 the items_data must be a tuple(list[domish.Element], dict[unicode, unicode]) | 1107 the items_data must be a tuple(list[domish.Element], dict[unicode, unicode]) |
1098 as returned by [getItems]. metadata values are then casted to unicode and | 1108 as returned by [getItems]. metadata values are then casted to unicode and |
1099 each item is passed to items_cb | 1109 each item is passed to items_cb then optionally serialised with |
1100 An errback is added to item_cb, and when it is fired the value is filtered from final items | 1110 data_format.serialise. |
1111 An errback is added to item_cb, and when it is fired the value is filtered from | |
1112 final items | |
1101 @param items_data(tuple): tuple returned by [getItems] | 1113 @param items_data(tuple): tuple returned by [getItems] |
1102 @param item_cb(callable): method to transform each item (must return a deferred) | 1114 @param item_cb(callable): method to transform each item (must return a deferred) |
1103 @return (tuple): a deferred which fire a serialised form ready to go throught bridge | 1115 @param serialise(bool): if True do a data_format.serialise |
1116 after applying item_cb | |
1117 @return (tuple): a deferred which fire a serialised form ready to go throught | |
1118 bridge | |
1104 """ | 1119 """ |
1105 items, metadata = items_data | 1120 items, metadata = items_data |
1106 | 1121 |
1107 def eb(failure): | 1122 def eb(failure): |
1108 log.warning( | 1123 log.warning( |
1109 "Error while serialising/parsing item: {}".format(unicode(failure.value)) | 1124 "Error while serialising/parsing item: {}".format(unicode(failure.value)) |
1110 ) | 1125 ) |
1111 | 1126 |
1112 d = defer.gatherResults([item_cb(item).addErrback(eb) for item in items]) | 1127 d = defer.gatherResults([item_cb(item).addErrback(eb) for item in items]) |
1113 | 1128 |
1114 def finishSerialisation(serialised_items): | 1129 def finishSerialisation(parsed_items): |
1130 if serialise: | |
1131 items = [data_format.serialise(i) for i in parsed_items if i is not None] | |
1132 else: | |
1133 items = [i for i in parsed_items if i is not None] | |
1134 | |
1115 return ( | 1135 return ( |
1116 [item for item in serialised_items if item is not None], | 1136 items, |
1117 {key: unicode(value) for key, value in metadata.iteritems()}, | 1137 {key: unicode(value) for key, value in metadata.iteritems()}, |
1118 ) | 1138 ) |
1119 | 1139 |
1120 d.addCallback(finishSerialisation) | 1140 d.addCallback(finishSerialisation) |
1121 return d | 1141 return d |
1313 - metadata(dict): serialised metadata | 1333 - metadata(dict): serialised metadata |
1314 """ | 1334 """ |
1315 profile = self.host.getClient(profile_key).profile | 1335 profile = self.host.getClient(profile_key).profile |
1316 d = self.rt_sessions.getResults( | 1336 d = self.rt_sessions.getResults( |
1317 session_id, | 1337 session_id, |
1318 on_success=lambda result: ("", self.serItemsData(result)), | 1338 on_success=lambda result: ("", self.transItemsData(result)), |
1319 on_error=lambda failure: (unicode(failure.value) or UNSPECIFIED, ([], {})), | 1339 on_error=lambda failure: (unicode(failure.value) or UNSPECIFIED, ([], {})), |
1320 profile=profile, | 1340 profile=profile, |
1321 ) | 1341 ) |
1322 d.addCallback( | 1342 d.addCallback( |
1323 lambda ret: ( | 1343 lambda ret: ( |
1346 extra.rsm_request, | 1366 extra.rsm_request, |
1347 extra.extra, | 1367 extra.extra, |
1348 profile_key, | 1368 profile_key, |
1349 ) | 1369 ) |
1350 | 1370 |
1351 def getFromMany( | 1371 def getFromMany(self, node_data, max_item=None, rsm_request=None, extra=None, |
1352 self, | 1372 profile_key=C.PROF_KEY_NONE): |
1353 node_data, | |
1354 max_item=None, | |
1355 rsm_request=None, | |
1356 extra=None, | |
1357 profile_key=C.PROF_KEY_NONE, | |
1358 ): | |
1359 """Get items from many nodes at once | 1373 """Get items from many nodes at once |
1360 | 1374 |
1361 @param node_data (iterable[tuple]): iterable of tuple (service, node) where: | 1375 @param node_data (iterable[tuple]): iterable of tuple (service, node) where: |
1362 - service (jid.JID) is the pubsub service | 1376 - service (jid.JID) is the pubsub service |
1363 - node (unicode) is the node to get items from | 1377 - node (unicode) is the node to get items from |