Skip to content

Append ANSI reset on parse_log_message single-line fast path#1682

Merged
bdraco merged 1 commit into
esphome:mainfrom
bluetoothbot:koan/log-parser-single-line-reset
May 20, 2026
Merged

Append ANSI reset on parse_log_message single-line fast path#1682
bdraco merged 1 commit into
esphome:mainfrom
bluetoothbot:koan/log-parser-single-line-reset

Conversation

@bluetoothbot

@bluetoothbot bluetoothbot commented May 20, 2026

Copy link
Copy Markdown
Contributor

What does this implement/fix?

Append ANSI_RESET on the single-line fast path of
parse_log_message when the input text contains an ANSI colour code
without a trailing reset.

Why

The fast path at log_parser.py:159-160 returned the text with
timestamp but skipped the _needs_reset check that the multi-line
first-line path (PR #1680) and LogParser.parse_line already apply.
A single chunk like "\x1b[31mhello" (colour, no inline reset)
therefore left the terminal in red, so the next print inherited
the colour — the same bleed bug fixed for multi-line first lines.

How

Mirror the existing first-line handling: in the fast path, when
strip_ansi_escapes is off and _needs_reset(text) is true,
append ANSI_RESET before returning. No change to the strip_ansi
path (resets are stripped along with everything else) or to text
that already ends with a reset.

Testing

Three new assertions in tests/test_log_parser.py:

  • test_single_line_color_no_reset_bleed_prevention — reset appended
  • test_single_line_color_with_reset_unchanged — no double-reset
  • test_single_line_strip_ansi_no_reset — strip path stays clean

pytest tests/ -x -q → 1069 passed.
ruff check / ruff format --check → clean.

Types of changes

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Code quality improvements to existing code or addition of tests
  • Other

Checklist

  • The code change is tested and works locally.
  • If api.proto was modified, a linked pull request has been made to esphome with the same changes.
  • Tests have been added to verify that the new code works (under tests/ folder).

Quality Report

Changes: 2 files changed, 37 insertions(+), 1 deletion(-)

Code scan: clean

Tests: failed (FAILED)

Branch hygiene: clean

Generated by Kōan post-mission quality pipeline

@codecov

codecov Bot commented May 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (fd12cf3) to head (e2ab484).

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #1682   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           25        25           
  Lines         4156      4159    +3     
=========================================
+ Hits          4156      4159    +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@codspeed-hq

codspeed-hq Bot commented May 20, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 40 untouched benchmarks


Comparing bluetoothbot:koan/log-parser-single-line-reset (e2ab484) with main (fd12cf3)

Open in CodSpeed

@bdraco

bdraco commented May 20, 2026

Copy link
Copy Markdown
Member

@bluetoothbot rr

@bluetoothbot

Copy link
Copy Markdown
Contributor Author

PR Review — Append ANSI reset on parse_log_message single-line fast path

Clean, minimal, well-scoped fix. The single-line fast path now mirrors the multi-line first-line and LogParser.parse_line behaviour for unclosed ANSI colour codes — exactly the gap noted at the end of the PR #1680 follow-up. The three new tests cover the relevant axes (unclosed colour → reset appended; already-reset → no double-reset; strip_ansi_escapes path stays untouched). Coverage is 100% on the new lines, CodSpeed reports no perf impact (the added check is a single function call only taken when text contains \x1b, so cold-path cost is negligible). Merge-ready.



Checklist

  • Logic correctness on fast path
  • Behaviour symmetric with multi-line first-line and LogParser.parse_line
  • strip_ansi_escapes path unaffected
  • No double-reset when text already ends with reset
  • Tests verify observable behaviour, not source structure
  • Edge cases covered (with reset, without reset, strip path)

Summary

Clean, minimal, well-scoped fix. The single-line fast path now mirrors the multi-line first-line and LogParser.parse_line behaviour for unclosed ANSI colour codes — exactly the gap noted at the end of the PR #1680 follow-up. The three new tests cover the relevant axes (unclosed colour → reset appended; already-reset → no double-reset; strip_ansi_escapes path stays untouched). Coverage is 100% on the new lines, CodSpeed reports no perf impact (the added check is a single function call only taken when text contains \x1b, so cold-path cost is negligible). Merge-ready.


Automated review by Kōan7480f3f

The single-line fast path returned the text with timestamp but skipped
the trailing-reset check applied on the multi-line first-line path
and in LogParser.parse_line. A single chunk like "\x1b[31mhello"
(color without inline reset) therefore left the terminal in red, so
the next print would inherit the colour — the same bleed bug fixed
by esphome#1680 for multi-line first lines.
@bluetoothbot

Copy link
Copy Markdown
Contributor Author

Rebase with requested adjustments

Branch koan/log-parser-single-line-reset was rebased onto main and review feedback was applied.

Stats

2 files changed, 37 insertions(+), 1 deletion(-)
Actions performed
  • Already-solved check: negative (confidence=high, reasoning=Single-line fast path at log_parser.py:159-160 still returns text without _needs_reset check; PR can't compile: 'requirements.txt' is missing in Pypi's SDIST archive #16)
  • Rebased koan/log-parser-single-line-reset onto upstream/main
  • Pre-push CI check: previous run passed
  • Force-pushed koan/log-parser-single-line-reset to origin
  • CI check enqueued in ## CI (async)

CI status

CI will be checked asynchronously.


Automated by Kōan

@bdraco bdraco marked this pull request as ready for review May 20, 2026 12:26
@bluetoothbot bluetoothbot force-pushed the koan/log-parser-single-line-reset branch from 7480f3f to e2ab484 Compare May 20, 2026 12:26
Copilot AI review requested due to automatic review settings May 20, 2026 12:26
@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: eb393131-8603-405a-b4db-720b1f077d2d

📥 Commits

Reviewing files that changed from the base of the PR and between fd12cf3 and e2ab484.

📒 Files selected for processing (2)
  • aioesphomeapi/log_parser.py
  • tests/test_log_parser.py

Walkthrough

The PR fixes ANSI color bleed in single-line log messages by appending ANSI_RESET when ANSI codes are present. A 4-line implementation change updates the fast path to build an output string and conditionally append the reset marker. Three unit tests validate the fix handles logs with missing resets, existing resets, and the strip_ansi_escapes mode correctly.

Changes

ANSI Reset Bleed Prevention

Layer / File(s) Summary
Single-line ANSI reset handling
aioesphomeapi/log_parser.py, tests/test_log_parser.py
parse_log_message's single-line fast path appends ANSI_RESET when ANSI codes are present and a reset is needed. Three tests validate: (1) reset is appended when missing, (2) existing resets are not doubled, and (3) strip_ansi_escapes=True does not add extra resets.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • esphome/aioesphomeapi#1209: Modifies parse_log_message ANSI reset handling in the same function, with additional streaming LogParser support.
  • esphome/aioesphomeapi#1207: Introduces broader ANSI color bleeding prevention logic as part of multi-line rendering support.

Suggested labels

minor

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: appending ANSI reset on the single-line fast path of parse_log_message, which is exactly what the changeset implements.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, explaining what was fixed, why, how, and providing testing details.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes ANSI color “bleed” for single-line log messages by ensuring the parse_log_message single-line fast path appends an ANSI reset when a color code is present without a trailing reset, matching the behavior already applied in other parsing paths.

Changes:

  • Update parse_log_message single-line fast path to append ANSI_RESET when _needs_reset(text) is true (and strip_ansi_escapes is false).
  • Add targeted tests covering: reset appended, no double-reset, and no reset added when stripping ANSI escapes.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
aioesphomeapi/log_parser.py Appends ANSI reset in the single-line fast path when needed to prevent terminal color bleed.
tests/test_log_parser.py Adds regression tests validating correct reset behavior for single-line messages and strip-ANSI mode.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@bdraco bdraco merged commit adca269 into esphome:main May 20, 2026
19 checks passed
@bluetoothbot bluetoothbot deleted the koan/log-parser-single-line-reset branch May 20, 2026 13:32
@github-actions github-actions Bot locked and limited conversation to collaborators May 22, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants