From d5c1172a5b93de1a0a8b9283f3eefa4eb2b1e44f Mon Sep 17 00:00:00 2001 From: jihtsan <15151999611@163.com> Date: Wed, 21 Oct 2026 10:26:17 +0800 Subject: [PATCH 1/2] Keep wrapping widths positive when indentation exhausts available space Fixes #178. Clamp the remaining wrapping budget to one character for strings, bytes, bytearrays and raw reprs; preserve normal-width behavior and indentation. AI assistance: OpenAI GPT-6 (Codex), authorized by the account owner. Prompt summary: reproduce positive-width and deeply nested formatting crashes, add regression coverage, and verify the frozen toolchain tests, lint and independent reviews. --- devtools/prettier.py | 4 ++-- tests/test_prettier.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/devtools/prettier.py b/devtools/prettier.py index b603bef..f210cf4 100644 --- a/devtools/prettier.py +++ b/devtools/prettier.py @@ -218,7 +218,7 @@ def _str_lines(self, lines: Iterable[str | bytes], indent_current: int, indent_n self._stream.write(indent_current * self._c + ')') def _wrap_lines(self, s: str | bytes, indent_new: int) -> Generator[str | bytes, None, None]: - width = self._width - indent_new - 3 + width = max(1, self._width - indent_new - 3) for line in s.splitlines(True): start = 0 for pos in range(width, len(line), width): @@ -285,7 +285,7 @@ def _format_raw(self, _: Any, value_repr: str, indent_current: int, indent_new: lines = value_repr.splitlines(True) if len(lines) > 1 or (len(value_repr) + indent_current) >= self._width: self._stream.write('(\n') - wrap_at = self._width - indent_new + wrap_at = max(1, self._width - indent_new) prefix = indent_new * self._c from textwrap import wrap diff --git a/tests/test_prettier.py b/tests/test_prettier.py index cf069a9..e8281ea 100644 --- a/tests/test_prettier.py +++ b/tests/test_prettier.py @@ -513,3 +513,37 @@ def test_ast_expr(): def test_ast_module(): assert pformat(ast.parse('print(1, 2, round(3))')).startswith('Module(\n body=[') + + +@pytest.mark.parametrize('width', [7, 11, 15]) +@pytest.mark.parametrize('value', ['abcdefghijk', b'abcdefghijk']) +def test_nested_string_exhausted_width(width: int, value: str | bytes): + output = PrettyFormat(width=width)([value]) + assert ast.literal_eval(output) == [value] + + +@pytest.mark.parametrize('width', [7, 11, 15]) +def test_nested_bytearray_exhausted_width(width: int): + value = bytearray(b'abcdefghijk') + output = PrettyFormat(width=width)([value]) + node = ast.parse(output, mode='eval').body + assert isinstance(node, ast.List) + call = node.elts[0] + assert isinstance(call, ast.Call) + assert ast.literal_eval(call.args[0]) == bytes(value) + + +@pytest.mark.parametrize('width', [12, 120]) +@pytest.mark.parametrize('depth', [2, 30]) +@pytest.mark.parametrize('highlight', [False, True]) +def test_nested_raw_repr_exhausted_width(width: int, depth: int, highlight: bool): + class LongRepr: + def __repr__(self) -> str: + return 'Custom(value=' + 'x' * 120 + ')' + + leaf = LongRepr() + value: Any = leaf + for _ in range(depth): + value = [value] + output = PrettyFormat(width=width)(value, highlight=highlight) + assert repr(leaf) in ''.join(strip_ansi(output).split()) From c89e54c4e84b27f64f428df71da6ab1232e2b074 Mon Sep 17 00:00:00 2001 From: jihtsan <15151999611@163.com> Date: Wed, 21 Oct 2026 15:58:01 +0800 Subject: [PATCH 2/2] Preserve raw repr whitespace when wrapping at one character Keep spaces and tabs as individual content lines when indentation exhausts the wrapping width. Leave normal-width textwrap output unchanged. Add exact-content regression coverage for narrow and deep nesting, with and without highlighting. Refs #178 AI assistance: OpenAI GPT-6 (Codex) performed analysis, implementation and validation at the account owner's request. --- devtools/prettier.py | 3 ++- tests/test_prettier.py | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/devtools/prettier.py b/devtools/prettier.py index f210cf4..b288438 100644 --- a/devtools/prettier.py +++ b/devtools/prettier.py @@ -291,7 +291,8 @@ def _format_raw(self, _: Any, value_repr: str, indent_current: int, indent_new: from textwrap import wrap for line in lines: - sub_lines = wrap(line, wrap_at) + # At width one, whitespace must occupy its own line instead of being dropped by textwrap. + sub_lines = line.rstrip('\r\n') if wrap_at == 1 else wrap(line, wrap_at) for sline in sub_lines: self._stream.write(prefix + sline + '\n') self._stream.write(indent_current * self._c + ')') diff --git a/tests/test_prettier.py b/tests/test_prettier.py index e8281ea..041add4 100644 --- a/tests/test_prettier.py +++ b/tests/test_prettier.py @@ -547,3 +547,21 @@ def __repr__(self) -> str: value = [value] output = PrettyFormat(width=width)(value, highlight=highlight) assert repr(leaf) in ''.join(strip_ansi(output).split()) + + +@pytest.mark.parametrize('width,depth', [(12, 2), (13, 2), (120, 30)]) +@pytest.mark.parametrize('highlight', [False, True]) +@pytest.mark.parametrize('payload', ['alpha beta gamma', ' leading and trailing ', 'alpha\tbeta']) +def test_exhausted_raw_repr_preserves_whitespace(width: int, depth: int, highlight: bool, payload: str): + class RawRepr: + def __repr__(self) -> str: + return f"Custom('{payload}')" + + leaf = RawRepr() + value: Any = leaf + for _ in range(depth): + value = [value] + output = strip_ansi(PrettyFormat(width=width)(value, highlight=highlight)) + prefix = ' ' * ((depth + 1) * 4) + content = ''.join(line[len(prefix) :] for line in output.splitlines() if line.startswith(prefix)) + assert content == repr(leaf)