iterative/dvc

View on GitHub
dvc/utils/table.py

Summary

Maintainability
B
4 hrs
Test Coverage
from typing import TYPE_CHECKING, Any, List

from rich.table import Table as RichTable

if TYPE_CHECKING:
    from rich.console import Console, ConsoleOptions


class Table(RichTable):
    def add_column(  # pylint: disable=arguments-differ
        self, *args: Any, collapse: bool = False, **kwargs: Any
    ) -> None:
        super().add_column(*args, **kwargs)
        self.columns[-1].collapse = collapse  # type: ignore[attr-defined]

    def _calculate_column_widths(
        self, console: "Console", options: "ConsoleOptions"
    ) -> List[int]:
        """Calculate the widths of each column, including padding, not
        including borders.

        Adjacent collapsed columns will be removed until there is only a single
        truncated column remaining.
        """
        widths = super()._calculate_column_widths(console, options)
        last_collapsed = -1
        columns = self.columns
        for i in range(len(columns) - 1, -1, -1):
            if (
                widths[i] == 0
                and columns[i].collapse  # type: ignore[attr-defined]
            ):
                if last_collapsed >= 0:
                    del widths[last_collapsed]
                    del columns[last_collapsed]
                    if self.box:
                        options.max_width += 1
                    for column in columns[last_collapsed:]:
                        column._index -= 1
                last_collapsed = i
                padding = self._get_padding_width(i)
                if (
                    columns[i].overflow == "ellipsis"
                    and (sum(widths) + padding) <= options.max_width
                ):
                    # Set content width to 1 (plus padding) if we can fit a
                    # single unicode ellipsis in this column
                    widths[i] = 1 + padding
            else:
                last_collapsed = -1
        return widths

    def _collapse_widths(  # type: ignore[override]
        # pylint: disable=arguments-differ
        self,
        widths: List[int],
        wrapable: List[bool],
        max_width: int,
    ) -> List[int]:
        """Collapse columns right-to-left if possible to fit table into
        max_width.

        If table is still too wide after collapsing, rich's automatic overflow
        handling will be used.
        """
        collapsible = [
            column.collapse  # type: ignore[attr-defined]
            for column in self.columns
        ]
        total_width = sum(widths)
        excess_width = total_width - max_width
        if any(collapsible):
            for i in range(len(widths) - 1, -1, -1):
                if collapsible[i]:
                    excess_width -= widths[i]
                    widths[i] = 0
                    if excess_width <= 0:
                        break
        return super()._collapse_widths(widths, wrapable, max_width)