Whole file
mahmoud/boltons
The author described this change as “tableutils: fix Table.to_text crashes on degenerate tables and headers”. It counts as a record because the checks below fail on the code as it stood at e66cade32 and pass on eb659013f, with nothing else changed between the two runs.
Projectmahmoud/boltons
Fix saved2026-08-06
Sharing licenceBSD-2-Clause · LICENSE
Change size+11 −6
What the code was meant to do, written into the code itself as a save note
tableutils: fix Table.to_text crashes on degenerate tables and headers
The change
| 290 | 290 | if self.headers: | |
| 291 | 291 | self._width = len(self.headers) | |
| 292 | 292 | return | |
| 293 | - | self._width = max([len(d) for d in self._data]) | |
| 293 | + | self._width = max([len(d) for d in self._data], default=0) | |
| 294 | 294 | ||
| 295 | 295 | def _fill(self): | |
| 296 | 296 | width, filler = self._width, [None] | |
| ⋯ | |||
| 566 | 566 | lines = [] | |
| 567 | 567 | widths = [] | |
| 568 | 568 | headers = list(self.headers) | |
| 569 | + | if with_headers and headers: | |
| 570 | + | headers.extend([None] * (self._width - len(headers))) | |
| 571 | + | else: | |
| 572 | + | headers = [] | |
| 573 | + | text_headers = [to_text(h, maxlen=maxlen) for h in headers] | |
| 569 | 574 | text_data = [[to_text(cell, maxlen=maxlen) for cell in row] | |
| 570 | 575 | for row in self._data] | |
| 571 | 576 | for idx in range(self._width): | |
| 572 | 577 | cur_widths = [len(row[idx]) for row in text_data] | |
| 573 | - | if with_headers: | |
| 574 | - | cur_widths.append(len(to_text(headers[idx], maxlen=maxlen))) | |
| 575 | - | widths.append(max(cur_widths)) | |
| 576 | - | if with_headers: | |
| 578 | + | if text_headers: | |
| 579 | + | cur_widths.append(len(text_headers[idx])) | |
| 580 | + | widths.append(max(cur_widths, default=0)) | |
| 581 | + | if text_headers: | |
| 577 | 582 | lines.append(' | '.join([h.center(widths[i]) | |
| 578 | - | for i, h in enumerate(headers)])) | |
| 583 | + | for i, h in enumerate(text_headers)])) | |
| 579 | 584 | lines.append('-|-'.join(['-' * w for w in widths])) | |
| 580 | 585 | for row in text_data: | |
| 581 | 586 | lines.append(' | '.join([cell.center(widths[j]) | |
The check that tells the two apart
fail→pass·tests/test_tableutils.py::test_to_text_empty_table
fail→pass·tests/test_tableutils.py::test_to_text_no_headers
fail→pass·tests/test_tableutils.py::test_to_text_none_headers
fail→pass·tests/test_tableutils.py::test_to_text_short_headers_padded
Check file tests/test_tableutils.py, taken without changes from the fix and copied onto the older code, so the exact same check runs against both versions.
Origin and history
The code before ite66cade323f5c11cebb4bd0f099e634b245adccd
Broken version dated2026-07-17
Moduleboltons.tableutils
Units changedTable
Fingerprintffb30f3885c482b8
Checked2026-08-18 by goldset/0.1
Every field above is generated by our program. None of it is written by hand.
Other bugs found in mahmoud/boltons
- 2026-08-06Bits
- 2026-08-06JSONLIterator
- 2026-07-18backoff_iter
- 2026-07-17singularize
- 2026-07-17fix(fileutils): accept os.PathLike in AtomicSaver
- 2026-07-17Fix copy.copy/copy.deepcopy collapsing OrderedMultiDict values