griddle

 1import os
 2from typing import Any, Iterable, Mapping, Sequence
 3
 4from tabulate import tabulate
 5
 6
 7def griddy(
 8    data: Mapping[str, Iterable[Any]] | Iterable[Iterable[Any]],
 9    headers: str | dict[str, str] | Sequence[str] = (),
10    shrink_to_terminal: bool = True,
11    margin: int = 10,
12    table_format: str = "rounded_grid",
13    disable_numparse: bool = True,
14) -> str:
15    """Convert `data` into a formatted string grid representation.
16
17    #### :params:
18
19    * `headers`: Can either be an explicit list of column names, `"keys"`, or `"firstrow"`.
20    If not given, the grid will have no headers.
21
22    * `shrink_to_terminal`: When `True`, `griddy` will limit column widths so that the total width of the output will fit within the terminal.
23
24    * `margin`: When shrinking to the terminal, `griddy` will try to maximize the output width such that `terminal_width - margin < output_width < terminal_width`.
25    The larger this value, the larger the acceptable output width and, likely, the faster this function will return.
26    Note: `griddy` will, internally, increase the margin when necessary to avoid getting stuck in an infinite loop.
27
28
29    * `table_format`: The grid asthetic. See the `tabulate` package for a full list of options.
30
31    * `disable_numparse`: Turn off treating and aligning numbers differently from non-numbers.
32
33    """
34    output = tabulate(
35        data,
36        headers=headers,
37        disable_numparse=disable_numparse,
38        tablefmt=table_format,
39    )
40    if not shrink_to_terminal:
41        return output
42
43    grid = lambda w: tabulate(
44        data,
45        headers=headers,
46        disable_numparse=True,
47        tablefmt=table_format,
48        maxcolwidths=w,
49    )
50
51    terminal_width = os.get_terminal_size().columns
52    max_col_width = terminal_width
53    current_width = output.find("\n")
54    if current_width < terminal_width:
55        return output
56
57    previous_col_width = max_col_width
58    acceptable_width = terminal_width - margin
59    while max_col_width > 1:
60        if current_width >= terminal_width:
61            previous_col_width = max_col_width
62            max_col_width = int(max_col_width * 0.5)
63        elif current_width < terminal_width:
64            # Without lowering acceptable width, this condition will cause an infinite loop
65            if max_col_width == previous_col_width - 1:
66                acceptable_width -= margin
67            max_col_width = int(
68                max_col_width + (0.5 * (previous_col_width - max_col_width))
69            )
70        # Check if output width is in the acceptable range
71        output = grid(max_col_width)
72        current_width = output.find("\n")
73        if acceptable_width < current_width < terminal_width:
74            return output
75    raise RuntimeError("Could not resize grid to fit within the terminal :/.")
def griddy( data: Union[Mapping[str, Iterable[Any]], Iterable[Iterable[Any]]], headers: Union[str, dict[str, str], Sequence[str]] = (), shrink_to_terminal: bool = True, margin: int = 10, table_format: str = 'rounded_grid', disable_numparse: bool = True) -> str:
 8def griddy(
 9    data: Mapping[str, Iterable[Any]] | Iterable[Iterable[Any]],
10    headers: str | dict[str, str] | Sequence[str] = (),
11    shrink_to_terminal: bool = True,
12    margin: int = 10,
13    table_format: str = "rounded_grid",
14    disable_numparse: bool = True,
15) -> str:
16    """Convert `data` into a formatted string grid representation.
17
18    #### :params:
19
20    * `headers`: Can either be an explicit list of column names, `"keys"`, or `"firstrow"`.
21    If not given, the grid will have no headers.
22
23    * `shrink_to_terminal`: When `True`, `griddy` will limit column widths so that the total width of the output will fit within the terminal.
24
25    * `margin`: When shrinking to the terminal, `griddy` will try to maximize the output width such that `terminal_width - margin < output_width < terminal_width`.
26    The larger this value, the larger the acceptable output width and, likely, the faster this function will return.
27    Note: `griddy` will, internally, increase the margin when necessary to avoid getting stuck in an infinite loop.
28
29
30    * `table_format`: The grid asthetic. See the `tabulate` package for a full list of options.
31
32    * `disable_numparse`: Turn off treating and aligning numbers differently from non-numbers.
33
34    """
35    output = tabulate(
36        data,
37        headers=headers,
38        disable_numparse=disable_numparse,
39        tablefmt=table_format,
40    )
41    if not shrink_to_terminal:
42        return output
43
44    grid = lambda w: tabulate(
45        data,
46        headers=headers,
47        disable_numparse=True,
48        tablefmt=table_format,
49        maxcolwidths=w,
50    )
51
52    terminal_width = os.get_terminal_size().columns
53    max_col_width = terminal_width
54    current_width = output.find("\n")
55    if current_width < terminal_width:
56        return output
57
58    previous_col_width = max_col_width
59    acceptable_width = terminal_width - margin
60    while max_col_width > 1:
61        if current_width >= terminal_width:
62            previous_col_width = max_col_width
63            max_col_width = int(max_col_width * 0.5)
64        elif current_width < terminal_width:
65            # Without lowering acceptable width, this condition will cause an infinite loop
66            if max_col_width == previous_col_width - 1:
67                acceptable_width -= margin
68            max_col_width = int(
69                max_col_width + (0.5 * (previous_col_width - max_col_width))
70            )
71        # Check if output width is in the acceptable range
72        output = grid(max_col_width)
73        current_width = output.find("\n")
74        if acceptable_width < current_width < terminal_width:
75            return output
76    raise RuntimeError("Could not resize grid to fit within the terminal :/.")

Convert data into a formatted string grid representation.

:params:

  • headers: Can either be an explicit list of column names, "keys", or "firstrow". If not given, the grid will have no headers.

  • shrink_to_terminal: When True, griddy will limit column widths so that the total width of the output will fit within the terminal.

  • margin: When shrinking to the terminal, griddy will try to maximize the output width such that terminal_width - margin < output_width < terminal_width. The larger this value, the larger the acceptable output width and, likely, the faster this function will return. Note: griddy will, internally, increase the margin when necessary to avoid getting stuck in an infinite loop.

  • table_format: The grid asthetic. See the tabulate package for a full list of options.

  • disable_numparse: Turn off treating and aligning numbers differently from non-numbers.