comparison sat/plugins/plugin_exp_pubsub_hook.py @ 2624:56f94936df1e

code style reformatting using black
author Goffi <goffi@goffi.org>
date Wed, 27 Jun 2018 20:14:46 +0200
parents 26edcf3a30eb
children 003b8b4b56a7
comparison
equal deleted inserted replaced
2623:49533de4540b 2624:56f94936df1e
22 from sat.core import exceptions 22 from sat.core import exceptions
23 from sat.core.log import getLogger 23 from sat.core.log import getLogger
24 from sat.memory import persistent 24 from sat.memory import persistent
25 from twisted.words.protocols.jabber import jid 25 from twisted.words.protocols.jabber import jid
26 from twisted.internet import defer 26 from twisted.internet import defer
27
27 log = getLogger(__name__) 28 log = getLogger(__name__)
28 29
29 NS_PUBSUB_HOOK = 'PUBSUB_HOOK' 30 NS_PUBSUB_HOOK = "PUBSUB_HOOK"
30 31
31 PLUGIN_INFO = { 32 PLUGIN_INFO = {
32 C.PI_NAME: "PubSub Hook", 33 C.PI_NAME: "PubSub Hook",
33 C.PI_IMPORT_NAME: NS_PUBSUB_HOOK, 34 C.PI_IMPORT_NAME: NS_PUBSUB_HOOK,
34 C.PI_TYPE: "EXP", 35 C.PI_TYPE: "EXP",
35 C.PI_PROTOCOLS: [], 36 C.PI_PROTOCOLS: [],
36 C.PI_DEPENDENCIES: ["XEP-0060"], 37 C.PI_DEPENDENCIES: ["XEP-0060"],
37 C.PI_MAIN: "PubsubHook", 38 C.PI_MAIN: "PubsubHook",
38 C.PI_HANDLER: "no", 39 C.PI_HANDLER: "no",
39 C.PI_DESCRIPTION: _("""Experimental plugin to launch on action on Pubsub notifications""") 40 C.PI_DESCRIPTION: _(
41 """Experimental plugin to launch on action on Pubsub notifications"""
42 ),
40 } 43 }
41 44
42 # python module 45 #  python module
43 HOOK_TYPE_PYTHON = u'python' 46 HOOK_TYPE_PYTHON = u"python"
44 # python file path 47 # python file path
45 HOOK_TYPE_PYTHON_FILE = u'python_file' 48 HOOK_TYPE_PYTHON_FILE = u"python_file"
46 # python code directly 49 # python code directly
47 HOOK_TYPE_PYTHON_CODE = u'python_code' 50 HOOK_TYPE_PYTHON_CODE = u"python_code"
48 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)
49 52
50 53
51 class PubsubHook(object): 54 class PubsubHook(object):
52
53 def __init__(self, host): 55 def __init__(self, host):
54 log.info(_(u"PubSub Hook initialization")) 56 log.info(_(u"PubSub Hook initialization"))
55 self.host = host 57 self.host = host
56 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)
57 host.bridge.addMethod("psHookAdd", ".plugin", 59 host.bridge.addMethod(
58 in_sign='ssssbs', out_sign='', 60 "psHookAdd", ".plugin", in_sign="ssssbs", out_sign="", method=self._addHook
59 method=self._addHook 61 )
60 ) 62 host.bridge.addMethod(
61 host.bridge.addMethod("psHookRemove", ".plugin", 63 "psHookRemove",
62 in_sign='sssss', out_sign='i', 64 ".plugin",
63 method=self._removeHook 65 in_sign="sssss",
64 ) 66 out_sign="i",
65 host.bridge.addMethod("psHookList", ".plugin", 67 method=self._removeHook,
66 in_sign='s', out_sign='aa{ss}', 68 )
67 method=self._listHooks 69 host.bridge.addMethod(
68 ) 70 "psHookList",
71 ".plugin",
72 in_sign="s",
73 out_sign="aa{ss}",
74 method=self._listHooks,
75 )
69 76
70 @defer.inlineCallbacks 77 @defer.inlineCallbacks
71 def profileConnected(self, client): 78 def profileConnected(self, client):
72 hooks = client._hooks = persistent.PersistentBinaryDict(NS_PUBSUB_HOOK, client.profile) 79 hooks = client._hooks = persistent.PersistentBinaryDict(
80 NS_PUBSUB_HOOK, client.profile
81 )
73 client._hooks_temporary = {} 82 client._hooks_temporary = {}
74 yield hooks.load() 83 yield hooks.load()
75 for node in hooks: 84 for node in hooks:
76 self._installNodeManager(client, node) 85 self._installNodeManager(client, node)
77 86
83 if node in self.node_hooks: 92 if node in self.node_hooks:
84 log.debug(_(u"node manager already set for {node}").format(node=node)) 93 log.debug(_(u"node manager already set for {node}").format(node=node))
85 self.node_hooks[node] += 1 94 self.node_hooks[node] += 1
86 else: 95 else:
87 # first hook on this node 96 # first hook on this node
88 self.host.plugins['XEP-0060'].addManagedNode(node, items_cb=self._itemsReceived) 97 self.host.plugins["XEP-0060"].addManagedNode(
98 node, items_cb=self._itemsReceived
99 )
89 self.node_hooks[node] = 0 100 self.node_hooks[node] = 0
90 log.info(_(u"node manager installed on {node}").format( 101 log.info(_(u"node manager installed on {node}").format(node=node))
91 node = node))
92 102
93 def _removeNodeManager(self, client, node): 103 def _removeNodeManager(self, client, node):
94 try: 104 try:
95 self.node_hooks[node] -= 1 105 self.node_hooks[node] -= 1
96 except KeyError: 106 except KeyError:
97 log.error(_(u"trying to remove a {node} without hook").format(node=node)) 107 log.error(_(u"trying to remove a {node} without hook").format(node=node))
98 else: 108 else:
99 if self.node_hooks[node] == 0: 109 if self.node_hooks[node] == 0:
100 del self.node_hooks[node] 110 del self.node_hooks[node]
101 self.host.plugins['XEP-0060'].removeManagedNode(node, self._itemsReceived) 111 self.host.plugins["XEP-0060"].removeManagedNode(node, self._itemsReceived)
102 log.debug(_(u"hook removed")) 112 log.debug(_(u"hook removed"))
103 else: 113 else:
104 log.debug(_(u"node still needed for an other hook")) 114 log.debug(_(u"node still needed for an other hook"))
105 115
106 def installHook(self, client, service, node, hook_type, hook_arg, persistent): 116 def installHook(self, client, service, node, hook_type, hook_arg, persistent):
107 if hook_type not in HOOK_TYPES: 117 if hook_type not in HOOK_TYPES:
108 raise exceptions.DataError(_(u'{hook_type} is not handled').format(hook_type=hook_type)) 118 raise exceptions.DataError(
119 _(u"{hook_type} is not handled").format(hook_type=hook_type)
120 )
109 if hook_type != HOOK_TYPE_PYTHON_FILE: 121 if hook_type != HOOK_TYPE_PYTHON_FILE:
110 raise NotImplementedError(_(u'{hook_type} hook type not implemented yet').format(hook_type=hook_type)) 122 raise NotImplementedError(
123 _(u"{hook_type} hook type not implemented yet").format(
124 hook_type=hook_type
125 )
126 )
111 self._installNodeManager(client, node) 127 self._installNodeManager(client, node)
112 hook_data = {'service': service, 128 hook_data = {"service": service, "type": hook_type, "arg": hook_arg}
113 'type': hook_type,
114 'arg': hook_arg
115 }
116 129
117 if persistent: 130 if persistent:
118 hooks_list = client._hooks.setdefault(node,[]) 131 hooks_list = client._hooks.setdefault(node, [])
119 hooks_list.append(hook_data) 132 hooks_list.append(hook_data)
120 client._hooks.force(node) 133 client._hooks.force(node)
121 else: 134 else:
122 hooks_list = client._hooks_temporary.setdefault(node,[]) 135 hooks_list = client._hooks_temporary.setdefault(node, [])
123 hooks_list.append(hook_data) 136 hooks_list.append(hook_data)
124 137
125 log.info(_(u"{persistent} hook installed on {node} for {profile}").format( 138 log.info(
126 persistent = _(u'persistent') if persistent else _(u'temporary'), 139 _(u"{persistent} hook installed on {node} for {profile}").format(
127 node = node, 140 persistent=_(u"persistent") if persistent else _(u"temporary"),
128 profile = client.profile)) 141 node=node,
142 profile=client.profile,
143 )
144 )
129 145
130 def _itemsReceived(self, client, itemsEvent): 146 def _itemsReceived(self, client, itemsEvent):
131 node = itemsEvent.nodeIdentifier 147 node = itemsEvent.nodeIdentifier
132 for hooks in (client._hooks, client._hooks_temporary): 148 for hooks in (client._hooks, client._hooks_temporary):
133 if node not in hooks: 149 if node not in hooks:
134 continue 150 continue
135 hooks_list = hooks[node] 151 hooks_list = hooks[node]
136 for hook_data in hooks_list[:]: 152 for hook_data in hooks_list[:]:
137 if hook_data['service'] != itemsEvent.sender.userhostJID(): 153 if hook_data["service"] != itemsEvent.sender.userhostJID():
138 continue 154 continue
139 try: 155 try:
140 callback = hook_data['callback'] 156 callback = hook_data["callback"]
141 except KeyError: 157 except KeyError:
142 # first time we get this hook, we create the callback 158 # first time we get this hook, we create the callback
143 hook_type = hook_data['type'] 159 hook_type = hook_data["type"]
144 try: 160 try:
145 if hook_type == HOOK_TYPE_PYTHON_FILE: 161 if hook_type == HOOK_TYPE_PYTHON_FILE:
146 hook_globals = {} 162 hook_globals = {}
147 execfile(hook_data['arg'], hook_globals) 163 execfile(hook_data["arg"], hook_globals)
148 callback = hook_globals['hook'] 164 callback = hook_globals["hook"]
149 else: 165 else:
150 raise NotImplementedError(_(u'{hook_type} hook type not implemented yet').format( 166 raise NotImplementedError(
151 hook_type=hook_type)) 167 _(u"{hook_type} hook type not implemented yet").format(
168 hook_type=hook_type
169 )
170 )
152 except Exception as e: 171 except Exception as e:
153 log.warning(_(u"Can't load Pubsub hook at node {node}, it will be removed: {reason}").format( 172 log.warning(
154 node=node, reason=e)) 173 _(
174 u"Can't load Pubsub hook at node {node}, it will be removed: {reason}"
175 ).format(node=node, reason=e)
176 )
155 hooks_list.remove(hook_data) 177 hooks_list.remove(hook_data)
156 continue 178 continue
157 179
158 for item in itemsEvent.items: 180 for item in itemsEvent.items:
159 try: 181 try:
160 callback(self.host, client, item) 182 callback(self.host, client, item)
161 except Exception as e: 183 except Exception as e:
162 log.warning(_(u"Error while running Pubsub hook for node {node}: {msg}").format( 184 log.warning(
163 node = node, 185 _(
164 msg = e)) 186 u"Error while running Pubsub hook for node {node}: {msg}"
187 ).format(node=node, msg=e)
188 )
165 189
166 def _addHook(self, service, node, hook_type, hook_arg, persistent, profile): 190 def _addHook(self, service, node, hook_type, hook_arg, persistent, profile):
167 client = self.host.getClient(profile) 191 client = self.host.getClient(profile)
168 service = jid.JID(service) if service else client.jid.userhostJID() 192 service = jid.JID(service) if service else client.jid.userhostJID()
169 return self.addHook(client, service, unicode(node), unicode(hook_type), unicode(hook_arg), persistent) 193 return self.addHook(
194 client,
195 service,
196 unicode(node),
197 unicode(hook_type),
198 unicode(hook_arg),
199 persistent,
200 )
170 201
171 def addHook(self, client, service, node, hook_type, hook_arg, persistent): 202 def addHook(self, client, service, node, hook_type, hook_arg, persistent):
172 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
173 204
174 @param service(jid.JID): service of the node 205 @param service(jid.JID): service of the node
208 """ 239 """
209 removed = 0 240 removed = 0
210 for hooks in (client._hooks, client._hooks_temporary): 241 for hooks in (client._hooks, client._hooks_temporary):
211 if node in hooks: 242 if node in hooks:
212 for hook_data in hooks[node]: 243 for hook_data in hooks[node]:
213 if (service != hook_data[u'service'] 244 if (
214 or hook_type is not None and hook_type != hook_data[u'type'] 245 service != hook_data[u"service"]
215 or hook_arg is not None and hook_arg != hook_data[u'arg']): 246 or hook_type is not None
247 and hook_type != hook_data[u"type"]
248 or hook_arg is not None
249 and hook_arg != hook_data[u"arg"]
250 ):
216 continue 251 continue
217 hooks[node].remove(hook_data) 252 hooks[node].remove(hook_data)
218 removed += 1 253 removed += 1
219 if not hooks[node]: 254 if not hooks[node]:
220 # no more hooks, we can remove the node 255 #  no more hooks, we can remove the node
221 del hooks[node] 256 del hooks[node]
222 self._removeNodeManager(client, node) 257 self._removeNodeManager(client, node)
223 else: 258 else:
224 if hooks == client._hooks: 259 if hooks == client._hooks:
225 hooks.force(node) 260 hooks.force(node)
226 return removed 261 return removed
227 262
228 def _listHooks(self, profile): 263 def _listHooks(self, profile):
229 hooks_list = self.listHooks(self.host.getClient(profile)) 264 hooks_list = self.listHooks(self.host.getClient(profile))
230 for hook in hooks_list: 265 for hook in hooks_list:
231 hook[u'service'] = hook[u'service'].full() 266 hook[u"service"] = hook[u"service"].full()
232 hook[u'persistent'] = C.boolConst(hook[u'persistent']) 267 hook[u"persistent"] = C.boolConst(hook[u"persistent"])
233 return hooks_list 268 return hooks_list
234 269
235 def listHooks(self, client): 270 def listHooks(self, client):
236 """return list of registered hooks""" 271 """return list of registered hooks"""
237 hooks_list = [] 272 hooks_list = []
238 for hooks in (client._hooks, client._hooks_temporary): 273 for hooks in (client._hooks, client._hooks_temporary):
239 persistent = hooks is client._hooks 274 persistent = hooks is client._hooks
240 for node, hooks_data in hooks.iteritems(): 275 for node, hooks_data in hooks.iteritems():
241 for hook_data in hooks_data: 276 for hook_data in hooks_data:
242 hooks_list.append({u'service': hook_data[u'service'], 277 hooks_list.append(
243 u'node': node, 278 {
244 u'type': hook_data[u'type'], 279 u"service": hook_data[u"service"],
245 u'arg': hook_data[u'arg'], 280 u"node": node,
246 u'persistent': persistent 281 u"type": hook_data[u"type"],
247 }) 282 u"arg": hook_data[u"arg"],
283 u"persistent": persistent,
284 }
285 )
248 return hooks_list 286 return hooks_list
249