|
4 | 4 | PackageNotFoundError as _PackageNotFoundError, |
5 | 5 | version as _version, |
6 | 6 | ) |
| 7 | +from typing import Callable, Union |
7 | 8 |
|
8 | 9 | try: |
9 | 10 | __version__ = _version("tabulate") |
|
17 | 18 | from collections.abc import Iterable, Sized |
18 | 19 | import dataclasses |
19 | 20 | from decimal import Decimal |
| 21 | +from dataclasses import dataclass |
20 | 22 | from functools import partial, reduce |
21 | 23 | from html import escape as htmlescape |
22 | 24 | import io |
@@ -69,7 +71,12 @@ def _is_file(f): |
69 | 71 | Line = namedtuple("Line", ["begin", "hline", "sep", "end"]) |
70 | 72 |
|
71 | 73 |
|
72 | | -DataRow = namedtuple("DataRow", ["begin", "sep", "end"]) |
| 74 | +@dataclass |
| 75 | +class DataRow: |
| 76 | + begin: str |
| 77 | + sep: str |
| 78 | + end: str |
| 79 | + escape_map: dict = None |
73 | 80 |
|
74 | 81 |
|
75 | 82 | # A table structure is supposed to be: |
@@ -323,13 +330,7 @@ def make_header_line(is_header, colwidths, colaligns): |
323 | 330 | } |
324 | 331 |
|
325 | 332 |
|
326 | | -def _latex_row(cell_values, colwidths, colaligns, escrules=LATEX_ESCAPE_RULES): |
327 | | - def escape_char(c): |
328 | | - return escrules.get(c, c) |
329 | | - |
330 | | - escaped_values = ["".join(map(escape_char, cell)) for cell in cell_values] |
331 | | - rowfmt = DataRow("", "&", "\\\\") |
332 | | - return _build_simple_row(escaped_values, rowfmt) |
| 333 | +_latex_row = DataRow("", "&", "\\\\", LATEX_ESCAPE_RULES) |
333 | 334 |
|
334 | 335 |
|
335 | 336 | def _rst_escape_first_column(rows, headers): |
@@ -652,8 +653,8 @@ def escape_empty(val): |
652 | 653 | linebelowheader=Line("\\hline", "", "", ""), |
653 | 654 | linebetweenrows=None, |
654 | 655 | linebelow=Line("\\hline\n\\end{tabular}", "", "", ""), |
655 | | - headerrow=partial(_latex_row, escrules={}), |
656 | | - datarow=partial(_latex_row, escrules={}), |
| 656 | + headerrow=DataRow("", "&", "\\\\", {}), |
| 657 | + datarow=DataRow("", "&", "\\\\", {}), |
657 | 658 | padding=1, |
658 | 659 | with_header_hide=None, |
659 | 660 | ), |
@@ -2506,13 +2507,24 @@ def _pad_row(cells, padding): |
2506 | 2507 | return cells |
2507 | 2508 |
|
2508 | 2509 |
|
2509 | | -def _build_simple_row(padded_cells, rowfmt): |
| 2510 | +def _build_simple_row(padded_cells: list[list], rowfmt: DataRow) -> str: |
2510 | 2511 | "Format row according to DataRow format without padding." |
2511 | | - begin, sep, end = rowfmt |
2512 | | - return (begin + sep.join(padded_cells) + end).rstrip() |
| 2512 | + begin = rowfmt.begin |
| 2513 | + sep = rowfmt.sep |
| 2514 | + end = rowfmt.end |
| 2515 | + escape_map: dict = rowfmt.escape_map |
| 2516 | + |
| 2517 | + if escape_map: |
| 2518 | + def escape_char(c): |
| 2519 | + return escape_map.get(c, c) |
| 2520 | + escaped_cells = ["".join(map(escape_char, cell)) for cell in padded_cells] |
| 2521 | + else: |
| 2522 | + escaped_cells = padded_cells |
| 2523 | + |
| 2524 | + return (begin + sep.join(escaped_cells) + end).rstrip() |
2513 | 2525 |
|
2514 | 2526 |
|
2515 | | -def _build_row(padded_cells, colwidths, colaligns, rowfmt): |
| 2527 | +def _build_row(padded_cells: list[list], colwidths: list[int], colaligns: list[str], rowfmt: Union[DataRow, Callable]) -> str: |
2516 | 2528 | "Return a string which represents a row of data cells." |
2517 | 2529 | if not rowfmt: |
2518 | 2530 | return None |
@@ -2571,7 +2583,8 @@ def _build_line(colwidths, colaligns, linefmt): |
2571 | 2583 | else: |
2572 | 2584 | begin, fill, sep, end = linefmt |
2573 | 2585 | cells = [fill * w for w in colwidths] |
2574 | | - return _build_simple_row(cells, (begin, sep, end)) |
| 2586 | + rowfmt = DataRow(begin, sep, end) |
| 2587 | + return _build_simple_row(cells, rowfmt) |
2575 | 2588 |
|
2576 | 2589 |
|
2577 | 2590 | def _append_line(lines, colwidths, colaligns, linefmt): |
|
0 commit comments