mirror of
https://github.com/esphome/esphome.git
synced 2026-10-07 03:16:37 +00:00
[core] Warn on crystal frequency mismatch during serial upload (#14582)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
8d988723cd
commit
6356e3def9
+36
-9
@@ -125,7 +125,12 @@ ANSI_ESCAPE = re.compile(r"\033[@-_][0-?]*[ -/]*[@-~]")
|
||||
|
||||
|
||||
class RedirectText:
|
||||
def __init__(self, out, filter_lines=None):
|
||||
def __init__(
|
||||
self,
|
||||
out,
|
||||
filter_lines: list[str] | None = None,
|
||||
line_callbacks: list[Callable[[str], str | None]] | None = None,
|
||||
) -> None:
|
||||
self._out = out
|
||||
if filter_lines is None:
|
||||
self._filter_pattern = None
|
||||
@@ -133,6 +138,7 @@ class RedirectText:
|
||||
pattern = r"|".join(r"(?:" + pattern + r")" for pattern in filter_lines)
|
||||
self._filter_pattern = re.compile(pattern)
|
||||
self._line_buffer = ""
|
||||
self._line_callbacks = line_callbacks or []
|
||||
|
||||
def __getattr__(self, item):
|
||||
return getattr(self._out, item)
|
||||
@@ -157,7 +163,7 @@ class RedirectText:
|
||||
if not isinstance(s, str):
|
||||
s = s.decode()
|
||||
|
||||
if self._filter_pattern is not None:
|
||||
if self._filter_pattern is not None or self._line_callbacks:
|
||||
self._line_buffer += s
|
||||
lines = self._line_buffer.splitlines(True)
|
||||
for line in lines:
|
||||
@@ -169,7 +175,10 @@ class RedirectText:
|
||||
|
||||
line_without_ansi = ANSI_ESCAPE.sub("", line)
|
||||
line_without_end = line_without_ansi.rstrip()
|
||||
if self._filter_pattern.match(line_without_end) is not None:
|
||||
if (
|
||||
self._filter_pattern is not None
|
||||
and self._filter_pattern.match(line_without_end) is not None
|
||||
):
|
||||
# Filter pattern matched, ignore the line
|
||||
continue
|
||||
|
||||
@@ -181,6 +190,9 @@ class RedirectText:
|
||||
and (help_msg := get_esp32_arduino_flash_error_help())
|
||||
):
|
||||
self._write_color_replace(help_msg)
|
||||
for callback in self._line_callbacks:
|
||||
if msg := callback(line_without_end):
|
||||
self._write_color_replace(msg)
|
||||
else:
|
||||
self._write_color_replace(s)
|
||||
|
||||
@@ -194,7 +206,11 @@ class RedirectText:
|
||||
|
||||
|
||||
def run_external_command(
|
||||
func, *cmd, capture_stdout: bool = False, filter_lines: str = None
|
||||
func,
|
||||
*cmd,
|
||||
capture_stdout: bool = False,
|
||||
filter_lines: list[str] | None = None,
|
||||
line_callbacks: list[Callable[[str], str | None]] | None = None,
|
||||
) -> int | str:
|
||||
"""
|
||||
Run a function from an external package that acts like a main method.
|
||||
@@ -204,7 +220,9 @@ def run_external_command(
|
||||
:param func: Function to execute
|
||||
:param cmd: Command to run as (eg first element of sys.argv)
|
||||
:param capture_stdout: Capture text from stdout and return that.
|
||||
:param filter_lines: Regular expression used to filter captured output.
|
||||
Note: line_callbacks are not invoked when capture_stdout is True.
|
||||
:param filter_lines: Regular expressions used to filter captured output.
|
||||
:param line_callbacks: Callbacks invoked per line; non-None returns are written to output.
|
||||
:return: str if `capture_stdout` is set else int exit code.
|
||||
|
||||
"""
|
||||
@@ -218,9 +236,13 @@ def run_external_command(
|
||||
_LOGGER.debug("Running: %s", full_cmd)
|
||||
|
||||
orig_stdout = sys.stdout
|
||||
sys.stdout = RedirectText(sys.stdout, filter_lines=filter_lines)
|
||||
sys.stdout = RedirectText(
|
||||
sys.stdout, filter_lines=filter_lines, line_callbacks=line_callbacks
|
||||
)
|
||||
orig_stderr = sys.stderr
|
||||
sys.stderr = RedirectText(sys.stderr, filter_lines=filter_lines)
|
||||
sys.stderr = RedirectText(
|
||||
sys.stderr, filter_lines=filter_lines, line_callbacks=line_callbacks
|
||||
)
|
||||
|
||||
if capture_stdout:
|
||||
cap_stdout = sys.stdout = io.StringIO()
|
||||
@@ -254,14 +276,19 @@ def run_external_process(*cmd: str, **kwargs: Any) -> int | str:
|
||||
full_cmd = " ".join(shlex_quote(x) for x in cmd)
|
||||
_LOGGER.debug("Running: %s", full_cmd)
|
||||
filter_lines = kwargs.get("filter_lines")
|
||||
line_callbacks = kwargs.get("line_callbacks")
|
||||
|
||||
capture_stdout = kwargs.get("capture_stdout", False)
|
||||
if capture_stdout:
|
||||
sub_stdout = subprocess.PIPE
|
||||
else:
|
||||
sub_stdout = RedirectText(sys.stdout, filter_lines=filter_lines)
|
||||
sub_stdout = RedirectText(
|
||||
sys.stdout, filter_lines=filter_lines, line_callbacks=line_callbacks
|
||||
)
|
||||
|
||||
sub_stderr = RedirectText(sys.stderr, filter_lines=filter_lines)
|
||||
sub_stderr = RedirectText(
|
||||
sys.stderr, filter_lines=filter_lines, line_callbacks=line_callbacks
|
||||
)
|
||||
|
||||
try:
|
||||
proc = subprocess.run(
|
||||
|
||||
Reference in New Issue
Block a user