Skip to content

textwrap.wrap() and fill() loop forever when the indent is wider than width #158979

Open

Description

@sricursion

Bug report

Bug description:

textwrap.wrap() and textwrap.fill() never return when the indent is wider than width and the text starts with whitespace, or when drop_whitespace is false:

import textwrap

textwrap.wrap(' x', width=1, initial_indent='  ')
textwrap.wrap('abc', width=2, subsequent_indent='   ', drop_whitespace=False)

Both calls spin at 100% CPU forever. With drop_whitespace=False the list of lines inside _wrap_chunks() also grows without bound. Any text that starts with whitespace is enough to trigger it, for example one starting with a newline, as a triple-quoted string does: textwrap.wrap('\nHello', width=4, initial_indent=' ').

Expected: both calls return, with the text broken one character per line as the width < 1 guard in _handle_long_word() intends ([' x'] and ['ab', ' c']).

_handle_long_word() sets space_left = 1 when width < 1 so that at least one character is taken on every pass. If the chunk is a single character, it is used up completely, but reversed_chunks[-1] = chunk[end:] still stores the now empty string back as the next chunk. An empty chunk does not fit in a negative width, so _wrap_chunks() hands it to _handle_long_word() again and again. Usually the empty chunk is dropped as the leading whitespace chunk of the next line, so only a first line that starts with whitespace, or drop_whitespace=False, gets stuck.

A related symptom that does terminate: textwrap.wrap('x', width=1, initial_indent=' ', drop_whitespace=False) returns [' x', ''], and textwrap.wrap('abcdef', width=3, subsequent_indent=' ', drop_whitespace=False) ends with a spurious ' ' line.

CPython versions tested on:

CPython main branch, 3.13.1, 3.12

Operating systems tested on:

Windows

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions