Handle wrapping when indentation exhausts the available width

JI
1d ago
+56-3

Fixes #178.

Formatting can raise ValueError when a valid positive width is consumed by indentation. String/byte wrapping gets a zero range step, and raw repr wrapping gives textwrap a non-positive width. Deep nesting can hit the latter even at the default width.

Keep the remaining wrapping budget at least one character in both paths. When raw reprs wrap at one character, retain every space and tab as content instead of letting textwrap discard or normalize it. Preserve indentation and normal-width wrapping. This does not change syntax-highlighting behavior in #161 or circular-reference handling in #177.

Validation using the frozen uv.lock, CPython 3.13.12 on macOS:

  • Original 17 string/bytes/bytearray/raw-repr cases: base 9 fail / 8 pass; fixed 17 pass. Includes narrow widths, default-width deep nesting and highlighting on/off.
  • 18 additional exact-content raw-repr whitespace cases: all fail on prior PR head d5c1172 and pass after the follow-up. Covers zero, negative and one-character remaining widths, spaces/tabs and highlighting on/off.
  • env -u NO_COLOR CONTEXT=macOS-py3.13-with-extras COLUMNS=150 UV_FROZEN=1 uv run coverage run -m pytest: 185 passed, 4 skipped.
  • UV_FROZEN=1 make lint: Ruff format/check and strict basedpyright all pass, 0 type errors/warnings.
  • SHA-bound independent Codex Standards/Spec incremental reviews: 0 pending findings. Original reviews and validation remain preserved separately.

The execution environment sets NO_COLOR=1, which makes an unrelated existing test_print_is_tty fail on both the base and this branch. It passes with that variable unset; no ANSI code/test was changed to hide it. Other Python/OS combinations have not been run locally. Upstream CI for the original head passed; a new run is required for the follow-up commit and is not represented as passing by local results.

AI assistance: OpenAI GPT-6 (Codex) performed reproduction, implementation, tests, drafting and independent agent reviews at the account owner's request.


Summary by cubic

Fixes a ValueError crash when indentation exhausts the available formatting width. String/byte wrapping could get a zero-width range step, and raw repr wrapping could pass a non-positive width to textwrap; deep nesting triggered the latter even at the default width.

Both wrapping paths now clamp the remaining budget to at least one character. When raw reprs wrap at one character, spaces and tabs are kept as their own lines so textwrap cannot drop or normalize them. Indentation, payloads, and normal-width wrapping are preserved; highlighting behavior is unchanged.

Tests

  • Adds regression cases for narrow widths, default-width deep nesting, and highlighting on/off across strings, bytes, bytearrays, and raw reprs.