Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions taskuary/chatformat.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,11 @@ def split(text: str, limit: int = HARD) -> list:
"""One section that will not fit, broken where a reader would break it: a blank line, then a
line end, and only as a last resort a space. The old splitter took max() of those three
positions, so the space always won and every break landed mid-sentence."""
if limit < 1:
# A non-positive limit makes every cut 0 (or -1): text[:0] is appended, text never gets
# shorter, and the loop grows a list for ever (issue #60). Callers pass sensible limits,
# so this is a bug in the caller - say so instead of hanging the process.
raise ValueError(f'limit must be at least 1, got {limit}')
out = []
while len(text) > limit:
window = text[:limit]
Expand Down
15 changes: 15 additions & 0 deletions tests/test_chatformat.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,21 @@ def test_blocks_leave_the_spelling_to_the_door(self):
self.assertIn('## Top', got[0])


class SplitLimitTests(unittest.TestCase):
"""split() is pure and its callers pass sensible limits, so a limit <= 0 was latent - but the
arithmetic made it hang: every cut was 0 (or -1), text[:0] was appended and text never got
shorter, so the loop grew a list for ever. Reject it at the door."""

def test_a_non_positive_limit_raises_instead_of_hanging(self):
with self.assertRaises(ValueError):
cf.split('abc', 0)
with self.assertRaises(ValueError):
cf.split('abc', -5)

def test_limit_one_still_splits_one_character_at_a_time(self):
self.assertEqual(cf.split('ab', 1), ['a', 'b'])


if __name__ == '__main__':
unittest.main()

Expand Down