Mercurial > libervia-backend
annotate libervia/cli/loops.py @ 4321:2246eeeccc74
tests (unit): fix tests:
- test_ap-gateway: fix missing implementation of `client.is_local`
- test_plugin_xep_0215: fix missing return value of `has_feature`
author | Goffi <goffi@goffi.org> |
---|---|
date | Mon, 30 Sep 2024 14:15:47 +0200 |
parents | 0d7bb4df2343 |
children |
rev | line source |
---|---|
3043 | 1 #!/usr/bin/env python3 |
2 | |
4075
47401850dec6
refactoring: rename `libervia.frontends.jp` to `libervia.cli`
Goffi <goffi@goffi.org>
parents:
4074
diff
changeset
|
3 # Libervia CLI |
3479 | 4 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org) |
3043 | 5 |
6 # This program is free software: you can redistribute it and/or modify | |
7 # it under the terms of the GNU Affero General Public License as published by | |
8 # the Free Software Foundation, either version 3 of the License, or | |
9 # (at your option) any later version. | |
10 | |
11 # This program is distributed in the hope that it will be useful, | |
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 # GNU Affero General Public License for more details. | |
15 | |
16 # You should have received a copy of the GNU Affero General Public License | |
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
18 | |
19 import sys | |
20 import asyncio | |
21 import logging as log | |
4071
4b842c1fb686
refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents:
4037
diff
changeset
|
22 from libervia.backend.core.i18n import _ |
4075
47401850dec6
refactoring: rename `libervia.frontends.jp` to `libervia.cli`
Goffi <goffi@goffi.org>
parents:
4074
diff
changeset
|
23 from libervia.cli.constants import Const as C |
4141
ba8ddfdd334f
cli (loops): run GLib loop in same thread as asyncio:
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
24 from libervia.frontends.tools import aio |
3043 | 25 |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
26 log.basicConfig(level=log.WARNING, format="[%(name)s] %(message)s") |
3043 | 27 |
28 USER_INTER_MSG = _("User interruption: good bye") | |
29 | |
30 | |
31 class QuitException(BaseException): | |
32 """Quitting is requested | |
33 | |
34 This is used to stop execution when host.quit() is called | |
35 """ | |
36 | |
37 | |
4075
47401850dec6
refactoring: rename `libervia.frontends.jp` to `libervia.cli`
Goffi <goffi@goffi.org>
parents:
4074
diff
changeset
|
38 def get_libervia_cli_loop(bridge_name): |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
39 if "dbus" in bridge_name: |
3043 | 40 import signal |
41 | |
4075
47401850dec6
refactoring: rename `libervia.frontends.jp` to `libervia.cli`
Goffi <goffi@goffi.org>
parents:
4074
diff
changeset
|
42 class LiberviaCLILoop: |
3043 | 43 |
4141
ba8ddfdd334f
cli (loops): run GLib loop in same thread as asyncio:
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
44 def __init__(self): |
4206 | 45 self.loop = asyncio.get_event_loop() |
4141
ba8ddfdd334f
cli (loops): run GLib loop in same thread as asyncio:
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
46 |
4075
47401850dec6
refactoring: rename `libervia.frontends.jp` to `libervia.cli`
Goffi <goffi@goffi.org>
parents:
4074
diff
changeset
|
47 def run(self, libervia_cli, args, namespace): |
4141
ba8ddfdd334f
cli (loops): run GLib loop in same thread as asyncio:
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
48 aio.install_glib_asyncio_iteration() |
3043 | 49 signal.signal(signal.SIGINT, self._on_sigint) |
4141
ba8ddfdd334f
cli (loops): run GLib loop in same thread as asyncio:
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
50 loop = self.loop |
4075
47401850dec6
refactoring: rename `libervia.frontends.jp` to `libervia.cli`
Goffi <goffi@goffi.org>
parents:
4074
diff
changeset
|
51 loop.run_until_complete(libervia_cli.main(args=args, namespace=namespace)) |
3043 | 52 loop.run_forever() |
53 | |
54 def quit(self, exit_code): | |
55 loop = asyncio.get_event_loop() | |
56 loop.stop() | |
57 sys.exit(exit_code) | |
58 | |
59 def call_later(self, delay, callback, *args): | |
60 """call a callback repeatedly | |
61 | |
62 @param delay(int): delay between calls in s | |
63 @param callback(callable): method to call | |
64 if the callback return True, the call will continue | |
65 else the calls will stop | |
66 @param *args: args of the callbac | |
67 """ | |
68 loop = asyncio.get_event_loop() | |
69 loop.call_later(delay, callback, *args) | |
70 | |
71 def _on_sigint(self, sig_number, stack_frame): | |
72 """Called on keyboard interruption | |
73 | |
74 Print user interruption message, set exit code and stop reactor | |
75 """ | |
76 print("\r" + USER_INTER_MSG) | |
77 self.quit(C.EXIT_USER_CANCELLED) | |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
78 |
3043 | 79 else: |
80 import signal | |
81 from twisted.internet import asyncioreactor | |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
82 |
3043 | 83 asyncioreactor.install() |
84 from twisted.internet import reactor, defer | |
85 | |
4075
47401850dec6
refactoring: rename `libervia.frontends.jp` to `libervia.cli`
Goffi <goffi@goffi.org>
parents:
4074
diff
changeset
|
86 class LiberviaCLILoop: |
3043 | 87 |
88 def __init__(self): | |
89 # exit code must be set when using quit, so if it's not set | |
90 # something got wrong and we must report it | |
91 self._exit_code = C.EXIT_INTERNAL_ERROR | |
92 | |
4075
47401850dec6
refactoring: rename `libervia.frontends.jp` to `libervia.cli`
Goffi <goffi@goffi.org>
parents:
4074
diff
changeset
|
93 def run(self, libervia_cli, *args): |
47401850dec6
refactoring: rename `libervia.frontends.jp` to `libervia.cli`
Goffi <goffi@goffi.org>
parents:
4074
diff
changeset
|
94 self.libervia_cli = libervia_cli |
3043 | 95 signal.signal(signal.SIGINT, self._on_sigint) |
4075
47401850dec6
refactoring: rename `libervia.frontends.jp` to `libervia.cli`
Goffi <goffi@goffi.org>
parents:
4074
diff
changeset
|
96 defer.ensureDeferred(self._start(libervia_cli, *args)) |
3043 | 97 try: |
98 reactor.run(installSignalHandlers=False) | |
99 except SystemExit as e: | |
100 self._exit_code = e.code | |
101 sys.exit(self._exit_code) | |
102 | |
4075
47401850dec6
refactoring: rename `libervia.frontends.jp` to `libervia.cli`
Goffi <goffi@goffi.org>
parents:
4074
diff
changeset
|
103 async def _start(self, libervia_cli, *args): |
47401850dec6
refactoring: rename `libervia.frontends.jp` to `libervia.cli`
Goffi <goffi@goffi.org>
parents:
4074
diff
changeset
|
104 fut = asyncio.ensure_future(libervia_cli.main(*args)) |
3043 | 105 try: |
106 await defer.Deferred.fromFuture(fut) | |
107 except BaseException: | |
108 import traceback | |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
109 |
3043 | 110 traceback.print_exc() |
4075
47401850dec6
refactoring: rename `libervia.frontends.jp` to `libervia.cli`
Goffi <goffi@goffi.org>
parents:
4074
diff
changeset
|
111 libervia_cli.quit(1) |
3043 | 112 |
113 def quit(self, exit_code): | |
114 self._exit_code = exit_code | |
115 reactor.stop() | |
116 | |
117 def _timeout_cb(self, args, callback, delay): | |
118 try: | |
119 ret = callback(*args) | |
120 # FIXME: temporary hack to avoid traceback when using XMLUI | |
121 # to be removed once create_task is not used anymore in | |
4074
26b7ed2817da
refactoring: rename `sat_frontends` to `libervia.frontends`
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
122 # xmlui_manager (i.e. once libervia.frontends.tools.xmlui fully supports |
3043 | 123 # async syntax) |
124 except QuitException: | |
125 return | |
126 if ret: | |
127 reactor.callLater(delay, self._timeout_cb, args, callback, delay) | |
128 | |
129 def call_later(self, delay, callback, *args): | |
130 reactor.callLater(delay, self._timeout_cb, args, callback, delay) | |
131 | |
132 def _on_sigint(self, sig_number, stack_frame): | |
133 """Called on keyboard interruption | |
134 | |
135 Print user interruption message, set exit code and stop reactor | |
136 """ | |
137 print("\r" + USER_INTER_MSG) | |
138 self._exit_code = C.EXIT_USER_CANCELLED | |
139 reactor.callFromThread(reactor.stop) | |
140 | |
141 if bridge_name == "embedded": | |
142 raise NotImplementedError | |
143 # from sat.core import sat_main | |
144 # sat = sat_main.SAT() | |
145 | |
4075
47401850dec6
refactoring: rename `libervia.frontends.jp` to `libervia.cli`
Goffi <goffi@goffi.org>
parents:
4074
diff
changeset
|
146 return LiberviaCLILoop |