-
-
Notifications
You must be signed in to change notification settings - Fork 2k
Open
Labels
Description
- I've checked docs and closed issues for possible solutions.
- I can't find my issue in the FAQ.
Describe the bug
As the title says
from rich import get_console
console = get_console()
console.print('1\u200d2')
# --- Or a simpler one ---
from rich import print as rich_print
rich_print('\u200d')
# --- This can output normally, but b has been stretched---
from rich import print as rich_print
rich_print('a\u200db')
# --- But this still throws a RuntimeError --
from rich import print as rich_print
rich_print('a\u200d\nb')
# --- Including this...---
from rich import print as rich_print
rich_print('a\u200db(') Perhaps it's missing a check for whether \u200d is the last character here?
Lines 138 to 150 in 1d402e0
| iter_characters = iter(text) | |
| for character in iter_characters: | |
| if character in SPECIAL: | |
| if character == "\u200d": | |
| next(iter_characters) | |
| elif last_measured_character: | |
| total_width += last_measured_character in cell_table.narrow_to_wide | |
| last_measured_character = None | |
| else: | |
| if character_width := get_character_cell_size(character, unicode_version): | |
| last_measured_character = character | |
| total_width += character_width |
Traceback (show_locals=True)
Click to expand
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /usr/local/python3.14/lib/python3.14/site-packages/rich/segment.py:375 in <genexpr> │
│ │
│ 372 │ │ Returns: │
│ 373 │ │ │ List[Segment]: A line of segments with the desired length. │
│ 374 │ │ """ │
│ ❱ 375 │ │ line_length = sum(segment.cell_length for segment in line) │
│ 376 │ │ new_line: List[Segment] │
│ 377 │ │ │
│ 378 │ │ if line_length < length: │
│ │
│ ╭───────────────────── locals ─────────────────────╮ │
│ │ .0 = <list_iterator object at 0x74b7f85870> │ │
│ │ segment = Segment('\u200d', Style()) │ │
│ ╰──────────────────────────────────────────────────╯ │
│ │
│ /usr/local/python3.14/lib/python3.14/site-packages/rich/segment.py:89 in cell_length │
│ │
│ 86 │ │ │ int: A number of cells. │
│ 87 │ │ """ │
│ 88 │ │ text, _style, control = self │
│ ❱ 89 │ │ return 0 if control else cell_len(text) │
│ 90 │ │
│ 91 │ def __rich_repr__(self) -> Result: │
│ 92 │ │ yield self.text │
│ │
│ ╭─────────────── locals ───────────────╮ │
│ │ _style = Style() │ │
│ │ control = None │ │
│ │ self = Segment('\u200d', Style()) │ │
│ │ text = '\u200d' │ │
│ ╰──────────────────────────────────────╯ │
│ │
│ /usr/local/python3.14/lib/python3.14/site-packages/rich/cells.py:106 in cell_len │
│ │
│ 103 │ │ Length of string in terminal cells. │
│ 104 │ """ │
│ 105 │ if len(text) < 512: │
│ ❱ 106 │ │ return cached_cell_len(text, unicode_version) │
│ 107 │ return _cell_len(text, unicode_version) │
│ 108 │
│ 109 │
│ │
│ ╭────────── locals ──────────╮ │
│ │ text = '\u200d' │ │
│ │ unicode_version = 'auto' │ │
│ ╰────────────────────────────╯ │
│ │
│ /usr/local/python3.14/lib/python3.14/site-packages/rich/cells.py:92 in cached_cell_len │
│ │
│ 89 │ Returns: │
│ 90 │ │ int: Get the number of cells required to display text. │
│ 91 │ """ │
│ ❱ 92 │ return _cell_len(text, unicode_version) │
│ 93 │
│ 94 │
│ 95 def cell_len(text: str, unicode_version: str = "auto") -> int: │
│ │
│ ╭────────── locals ──────────╮ │
│ │ text = '\u200d' │ │
│ │ unicode_version = 'auto' │ │
│ ╰────────────────────────────╯ │
│ │
│ /usr/local/python3.14/lib/python3.14/site-packages/rich/cells.py:143 in _cell_len │
│ │
│ 140 │ for character in iter_characters: │
│ 141 │ │ if character in SPECIAL: │
│ 142 │ │ │ if character == "\u200d": │
│ ❱ 143 │ │ │ │ next(iter_characters) │
│ 144 │ │ │ elif last_measured_character: │
│ 145 │ │ │ │ total_width += last_measured_character in cell_table.narrow_to_wide │
│ 146 │ │ │ │ last_measured_character = None │
│ │
│ ╭──────────────────────────── locals ─────────────────────────────╮ │
│ │ cell_table = CellTable( │ │
│ │ │ unicode_version='17.0.0', │ │
│ │ │ widths=[ │ │
│ │ │ │ (0, 0, 0), │ │
│ │ │ │ (768, 879, 0), │ │
│ │ │ │ (1155, 1161, 0), │ │
│ │ │ │ (1425, 1469, 0), │ │
│ │ │ │ (1471, 1471, 0), │ │
│ │ │ │ (1473, 1474, 0), │ │
│ │ │ │ (1476, 1477, 0), │ │
│ │ │ │ (1479, 1479, 0), │ │
│ │ │ │ (1552, 1562, 0), │ │
│ │ │ │ (1564, 1564, 0), │ │
│ │ │ │ ... +454 │ │
│ │ │ ], │ │
│ │ │ narrow_to_wide=frozenset({ │ │
│ │ │ │ '↙', │ │
│ │ │ │ '⚜', │ │
│ │ │ │ '🛳', │ │
│ │ │ │ '🏝', │ │
│ │ │ │ '☝', │ │
│ │ │ │ '🖊', │ │
│ │ │ │ '🖌', │ │
│ │ │ │ '🌨', │ │
│ │ │ │ '🖨', │ │
│ │ │ │ '🗒', │ │
│ │ │ │ ... +203 │ │
│ │ │ }) │ │
│ │ ) │ │
│ │ character = '\u200d' │ │
│ │ iter_characters = <str_iterator object at 0x74b6265b40> │ │
│ │ last_measured_character = None │ │
│ │ SPECIAL = {'️', '\u200d'} │ │
│ │ text = '\u200d' │ │
│ │ total_width = 0 │ │
│ │ unicode_version = 'auto' │ │
│ ╰─────────────────────────────────────────────────────────────────╯ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
StopIteration
The above exception was the direct cause of the following exception:
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ in <module>:1 │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │ asyncio = <module 'asyncio' from │ │
│ │ '/usr/local/python3.14/lib/python3.14/asyncio/__init__.py'> │ │
│ │ console = <console width=201 ColorSystem.EIGHT_BIT> │ │
│ │ rich = <module 'rich' from │ │
│ │ '/usr/local/python3.14/lib/python3.14/site-packages/rich/__init__.py'> │ │
│ │ rich_print = <bound method Console.print of <console width=201 ColorSystem.EIGHT_BIT>> │ │
│ │ threading = <module 'threading' from '/usr/local/python3.14/lib/python3.14/threading.py'> │ │
│ │ typing = <module 'typing' from '/usr/local/python3.14/lib/python3.14/typing.py'> │ │
│ │ uuid = <module 'uuid' from '/usr/local/python3.14/lib/python3.14/uuid.py'> │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ /usr/local/python3.14/lib/python3.14/site-packages/rich/__init__.py:74 in print │
│ │
│ 71 │ from .console import Console │
│ 72 │ │
│ 73 │ write_console = get_console() if file is None else Console(file=file) │
│ ❱ 74 │ return write_console.print(*objects, sep=sep, end=end) │
│ 75 │
│ 76 │
│ 77 def print_json( │
│ │
│ ╭───────────────────────── locals ──────────────────────────╮ │
│ │ end = '\n' │ │
│ │ file = None │ │
│ │ flush = False │ │
│ │ objects = ('1\u200d2',) │ │
│ │ sep = ' ' │ │
│ │ write_console = <console width=201 ColorSystem.EIGHT_BIT> │ │
│ ╰───────────────────────────────────────────────────────────╯ │
│ │
│ /usr/local/python3.14/lib/python3.14/site-packages/rich/console.py:1744 in print │
│ │
│ 1741 │ │ │ │ │ new_segments.insert(0, Segment.line()) │
│ 1742 │ │ │ if crop: │
│ 1743 │ │ │ │ buffer_extend = self._buffer.extend │
│ ❱ 1744 │ │ │ │ for line in Segment.split_and_crop_lines( │
│ 1745 │ │ │ │ │ new_segments, self.width, pad=False │
│ 1746 │ │ │ │ ): │
│ 1747 │ │ │ │ │ buffer_extend(line) │
│ │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │ buffer_extend = <built-in method extend of list object at 0x74b62903c0> │ │
│ │ crop = True │ │
│ │ emoji = None │ │
│ │ end = '\n' │ │
│ │ extend = <built-in method extend of list object at 0x74b60bd0c0> │ │
│ │ height = None │ │
│ │ highlight = None │ │
│ │ justify = None │ │
│ │ markup = None │ │
│ │ new_line_start = False │ │
│ │ new_segments = [ │ │
│ │ │ Segment( │ │
│ │ │ │ '1', │ │
│ │ │ │ Style( │ │
│ │ │ │ │ color=Color('cyan', ColorType.STANDARD, number=6), │ │
│ │ │ │ │ bold=True, │ │
│ │ │ │ │ italic=False │ │
│ │ │ │ ) │ │
│ │ │ ), │ │
│ │ │ Segment('\u200d', Style()), │ │
│ │ │ Segment( │ │
│ │ │ │ '2', │ │
│ │ │ │ Style( │ │
│ │ │ │ │ color=Color('cyan', ColorType.STANDARD, number=6), │ │
│ │ │ │ │ bold=True, │ │
│ │ │ │ │ italic=False │ │
│ │ │ │ ) │ │
│ │ │ ), │ │
│ │ │ Segment('\n') │ │
│ │ ] │ │
│ │ no_wrap = None │ │
│ │ objects = ('1\u200d2',) │ │
│ │ overflow = None │ │
│ │ render = <bound method Console.render of <console width=201 ColorSystem.EIGHT_BIT>> │ │
│ │ render_hooks = [] │ │
│ │ render_options = ConsoleOptions( │ │
│ │ │ size=ConsoleDimensions(width=201, height=42), │ │
│ │ │ legacy_windows=False, │ │
│ │ │ min_width=1, │ │
│ │ │ max_width=201, │ │
│ │ │ is_terminal=True, │ │
│ │ │ encoding='utf-8', │ │
│ │ │ max_height=42, │ │
│ │ │ justify=None, │ │
│ │ │ overflow=None, │ │
│ │ │ no_wrap=None, │ │
│ │ │ highlight=None, │ │
│ │ │ markup=None, │ │
│ │ │ height=None │ │
│ │ ) │ │
│ │ renderable = <text '1\u200d2' [Span(0, 1, 'repr.number'), Span(2, 3, 'repr.number')] ''> │ │
│ │ renderables = [ │ │
│ │ │ <text '1\u200d2' [Span(0, 1, 'repr.number'), Span(2, 3, 'repr.number')] │ │
│ │ ''> │ │
│ │ ] │ │
│ │ self = <console width=201 ColorSystem.EIGHT_BIT> │ │
│ │ sep = ' ' │ │
│ │ soft_wrap = False │ │
│ │ style = None │ │
│ │ width = None │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ /usr/local/python3.14/lib/python3.14/site-packages/rich/segment.py:344 in split_and_crop_lines │
│ │
│ 341 │ │ │ │ │ if _text: │
│ 342 │ │ │ │ │ │ append(cls(_text, segment_style)) │
│ 343 │ │ │ │ │ if new_line: │
│ ❱ 344 │ │ │ │ │ │ cropped_line = adjust_line_length( │
│ 345 │ │ │ │ │ │ │ line, length, style=style, pad=pad │
│ 346 │ │ │ │ │ │ ) │
│ 347 │ │ │ │ │ │ if include_new_lines: │
│ │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │ _ = None │ │
│ │ _text = '' │ │
│ │ adjust_line_length = <bound method Segment.adjust_line_length of <class │ │
│ │ 'rich.segment.Segment'>> │ │
│ │ append = <built-in method append of list object at 0x74b60ae640> │ │
│ │ include_new_lines = True │ │
│ │ length = 201 │ │
│ │ line = [ │ │
│ │ │ Segment( │ │
│ │ │ │ '1', │ │
│ │ │ │ Style( │ │
│ │ │ │ │ color=Color('cyan', ColorType.STANDARD, number=6), │ │
│ │ │ │ │ bold=True, │ │
│ │ │ │ │ italic=False │ │
│ │ │ │ ) │ │
│ │ │ ), │ │
│ │ │ Segment('\u200d', Style()), │ │
│ │ │ Segment( │ │
│ │ │ │ '2', │ │
│ │ │ │ Style( │ │
│ │ │ │ │ color=Color('cyan', ColorType.STANDARD, number=6), │ │
│ │ │ │ │ bold=True, │ │
│ │ │ │ │ italic=False │ │
│ │ │ │ ) │ │
│ │ │ ) │ │
│ │ ] │ │
│ │ new_line = '\n' │ │
│ │ new_line_segment = Segment('\n') │ │
│ │ pad = False │ │
│ │ segment = Segment('\n') │ │
│ │ segment_style = None │ │
│ │ segments = [ │ │
│ │ │ Segment( │ │
│ │ │ │ '1', │ │
│ │ │ │ Style( │ │
│ │ │ │ │ color=Color('cyan', ColorType.STANDARD, number=6), │ │
│ │ │ │ │ bold=True, │ │
│ │ │ │ │ italic=False │ │
│ │ │ │ ) │ │
│ │ │ ), │ │
│ │ │ Segment('\u200d', Style()), │ │
│ │ │ Segment( │ │
│ │ │ │ '2', │ │
│ │ │ │ Style( │ │
│ │ │ │ │ color=Color('cyan', ColorType.STANDARD, number=6), │ │
│ │ │ │ │ bold=True, │ │
│ │ │ │ │ italic=False │ │
│ │ │ │ ) │ │
│ │ │ ), │ │
│ │ │ Segment('\n') │ │
│ │ ] │ │
│ │ style = None │ │
│ │ text = '' │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ /usr/local/python3.14/lib/python3.14/site-packages/rich/segment.py:375 in adjust_line_length │
│ │
│ 372 │ │ Returns: │
│ 373 │ │ │ List[Segment]: A line of segments with the desired length. │
│ 374 │ │ """ │
│ ❱ 375 │ │ line_length = sum(segment.cell_length for segment in line) │
│ 376 │ │ new_line: List[Segment] │
│ 377 │ │ │
│ 378 │ │ if line_length < length: │
│ │
│ ╭──────────────────────────────── locals ─────────────────────────────────╮ │
│ │ length = 201 │ │
│ │ line = [ │ │
│ │ │ Segment( │ │
│ │ │ │ '1', │ │
│ │ │ │ Style( │ │
│ │ │ │ │ color=Color( │ │
│ │ │ │ │ │ 'cyan', │ │
│ │ │ │ │ │ ColorType.STANDARD, │ │
│ │ │ │ │ │ number=6 │ │
│ │ │ │ │ ), │ │
│ │ │ │ │ bold=True, │ │
│ │ │ │ │ italic=False │ │
│ │ │ │ ) │ │
│ │ │ ), │ │
│ │ │ Segment('\u200d', Style()), │ │
│ │ │ Segment( │ │
│ │ │ │ '2', │ │
│ │ │ │ Style( │ │
│ │ │ │ │ color=Color( │ │
│ │ │ │ │ │ 'cyan', │ │
│ │ │ │ │ │ ColorType.STANDARD, │ │
│ │ │ │ │ │ number=6 │ │
│ │ │ │ │ ), │ │
│ │ │ │ │ bold=True, │ │
│ │ │ │ │ italic=False │ │
│ │ │ │ ) │ │
│ │ │ ) │ │
│ │ ] │ │
│ │ pad = False │ │
│ │ style = None │ │
│ ╰─────────────────────────────────────────────────────────────────────────╯ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
RuntimeError: generator raised StopIteration
Platform
Click to expand
╭───────────────────────── <class 'rich.console.Console'> ─────────────────────────╮
│ A high level console interface. │
│ │
│ ╭──────────────────────────────────────────────────────────────────────────────╮ │
│ │ <console width=201 ColorSystem.EIGHT_BIT> │ │
│ ╰──────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ color_system = '256' │
│ encoding = 'utf-8' │
│ file = <_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'> │
│ height = 42 │
│ is_alt_screen = False │
│ is_dumb_terminal = False │
│ is_interactive = True │
│ is_jupyter = False │
│ is_terminal = True │
│ legacy_windows = False │
│ no_color = False │
│ options = ConsoleOptions( │
│ size=ConsoleDimensions(width=201, height=42), │
│ legacy_windows=False, │
│ min_width=1, │
│ max_width=201, │
│ is_terminal=True, │
│ encoding='utf-8', │
│ max_height=42, │
│ justify=None, │
│ overflow=None, │
│ no_wrap=False, │
│ highlight=None, │
│ markup=None, │
│ height=None │
│ ) │
│ quiet = False │
│ record = False │
│ safe_box = True │
│ size = ConsoleDimensions(width=201, height=42) │
│ soft_wrap = False │
│ stderr = False │
│ style = None │
│ tab_size = 8 │
│ width = 201 │
╰──────────────────────────────────────────────────────────────────────────────────╯
╭─── <class 'rich._windows.WindowsConsoleFeatures'> ────╮
│ Windows features available. │
│ │
│ ╭───────────────────────────────────────────────────╮ │
│ │ WindowsConsoleFeatures(vt=False, truecolor=False) │ │
│ ╰───────────────────────────────────────────────────╯ │
│ │
│ truecolor = False │
│ vt = False │
╰───────────────────────────────────────────────────────╯
╭────── Environment Variables ───────╮
│ { │
│ 'CLICOLOR': None, │
│ 'COLORTERM': None, │
│ 'COLUMNS': None, │
│ 'JPY_PARENT_PID': None, │
│ 'JUPYTER_COLUMNS': None, │
│ 'JUPYTER_LINES': None, │
│ 'LINES': None, │
│ 'NO_COLOR': None, │
│ 'TERM_PROGRAM': None, │
│ 'TERM': 'xterm-256color', │
│ 'TTY_COMPATIBLE': None, │
│ 'TTY_INTERACTIVE': None, │
│ 'VSCODE_VERBOSE_LOGGING': None │
│ } │
╰────────────────────────────────────╯
platform="Linux"
rich==14.3.1