Skip to content

textwrap.wrap() can hang when initial_indent or subsequent_indent is longer than width #160558

Closed as duplicate

Description

@devdavidejesus

Bug report

Bug description:

textwrap.wrap() (and fill()) can loop forever when an indent is longer than width:

import textwrap
textwrap.wrap(' a', width=3, initial_indent='----')  # never returns
textwrap.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.

CPython versions tested on:

3.13, 3.14, 3.15, CPython main branch

Operating systems tested on:

macOS

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