Skip to content
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

ValueError: could not convert string to float: 'True' #135

Open
wjfwzzc opened this issue Jul 30, 2021 · 4 comments · May be fixed by #236
Open

ValueError: could not convert string to float: 'True' #135

wjfwzzc opened this issue Jul 30, 2021 · 4 comments · May be fixed by #236
Labels
bug Something isn't working good first issue Good for newcomers
Milestone

Comments

@wjfwzzc
Copy link

wjfwzzc commented Jul 30, 2021

version: 0.8.9, Python 3.6.9, reproduction code:

In [1]: from tabulate import tabulate
   ...: data = dict(a=0.1, b=True, c="c")
   ...: table = [(str(k), str(v)) for k, v in data.items()]

In [2]: print(tabulate(table))
-  ----
a  0.1
b  True
c  c
-  ----

In [3]: print(tabulate(table[:2]))
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-3-16d27c33d4d2> in <module>
----> 1 print(tabulate(table[:2]))

/usr/local/lib/python3.6/dist-packages/tabulate.py in tabulate(tabular_data, headers, tablefmt, floatfmt, numalign, stralign, missingval, showindex, disable_numparse, colalign)
   1299             missing_vals.extend( (len(cols)-len(missing_vals)) * [_DEFAULT_MISSINGVAL] )
   1300     cols = [[_format(v, ct, fl_fmt, miss_v, has_invisible) for v in c]
-> 1301              for c, ct, fl_fmt, miss_v in zip(cols, coltypes, float_formats, missing_vals)]
   1302 
   1303     # align columns

/usr/local/lib/python3.6/dist-packages/tabulate.py in <listcomp>(.0)
   1299             missing_vals.extend( (len(cols)-len(missing_vals)) * [_DEFAULT_MISSINGVAL] )
   1300     cols = [[_format(v, ct, fl_fmt, miss_v, has_invisible) for v in c]
-> 1301              for c, ct, fl_fmt, miss_v in zip(cols, coltypes, float_formats, missing_vals)]
   1302 
   1303     # align columns

/usr/local/lib/python3.6/dist-packages/tabulate.py in <listcomp>(.0)
   1298         if len(missing_vals) < len(cols):
   1299             missing_vals.extend( (len(cols)-len(missing_vals)) * [_DEFAULT_MISSINGVAL] )
-> 1300     cols = [[_format(v, ct, fl_fmt, miss_v, has_invisible) for v in c]
   1301              for c, ct, fl_fmt, miss_v in zip(cols, coltypes, float_formats, missing_vals)]
   1302 

/usr/local/lib/python3.6/dist-packages/tabulate.py in _format(val, valtype, floatfmt, missingval, has_invisible)
    766             return val.replace(raw_val, formatted_val)
    767         else:
--> 768             return format(float(val), floatfmt)
    769     else:
    770         return "{0}".format(val)

ValueError: could not convert string to float: 'True'

If I replace str(v) by v:

In [1]: from tabulate import tabulate
   ...: data = dict(a=0.1, b=True, c="c")
   ...: table = [(str(k), v) for k, v in data.items()]

In [2]: print(tabulate(table))
-  ----
a  0.1
b  True
c  c
-  ----

In [3]: print(tabulate(table[:2]))
-  ---
a  0.1
b  1
-  ---
@astanin
Copy link
Owner

astanin commented Oct 19, 2022

The basic assumption of tabulate is that values in the same column are of the same type. Though I agree that the exception should not be thrown. The minimal example to reproduce this error is this one:

tabulate([[0.1], ['True']])

@astanin astanin added bug Something isn't working good first issue Good for newcomers labels Oct 19, 2022
@astanin
Copy link
Owner

astanin commented Oct 19, 2022

Duplicate of #209 ?

@astanin astanin added this to the v0.9.1 milestone Oct 19, 2022
@ilya112358
Copy link
Contributor

ilya112358 commented Dec 31, 2022

While looking into this issue I found a similar bug:

>>> tabulate([[1000], ['True']], intfmt=',')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\Ibo\Python\python-tabulate\tabulate\__init__.py", line 2176, in tabulate
    cols = [
           ^
  File "C:\Users\Ibo\Python\python-tabulate\tabulate\__init__.py", line 2177, in <listcomp>
    [_format(v, ct, fl_fmt, int_fmt, miss_v, has_invisible) for v in c]
  File "C:\Users\Ibo\Python\python-tabulate\tabulate\__init__.py", line 2177, in <listcomp>
    [_format(v, ct, fl_fmt, int_fmt, miss_v, has_invisible) for v in c]
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Ibo\Python\python-tabulate\tabulate\__init__.py", line 1231, in _format
    return format(val, intfmt)
           ^^^^^^^^^^^^^^^^^^^
ValueError: Cannot specify ',' with 's'.

And another one:

>>> tabulate([["1000"]], intfmt=',')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\Ibo\Python\python-tabulate\tabulate\__init__.py", line 2176, in tabulate
    cols = [
           ^
  File "C:\Users\Ibo\Python\python-tabulate\tabulate\__init__.py", line 2177, in <listcomp>
    [_format(v, ct, fl_fmt, int_fmt, miss_v, has_invisible) for v in c]
  File "C:\Users\Ibo\Python\python-tabulate\tabulate\__init__.py", line 2177, in <listcomp>
    [_format(v, ct, fl_fmt, int_fmt, miss_v, has_invisible) for v in c]
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Ibo\Python\python-tabulate\tabulate\__init__.py", line 1231, in _format
    return format(val, intfmt)
           ^^^^^^^^^^^^^^^^^^^
ValueError: Cannot specify ',' with 's'.

@ilya112358
Copy link
Contributor

All these bugs happen in _format():

def _format(val, valtype, floatfmt, intfmt, missingval="", has_invisible=True):
"""Format a value according to its type.
Unicode is supported:
>>> hrow = ['\u0431\u0443\u043a\u0432\u0430', '\u0446\u0438\u0444\u0440\u0430'] ; \
tbl = [['\u0430\u0437', 2], ['\u0431\u0443\u043a\u0438', 4]] ; \
good_result = '\\u0431\\u0443\\u043a\\u0432\\u0430 \\u0446\\u0438\\u0444\\u0440\\u0430\\n------- -------\\n\\u0430\\u0437 2\\n\\u0431\\u0443\\u043a\\u0438 4' ; \
tabulate(tbl, headers=hrow) == good_result
True
""" # noqa
if val is None:
return missingval
if valtype is str:
return f"{val}"
elif valtype is int:
return format(val, intfmt)
elif valtype is bytes:
try:
return str(val, "ascii")
except (TypeError, UnicodeDecodeError):
return str(val)
elif valtype is float:
is_a_colored_number = has_invisible and isinstance(val, (str, bytes))
if is_a_colored_number:
raw_val = _strip_ansi(val)
formatted_val = format(float(raw_val), floatfmt)
return val.replace(raw_val, formatted_val)
else:
return format(float(val), floatfmt)
else:
return f"{val}"

...when

  1. a bool represented as a string is subjected to explicit conversion into a float (L1244),
  2. a bool (or an integer) represented as a string is subjected to some integer formatting (L1231).

I'll have a go at fixing those.

Interestingly, this is one of the core functions of the library. It existed as early as in the first commit a83993e of this repo, made more than 10 years ago, although it was much cuter at the time:

def _format(v, numfmt, isnum):
"Format value if it is not a string."
if isinstance(v, basestring) or not isnum or not numfmt:
return unicode(v)
else:
return format(v, numfmt)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working good first issue Good for newcomers
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants