Mercurial > libervia-backend
comparison sat/plugins/plugin_exp_pubsub_hook.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 | 003b8b4b56a7 |
children | 9d0df638c8b4 |
comparison
equal
deleted
inserted
replaced
3027:ff5bcb12ae60 | 3028:ab2696e34d29 |
---|---|
1 #!/usr/bin/env python2 | 1 #!/usr/bin/env python3 |
2 # -*- coding: utf-8 -*- | 2 # -*- coding: utf-8 -*- |
3 | 3 |
4 # SAT plugin for Pubsub Hooks | 4 # SAT plugin for Pubsub Hooks |
5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org) | 5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org) |
6 | 6 |
41 """Experimental plugin to launch on action on Pubsub notifications""" | 41 """Experimental plugin to launch on action on Pubsub notifications""" |
42 ), | 42 ), |
43 } | 43 } |
44 | 44 |
45 # python module | 45 # python module |
46 HOOK_TYPE_PYTHON = u"python" | 46 HOOK_TYPE_PYTHON = "python" |
47 # python file path | 47 # python file path |
48 HOOK_TYPE_PYTHON_FILE = u"python_file" | 48 HOOK_TYPE_PYTHON_FILE = "python_file" |
49 # python code directly | 49 # python code directly |
50 HOOK_TYPE_PYTHON_CODE = u"python_code" | 50 HOOK_TYPE_PYTHON_CODE = "python_code" |
51 HOOK_TYPES = (HOOK_TYPE_PYTHON, HOOK_TYPE_PYTHON_FILE, HOOK_TYPE_PYTHON_CODE) | 51 HOOK_TYPES = (HOOK_TYPE_PYTHON, HOOK_TYPE_PYTHON_FILE, HOOK_TYPE_PYTHON_CODE) |
52 | 52 |
53 | 53 |
54 class PubsubHook(object): | 54 class PubsubHook(object): |
55 def __init__(self, host): | 55 def __init__(self, host): |
56 log.info(_(u"PubSub Hook initialization")) | 56 log.info(_("PubSub Hook initialization")) |
57 self.host = host | 57 self.host = host |
58 self.node_hooks = {} # keep track of the number of hooks per node (for all profiles) | 58 self.node_hooks = {} # keep track of the number of hooks per node (for all profiles) |
59 host.bridge.addMethod( | 59 host.bridge.addMethod( |
60 "psHookAdd", ".plugin", in_sign="ssssbs", out_sign="", method=self._addHook | 60 "psHookAdd", ".plugin", in_sign="ssssbs", out_sign="", method=self._addHook |
61 ) | 61 ) |
88 for node in client._hooks: | 88 for node in client._hooks: |
89 self._removeNodeManager(client, node) | 89 self._removeNodeManager(client, node) |
90 | 90 |
91 def _installNodeManager(self, client, node): | 91 def _installNodeManager(self, client, node): |
92 if node in self.node_hooks: | 92 if node in self.node_hooks: |
93 log.debug(_(u"node manager already set for {node}").format(node=node)) | 93 log.debug(_("node manager already set for {node}").format(node=node)) |
94 self.node_hooks[node] += 1 | 94 self.node_hooks[node] += 1 |
95 else: | 95 else: |
96 # first hook on this node | 96 # first hook on this node |
97 self.host.plugins["XEP-0060"].addManagedNode( | 97 self.host.plugins["XEP-0060"].addManagedNode( |
98 node, items_cb=self._itemsReceived | 98 node, items_cb=self._itemsReceived |
99 ) | 99 ) |
100 self.node_hooks[node] = 0 | 100 self.node_hooks[node] = 0 |
101 log.info(_(u"node manager installed on {node}").format(node=node)) | 101 log.info(_("node manager installed on {node}").format(node=node)) |
102 | 102 |
103 def _removeNodeManager(self, client, node): | 103 def _removeNodeManager(self, client, node): |
104 try: | 104 try: |
105 self.node_hooks[node] -= 1 | 105 self.node_hooks[node] -= 1 |
106 except KeyError: | 106 except KeyError: |
107 log.error(_(u"trying to remove a {node} without hook").format(node=node)) | 107 log.error(_("trying to remove a {node} without hook").format(node=node)) |
108 else: | 108 else: |
109 if self.node_hooks[node] == 0: | 109 if self.node_hooks[node] == 0: |
110 del self.node_hooks[node] | 110 del self.node_hooks[node] |
111 self.host.plugins["XEP-0060"].removeManagedNode(node, self._itemsReceived) | 111 self.host.plugins["XEP-0060"].removeManagedNode(node, self._itemsReceived) |
112 log.debug(_(u"hook removed")) | 112 log.debug(_("hook removed")) |
113 else: | 113 else: |
114 log.debug(_(u"node still needed for an other hook")) | 114 log.debug(_("node still needed for an other hook")) |
115 | 115 |
116 def installHook(self, client, service, node, hook_type, hook_arg, persistent): | 116 def installHook(self, client, service, node, hook_type, hook_arg, persistent): |
117 if hook_type not in HOOK_TYPES: | 117 if hook_type not in HOOK_TYPES: |
118 raise exceptions.DataError( | 118 raise exceptions.DataError( |
119 _(u"{hook_type} is not handled").format(hook_type=hook_type) | 119 _("{hook_type} is not handled").format(hook_type=hook_type) |
120 ) | 120 ) |
121 if hook_type != HOOK_TYPE_PYTHON_FILE: | 121 if hook_type != HOOK_TYPE_PYTHON_FILE: |
122 raise NotImplementedError( | 122 raise NotImplementedError( |
123 _(u"{hook_type} hook type not implemented yet").format( | 123 _("{hook_type} hook type not implemented yet").format( |
124 hook_type=hook_type | 124 hook_type=hook_type |
125 ) | 125 ) |
126 ) | 126 ) |
127 self._installNodeManager(client, node) | 127 self._installNodeManager(client, node) |
128 hook_data = {"service": service, "type": hook_type, "arg": hook_arg} | 128 hook_data = {"service": service, "type": hook_type, "arg": hook_arg} |
134 else: | 134 else: |
135 hooks_list = client._hooks_temporary.setdefault(node, []) | 135 hooks_list = client._hooks_temporary.setdefault(node, []) |
136 hooks_list.append(hook_data) | 136 hooks_list.append(hook_data) |
137 | 137 |
138 log.info( | 138 log.info( |
139 _(u"{persistent} hook installed on {node} for {profile}").format( | 139 _("{persistent} hook installed on {node} for {profile}").format( |
140 persistent=_(u"persistent") if persistent else _(u"temporary"), | 140 persistent=_("persistent") if persistent else _("temporary"), |
141 node=node, | 141 node=node, |
142 profile=client.profile, | 142 profile=client.profile, |
143 ) | 143 ) |
144 ) | 144 ) |
145 | 145 |
158 # first time we get this hook, we create the callback | 158 # first time we get this hook, we create the callback |
159 hook_type = hook_data["type"] | 159 hook_type = hook_data["type"] |
160 try: | 160 try: |
161 if hook_type == HOOK_TYPE_PYTHON_FILE: | 161 if hook_type == HOOK_TYPE_PYTHON_FILE: |
162 hook_globals = {} | 162 hook_globals = {} |
163 execfile(hook_data["arg"], hook_globals) | 163 exec(compile(open(hook_data["arg"], "rb").read(), hook_data["arg"], 'exec'), hook_globals) |
164 callback = hook_globals["hook"] | 164 callback = hook_globals["hook"] |
165 else: | 165 else: |
166 raise NotImplementedError( | 166 raise NotImplementedError( |
167 _(u"{hook_type} hook type not implemented yet").format( | 167 _("{hook_type} hook type not implemented yet").format( |
168 hook_type=hook_type | 168 hook_type=hook_type |
169 ) | 169 ) |
170 ) | 170 ) |
171 except Exception as e: | 171 except Exception as e: |
172 log.warning( | 172 log.warning( |
173 _( | 173 _( |
174 u"Can't load Pubsub hook at node {node}, it will be removed: {reason}" | 174 "Can't load Pubsub hook at node {node}, it will be removed: {reason}" |
175 ).format(node=node, reason=e) | 175 ).format(node=node, reason=e) |
176 ) | 176 ) |
177 hooks_list.remove(hook_data) | 177 hooks_list.remove(hook_data) |
178 continue | 178 continue |
179 | 179 |
181 try: | 181 try: |
182 callback(self.host, client, item) | 182 callback(self.host, client, item) |
183 except Exception as e: | 183 except Exception as e: |
184 log.warning( | 184 log.warning( |
185 _( | 185 _( |
186 u"Error while running Pubsub hook for node {node}: {msg}" | 186 "Error while running Pubsub hook for node {node}: {msg}" |
187 ).format(node=node, msg=e) | 187 ).format(node=node, msg=e) |
188 ) | 188 ) |
189 | 189 |
190 def _addHook(self, service, node, hook_type, hook_arg, persistent, profile): | 190 def _addHook(self, service, node, hook_type, hook_arg, persistent, profile): |
191 client = self.host.getClient(profile) | 191 client = self.host.getClient(profile) |
192 service = jid.JID(service) if service else client.jid.userhostJID() | 192 service = jid.JID(service) if service else client.jid.userhostJID() |
193 return self.addHook( | 193 return self.addHook( |
194 client, | 194 client, |
195 service, | 195 service, |
196 unicode(node), | 196 str(node), |
197 unicode(hook_type), | 197 str(hook_type), |
198 unicode(hook_arg), | 198 str(hook_arg), |
199 persistent, | 199 persistent, |
200 ) | 200 ) |
201 | 201 |
202 def addHook(self, client, service, node, hook_type, hook_arg, persistent): | 202 def addHook(self, client, service, node, hook_type, hook_arg, persistent): |
203 r"""Add a hook which will be triggered on a pubsub notification | 203 r"""Add a hook which will be triggered on a pubsub notification |
240 removed = 0 | 240 removed = 0 |
241 for hooks in (client._hooks, client._hooks_temporary): | 241 for hooks in (client._hooks, client._hooks_temporary): |
242 if node in hooks: | 242 if node in hooks: |
243 for hook_data in hooks[node]: | 243 for hook_data in hooks[node]: |
244 if ( | 244 if ( |
245 service != hook_data[u"service"] | 245 service != hook_data["service"] |
246 or hook_type is not None | 246 or hook_type is not None |
247 and hook_type != hook_data[u"type"] | 247 and hook_type != hook_data["type"] |
248 or hook_arg is not None | 248 or hook_arg is not None |
249 and hook_arg != hook_data[u"arg"] | 249 and hook_arg != hook_data["arg"] |
250 ): | 250 ): |
251 continue | 251 continue |
252 hooks[node].remove(hook_data) | 252 hooks[node].remove(hook_data) |
253 removed += 1 | 253 removed += 1 |
254 if not hooks[node]: | 254 if not hooks[node]: |
261 return removed | 261 return removed |
262 | 262 |
263 def _listHooks(self, profile): | 263 def _listHooks(self, profile): |
264 hooks_list = self.listHooks(self.host.getClient(profile)) | 264 hooks_list = self.listHooks(self.host.getClient(profile)) |
265 for hook in hooks_list: | 265 for hook in hooks_list: |
266 hook[u"service"] = hook[u"service"].full() | 266 hook["service"] = hook["service"].full() |
267 hook[u"persistent"] = C.boolConst(hook[u"persistent"]) | 267 hook["persistent"] = C.boolConst(hook["persistent"]) |
268 return hooks_list | 268 return hooks_list |
269 | 269 |
270 def listHooks(self, client): | 270 def listHooks(self, client): |
271 """return list of registered hooks""" | 271 """return list of registered hooks""" |
272 hooks_list = [] | 272 hooks_list = [] |
273 for hooks in (client._hooks, client._hooks_temporary): | 273 for hooks in (client._hooks, client._hooks_temporary): |
274 persistent = hooks is client._hooks | 274 persistent = hooks is client._hooks |
275 for node, hooks_data in hooks.iteritems(): | 275 for node, hooks_data in hooks.items(): |
276 for hook_data in hooks_data: | 276 for hook_data in hooks_data: |
277 hooks_list.append( | 277 hooks_list.append( |
278 { | 278 { |
279 u"service": hook_data[u"service"], | 279 "service": hook_data["service"], |
280 u"node": node, | 280 "node": node, |
281 u"type": hook_data[u"type"], | 281 "type": hook_data["type"], |
282 u"arg": hook_data[u"arg"], | 282 "arg": hook_data["arg"], |
283 u"persistent": persistent, | 283 "persistent": persistent, |
284 } | 284 } |
285 ) | 285 ) |
286 return hooks_list | 286 return hooks_list |