Mercurial > libervia-backend
diff sat/plugins/plugin_xep_0060.py @ 3028:ab2696e34d29
Python 3 port:
/!\ this is a huge commit
/!\ starting from this commit, SàT is needs Python 3.6+
/!\ SàT maybe be instable or some feature may not work anymore, this will improve with time
This patch port backend, bridge and frontends to Python 3.
Roughly this has been done this way:
- 2to3 tools has been applied (with python 3.7)
- all references to python2 have been replaced with python3 (notably shebangs)
- fixed files not handled by 2to3 (notably the shell script)
- several manual fixes
- fixed issues reported by Python 3 that where not handled in Python 2
- replaced "async" with "async_" when needed (it's a reserved word from Python 3.7)
- replaced zope's "implements" with @implementer decorator
- temporary hack to handle data pickled in database, as str or bytes may be returned,
to be checked later
- fixed hash comparison for password
- removed some code which is not needed anymore with Python 3
- deactivated some code which needs to be checked (notably certificate validation)
- tested with jp, fixed reported issues until some basic commands worked
- ported Primitivus (after porting dependencies like urwid satext)
- more manual fixes
author | Goffi <goffi@goffi.org> |
---|---|
date | Tue, 13 Aug 2019 19:08:41 +0200 |
parents | cd391ea847cb |
children | 93e8793a735a |
line wrap: on
line diff
--- a/sat/plugins/plugin_xep_0060.py Wed Jul 31 11:31:22 2019 +0200 +++ b/sat/plugins/plugin_xep_0060.py Tue Aug 13 19:08:41 2019 +0200 @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # SAT plugin for Publish-Subscribe (xep-0060) @@ -31,9 +31,9 @@ from wokkel import disco from wokkel import data_form from wokkel import generic -from zope.interface import implements +from zope.interface import implementer from collections import namedtuple -import urllib +import urllib.request, urllib.parse, urllib.error # XXX: sat_tmp.wokkel.pubsub is actually use instead of wokkel version # mam and rsm come from sat_tmp.wokkel too @@ -43,15 +43,15 @@ PLUGIN_INFO = { - C.PI_NAME: u"Publish-Subscribe", - C.PI_IMPORT_NAME: u"XEP-0060", - C.PI_TYPE: u"XEP", - C.PI_PROTOCOLS: [u"XEP-0060"], + C.PI_NAME: "Publish-Subscribe", + C.PI_IMPORT_NAME: "XEP-0060", + C.PI_TYPE: "XEP", + C.PI_PROTOCOLS: ["XEP-0060"], C.PI_DEPENDENCIES: [], - C.PI_RECOMMENDATIONS: [u"XEP-0059", u"XEP-0313"], - C.PI_MAIN: u"XEP_0060", - C.PI_HANDLER: u"yes", - C.PI_DESCRIPTION: _(u"""Implementation of PubSub Protocol"""), + C.PI_RECOMMENDATIONS: ["XEP-0059", "XEP-0313"], + C.PI_MAIN: "XEP_0060", + C.PI_HANDLER: "yes", + C.PI_DESCRIPTION: _("""Implementation of PubSub Protocol"""), } UNSPECIFIED = "unspecified error" @@ -82,10 +82,10 @@ ID_SINGLETON = "current" def __init__(self, host): - log.info(_(u"PubSub plugin initialization")) + log.info(_("PubSub plugin initialization")) self.host = host - self._rsm = host.plugins.get(u"XEP-0059") - self._mam = host.plugins.get(u"XEP-0313") + self._rsm = host.plugins.get("XEP-0059") + self._mam = host.plugins.get("XEP-0313") self._node_cb = {} # dictionnary of callbacks for node (key: node, value: list of callbacks) self.rt_sessions = sat_defer.RTDeferredSessions() host.bridge.addMethod( @@ -94,7 +94,7 @@ in_sign="ssa{ss}s", out_sign="s", method=self._createNode, - async=True, + async_=True, ) host.bridge.addMethod( "psNodeConfigurationGet", @@ -102,7 +102,7 @@ in_sign="sss", out_sign="a{ss}", method=self._getNodeConfiguration, - async=True, + async_=True, ) host.bridge.addMethod( "psNodeConfigurationSet", @@ -110,7 +110,7 @@ in_sign="ssa{ss}s", out_sign="", method=self._setNodeConfiguration, - async=True, + async_=True, ) host.bridge.addMethod( "psNodeAffiliationsGet", @@ -118,7 +118,7 @@ in_sign="sss", out_sign="a{ss}", method=self._getNodeAffiliations, - async=True, + async_=True, ) host.bridge.addMethod( "psNodeAffiliationsSet", @@ -126,7 +126,7 @@ in_sign="ssa{ss}s", out_sign="", method=self._setNodeAffiliations, - async=True, + async_=True, ) host.bridge.addMethod( "psNodeSubscriptionsGet", @@ -134,7 +134,7 @@ in_sign="sss", out_sign="a{ss}", method=self._getNodeSubscriptions, - async=True, + async_=True, ) host.bridge.addMethod( "psNodeSubscriptionsSet", @@ -142,7 +142,7 @@ in_sign="ssa{ss}s", out_sign="", method=self._setNodeSubscriptions, - async=True, + async_=True, ) host.bridge.addMethod( "psNodePurge", @@ -150,7 +150,7 @@ in_sign="sss", out_sign="", method=self._purgeNode, - async=True, + async_=True, ) host.bridge.addMethod( "psNodeDelete", @@ -158,7 +158,7 @@ in_sign="sss", out_sign="", method=self._deleteNode, - async=True, + async_=True, ) host.bridge.addMethod( "psNodeWatchAdd", @@ -166,7 +166,7 @@ in_sign="sss", out_sign="", method=self._addWatch, - async=False, + async_=False, ) host.bridge.addMethod( "psNodeWatchRemove", @@ -174,7 +174,7 @@ in_sign="sss", out_sign="", method=self._removeWatch, - async=False, + async_=False, ) host.bridge.addMethod( "psAffiliationsGet", @@ -182,7 +182,7 @@ in_sign="sss", out_sign="a{ss}", method=self._getAffiliations, - async=True, + async_=True, ) host.bridge.addMethod( "psItemsGet", @@ -190,7 +190,7 @@ in_sign="ssiassa{ss}s", out_sign="(asa{ss})", method=self._getItems, - async=True, + async_=True, ) host.bridge.addMethod( "psItemSend", @@ -198,7 +198,7 @@ in_sign="ssssa{ss}s", out_sign="s", method=self._sendItem, - async=True, + async_=True, ) host.bridge.addMethod( "psItemsSend", @@ -206,7 +206,7 @@ in_sign="ssasa{ss}s", out_sign="as", method=self._sendItems, - async=True, + async_=True, ) host.bridge.addMethod( "psRetractItem", @@ -214,7 +214,7 @@ in_sign="sssbs", out_sign="", method=self._retractItem, - async=True, + async_=True, ) host.bridge.addMethod( "psRetractItems", @@ -222,7 +222,7 @@ in_sign="ssasbs", out_sign="", method=self._retractItems, - async=True, + async_=True, ) host.bridge.addMethod( "psSubscribe", @@ -230,7 +230,7 @@ in_sign="ssa{ss}s", out_sign="s", method=self._subscribe, - async=True, + async_=True, ) host.bridge.addMethod( "psUnsubscribe", @@ -238,7 +238,7 @@ in_sign="sss", out_sign="", method=self._unsubscribe, - async=True, + async_=True, ) host.bridge.addMethod( "psSubscriptionsGet", @@ -246,7 +246,7 @@ in_sign="sss", out_sign="aa{ss}", method=self._subscriptions, - async=True, + async_=True, ) host.bridge.addMethod( "psSubscribeToMany", @@ -261,7 +261,7 @@ in_sign="ss", out_sign="(ua(sss))", method=self._manySubscribeRTResult, - async=True, + async_=True, ) host.bridge.addMethod( "psGetFromMany", @@ -276,7 +276,7 @@ in_sign="ss", out_sign="(ua(sssasa{ss}))", method=self._getFromManyRTResult, - async=True, + async_=True, ) # high level observer method @@ -303,7 +303,7 @@ except RuntimeError: log.info( _( - u"Can't retrieve pubsub_service from conf, we'll use first one that we find" + "Can't retrieve pubsub_service from conf, we'll use first one that we find" ) ) client.pubsub_service = yield self.host.findServiceEntity( @@ -359,8 +359,8 @@ mam_request = self._mam.parseExtra(extra, with_rsm=False) if mam_request is not None: - assert u"mam" not in extra - extra[u"mam"] = mam_request + assert "mam" not in extra + extra["mam"] = mam_request return Extra(rsm_request, extra) @@ -377,7 +377,7 @@ assert node is not None assert kwargs callbacks = self._node_cb.setdefault(node, {}) - for event, cb in kwargs.iteritems(): + for event, cb in kwargs.items(): event_name = event[:-3] assert event_name in C.PS_EVENTS callbacks.setdefault(event_name, []).append(cb) @@ -395,14 +395,14 @@ pass else: for callback in args: - for event, cb_list in registred_cb.iteritems(): + for event, cb_list in registred_cb.items(): try: cb_list.remove(callback) except ValueError: pass else: log.debug( - u"removed callback {cb} for event {event} on node {node}".format( + "removed callback {cb} for event {event} on node {node}".format( cb=callback, event=event, node=node ) ) @@ -412,7 +412,7 @@ del self._node_cb[node] return log.error( - u"Trying to remove inexistant callback {cb} for node {node}".format( + "Trying to remove inexistant callback {cb} for node {node}".format( cb=callback, node=node ) ) @@ -454,7 +454,7 @@ d = self.sendItem( client, service, nodeIdentifier, payload, item_id or None, extra ) - d.addCallback(lambda ret: ret or u"") + d.addCallback(lambda ret: ret or "") return d def _sendItems(self, service, nodeIdentifier, items, extra=None, @@ -464,7 +464,7 @@ try: items = [generic.parseXml(item.encode('utf-8')) for item in items] except Exception as e: - raise exceptions.DataError(_(u"Can't parse items: {msg}").format( + raise exceptions.DataError(_("Can't parse items: {msg}").format( msg=e)) d = self.sendItems( client, service, nodeIdentifier, items, extra @@ -504,7 +504,7 @@ """Parse publish result, and return ids given by pubsub service""" try: item_ids = [item['id'] - for item in iq_result.pubsub.publish.elements(pubsub.NS_PUBSUB, u'item')] + for item in iq_result.pubsub.publish.elements(pubsub.NS_PUBSUB, 'item')] except AttributeError: return [] return item_ids @@ -522,9 +522,9 @@ """ parsed_items = [] for item in items: - if item.name != u'item': - raise exceptions.DataError(_(u"Invalid item: {xml}").format(item.toXml())) - item_id = item.getAttribute(u"id") + if item.name != 'item': + raise exceptions.DataError(_("Invalid item: {xml}").format(item.toXml())) + item_id = item.getAttribute("id") parsed_items.append(pubsub.Item(id=item_id, payload=item.firstChildElement())) d = self.publish(client, service, nodeIdentifier, parsed_items) d.addCallback(self._publishCb) @@ -538,15 +538,15 @@ def _unwrapMAMMessage(self, message_elt): try: item_elt = ( - message_elt.elements(mam.NS_MAM, "result").next() + next(message_elt.elements(mam.NS_MAM, "result").next() .elements(C.NS_FORWARD, "forwarded").next() .elements(C.NS_CLIENT, "message").next() .elements("http://jabber.org/protocol/pubsub#event", "event").next() .elements("http://jabber.org/protocol/pubsub#event", "items").next() - .elements("http://jabber.org/protocol/pubsub#event", "item").next() + .elements("http://jabber.org/protocol/pubsub#event", "item")) ) except StopIteration: - raise exceptions.DataError(u"Can't find Item in MAM message element") + raise exceptions.DataError("Can't find Item in MAM message element") return item_elt def _getItems(self, service="", node="", max_items=10, item_ids=None, sub_id=None, @@ -593,7 +593,7 @@ if item_ids and max_items is not None: max_items = None if rsm_request and item_ids: - raise ValueError(u"items_id can't be used with rsm") + raise ValueError("items_id can't be used with rsm") if extra is None: extra = {} try: @@ -616,23 +616,23 @@ else: # if mam is requested, we have to do a totally different query if self._mam is None: - raise exceptions.NotFound(u"MAM (XEP-0313) plugin is not available") + raise exceptions.NotFound("MAM (XEP-0313) plugin is not available") if max_items is not None: - raise exceptions.DataError(u"max_items parameter can't be used with MAM") + raise exceptions.DataError("max_items parameter can't be used with MAM") if item_ids: - raise exceptions.DataError(u"items_ids parameter can't be used with MAM") + raise exceptions.DataError("items_ids parameter can't be used with MAM") if mam_query.node is None: mam_query.node = node elif mam_query.node != node: raise exceptions.DataError( - u"MAM query node is incoherent with getItems's node" + "MAM query node is incoherent with getItems's node" ) if mam_query.rsm is None: mam_query.rsm = rsm_request else: if mam_query.rsm != rsm_request: raise exceptions.DataError( - u"Conflict between RSM request and MAM's RSM request" + "Conflict between RSM request and MAM's RSM request" ) d = self._mam.getArchives(client, mam_query, service, self._unwrapMAMMessage) @@ -644,8 +644,8 @@ def subscribeEb(failure, service, node): failure.trap(error.StanzaError) log.warning( - u"Could not subscribe to node {} on service {}: {}".format( - node, unicode(service), unicode(failure.value) + "Could not subscribe to node {} on service {}: {}".format( + node, str(service), str(failure.value) ) ) @@ -670,13 +670,13 @@ if rsm_request is not None and rsm_response is not None: metadata.update( { - u"rsm_" + key: value - for key, value in rsm_response.toDict().iteritems() + "rsm_" + key: value + for key, value in rsm_response.toDict().items() } ) if mam_response is not None: - for key, value in mam_response.iteritems(): - metadata[u"mam_" + key] = value + for key, value in mam_response.items(): + metadata["mam_" + key] = value return (items, metadata) d.addCallback(addMetadata) @@ -758,7 +758,7 @@ def serialize(form): # FIXME: better more generic dataform serialisation should be available in SàT - return {f.var: unicode(f.value) for f in form.fields.values()} + return {f.var: str(f.value) for f in list(form.fields.values())} d.addCallback(serialize) return d @@ -822,7 +822,7 @@ ) except StopIteration: raise ValueError( - _(u"Invalid result: missing <affiliations> element: {}").format( + _("Invalid result: missing <affiliations> element: {}").format( iq_elt.toXml ) ) @@ -833,7 +833,7 @@ } except KeyError: raise ValueError( - _(u"Invalid result: bad <affiliation> element: {}").format( + _("Invalid result: bad <affiliation> element: {}").format( iq_elt.toXml ) ) @@ -848,7 +848,7 @@ client, jid.JID(service_s) if service_s else None, nodeIdentifier ) d.addCallback( - lambda affiliations: {j.full(): a for j, a in affiliations.iteritems()} + lambda affiliations: {j.full(): a for j, a in affiliations.items()} ) return d @@ -865,7 +865,7 @@ ) except StopIteration: raise ValueError( - _(u"Invalid result: missing <affiliations> element: {}").format( + _("Invalid result: missing <affiliations> element: {}").format( iq_elt.toXml ) ) @@ -878,7 +878,7 @@ } except KeyError: raise ValueError( - _(u"Invalid result: bad <affiliation> element: {}").format( + _("Invalid result: bad <affiliation> element: {}").format( iq_elt.toXml ) ) @@ -892,7 +892,7 @@ ): client = self.host.getClient(profile_key) affiliations = { - jid.JID(jid_): affiliation for jid_, affiliation in affiliations.iteritems() + jid.JID(jid_): affiliation for jid_, affiliation in affiliations.items() } d = self.setNodeAffiliations( client, @@ -986,7 +986,7 @@ client = self.host.getClient(profile_key) service = None if not service else jid.JID(service) d = self.subscribe(client, service, nodeIdentifier, options=options or None) - d.addCallback(lambda subscription: subscription.subscriptionIdentifier or u"") + d.addCallback(lambda subscription: subscription.subscriptionIdentifier or "") return d def subscribe(self, client, service, nodeIdentifier, sub_jid=None, options=None): @@ -1065,8 +1065,8 @@ if item is not None: query_data.append(("item", item.encode("utf-8"))) return "xmpp:{service}?;{query}".format( - service=service.userhost(), query=urllib.urlencode(query_data) - ).decode("utf-8") + service=service.userhost(), query=urllib.parse.urlencode(query_data) + ) ## methods to manage several stanzas/jids at once ## @@ -1099,7 +1099,7 @@ return ( items, - {key: unicode(value) for key, value in metadata.iteritems()}, + {key: str(value) for key, value in metadata.items()}, ) def transItemsDataD(self, items_data, item_cb, serialise=False): @@ -1122,7 +1122,7 @@ def eb(failure): log.warning( - "Error while serialising/parsing item: {}".format(unicode(failure.value)) + "Error while serialising/parsing item: {}".format(str(failure.value)) ) d = defer.gatherResults([item_cb(item).addErrback(eb) for item in items]) @@ -1135,7 +1135,7 @@ return ( items, - {key: unicode(value) for key, value in metadata.iteritems()}, + {key: str(value) for key, value in metadata.items()}, ) d.addCallback(finishSerialisation) @@ -1156,7 +1156,7 @@ return [ ("", result) if success - else (unicode(result.result) or UNSPECIFIED, failure_result) + else (str(result.result) or UNSPECIFIED, failure_result) for success, result in results ] @@ -1168,7 +1168,7 @@ client, jid.JID(service_s) if service_s else None, nodeIdentifier ) d.addCallback( - lambda subscriptions: {j.full(): a for j, a in subscriptions.iteritems()} + lambda subscriptions: {j.full(): a for j, a in subscriptions.items()} ) return d @@ -1190,12 +1190,12 @@ ) except StopIteration: raise ValueError( - _(u"Invalid result: missing <subscriptions> element: {}").format( + _("Invalid result: missing <subscriptions> element: {}").format( iq_elt.toXml ) ) except AttributeError as e: - raise ValueError(_(u"Invalid result: {}").format(e)) + raise ValueError(_("Invalid result: {}").format(e)) try: return { jid.JID(s["jid"]): s["subscription"] @@ -1205,7 +1205,7 @@ } except KeyError: raise ValueError( - _(u"Invalid result: bad <subscription> element: {}").format( + _("Invalid result: bad <subscription> element: {}").format( iq_elt.toXml ) ) @@ -1220,7 +1220,7 @@ client = self.host.getClient(profile_key) subscriptions = { jid.JID(jid_): subscription - for jid_, subscription in subscriptions.iteritems() + for jid_, subscription in subscriptions.items() } d = self.setNodeSubscriptions( client, @@ -1241,7 +1241,7 @@ request.nodeIdentifier = nodeIdentifier request.subscriptions = { pubsub.Subscription(nodeIdentifier, jid_, state) - for jid_, state in subscriptions.iteritems() + for jid_, state in subscriptions.items() } d = request.send(client.xmlstream) return d @@ -1262,7 +1262,7 @@ d = self.rt_sessions.getResults( session_id, on_success=lambda result: "", - on_error=lambda failure: unicode(failure.value), + on_error=lambda failure: str(failure.value), profile=profile, ) # we need to convert jid.JID to unicode with full() to serialise it for the bridge @@ -1271,7 +1271,7 @@ ret[0], [ (service.full(), node, "" if success else failure or UNSPECIFIED) - for (service, node), (success, failure) in ret[1].iteritems() + for (service, node), (success, failure) in ret[1].items() ], ) ) @@ -1281,7 +1281,7 @@ self, node_data, subscriber=None, options=None, profile_key=C.PROF_KEY_NONE ): return self.subscribeToMany( - [(jid.JID(service), unicode(node)) for service, node in node_data], + [(jid.JID(service), str(node)) for service, node in node_data], jid.JID(subscriber), options, profile_key, @@ -1337,7 +1337,7 @@ d = self.rt_sessions.getResults( session_id, on_success=lambda result: ("", self.transItemsData(result)), - on_error=lambda failure: (unicode(failure.value) or UNSPECIFIED, ([], {})), + on_error=lambda failure: (str(failure.value) or UNSPECIFIED, ([], {})), profile=profile, ) d.addCallback( @@ -1347,7 +1347,7 @@ (service.full(), node, failure, items, metadata) for (service, node), (success, (failure, (items, metadata))) in ret[ 1 - ].iteritems() + ].items() ], ) ) @@ -1362,7 +1362,7 @@ max_item = None if max_item == C.NO_LIMIT else max_item extra = self.parseExtra(extra_dict) return self.getFromMany( - [(jid.JID(service), unicode(node)) for service, node in node_data], + [(jid.JID(service), str(node)) for service, node in node_data], max_item, extra.rsm_request, extra.extra, @@ -1390,8 +1390,8 @@ return self.rt_sessions.newSession(deferreds, client.profile) +@implementer(disco.IDisco) class SatPubSubClient(rsm.PubSubClient): - implements(disco.IDisco) def __init__(self, host, parent_plugin): self.host = host @@ -1409,7 +1409,7 @@ @param event(unicode): one of C.PS_ITEMS, C.PS_RETRACT, C.PS_DELETE @return (iterator[callable]): callbacks for this node/event """ - for registered_node, callbacks_dict in self.parent_plugin._node_cb.iteritems(): + for registered_node, callbacks_dict in self.parent_plugin._node_cb.items(): if not node.startswith(registered_node): continue try: @@ -1420,7 +1420,7 @@ def itemsReceived(self, event): - log.debug(u"Pubsub items received") + log.debug("Pubsub items received") for callback in self._getNodeCallbacks(event.nodeIdentifier, C.PS_ITEMS): callback(self.parent, event) client = self.parent @@ -1435,7 +1435,7 @@ ) def deleteReceived(self, event): - log.debug((u"Publish node deleted")) + log.debug(("Publish node deleted")) for callback in self._getNodeCallbacks(event.nodeIdentifier, C.PS_DELETE): callback(self.parent, event) client = self.parent