From 6d689e8297c3528acbca1f6908776ec601c84675 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 26 May 2026 22:18:09 -0500 Subject: [PATCH] [core] Suppress deprecation warning for lambda values in tagged fields Lambda values in cv.sensitive(cv.templatable(...)) fields still hit the legacy regex because Lambda isn't a str and therefore doesn't carry the SensitiveStr tag. The field IS tagged correctly; warning the author to add cv.sensitive would be misleading. Still wrap the first line so the user-visible output matches the prior regex. --- esphome/__main__.py | 11 +++++++++-- tests/unit_tests/test_main.py | 14 ++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index 7049f8025e..f4e9e89e57 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -1441,8 +1441,15 @@ def _redact_with_legacy_fallback(output: str) -> str: unmarked: set[str] = set() def _replace(m: re.Match[str]) -> str: - unmarked.add(m.group("key")) - return f"{m.group('key')}: \\033[8m{m.group('val')}\\033[28m" + val = m.group("val") + # Lambda values in a ``cv.sensitive(cv.templatable(...))`` field still + # hit this branch because ``Lambda`` isn't a ``str`` and so doesn't + # carry the ``SensitiveStr`` tag. The field itself IS tagged; warning + # the author to add ``cv.sensitive`` would be misleading. Still wrap + # the first line so the user-visible output matches the prior regex. + if not val.startswith("!lambda"): + unmarked.add(m.group("key")) + return f"{m.group('key')}: \\033[8m{val}\\033[28m" output = _LEGACY_REDACTION_RE.sub(_replace, output) for key in sorted(unmarked): diff --git a/tests/unit_tests/test_main.py b/tests/unit_tests/test_main.py index 1873988f83..77f852688d 100644 --- a/tests/unit_tests/test_main.py +++ b/tests/unit_tests/test_main.py @@ -388,6 +388,20 @@ def test_redact_with_legacy_fallback__deduplicates_warnings( assert len(password_warnings) == 1 +def test_redact_with_legacy_fallback__suppresses_warning_for_lambda( + caplog: pytest.LogCaptureFixture, +) -> None: + """Lambda values in cv.sensitive(cv.templatable(...)) fields hit the + legacy regex (Lambda isn't str so SensitiveStr tagging doesn't apply), + but the field IS tagged. The warning would mislead the author, so it's + suppressed; the first line still gets wrapped for visual parity.""" + text = ' ssid: !lambda |-\n return "x";\n' + with caplog.at_level(logging.WARNING, logger="esphome.__main__"): + out = _redact_with_legacy_fallback(text) + assert "ssid: \\033[8m!lambda |-\\033[28m" in out + assert not any("legacy substring" in rec.message for rec in caplog.records) + + def test_redact_with_legacy_fallback__does_not_match_fragment_in_middle( caplog: pytest.LogCaptureFixture, ) -> None: