mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-05 21:54:33 +02:00
feat(tools): idf_monitor: support for loadable hint provider modules
Currently hints are supported based on hints.yml only, which may be limiting for some use cases. This introduces a generic plugin approach, which allows to implement hint module that doesn't require entry in hints.yml. Such module has the full command output available and it is not limited to a single regex in hints.yml. Note that regex in hint.yml expects the output concatenated into a single line, but hint modules are getting the output unchanged. Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
This commit is contained in:
committed by
Frantisek Hrbata
parent
148b7f9a56
commit
924857d0b4
@@ -1,6 +1,7 @@
|
|||||||
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import importlib
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
@@ -8,6 +9,7 @@ import subprocess
|
|||||||
import sys
|
import sys
|
||||||
from asyncio.subprocess import Process
|
from asyncio.subprocess import Process
|
||||||
from io import open
|
from io import open
|
||||||
|
from pkgutil import iter_modules
|
||||||
from types import FunctionType
|
from types import FunctionType
|
||||||
from typing import Any, Dict, Generator, List, Match, Optional, TextIO, Tuple, Union
|
from typing import Any, Dict, Generator, List, Match, Optional, TextIO, Tuple, Union
|
||||||
|
|
||||||
@@ -165,16 +167,50 @@ def debug_print_idf_version() -> None:
|
|||||||
print_warning(f'ESP-IDF {idf_version() or "version unknown"}')
|
print_warning(f'ESP-IDF {idf_version() or "version unknown"}')
|
||||||
|
|
||||||
|
|
||||||
def load_hints() -> Any:
|
def load_hints() -> Dict:
|
||||||
"""Helper function to load hints yml file"""
|
"""Helper function to load hints yml file"""
|
||||||
with open(os.path.join(os.path.dirname(__file__), 'hints.yml'), 'r') as file:
|
hints: Dict = {
|
||||||
hints = yaml.safe_load(file)
|
'yml': [],
|
||||||
|
'modules': []
|
||||||
|
}
|
||||||
|
|
||||||
|
current_module_dir = os.path.dirname(__file__)
|
||||||
|
with open(os.path.join(current_module_dir, 'hints.yml'), 'r') as file:
|
||||||
|
hints['yml'] = yaml.safe_load(file)
|
||||||
|
|
||||||
|
hint_modules_dir = os.path.join(current_module_dir, 'hint_modules')
|
||||||
|
if not os.path.exists(hint_modules_dir):
|
||||||
|
return hints
|
||||||
|
|
||||||
|
sys.path.append(hint_modules_dir)
|
||||||
|
for _, name, _ in iter_modules([hint_modules_dir]):
|
||||||
|
# Import modules for hint processing and add list of their 'generate_hint' functions into hint dict.
|
||||||
|
# If the module doesn't have the function 'generate_hint', it will raise an exception
|
||||||
|
try:
|
||||||
|
hints['modules'].append(getattr(importlib.import_module(name), 'generate_hint'))
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
red_print(f'Failed to import "{name}" from "{hint_modules_dir}" as a module')
|
||||||
|
raise SystemExit(1)
|
||||||
|
except AttributeError:
|
||||||
|
red_print('Module "{}" does not have function generate_hint.'.format(name))
|
||||||
|
raise SystemExit(1)
|
||||||
|
|
||||||
return hints
|
return hints
|
||||||
|
|
||||||
|
|
||||||
def generate_hints_buffer(output: str, hints: list) -> Generator:
|
def generate_hints_buffer(output: str, hints: Dict) -> Generator:
|
||||||
"""Helper function to process hints within a string buffer"""
|
"""Helper function to process hints within a string buffer"""
|
||||||
for hint in hints:
|
# Call modules for possible hints with unchanged output. Note that
|
||||||
|
# hints in hints.yml expect new line trimmed, but modules should
|
||||||
|
# get the output unchanged. Please see tools/idf_py_actions/hints.yml
|
||||||
|
for generate_hint in hints['modules']:
|
||||||
|
module_hint = generate_hint(output)
|
||||||
|
if module_hint:
|
||||||
|
yield module_hint
|
||||||
|
|
||||||
|
# hints expect new lines trimmed
|
||||||
|
output = ' '.join(line.strip() for line in output.splitlines() if line.strip())
|
||||||
|
for hint in hints['yml']:
|
||||||
variables_list = hint.get('variables')
|
variables_list = hint.get('variables')
|
||||||
hint_list, hint_vars, re_vars = [], [], []
|
hint_list, hint_vars, re_vars = [], [], []
|
||||||
match: Optional[Match[str]] = None
|
match: Optional[Match[str]] = None
|
||||||
@@ -214,8 +250,7 @@ def generate_hints(*filenames: str) -> Generator:
|
|||||||
hints = load_hints()
|
hints = load_hints()
|
||||||
for file_name in filenames:
|
for file_name in filenames:
|
||||||
with open(file_name, 'r') as file:
|
with open(file_name, 'r') as file:
|
||||||
output = ' '.join(line.strip() for line in file if line.strip())
|
yield from generate_hints_buffer(file.read(), hints)
|
||||||
yield from generate_hints_buffer(output, hints)
|
|
||||||
|
|
||||||
|
|
||||||
def fit_text_in_terminal(out: str) -> str:
|
def fit_text_in_terminal(out: str) -> str:
|
||||||
|
Reference in New Issue
Block a user