From e464f569439c170d68617c964940b90d11ec8d7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Saugat=20Pachhai=20=28=E0=A4=B8=E0=A5=8C=E0=A4=97=E0=A4=BE?= =?UTF-8?q?=E0=A4=A4=29?= Date: Tue, 31 Mar 2026 10:14:55 +0545 Subject: [PATCH] fix(ls): support tabulate 0.10.0 preserve_whitespace tabulate 0.10.0 ignores the global PRESERVE_WHITESPACE and requires it as a kwarg instead. Pass it through plain_table with a version check to support both 0.9.0 and 0.10.0. --- dvc/commands/ls/__init__.py | 10 +--------- dvc/ui/__init__.py | 4 +++- dvc/ui/table.py | 36 +++++++++++++++++++++++++++--------- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/dvc/commands/ls/__init__.py b/dvc/commands/ls/__init__.py index d409d7ec22..190a5918d3 100644 --- a/dvc/commands/ls/__init__.py +++ b/dvc/commands/ls/__init__.py @@ -109,8 +109,6 @@ def _build_tree_structure( def show_tree(entries, with_color=False, with_size=False, with_hash=False): - import tabulate - rows = _build_tree_structure( entries, with_color=with_color, @@ -119,13 +117,7 @@ def show_tree(entries, with_color=False, with_size=False, with_hash=False): ) colalign = ("right",) if with_size else None - - _orig = tabulate.PRESERVE_WHITESPACE - tabulate.PRESERVE_WHITESPACE = True - try: - ui.table(rows, colalign=colalign) - finally: - tabulate.PRESERVE_WHITESPACE = _orig + ui.table(rows, colalign=colalign, preserve_whitespace=True) class CmdList(CmdBaseNoRepo): diff --git a/dvc/ui/__init__.py b/dvc/ui/__init__.py index 260e945fc3..2df6ab45cc 100644 --- a/dvc/ui/__init__.py +++ b/dvc/ui/__init__.py @@ -289,7 +289,7 @@ def error_console(self) -> "RichConsole": return console.Console(stderr=True) - def table( + def table( # noqa: PLR0913 self, data: "TableData", headers: Optional["Headers"] = None, @@ -301,6 +301,7 @@ def table( row_styles: Optional[Sequence["Styles"]] = None, borders: Union[bool, str] = False, colalign: Optional[tuple[str, ...]] = None, + preserve_whitespace: bool = False, ) -> None: from dvc.ui import table as t @@ -329,6 +330,7 @@ def table( pager=pager, force=force, colalign=colalign, + preserve_whitespace=preserve_whitespace, ) def status(self, status: str, **kwargs: Any) -> "Status": diff --git a/dvc/ui/table.py b/dvc/ui/table.py index f0156d266b..156b7fdfae 100644 --- a/dvc/ui/table.py +++ b/dvc/ui/table.py @@ -30,19 +30,37 @@ def plain_table( pager: bool = False, force: bool = True, colalign: Optional[tuple[str, ...]] = None, + preserve_whitespace: bool = False, ) -> None: + import tabulate as tabulate_mod from funcy import nullcontext + from packaging.version import Version from tabulate import tabulate - text: str = tabulate( - data, - headers if headers is not None else (), - tablefmt="github" if markdown else "plain", - disable_numparse=True, - # None will be shown as "" by default, overriding - missingval="-", - colalign=colalign, - ) + # NOTE: tabulate 0.10.0+ supports preserve_whitespace as a kwarg, + # while 0.9.0 only respects the global PRESERVE_WHITESPACE. + kwargs: dict = {} + _orig = tabulate_mod.PRESERVE_WHITESPACE + if preserve_whitespace: + if Version(tabulate_mod.__version__) >= Version("0.10"): + kwargs["preserve_whitespace"] = True + else: + tabulate_mod.PRESERVE_WHITESPACE = True + + try: + text: str = tabulate( + data, + headers if headers is not None else (), + tablefmt="github" if markdown else "plain", + disable_numparse=True, + # None will be shown as "" by default, overriding + missingval="-", + colalign=colalign, + **kwargs, + ) + finally: + tabulate_mod.PRESERVE_WHITESPACE = _orig + if markdown: # NOTE: md table is incomplete without the trailing newline text += "\n"