Mercurial > libervia-backend
comparison libervia/backend/bridge/bridge_constructor/constructors/dbus/constructor.py @ 4071:4b842c1fb686
refactoring: renamed `sat` package to `libervia.backend`
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 02 Jun 2023 11:49:51 +0200 |
parents | sat/bridge/bridge_constructor/constructors/dbus/constructor.py@524856bd7b19 |
children | 0d7bb4df2343 |
comparison
equal
deleted
inserted
replaced
4070:d10748475025 | 4071:4b842c1fb686 |
---|---|
1 #!/usr/bin/env python3 | |
2 | |
3 | |
4 # Libervia: an XMPP client | |
5 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org) | |
6 | |
7 # This program is free software: you can redistribute it and/or modify | |
8 # it under the terms of the GNU Affero General Public License as published by | |
9 # the Free Software Foundation, either version 3 of the License, or | |
10 # (at your option) any later version. | |
11 | |
12 # This program is distributed in the hope that it will be useful, | |
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 # GNU Affero General Public License for more details. | |
16 | |
17 # You should have received a copy of the GNU Affero General Public License | |
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 | |
20 from libervia.backend.bridge.bridge_constructor import base_constructor | |
21 | |
22 | |
23 class DbusConstructor(base_constructor.Constructor): | |
24 NAME = "dbus" | |
25 CORE_TEMPLATE = "dbus_core_template.py" | |
26 CORE_DEST = "dbus_bridge.py" | |
27 CORE_FORMATS = { | |
28 "methods_declarations": """\ | |
29 Method('{name}', arguments='{sig_in}', returns='{sig_out}'),""", | |
30 | |
31 "methods": """\ | |
32 def dbus_{name}(self, {args}): | |
33 {debug}return self._callback("{name}", {args_no_default})\n""", | |
34 | |
35 "signals_declarations": """\ | |
36 Signal('{name}', '{sig_in}'),""", | |
37 | |
38 "signals": """\ | |
39 def {name}(self, {args}): | |
40 self._obj.emitSignal("{name}", {args})\n""", | |
41 } | |
42 | |
43 FRONTEND_TEMPLATE = "dbus_frontend_template.py" | |
44 FRONTEND_DEST = CORE_DEST | |
45 FRONTEND_FORMATS = { | |
46 "methods": """\ | |
47 def {name}(self, {args}{async_comma}{async_args}): | |
48 {error_handler}{blocking_call}{debug}return {result}\n""", | |
49 "async_methods": """\ | |
50 def {name}(self{async_comma}{args}): | |
51 loop = asyncio.get_running_loop() | |
52 fut = loop.create_future() | |
53 reply_handler = lambda ret=None: loop.call_soon_threadsafe(fut.set_result, ret) | |
54 error_handler = lambda err: loop.call_soon_threadsafe(fut.set_exception, dbus_to_bridge_exception(err)) | |
55 self.db_{category}_iface.{name}({args_result}{async_comma}timeout=const_TIMEOUT, reply_handler=reply_handler, error_handler=error_handler) | |
56 {debug}return fut\n""", | |
57 } | |
58 | |
59 def core_completion_signal(self, completion, function, default, arg_doc, async_): | |
60 completion["category"] = completion["category"].upper() | |
61 completion["body"] = ( | |
62 "pass" | |
63 if not self.args.debug | |
64 else 'log.debug ("{}")'.format(completion["name"]) | |
65 ) | |
66 | |
67 def core_completion_method(self, completion, function, default, arg_doc, async_): | |
68 completion.update( | |
69 { | |
70 "debug": ( | |
71 "" if not self.args.debug | |
72 else f'log.debug ("{completion["name"]}")\n{8 * " "}' | |
73 ) | |
74 } | |
75 ) | |
76 | |
77 def frontend_completion_method(self, completion, function, default, arg_doc, async_): | |
78 completion.update( | |
79 { | |
80 # XXX: we can manage blocking call in the same way as async one: if callback is None the call will be blocking | |
81 "debug": "" | |
82 if not self.args.debug | |
83 else 'log.debug ("%s")\n%s' % (completion["name"], 8 * " "), | |
84 "args_result": self.get_arguments(function["sig_in"], name=arg_doc), | |
85 "async_args": "callback=None, errback=None", | |
86 "async_comma": ", " if function["sig_in"] else "", | |
87 "error_handler": """if callback is None: | |
88 error_handler = None | |
89 else: | |
90 if errback is None: | |
91 errback = log.error | |
92 error_handler = lambda err:errback(dbus_to_bridge_exception(err)) | |
93 """, | |
94 } | |
95 ) | |
96 if async_: | |
97 completion["blocking_call"] = "" | |
98 completion[ | |
99 "async_args_result" | |
100 ] = "timeout=const_TIMEOUT, reply_handler=callback, error_handler=error_handler" | |
101 else: | |
102 # XXX: To have a blocking call, we must have not reply_handler, so we test if callback exists, and add reply_handler only in this case | |
103 completion[ | |
104 "blocking_call" | |
105 ] = """kwargs={} | |
106 if callback is not None: | |
107 kwargs['timeout'] = const_TIMEOUT | |
108 kwargs['reply_handler'] = callback | |
109 kwargs['error_handler'] = error_handler | |
110 """ | |
111 completion["async_args_result"] = "**kwargs" | |
112 result = ( | |
113 "self.db_%(category)s_iface.%(name)s(%(args_result)s%(async_comma)s%(async_args_result)s)" | |
114 % completion | |
115 ) | |
116 completion["result"] = ( | |
117 "str(%s)" if self.args.unicode and function["sig_out"] == "s" else "%s" | |
118 ) % result |