1from dataclasses
import dataclass, field, replace
14from .
import box, errors
15from ._loop
import loop_first_last, loop_last
16from ._pick
import pick_bool
17from ._ratio
import ratio_distribute, ratio_reduce
18from .align
import VerticalAlignMethod
19from .jupyter
import JupyterMixin
20from .measure
import Measurement
21from .padding
import Padding, PaddingDimensions
22from .protocol
import is_renderable
23from .segment
import Segment
24from .style
import Style, StyleType
25from .text
import Text, TextType
28 from .console
import (
40 """Defines a column within a ~Table.
43 title (Union[str, Text], optional): The title of the table rendered at the top. Defaults to None.
44 caption (Union[str, Text], optional): The table caption rendered below. Defaults to None.
45 width (int, optional): The width in characters of the table, or ``None`` to automatically fit. Defaults to None.
46 min_width (Optional[int], optional): The minimum width of the table, or ``None`` for no minimum. Defaults to None.
47 box (box.Box, optional): One of the constants in box.py used to draw the edges (see :ref:`appendix_box`), or ``None`` for no box lines. Defaults to box.HEAVY_HEAD.
48 safe_box (Optional[bool], optional): Disable box characters that don't display on windows legacy terminal with *raster* fonts. Defaults to True.
49 padding (PaddingDimensions, optional): Padding for cells (top, right, bottom, left). Defaults to (0, 1).
50 collapse_padding (bool, optional): Enable collapsing of padding around cells. Defaults to False.
51 pad_edge (bool, optional): Enable padding of edge cells. Defaults to True.
52 expand (bool, optional): Expand the table to fit the available space if ``True``, otherwise the table width will be auto-calculated. Defaults to False.
53 show_header (bool, optional): Show a header row. Defaults to True.
54 show_footer (bool, optional): Show a footer row. Defaults to False.
55 show_edge (bool, optional): Draw a box around the outside of the table. Defaults to True.
56 show_lines (bool, optional): Draw lines between every row. Defaults to False.
57 leading (bool, optional): Number of blank lines between rows (precludes ``show_lines``). Defaults to 0.
58 style (Union[str, Style], optional): Default style for the table. Defaults to "none".
59 row_styles (List[Union, str], optional): Optional list of row styles, if more than one style is given then the styles will alternate. Defaults to None.
60 header_style (Union[str, Style], optional): Style of the header. Defaults to "table.header".
61 footer_style (Union[str, Style], optional): Style of the footer. Defaults to "table.footer".
62 border_style (Union[str, Style], optional): Style of the border. Defaults to None.
63 title_style (Union[str, Style], optional): Style of the title. Defaults to None.
64 caption_style (Union[str, Style], optional): Style of the caption. Defaults to None.
65 title_justify (str, optional): Justify method for title. Defaults to "center".
66 caption_justify (str, optional): Justify method for caption. Defaults to "center".
67 highlight (bool, optional): Highlight cell contents (if str). Defaults to False.
70 header:
"RenderableType" =
""
71 """RenderableType: Renderable for the header (typically a string)"""
73 footer:
"RenderableType" =
""
74 """RenderableType: Renderable for the footer (typically a string)"""
76 header_style: StyleType =
""
77 """StyleType: The style of the header."""
79 footer_style: StyleType =
""
80 """StyleType: The style of the footer."""
83 """StyleType: The style of the column."""
85 justify:
"JustifyMethod" =
"left"
86 """str: How to justify text within the column ("left", "center", "right", or "full")"""
88 vertical:
"VerticalAlignMethod" =
"top"
89 """str: How to vertically align content ("top", "middle", or "bottom")"""
91 overflow:
"OverflowMethod" =
"ellipsis"
92 """str: Overflow method."""
94 width: Optional[int] =
None
95 """Optional[int]: Width of the column, or ``None`` (default) to auto calculate width."""
97 min_width: Optional[int] =
None
98 """Optional[int]: Minimum width of column, or ``None`` for no minimum. Defaults to None."""
100 max_width: Optional[int] =
None
101 """Optional[int]: Maximum width of column, or ``None`` for no maximum. Defaults to None."""
103 ratio: Optional[int] =
None
104 """Optional[int]: Ratio to use when calculating column width, or ``None`` (default) to adapt to column contents."""
106 no_wrap: bool =
False
107 """bool: Prevent wrapping of text within the column. Defaults to ``False``."""
110 """Index of column."""
112 _cells: List[
"RenderableType"] = field(default_factory=list)
114 def copy(self) -> "Column":
115 """Return a copy of this Column."""
116 return replace(self, _cells=[])
119 def cells(self) -> Iterable["RenderableType"]:
120 """Get all cells in the column, not including header."""
125 """Check if this column is flexible."""
126 return self.
ratio is not None
131 """Information regarding a row."""
133 style: Optional[StyleType] =
None
134 """Style to apply to row."""
136 end_section: bool =
False
137 """Indicated end of section, which will force a line beneath the row."""
141 """A single cell in a table."""
144 """Style to apply to cell."""
145 renderable:
"RenderableType"
146 """Cell renderable."""
147 vertical: VerticalAlignMethod
148 """Cell vertical alignment."""
152 """A console renderable to draw a table.
155 *headers (Union[Column, str]): Column headers, either as a string, or :class:`~rich.table.Column` instance.
156 title (Union[str, Text], optional): The title of the table rendered at the top. Defaults to None.
157 caption (Union[str, Text], optional): The table caption rendered below. Defaults to None.
158 width (int, optional): The width in characters of the table, or ``None`` to automatically fit. Defaults to None.
159 min_width (Optional[int], optional): The minimum width of the table, or ``None`` for no minimum. Defaults to None.
160 box (box.Box, optional): One of the constants in box.py used to draw the edges (see :ref:`appendix_box`), or ``None`` for no box lines. Defaults to box.HEAVY_HEAD.
161 safe_box (Optional[bool], optional): Disable box characters that don't display on windows legacy terminal with *raster* fonts. Defaults to True.
162 padding (PaddingDimensions, optional): Padding for cells (top, right, bottom, left). Defaults to (0, 1).
163 collapse_padding (bool, optional): Enable collapsing of padding around cells. Defaults to False.
164 pad_edge (bool, optional): Enable padding of edge cells. Defaults to True.
165 expand (bool, optional): Expand the table to fit the available space if ``True``, otherwise the table width will be auto-calculated. Defaults to False.
166 show_header (bool, optional): Show a header row. Defaults to True.
167 show_footer (bool, optional): Show a footer row. Defaults to False.
168 show_edge (bool, optional): Draw a box around the outside of the table. Defaults to True.
169 show_lines (bool, optional): Draw lines between every row. Defaults to False.
170 leading (bool, optional): Number of blank lines between rows (precludes ``show_lines``). Defaults to 0.
171 style (Union[str, Style], optional): Default style for the table. Defaults to "none".
172 row_styles (List[Union, str], optional): Optional list of row styles, if more than one style is given then the styles will alternate. Defaults to None.
173 header_style (Union[str, Style], optional): Style of the header. Defaults to "table.header".
174 footer_style (Union[str, Style], optional): Style of the footer. Defaults to "table.footer".
175 border_style (Union[str, Style], optional): Style of the border. Defaults to None.
176 title_style (Union[str, Style], optional): Style of the title. Defaults to None.
177 caption_style (Union[str, Style], optional): Style of the caption. Defaults to None.
178 title_justify (str, optional): Justify method for title. Defaults to "center".
179 caption_justify (str, optional): Justify method for caption. Defaults to "center".
180 highlight (bool, optional): Highlight cell contents (if str). Defaults to False.
183 columns: List[Column]
188 *headers: Union[Column, str],
189 title: Optional[TextType] =
None,
190 caption: Optional[TextType] =
None,
191 width: Optional[int] =
None,
192 min_width: Optional[int] =
None,
194 safe_box: Optional[bool] =
None,
195 padding: PaddingDimensions = (0, 1),
196 collapse_padding: bool =
False,
197 pad_edge: bool =
True,
198 expand: bool =
False,
199 show_header: bool =
True,
200 show_footer: bool =
False,
201 show_edge: bool =
True,
202 show_lines: bool =
False,
204 style: StyleType =
"none",
205 row_styles: Optional[Iterable[StyleType]] =
None,
206 header_style: Optional[StyleType] =
"table.header",
207 footer_style: Optional[StyleType] =
"table.footer",
208 border_style: Optional[StyleType] =
None,
209 title_style: Optional[StyleType] =
None,
210 caption_style: Optional[StyleType] =
None,
211 title_justify:
"JustifyMethod" =
"center",
212 caption_justify:
"JustifyMethod" =
"center",
213 highlight: bool =
False,
239 self.title_justify:
"JustifyMethod" = title_justify
240 self.caption_justify:
"JustifyMethod" = caption_justify
242 self.row_styles: Sequence[StyleType] = list(row_styles
or [])
244 for header
in headers:
254 *headers: Union[Column, str],
255 padding: PaddingDimensions = 0,
256 collapse_padding: bool =
True,
257 pad_edge: bool =
False,
258 expand: bool =
False,
260 """Get a table with no lines, headers, or footer.
263 *headers (Union[Column, str]): Column headers, either as a string, or :class:`~rich.table.Column` instance.
264 padding (PaddingDimensions, optional): Get padding around cells. Defaults to 0.
265 collapse_padding (bool, optional): Enable collapsing of padding around cells. Defaults to True.
266 pad_edge (bool, optional): Enable padding around edges of table. Defaults to False.
267 expand (bool, optional): Expand the table to fit the available space if ``True``, otherwise the table width will be auto-calculated. Defaults to False.
270 Table: A table instance.
276 collapse_padding=collapse_padding,
286 """Setting a non-None self.width implies expand."""
296 """Get extra width to add to cell content."""
306 """Get the current number of rows."""
310 """Get the current row style."""
314 row_style = self.
rowsrows[index].style
315 if row_style
is not None:
320 self, console:
"Console", options:
"ConsoleOptions"
323 if self.
width is not None:
324 max_width = self.
width
345 if (self.
width is None)
348 measurement =
Measurement(minimum_width, maximum_width)
353 def padding(self) -> Tuple[int, int, int, int]:
354 """Get cell padding."""
358 def padding(self, padding: PaddingDimensions) ->
"Table":
359 """Set cell padding."""
365 header:
"RenderableType" =
"",
366 footer:
"RenderableType" =
"",
368 header_style: Optional[StyleType] =
None,
369 footer_style: Optional[StyleType] =
None,
370 style: Optional[StyleType] =
None,
371 justify:
"JustifyMethod" =
"left",
372 vertical:
"VerticalAlignMethod" =
"top",
373 overflow:
"OverflowMethod" =
"ellipsis",
374 width: Optional[int] =
None,
375 min_width: Optional[int] =
None,
376 max_width: Optional[int] =
None,
377 ratio: Optional[int] =
None,
378 no_wrap: bool =
False,
380 """Add a column to the table.
383 header (RenderableType, optional): Text or renderable for the header.
385 footer (RenderableType, optional): Text or renderable for the footer.
387 header_style (Union[str, Style], optional): Style for the header, or None for default. Defaults to None.
388 footer_style (Union[str, Style], optional): Style for the footer, or None for default. Defaults to None.
389 style (Union[str, Style], optional): Style for the column cells, or None for default. Defaults to None.
390 justify (JustifyMethod, optional): Alignment for cells. Defaults to "left".
391 vertical (VerticalAlignMethod, optional): Vertical alignment, one of "top", "middle", or "bottom". Defaults to "top".
392 overflow (OverflowMethod): Overflow method: "crop", "fold", "ellipsis". Defaults to "ellipsis".
393 width (int, optional): Desired width of column in characters, or None to fit to contents. Defaults to None.
394 min_width (Optional[int], optional): Minimum width of column, or ``None`` for no minimum. Defaults to None.
395 max_width (Optional[int], optional): Maximum width of column, or ``None`` for no maximum. Defaults to None.
396 ratio (int, optional): Flexible ratio for the column (requires ``Table.expand`` or ``Table.width``). Defaults to None.
397 no_wrap (bool, optional): Set to ``True`` to disable wrapping of this column.
404 header_style=header_style
or "",
405 footer_style=footer_style
or "",
420 *renderables: Optional[
"RenderableType"],
421 style: Optional[StyleType] =
None,
422 end_section: bool =
False,
424 """Add a row of renderables.
427 *renderables (None or renderable): Each cell in a row must be a renderable object (including str),
428 or ``None`` for a blank cell.
429 style (StyleType, optional): An optional style to apply to the entire row. Defaults to None.
430 end_section (bool, optional): End a section and draw a line. Defaults to False.
433 errors.NotRenderableError: If you add something that can't be rendered.
436 def add_cell(column: Column, renderable:
"RenderableType") ->
None:
439 cell_renderables: List[Optional[
"RenderableType"]] = list(renderables)
442 if len(cell_renderables) <
len(columns):
445 *[
None] * (
len(columns) -
len(cell_renderables)),
447 for index, renderable
in enumerate(cell_renderables):
448 if index ==
len(columns):
449 column =
Column(_index=index)
454 column = columns[index]
455 if renderable
is None:
457 elif is_renderable(renderable):
461 f
"unable to render {type(renderable).__name__}; a string or other renderable object is required"
463 self.
rowsrows.append(
Row(style=style, end_section=end_section))
466 """Add a new section (draw a line after current row)."""
469 self.
rowsrows[-1].end_section =
True
472 self, console:
"Console", options:
"ConsoleOptions"
480 if self.
width is not None:
481 max_width = self.
width
487 table_width =
sum(widths) + extra_width
490 width=table_width, highlight=self.
highlight, height=
None
494 text: TextType, style: StyleType, justify:
"JustifyMethod" =
"center"
509 justify=self.title_justify,
511 yield from self.
_render(console, render_options, widths)
516 justify=self.caption_justify,
520 self, console:
"Console", options:
"ConsoleOptions"
522 """Calculate the widths of each column, including padding, not including borders."""
536 for _range, column
in zip(width_ranges, columns)
540 for column
in columns
543 flexible_width = max_width -
sum(fixed_widths)
544 flex_widths = ratio_distribute(flexible_width, ratios, flex_minimum)
545 iter_flex_widths = iter(flex_widths)
548 widths[index] = fixed_widths[index] + next(iter_flex_widths)
549 table_width =
sum(widths)
551 if table_width > max_width:
557 table_width =
sum(widths)
559 if table_width > max_width:
560 excess_width = table_width - max_width
561 widths = ratio_reduce(excess_width, [1] *
len(widths), widths, widths)
562 table_width =
sum(widths)
566 for width, column
in zip(widths, columns)
576 else min(self.
min_width - extra_width, max_width)
578 pad_widths = ratio_distribute(_max_width - table_width, widths)
579 widths = [_width + pad
for _width, pad
in zip(widths, pad_widths)]
585 cls, widths: List[int], wrapable: List[bool], max_width: int
587 """Reduce widths so that the total is under max_width.
590 widths (List[int]): List of widths.
591 wrapable (List[bool]): List of booleans that indicate if a column may shrink.
592 max_width (int): Maximum width to reduce to.
595 List[int]: A new list of widths.
597 total_width =
sum(widths)
598 excess_width = total_width - max_width
600 while total_width
and excess_width > 0:
602 width
for width, allow_wrap
in zip(widths, wrapable)
if allow_wrap
604 second_max_column = max(
605 width
if allow_wrap
and width != max_column
else 0
606 for width, allow_wrap
in zip(widths, wrapable)
608 column_difference = max_column - second_max_column
610 (1
if (width == max_column
and allow_wrap)
else 0)
611 for width, allow_wrap
in zip(widths, wrapable)
613 if not any(ratios)
or not column_difference:
615 max_reduce = [min(excess_width, column_difference)] *
len(widths)
616 widths = ratio_reduce(excess_width, ratios, max_reduce, widths)
618 total_width =
sum(widths)
619 excess_width = total_width - max_width
623 self, console:
"Console", column_index: int, column: Column
624 ) -> Iterable[_Cell]:
625 """Get all the cells with padding and optional header."""
630 any_padding =
any(padding)
632 first_column = column_index == 0
635 _padding_cache: Dict[Tuple[bool, bool], Tuple[int, int, int, int]] = {}
637 def get_padding(first_row: bool, last_row: bool) -> Tuple[int, int, int, int]:
641 top, right, bottom, left = padding
645 left = max(0, left - right)
647 bottom = max(0, top - bottom)
658 _padding = (top, right, bottom, left)
659 _padding_cache[(first_row, last_row)] = _padding
662 raw_cells: List[Tuple[StyleType,
"RenderableType"]] = []
666 header_style = get_style(self.
header_style or "") + get_style(
674 footer_style = get_style(self.
footer_style or "") + get_style(
681 for first, last, (style, renderable)
in loop_first_last(raw_cells):
688 for (style, renderable)
in raw_cells:
696 """Get extra width from padding."""
700 pad_left = max(0, pad_left - pad_right)
701 return pad_left + pad_right
706 options:
"ConsoleOptions",
709 """Get the minimum and maximum width of the column."""
721 ).with_maximum(max_width)
723 min_widths: List[int] = []
724 max_widths: List[int] = []
734 max(min_widths)
if min_widths
else 1,
735 max(max_widths)
if max_widths
else max_width,
736 ).with_maximum(max_width)
744 self, console:
"Console", options:
"ConsoleOptions", widths: List[int]
750 self.
_get_cells(console, column_index, column)
753 row_cells: List[Tuple[_Cell, ...]] = list(
zip(*_column_cells))
800 for index, (first, last, row_cell)
in enumerate(loop_first_last(row_cells)):
801 header_row = first
and show_header
802 footer_row = last
and show_footer
805 if (
not header_row
and not footer_row)
809 cells: List[List[List[Segment]]] = []
810 if header_row
or footer_row:
813 row_style = get_style(
816 for width, cell, column
in zip(widths, row_cell, columns):
829 max_height = max(max_height,
len(lines))
832 row_height = max(
len(cell)
for cell
in cells)
835 cell: List[List[Segment]],
836 vertical:
"VerticalAlignMethod",
839 ) -> List[List[Segment]]:
845 if vertical ==
"top":
847 elif vertical ==
"middle":
862 for width, _cell, cell, column
in zip(widths, row_cell, cells, columns)
866 if last
and show_footer:
868 _box.get_row(widths,
"foot", edge=show_edge), border_style
871 left, right, _divider = box_segments[0
if first
else (2
if last
else 1)]
881 for line_no
in range(max_height):
884 for last_cell, rendered_cell
in loop_last(cells):
885 yield from rendered_cell[line_no]
892 for line_no
in range(max_height):
893 for rendered_cell
in cells:
894 yield from rendered_cell[line_no]
896 if _box
and first
and show_header:
898 _box.get_row(widths,
"head", edge=show_edge), border_style
902 if _box
and (show_lines
or leading
or end_section):
905 and not (show_footer
and index >=
len(row_cells) - 2)
906 and not (show_header
and header_row)
915 _box.get_row(widths,
"row", edge=show_edge), border_style
919 if _box
and show_edge:
924if __name__ ==
"__main__":
929 from ._timer
import timer
931 with timer(
"Table render"):
933 title=
"Star Wars Movies",
934 caption=
"Rich example table",
935 caption_justify=
"right",
939 "Released", header_style=
"bright_cyan", style=
"cyan", no_wrap=
True
946 "Star Wars: The Rise of Skywalker",
949 table.add_row(
"May 25, 2018",
"Solo: A Star Wars Story",
"$393,151,347")
952 "Star Wars Ep. V111: The Last Jedi",
959 "Rogue One: A Star Wars Story",
985 header(
"row_styles=['dim', 'none']")
993 header(
"leading=1, row_styles=['dim', 'none']")
1001 header(
"show_lines=True, row_styles=['dim', 'none']")
Tuple[int, int, int, int] padding(self)
Iterable[_Cell] _get_cells(self, "Console" console, int column_index, Column column)
List[int] _calculate_column_widths(self, "Console" console, "ConsoleOptions" options)
StyleType get_row_style(self, "Console" console, int index)
"RenderResult" _render(self, "Console" console, "ConsoleOptions" options, List[int] widths)
"Table" padding(self, PaddingDimensions padding)
None __init__(self, *Union[Column, str] headers, Optional[TextType] title=None, Optional[TextType] caption=None, Optional[int] width=None, Optional[int] min_width=None, Optional[box.Box] box=box.HEAVY_HEAD, Optional[bool] safe_box=None, PaddingDimensions padding=(0, 1), bool collapse_padding=False, bool pad_edge=True, bool expand=False, bool show_header=True, bool show_footer=False, bool show_edge=True, bool show_lines=False, int leading=0, StyleType style="none", Optional[Iterable[StyleType]] row_styles=None, Optional[StyleType] header_style="table.header", Optional[StyleType] footer_style="table.footer", Optional[StyleType] border_style=None, Optional[StyleType] title_style=None, Optional[StyleType] caption_style=None, "JustifyMethod" title_justify="center", "JustifyMethod" caption_justify="center", bool highlight=False)
"Table" grid(cls, *Union[Column, str] headers, PaddingDimensions padding=0, bool collapse_padding=True, bool pad_edge=False, bool expand=False)
Measurement __rich_measure__(self, "Console" console, "ConsoleOptions" options)
None expand(self, bool expand)
Measurement _measure_column(self, "Console" console, "ConsoleOptions" options, Column column)
"RenderResult" __rich_console__(self, "Console" console, "ConsoleOptions" options)
int _get_padding_width(self, int column_index)
None add_row(self, *Optional["RenderableType"] renderables, Optional[StyleType] style=None, bool end_section=False)
None add_column(self, "RenderableType" header="", "RenderableType" footer="", *Optional[StyleType] header_style=None, Optional[StyleType] footer_style=None, Optional[StyleType] style=None, "JustifyMethod" justify="left", "VerticalAlignMethod" vertical="top", "OverflowMethod" overflow="ellipsis", Optional[int] width=None, Optional[int] min_width=None, Optional[int] max_width=None, Optional[int] ratio=None, bool no_wrap=False)
List[int] _collapse_widths(cls, List[int] widths, List[bool] wrapable, int max_width)