Mercurial > libervia-backend
comparison sat/plugins/plugin_adhoc_dbus.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 | 8dd9db785ac8 |
comparison
equal
deleted
inserted
replaced
2623:49533de4540b | 2624:56f94936df1e |
---|---|
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. | 18 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 | 19 |
20 from sat.core.i18n import _ | 20 from sat.core.i18n import _ |
21 from sat.core.constants import Const as C | 21 from sat.core.constants import Const as C |
22 from sat.core.log import getLogger | 22 from sat.core.log import getLogger |
23 | |
23 log = getLogger(__name__) | 24 log = getLogger(__name__) |
24 from sat.core import exceptions | 25 from sat.core import exceptions |
25 from twisted.internet import defer | 26 from twisted.internet import defer |
26 from wokkel import data_form | 27 from wokkel import data_form |
28 | |
27 try: | 29 try: |
28 from lxml import etree | 30 from lxml import etree |
29 except ImportError: | 31 except ImportError: |
30 raise exceptions.MissingModule(u"Missing module lxml, please download/install it from http://lxml.de/") | 32 raise exceptions.MissingModule( |
33 u"Missing module lxml, please download/install it from http://lxml.de/" | |
34 ) | |
31 import os.path | 35 import os.path |
32 import uuid | 36 import uuid |
33 import dbus | 37 import dbus |
34 from dbus.mainloop.glib import DBusGMainLoop | 38 from dbus.mainloop.glib import DBusGMainLoop |
39 | |
35 DBusGMainLoop(set_as_default=True) | 40 DBusGMainLoop(set_as_default=True) |
36 | 41 |
37 FD_NAME = "org.freedesktop.DBus" | 42 FD_NAME = "org.freedesktop.DBus" |
38 FD_PATH = "/org/freedekstop/DBus" | 43 FD_PATH = "/org/freedekstop/DBus" |
39 INTROSPECT_IFACE = "org.freedesktop.DBus.Introspectable" | 44 INTROSPECT_IFACE = "org.freedesktop.DBus.Introspectable" |
40 | 45 |
41 INTROSPECT_METHOD = "Introspect" | 46 INTROSPECT_METHOD = "Introspect" |
42 IGNORED_IFACES_START = ('org.freedesktop', 'org.qtproject', 'org.kde.KMainWindow') # commands in interface starting with these values will be ignored | 47 IGNORED_IFACES_START = ( |
43 FLAG_LOOP = 'LOOP' | 48 "org.freedesktop", |
49 "org.qtproject", | |
50 "org.kde.KMainWindow", | |
51 ) # commands in interface starting with these values will be ignored | |
52 FLAG_LOOP = "LOOP" | |
44 | 53 |
45 PLUGIN_INFO = { | 54 PLUGIN_INFO = { |
46 C.PI_NAME: "Ad-Hoc Commands - D-Bus", | 55 C.PI_NAME: "Ad-Hoc Commands - D-Bus", |
47 C.PI_IMPORT_NAME: "AD_HOC_DBUS", | 56 C.PI_IMPORT_NAME: "AD_HOC_DBUS", |
48 C.PI_TYPE: "Misc", | 57 C.PI_TYPE: "Misc", |
49 C.PI_PROTOCOLS: [], | 58 C.PI_PROTOCOLS: [], |
50 C.PI_DEPENDENCIES: ["XEP-0050"], | 59 C.PI_DEPENDENCIES: ["XEP-0050"], |
51 C.PI_MAIN: "AdHocDBus", | 60 C.PI_MAIN: "AdHocDBus", |
52 C.PI_HANDLER: "no", | 61 C.PI_HANDLER: "no", |
53 C.PI_DESCRIPTION: _("""Add D-Bus management to Ad-Hoc commands""") | 62 C.PI_DESCRIPTION: _("""Add D-Bus management to Ad-Hoc commands"""), |
54 } | 63 } |
55 | 64 |
56 | 65 |
57 class AdHocDBus(object): | 66 class AdHocDBus(object): |
58 | |
59 def __init__(self, host): | 67 def __init__(self, host): |
60 log.info(_("plugin Ad-Hoc D-Bus initialization")) | 68 log.info(_("plugin Ad-Hoc D-Bus initialization")) |
61 self.host = host | 69 self.host = host |
62 host.bridge.addMethod("adHocDBusAddAuto", ".plugin", in_sign='sasasasasasass', out_sign='(sa(sss))', | 70 host.bridge.addMethod( |
63 method=self._adHocDBusAddAuto, | 71 "adHocDBusAddAuto", |
64 async=True) | 72 ".plugin", |
73 in_sign="sasasasasasass", | |
74 out_sign="(sa(sss))", | |
75 method=self._adHocDBusAddAuto, | |
76 async=True, | |
77 ) | |
65 self.session_bus = dbus.SessionBus() | 78 self.session_bus = dbus.SessionBus() |
66 self.fd_object = self.session_bus.get_object(FD_NAME, FD_PATH, introspect=False) | 79 self.fd_object = self.session_bus.get_object(FD_NAME, FD_PATH, introspect=False) |
67 self.XEP_0050 = host.plugins['XEP-0050'] | 80 self.XEP_0050 = host.plugins["XEP-0050"] |
68 | 81 |
69 def _DBusAsyncCall(self, proxy, method, *args, **kwargs): | 82 def _DBusAsyncCall(self, proxy, method, *args, **kwargs): |
70 """ Call a DBus method asynchronously and return a deferred | 83 """ Call a DBus method asynchronously and return a deferred |
71 @param proxy: DBus object proxy, as returner by get_object | 84 @param proxy: DBus object proxy, as returner by get_object |
72 @param method: name of the method to call | 85 @param method: name of the method to call |
75 - interface: name of the interface to use | 88 - interface: name of the interface to use |
76 @return: a deferred | 89 @return: a deferred |
77 | 90 |
78 """ | 91 """ |
79 d = defer.Deferred() | 92 d = defer.Deferred() |
80 interface = kwargs.pop('interface', None) | 93 interface = kwargs.pop("interface", None) |
81 kwargs['reply_handler'] = lambda ret=None: d.callback(ret) | 94 kwargs["reply_handler"] = lambda ret=None: d.callback(ret) |
82 kwargs['error_handler'] = d.errback | 95 kwargs["error_handler"] = d.errback |
83 proxy.get_dbus_method(method, dbus_interface=interface)(*args, **kwargs) | 96 proxy.get_dbus_method(method, dbus_interface=interface)(*args, **kwargs) |
84 return d | 97 return d |
85 | 98 |
86 def _DBusListNames(self): | 99 def _DBusListNames(self): |
87 return self._DBusAsyncCall(self.fd_object, "ListNames") | 100 return self._DBusAsyncCall(self.fd_object, "ListNames") |
93 """ Return True if we accept the method for a command | 106 """ Return True if we accept the method for a command |
94 @param method: etree.Element | 107 @param method: etree.Element |
95 @return: True if the method is acceptable | 108 @return: True if the method is acceptable |
96 | 109 |
97 """ | 110 """ |
98 if method.xpath("arg[@direction='in']"): # we don't accept method with argument for the moment | 111 if method.xpath( |
112 "arg[@direction='in']" | |
113 ): # we don't accept method with argument for the moment | |
99 return False | 114 return False |
100 return True | 115 return True |
101 | 116 |
102 @defer.inlineCallbacks | 117 @defer.inlineCallbacks |
103 def _introspect(self, methods, bus_name, proxy): | 118 def _introspect(self, methods, bus_name, proxy): |
104 log.debug("introspecting path [%s]" % proxy.object_path) | 119 log.debug("introspecting path [%s]" % proxy.object_path) |
105 introspect_xml = yield self._DBusIntrospect(proxy) | 120 introspect_xml = yield self._DBusIntrospect(proxy) |
106 el = etree.fromstring(introspect_xml) | 121 el = etree.fromstring(introspect_xml) |
107 for node in el.iterchildren('node', 'interface'): | 122 for node in el.iterchildren("node", "interface"): |
108 if node.tag == 'node': | 123 if node.tag == "node": |
109 new_path = os.path.join(proxy.object_path, node.get('name')) | 124 new_path = os.path.join(proxy.object_path, node.get("name")) |
110 new_proxy = self.session_bus.get_object(bus_name, new_path, introspect=False) | 125 new_proxy = self.session_bus.get_object( |
126 bus_name, new_path, introspect=False | |
127 ) | |
111 yield self._introspect(methods, bus_name, new_proxy) | 128 yield self._introspect(methods, bus_name, new_proxy) |
112 elif node.tag == 'interface': | 129 elif node.tag == "interface": |
113 name = node.get('name') | 130 name = node.get("name") |
114 if any(name.startswith(ignored) for ignored in IGNORED_IFACES_START): | 131 if any(name.startswith(ignored) for ignored in IGNORED_IFACES_START): |
115 log.debug('interface [%s] is ignored' % name) | 132 log.debug("interface [%s] is ignored" % name) |
116 continue | 133 continue |
117 log.debug("introspecting interface [%s]" % name) | 134 log.debug("introspecting interface [%s]" % name) |
118 for method in node.iterchildren('method'): | 135 for method in node.iterchildren("method"): |
119 if self._acceptMethod(method): | 136 if self._acceptMethod(method): |
120 method_name = method.get('name') | 137 method_name = method.get("name") |
121 log.debug("method accepted: [%s]" % method_name) | 138 log.debug("method accepted: [%s]" % method_name) |
122 methods.add((proxy.object_path, name, method_name)) | 139 methods.add((proxy.object_path, name, method_name)) |
123 | 140 |
124 def _adHocDBusAddAuto(self, prog_name, allowed_jids, allowed_groups, allowed_magics, forbidden_jids, forbidden_groups, flags, profile_key): | 141 def _adHocDBusAddAuto( |
125 return self.adHocDBusAddAuto(prog_name, allowed_jids, allowed_groups, allowed_magics, forbidden_jids, forbidden_groups, flags, profile_key) | 142 self, |
143 prog_name, | |
144 allowed_jids, | |
145 allowed_groups, | |
146 allowed_magics, | |
147 forbidden_jids, | |
148 forbidden_groups, | |
149 flags, | |
150 profile_key, | |
151 ): | |
152 return self.adHocDBusAddAuto( | |
153 prog_name, | |
154 allowed_jids, | |
155 allowed_groups, | |
156 allowed_magics, | |
157 forbidden_jids, | |
158 forbidden_groups, | |
159 flags, | |
160 profile_key, | |
161 ) | |
126 | 162 |
127 @defer.inlineCallbacks | 163 @defer.inlineCallbacks |
128 def adHocDBusAddAuto(self, prog_name, allowed_jids=None, allowed_groups=None, allowed_magics=None, forbidden_jids=None, forbidden_groups=None, flags=None, profile_key=C.PROF_KEY_NONE): | 164 def adHocDBusAddAuto( |
165 self, | |
166 prog_name, | |
167 allowed_jids=None, | |
168 allowed_groups=None, | |
169 allowed_magics=None, | |
170 forbidden_jids=None, | |
171 forbidden_groups=None, | |
172 flags=None, | |
173 profile_key=C.PROF_KEY_NONE, | |
174 ): | |
129 bus_names = yield self._DBusListNames() | 175 bus_names = yield self._DBusListNames() |
130 bus_names = [bus_name for bus_name in bus_names if '.' + prog_name in bus_name] | 176 bus_names = [bus_name for bus_name in bus_names if "." + prog_name in bus_name] |
131 if not bus_names: | 177 if not bus_names: |
132 log.info("Can't find any bus for [%s]" % prog_name) | 178 log.info("Can't find any bus for [%s]" % prog_name) |
133 defer.returnValue(("", [])) | 179 defer.returnValue(("", [])) |
134 bus_names.sort() | 180 bus_names.sort() |
135 for bus_name in bus_names: | 181 for bus_name in bus_names: |
136 if bus_name.endswith(prog_name): | 182 if bus_name.endswith(prog_name): |
137 break | 183 break |
138 log.info("bus name found: [%s]" % bus_name) | 184 log.info("bus name found: [%s]" % bus_name) |
139 proxy = self.session_bus.get_object(bus_name, '/', introspect=False) | 185 proxy = self.session_bus.get_object(bus_name, "/", introspect=False) |
140 methods = set() | 186 methods = set() |
141 | 187 |
142 yield self._introspect(methods, bus_name, proxy) | 188 yield self._introspect(methods, bus_name, proxy) |
143 | 189 |
144 if methods: | 190 if methods: |
145 self._addCommand(prog_name, bus_name, methods, | 191 self._addCommand( |
146 allowed_jids = allowed_jids, | 192 prog_name, |
147 allowed_groups = allowed_groups, | 193 bus_name, |
148 allowed_magics = allowed_magics, | 194 methods, |
149 forbidden_jids = forbidden_jids, | 195 allowed_jids=allowed_jids, |
150 forbidden_groups = forbidden_groups, | 196 allowed_groups=allowed_groups, |
151 flags = flags, | 197 allowed_magics=allowed_magics, |
152 profile_key = profile_key) | 198 forbidden_jids=forbidden_jids, |
199 forbidden_groups=forbidden_groups, | |
200 flags=flags, | |
201 profile_key=profile_key, | |
202 ) | |
153 | 203 |
154 defer.returnValue((bus_name, methods)) | 204 defer.returnValue((bus_name, methods)) |
155 | 205 |
156 | 206 def _addCommand( |
157 def _addCommand(self, adhoc_name, bus_name, methods, allowed_jids=None, allowed_groups=None, allowed_magics=None, forbidden_jids=None, forbidden_groups=None, flags=None, profile_key=C.PROF_KEY_NONE): | 207 self, |
208 adhoc_name, | |
209 bus_name, | |
210 methods, | |
211 allowed_jids=None, | |
212 allowed_groups=None, | |
213 allowed_magics=None, | |
214 forbidden_jids=None, | |
215 forbidden_groups=None, | |
216 flags=None, | |
217 profile_key=C.PROF_KEY_NONE, | |
218 ): | |
158 if flags is None: | 219 if flags is None: |
159 flags = set() | 220 flags = set() |
160 | 221 |
161 def DBusCallback(command_elt, session_data, action, node, profile): | 222 def DBusCallback(command_elt, session_data, action, node, profile): |
162 actions = session_data.setdefault('actions',[]) | 223 actions = session_data.setdefault("actions", []) |
163 names_map = session_data.setdefault('names_map', {}) | 224 names_map = session_data.setdefault("names_map", {}) |
164 actions.append(action) | 225 actions.append(action) |
165 | 226 |
166 if len(actions) == 1: | 227 if len(actions) == 1: |
167 # it's our first request, we ask the desired new status | 228 # it's our first request, we ask the desired new status |
168 status = self.XEP_0050.STATUS.EXECUTING | 229 status = self.XEP_0050.STATUS.EXECUTING |
169 form = data_form.Form('form', title=_('Command selection')) | 230 form = data_form.Form("form", title=_("Command selection")) |
170 options = [] | 231 options = [] |
171 for path, iface, command in methods: | 232 for path, iface, command in methods: |
172 label = command.rsplit('.',1)[-1] | 233 label = command.rsplit(".", 1)[-1] |
173 name = str(uuid.uuid4()) | 234 name = str(uuid.uuid4()) |
174 names_map[name] = (path, iface, command) | 235 names_map[name] = (path, iface, command) |
175 options.append(data_form.Option(name, label)) | 236 options.append(data_form.Option(name, label)) |
176 | 237 |
177 field = data_form.Field('list-single', 'command', options=options, required=True) | 238 field = data_form.Field( |
239 "list-single", "command", options=options, required=True | |
240 ) | |
178 form.addField(field) | 241 form.addField(field) |
179 | 242 |
180 payload = form.toElement() | 243 payload = form.toElement() |
181 note = None | 244 note = None |
182 | 245 |
183 elif len(actions) == 2: | 246 elif len(actions) == 2: |
184 # we should have the answer here | 247 # we should have the answer here |
185 try: | 248 try: |
186 x_elt = command_elt.elements(data_form.NS_X_DATA,'x').next() | 249 x_elt = command_elt.elements(data_form.NS_X_DATA, "x").next() |
187 answer_form = data_form.Form.fromElement(x_elt) | 250 answer_form = data_form.Form.fromElement(x_elt) |
188 command = answer_form['command'] | 251 command = answer_form["command"] |
189 except (KeyError, StopIteration): | 252 except (KeyError, StopIteration): |
190 raise self.XEP_0050.AdHocError(self.XEP_0050.ERROR.BAD_PAYLOAD) | 253 raise self.XEP_0050.AdHocError(self.XEP_0050.ERROR.BAD_PAYLOAD) |
191 | 254 |
192 if command not in names_map: | 255 if command not in names_map: |
193 raise self.XEP_0050.AdHocError(self.XEP_0050.ERROR.BAD_PAYLOAD) | 256 raise self.XEP_0050.AdHocError(self.XEP_0050.ERROR.BAD_PAYLOAD) |
200 # job done, we can end the session, except if we have FLAG_LOOP | 263 # job done, we can end the session, except if we have FLAG_LOOP |
201 if FLAG_LOOP in flags: | 264 if FLAG_LOOP in flags: |
202 # We have a loop, so we clear everything and we execute again the command as we had a first call (command_elt is not used, so None is OK) | 265 # We have a loop, so we clear everything and we execute again the command as we had a first call (command_elt is not used, so None is OK) |
203 del actions[:] | 266 del actions[:] |
204 names_map.clear() | 267 names_map.clear() |
205 return DBusCallback(None, session_data, self.XEP_0050.ACTION.EXECUTE, node, profile) | 268 return DBusCallback( |
206 form = data_form.Form('form', title=_(u'Updated')) | 269 None, session_data, self.XEP_0050.ACTION.EXECUTE, node, profile |
207 form.addField(data_form.Field('fixed', u'Command sent')) | 270 ) |
271 form = data_form.Form("form", title=_(u"Updated")) | |
272 form.addField(data_form.Field("fixed", u"Command sent")) | |
208 status = self.XEP_0050.STATUS.COMPLETED | 273 status = self.XEP_0050.STATUS.COMPLETED |
209 payload = None | 274 payload = None |
210 note = (self.XEP_0050.NOTE.INFO, _(u"Command sent")) | 275 note = (self.XEP_0050.NOTE.INFO, _(u"Command sent")) |
211 else: | 276 else: |
212 raise self.XEP_0050.AdHocError(self.XEP_0050.ERROR.INTERNAL) | 277 raise self.XEP_0050.AdHocError(self.XEP_0050.ERROR.INTERNAL) |
213 | 278 |
214 return (payload, status, None, note) | 279 return (payload, status, None, note) |
215 | 280 |
216 self.XEP_0050.addAdHocCommand(DBusCallback, adhoc_name, | 281 self.XEP_0050.addAdHocCommand( |
217 allowed_jids = allowed_jids, | 282 DBusCallback, |
218 allowed_groups = allowed_groups, | 283 adhoc_name, |
219 allowed_magics = allowed_magics, | 284 allowed_jids=allowed_jids, |
220 forbidden_jids = forbidden_jids, | 285 allowed_groups=allowed_groups, |
221 forbidden_groups = forbidden_groups, | 286 allowed_magics=allowed_magics, |
222 profile_key = profile_key) | 287 forbidden_jids=forbidden_jids, |
288 forbidden_groups=forbidden_groups, | |
289 profile_key=profile_key, | |
290 ) |