Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 21 additions & 19 deletions tabulate/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1253,20 +1253,10 @@ def _column_type(strings, has_invisible=True, numparse=True):


def _format(val, valtype, floatfmt, intfmt, missingval="", has_invisible=True):
"""Format a value according to its type.
"""Format a value according to the type of the column."""

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:
Expand All @@ -1287,16 +1277,28 @@ def _format(val, valtype, floatfmt, intfmt, missingval="", has_invisible=True):
return str(val, "ascii")
except (TypeError, UnicodeDecodeError):
return str(val)

# the rest is for bool and number values in bool and number column types
is_ansi_colored = has_invisible and isinstance(val, (str, bytes))
# strip color if needed, reapply before return
if is_ansi_colored:
colored_val = val
val = raw_val = _strip_ansi(val)
if _isbool(val):
# val should be a boolean literal to convert into a number if needed
val = val in (True, "True")
if valtype is int:
# do not convert strings and bools into integers if there is no special formatting
if intfmt:
val = int(val)
val = format(val, intfmt)
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)
val = format(float(val), floatfmt)
else:
return f"{val}"
val = f"{val}"
if is_ansi_colored:
val = colored_val.replace(raw_val, val)
return val


def _align_header(
Expand Down
21 changes: 21 additions & 0 deletions test/test_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,27 @@ def test_iterable_of_iterables_firstrow():
assert_equal(expected, result)


def test_mixed_bools():
"Input: a list of lists with mixed number and bool values."
ll = [
["1.1", "1000", "1000"],
[True, True, True],
["False", "False", "False"],
]
# notice INCONSISTENCY in boolean representation
expected = "\n".join(
[
"--- ----- -----",
"1.1 1000 1,000",
"1.0 True 1",
"0.0 False 0",
"--- ----- -----",
]
)
result = tabulate(ll, floatfmt=".1f", intfmt=("", "", ","))
assert_equal(expected, result)


def test_list_of_lists():
"Input: a list of lists with headers."
ll = [["a", "one", 1], ["b", "two", None]]
Expand Down
Loading