Skip to content

fix for infinite loop in split_graphemes#4006

Merged
willmcgugan merged 7 commits intomasterfrom
fix-grapheme-stuck
Feb 19, 2026
Merged

fix for infinite loop in split_graphemes#4006
willmcgugan merged 7 commits intomasterfrom
fix-grapheme-stuck

Conversation

@willmcgugan
Copy link
Member

Fix for #3958

@codecov-commenter
Copy link

codecov-commenter commented Feb 19, 2026

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.87%. Comparing base (1568912) to head (905b397).
⚠️ Report is 9 commits behind head on master.
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #4006   +/-   ##
=======================================
  Coverage   97.87%   97.87%           
=======================================
  Files          96       96           
  Lines        8366     8370    +4     
=======================================
+ Hits         8188     8192    +4     
  Misses        178      178           
Flag Coverage Δ
unittests 97.87% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ 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.

@willmcgugan
Copy link
Member Author

@jmw182 Feel free to kick the tires.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes a hang in Rich’s terminal cell measurement logic (rich.cells.split_graphemes) when encountering zero-width characters such as ANSI escape codes, addressing #3958.

Changes:

  • Updated split_graphemes to ensure the loop advances for certain zero-width/special codepoints instead of stalling.
  • Added regression tests for zero-width inputs in chop_cells / split_graphemes.
  • Documented the fix in CHANGELOG.md under “Unreleased”.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.

File Description
rich/cells.py Adjusts grapheme splitting logic to avoid non-advancing index scenarios for zero-width/special characters.
tests/test_cells.py Adds regression coverage for zero-width inputs (and updates expected spans/cell lengths).
CHANGELOG.md Notes the infinite-loop fix in the Unreleased section.

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

Comment on lines 183 to 186

total_width = 0
spans: list[tuple[int, int, int]] = []
SPECIAL = {"\u200d", "\ufe0f"}
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

The new if not spans handling for SPECIAL chars avoids hangs when the string starts with VS16/ZWJ, but split_graphemes can still hang on "\ufe0f" when spans is non-empty and last_measured_character is None (e.g. "\x1b\ufe0f" after the new zero-width span logic). In that case the VS16 branch doesn't advance index. Make sure VS16 always increments index (and extends/creates a span) even when there is no prior measured character.

Copilot uses AI. Check for mistakes.
(
"\u200d\u200d",
[(0, 2, 0)],
0,
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

Remove the print(spans) debug output from this test; it will add noise to test runs/CI output and isn't needed for assertions.

Copilot uses AI. Check for mistakes.
Copy link
Member Author

Choose a reason for hiding this comment

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

The print is removed by pytest if the test passes.

0,
), # Variation selector 16, without anything to change should have zero width
(
"\ufe0f\ufe0f",
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

Typo in comment: "within noting prior" → "with nothing prior".

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Copilot AI commented Feb 19, 2026

@willmcgugan I've opened a new pull request, #4007, to work on those changes. Once the pull request is ready, I'll request review from you.

@willmcgugan willmcgugan merged commit 7338cb9 into master Feb 19, 2026
24 checks passed
@willmcgugan willmcgugan deleted the fix-grapheme-stuck branch February 19, 2026 17:04
@willmcgugan willmcgugan mentioned this pull request Feb 19, 2026
10 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants