Skip to content

Can not tabulate row with a field that looks like a Python Bool using maxcolwidths #305

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
dsollenberger opened this issue Dec 27, 2023 · 3 comments · May be fixed by #362
Open

Can not tabulate row with a field that looks like a Python Bool using maxcolwidths #305

dsollenberger opened this issue Dec 27, 2023 · 3 comments · May be fixed by #362

Comments

@dsollenberger
Copy link

The following line will fail with an error about "bool' object has no attribute 'expandtabs'

tabulate.tabulate([['init','True']], maxcolwidths=[None, 42])

This happens because the _wrap_text_to_col_widths method casts the cell to a casted cell by calling _type(cell, numpars)(cell) which will convert the string 'True' into a bool. Unfortunately the wrapper.wrap method called immediately after expects a str according to it's docstring and so explodes when passed a bool

My quick naïve reading suggests you could remove the entire if/else clause for casted_cell and just set casted cell equal to str(cell); if your next call only accepts a str why cast to anything else? Still I'll leave it to those that know the code better then ignorant me to figure out the best fix.

Also completely random nitpick, but I noticed the _type method docstring lists other types it will convert, but does not include bool in it's description despite checking for and handling bools so may want to update that for consistency.

@plankthom
Copy link

plankthom commented Nov 27, 2024

Still an issue with tabulate==0.9.0

>>> from tabulate import tabulate
>>> print(tabulate([['enabled','True']]))
-------  ----
enabled  True
-------  ----
>>> print(tabulate([['enabled','True']],maxcolwidths=[10, None]))
-------  ----
enabled  True
-------  ----
>>> print(tabulate([['enabled','True']],maxcolwidths=[10,10]))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File ".venv/lib/python3.11/site-packages/tabulate/__init__.py", line 2061, in tabulate
    list_of_lists = _wrap_text_to_colwidths(
                    ^^^^^^^^^^^^^^^^^^^^^^^^
  File ".venv/lib/python3.11/site-packages/tabulate/__init__.py", line 1518, in _wrap_text_to_colwidths
    wrapped = wrapper.wrap(casted_cell)
              ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Caskroom/miniconda/base/envs/py3.11/lib/python3.11/textwrap.py", line 356, in wrap
    chunks = self._split_chunks(text)
             ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Caskroom/miniconda/base/envs/py3.11/lib/python3.11/textwrap.py", line 342, in _split_chunks
    text = self._munge_whitespace(text)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Caskroom/miniconda/base/envs/py3.11/lib/python3.11/textwrap.py", line 151, in _munge_whitespace
    text = text.expandtabs(self.tabsize)
           ^^^^^^^^^^^^^^^
AttributeError: 'bool' object has no attribute 'expandtabs'

Hnasar added a commit to Hnasar/python-tabulate that referenced this issue Mar 17, 2025
calling _type is incorrect here; the subsequent lines need a `str`.
Also you can't reconstruct `None` with `type(None)(None)` anyway.
This regressed in e8e3091

Fixes astanin#305
@Hnasar Hnasar linked a pull request Mar 17, 2025 that will close this issue
@Hnasar
Copy link

Hnasar commented Mar 17, 2025

@astanin can you merge this PR to fix #362

This commit from a few years ago Introduced this bug. I agree with the original poster, this fix seems reasonable.

-                casted_cell = (
-                    str(cell) if _isnumber(cell) else _type(cell, numparse)(cell)
-                )
+                casted_cell = str(cell)

Until then, here's a workaround until a new version is released. It fixes the issues with "True"/"False" str bools, and also None.

import tabulate

def fix_tabulate() -> None:
    from unittest import mock

    import tabulate
    if hasattr(tabulate, '_original_wrap_text_to_colwidths'):
        return

    tabulate._original_wrap_text_to_colwidths = tabulate._wrap_text_to_colwidths
    def wrap_text_to_colwidths_mock(*args, **kwargs):
        with mock.patch('tabulate._type', return_value=str):
            return tabulate._original_wrap_text_to_colwidths(*args, **kwargs)
    tabulate._wrap_text_to_colwidths = wrap_text_to_colwidths_mock


fix_tabulate()

a = [["foo", None], ["bar", "True"]]
print(tabulate.tabulate(a, maxcolwidths=80))

@filbranden
Copy link

@astanin Would you please look into merging some of the pending PRs (such as #362) and release a new 0.9.x package?

Pandas currently depends on tabulate >= 0.9.0, so downgrading to 0.8.10 is not really an option at this point.

Let us know if you might need some help with some of the items here, or if you're potentially looking at new maintainers for this project.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants