From 12a8fba023a40201bc76ad8994b8cd6dacb6e0d3 Mon Sep 17 00:00:00 2001 From: jkerdreux-imt <jerome.kerdreux@imt-atlantique.fr> Date: Mon, 27 Jan 2025 15:40:13 +0100 Subject: [PATCH] Fix Event loop closed bug and format Check the previous commit for the Evevnt loop issue. Everything should be fine now. Black format once again wants to change some stuffs.. --- apps/tools/xaal/tools/toolbox.py | 97 +++++++++++++++++--------------- 1 file changed, 51 insertions(+), 46 deletions(-) diff --git a/apps/tools/xaal/tools/toolbox.py b/apps/tools/xaal/tools/toolbox.py index 81284ab1..72c190a2 100644 --- a/apps/tools/xaal/tools/toolbox.py +++ b/apps/tools/xaal/tools/toolbox.py @@ -11,6 +11,7 @@ if sys.argv[0].endswith('pkgrun'): # this is only needed for the pkgrun command try: from gevent import monkey + monkey.patch_all(thread=False) # print("Loaded gevent") except ModuleNotFoundError: @@ -37,22 +38,22 @@ import shutil # needed by the tail command HIDE_ACTION = ['get_attributes', 'get_description', 'get_keys_values', 'get_devices', 'is_alive'] TABLE_STYLE = 'psql' -LINE = "="*78 +LINE = "=" * 78 DB_DEV_TYPE = "metadatadb.basic" class Colors(enum.Enum): - DEFAULT = fore.WHITE - ALIVE = fore.LIGHT_GRAY + DEFAULT = fore.WHITE + ALIVE = fore.LIGHT_GRAY ATTRIBUTS = fore.YELLOW - REQUEST = fore.RED - IS_ALIVE = fore.MAGENTA - REPLY = fore.CYAN - NOTIFY = fore.LIGHT_GREEN - DEV_TYPE = fore.BLUE - ADDR = fore.RED - INFO = fore.CYAN - DB = fore.SPRING_GREEN_1 + REQUEST = fore.RED + IS_ALIVE = fore.MAGENTA + REPLY = fore.CYAN + NOTIFY = fore.LIGHT_GREEN + DEV_TYPE = fore.BLUE + ADDR = fore.RED + INFO = fore.CYAN + DB = fore.SPRING_GREEN_1 def __str__(self): return self.value @@ -105,7 +106,7 @@ class DeviceInfo(object): # attributes if self.attributes and len(self.attributes) > 0: # tabulate has no minimal width so used this trick - r.append(['-'*22, '-'*46]) + r.append(['-' * 22, '-' * 46]) r.append(['Attributes', '']) r.append(['==========', '']) for k, v in self.attributes.items(): @@ -117,7 +118,7 @@ class DeviceInfo(object): # metadata if self.db and len(self.db.keys()) > 0: - r.append(['-'*22, '-'*46]) + r.append(['-' * 22, '-' * 46]) r.append(['Metadata', '']) r.append(['========', '']) for k, v in self.db.items(): @@ -139,7 +140,7 @@ class DeviceInfo(object): # attributes if self.attributes and len(self.attributes) > 0: # tabulate has no minimal width so used this trick - r.append(['-'*22, '-'*46]) + r.append(['-' * 22, '-' * 46]) r.append(['Attributes', '']) r.append(['==========', '']) for k, v in self.attributes.items(): @@ -150,7 +151,7 @@ class DeviceInfo(object): r.append([k, tmp]) # metadata if self.db and len(self.db.keys()) > 0: - r.append(['-'*22, '-'*46]) + r.append(['-' * 22, '-' * 46]) r.append(['Metadata', '']) r.append(['========', '']) for k, v in self.db.items(): @@ -160,8 +161,8 @@ class DeviceInfo(object): class ToolboxHelper(object): def __init__(self) -> None: - self.name = None # cmdline name - self.devices = [] # devices list (alive / walker) + self.name = None # cmdline name + self.devices = [] # devices list (alive / walker) # idle detector / force exit self.exit_event = asyncio.Event() self.last_msg_time = now() @@ -225,8 +226,9 @@ class ToolboxHelper(object): ##################################################### def setup_msg_parser(self): # match the subscribe API (no return value) - def handle(msg:Message): + def handle(msg: Message): self.parse_msg(msg) + self.engine.subscribe(handle) def parse(self): @@ -300,7 +302,7 @@ class ToolboxHelper(object): print(color_value, end='') msg.dump() if color: - print(style.RESET, end='') # pyright: ignore + print(style.RESET, end='') # pyright: ignore def color_for_msg(self, msg): color_value = Colors.DEFAULT @@ -319,7 +321,7 @@ class ToolboxHelper(object): return color_value def parse_msg(self, msg): - """ default parser used for info/walker""" + """default parser used for info/walker""" target = self.get_device(msg.source) if target is None: target = DeviceInfo() @@ -379,11 +381,11 @@ class ToolboxHelper(object): def request_db_values(self, addr): if self.db_server: - self.engine.send_request(self.device, [self.db_server, ], "get_keys_values", {'device': addr}) + self.engine.send_request(self.device, [self.db_server], "get_keys_values", {'device': addr}) def request_db_devices(self, key, value): if self.db_server: - self.engine.send_request(self.device, [self.db_server, ], "get_devices", {'key': key, 'value': value}) + self.engine.send_request(self.device, [self.db_server], "get_devices", {'key': key, 'value': value}) def is_db_reply(self, msg): if match_dev_type(msg, DB_DEV_TYPE) and msg.is_reply() and self.device.address in msg.targets: @@ -408,7 +410,7 @@ class ToolboxHelper(object): self.quit() def run_until_timeout(self, timeout=3): - """ run the engine until timeout """ + """run the engine until timeout""" if self.engine: self.engine.add_timer(self.quit, timeout) self.engine.run() @@ -438,7 +440,7 @@ class ToolboxHelper(object): def colorize(color, text): - return f"{color}{text}{style.RESET}" # pyright: ignore + return f"{color}{text}{style.RESET}" # pyright: ignore def now(): @@ -465,7 +467,7 @@ def match_address(msg, addr): async def wait_for_event(event, timeout): - """ wait for a given event or timeout""" + """wait for a given event or timeout""" wait_task = asyncio.create_task(event.wait()) await asyncio.wait([wait_task], timeout=timeout) @@ -497,6 +499,7 @@ def dumper(): eng.subscribe(dumper_callback) helper.run_forever() + ##################################################### # alive ##################################################### @@ -532,6 +535,7 @@ def is_alive(): eng.on_start(start) helper.run_until_idle() + ##################################################### # info ##################################################### @@ -580,6 +584,7 @@ def info(): eng.on_start(run) helper.run_forever() + ##################################################### # walker ##################################################### @@ -627,6 +632,7 @@ def walker(): eng.on_start(start) helper.run_until_idle() + ##################################################### # log ##################################################### @@ -661,7 +667,7 @@ def log(): color_value = Colors.REPLY if color: - dump = f"{Colors.DEFAULT}{time.ctime()} {Colors.ADDR}{msg.source} {Colors.DEV_TYPE}{msg.dev_type}\t{color_value}{msg.action} {msg.body}{style.RESET}" # pyright: ignore + dump = f"{Colors.DEFAULT}{time.ctime()} {Colors.ADDR}{msg.source} {Colors.DEV_TYPE}{msg.dev_type}\t{color_value}{msg.action} {msg.body}{style.RESET}" # pyright: ignore else: dump = f"{time.ctime()} {msg.source} {msg.dev_type}\t{msg.action} {msg.body}" print(dump) @@ -669,6 +675,7 @@ def log(): eng.subscribe(log_callback) helper.run_forever() + ##################################################### # query db ##################################################### @@ -751,6 +758,7 @@ def query_db(): eng.on_start(run) helper.run_forever() + ##################################################### # cleanup db ##################################################### @@ -808,6 +816,7 @@ def clean_db(): helper.run_forever() # helper.run_until_idle() + ##################################################### # send request ##################################################### @@ -851,6 +860,7 @@ def send(): eng.on_start(run) helper.run_forever() + ##################################################### # tail msg ##################################################### @@ -858,7 +868,9 @@ def tail(): helper = ToolboxHelper() helper.parser.add_option("-f", dest="filter_address", help="only show given address") helper.parser.add_option("-t", dest="filter_type", help="only show given device type") - helper.parser.add_option("-m", dest="filter_mode", help="hide some messages:\n 1=alives, 2=core actions, 3=replies, 4=all except notif") + helper.parser.add_option( + "-m", dest="filter_mode", help="hide some messages:\n 1=alives, 2=core actions, 3=replies, 4=all except notif" + ) helper.parse() target = helper.check_address(helper.options.filter_address) @@ -903,8 +915,8 @@ def tail(): tmp = shutil.get_terminal_size()[0] - (2 + 18 + 36 + 20 + 16 + 7) if tmp < 22: tmp = 22 - BODY_FORMAT = '%-22.'+str(tmp)+'s' - FORMAT = '%-2.02s %-18.18s %-36.36s (%-20.20s) %-16.16s '+BODY_FORMAT + BODY_FORMAT = '%-22.' + str(tmp) + 's' + FORMAT = '%-2.02s %-18.18s %-36.36s (%-20.20s) %-16.16s ' + BODY_FORMAT res = FORMAT % (schem, msg.action, msg.source, msg.dev_type, targets, msg.body) if color: print(colorize(color_value, res)) @@ -919,6 +931,7 @@ def tail(): eng.subscribe(tail_callback) helper.run_forever() + ##################################################### # run pkg ##################################################### @@ -950,6 +963,7 @@ def pkgrun(): load_pkgs() helper.run_forever() + ##################################################### # ipdb shell on steroid ##################################################### @@ -969,17 +983,6 @@ def shell(): print("$ pip install ipython\n") exit(1) - # for a unknown reason, watchdog_task raise a RuntimeError: - # "Event loop is closed" on the shell exit. To avoid issue - # we need to stop all tasks. - async def on_stop(): - for task in eng.all_tasks(): - logging.debug("Stopping task %s", task.get_name()) - task.cancel() - await asyncio.sleep(0.1) - - eng.on_stop(on_stop) - logging.getLogger("parso").setLevel(logging.WARNING) logging.getLogger("blib2to3").setLevel(logging.WARNING) @@ -992,12 +995,14 @@ def shell(): from xaal.lib import Message, Attribute, Device from xaal.monitor import Monitor - IPython.embed(banner1="============================== xAAL Shell ==============================", - banner2=f"* AsyncEngine running in background:\n* eng = {eng}\n\n", - colors="Linux", - confirm_exit=False, - separate_in='', - autoawait=True) + IPython.embed( + banner1="============================== xAAL Shell ==============================", + banner2=f"* AsyncEngine running in background:\n* eng = {eng}\n\n", + colors="Linux", + confirm_exit=False, + separate_in='', + autoawait=True, + ) print("* Ending Engine") eng.shutdown() -- GitLab