You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
textwrap.wrap() can hang when initial_indent or subsequent_indent is longer than width #160558
textwrap.wrap() (and fill()) can loop forever when an indent is longer than width:
importtextwraptextwrap.wrap(' a', width=3, initial_indent='----') # never returnstextwrap.wrap('aaaa', width=3, subsequent_indent='----', drop_whitespace=False) # never returns
The first case needs the text to start with whitespace: textwrap.wrap('a', width=3, initial_indent='----') returns ['----a']. With an indent exactly as long as width, both calls return (the first one gives ['---a']).
In TextWrapper._wrap_chunks() the room left on a line is self.width - len(indent), which is negative here. A chunk that does not fit goes to _handle_long_word(), which then moves one character at a time onto the line (space_left = 1 when the room is less than 1). When it takes the last character of a chunk, it leaves an empty chunk behind.
In the first case that chunk is the leading whitespace. Each character moved onto the line is dropped again as trailing whitespace, so no line is ever added, and leading whitespace is only dropped after the first line. In the second case drop_whitespace=False keeps the empty chunk at the start of the next line.
An empty chunk never satisfies cur_len + l <= width while the room is negative, so it goes back to _handle_long_word(), which takes nothing from it, and the loop never ends.
Accepting zero-length chunks in that test (cur_len + l <= width or not l) fixes both cases. When the room is exactly 0 an empty chunk already passes the test, so the output now matches that case.
Activity