Repository navigation
gh-160633: Break the last chunk of a broken long word in textwrap truncation - #160634
Open
qiyuhuating wants to merge 1 commit into
Open
qiyuhuating wants to merge 1 commit into
qiyuhuating wants to merge 1 commit into
Conversation
Documentation build overview
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
shorten()andwrap(max_lines=...)currently discard the whole remaining piece of a broken long word on the final line instead of breaking it further to make room for the placeholder, so the output can carry no text at all:The truncation loop in
TextWrapper._wrap_chunks()drops chunks whole until the placeholder fits; for a line whose only chunk is a full-width piece produced by_handle_long_word(), nothing ever fits and the bare placeholder is emitted. Withbreak_long_words=True(the default) the wrapper already breaks this word on earlier lines, so breaking the piece further on the last line is consistent with the documented behavior of bothbreak_long_wordsandshorten()("enough words are dropped from the end so that the remaining words plus the placeholder fit within width").Scope
The new branch only fires when all of the following hold, so every other documented truncation behavior is unchanged:
max_linestruncation is happening (theelsebranch);break_long_wordsis true (the default);widthcharacters (a piece of a broken long word, or a word exactly as wide as the line);In particular: whole-word drops from the end (
['Hello', '[...]']cases), the placeholder backtracking onto the previous line, the eagerValueError("placeholder too large for max width")check, andbreak_long_words=Falseall behave byte-identically to before. The existing testtest_first_word_too_long_but_placeholder_fits(which asserts the bare-placeholder behavior for a word shorter than the width) still passes unchanged.After the cut,
cur_len + len(placeholder) == width, so the next loop iteration necessarily appends the placeholder and breaks out: no new looping risk (cf. gh-158979).Notes
test_max_lines_longexpected a placeholder-only final line below two full lines of the broken word"supercalifragilisticexpialidocious?"; it now expectsialido [...]. That expectation came from the original Multiline shortening #62925 (bpo-18585) implementation and was never discussed separately.shorten()documentation.Test evidence
Lib/test/test_textwrap.py: 70 tests, all passing with this change. Against unpatchedmainexactly 3 fail — the updatedtest_max_lines_longexpectation and the two new tests — confirming the change is limited to the intended behavior delta. New tests:LongWordTestCase.test_max_lines_long_word_broken(wrap withmax_lines, including the too-narrow andbreak_long_words=Falsefallbacks),ShortenTestCase.test_long_word_broken_to_fit_placeholder.