Repository: astanin/python-tabulate
Pull request #319 (2024-04-13 06:31:15)

Bug fix for issue #318 | `intfmt`: error for strings which contain integer values
# Bug fix for issue #318 | `intfmt`: error for strings which contain integer values

## Description.

Resolved the problem with the `intfmt` argument.

Added tests for these changes.
Test results: `308 passed, 2 skipped in 1.10s`.


Patch:
diff --git a/tabulate/__init__.py b/tabulate/__init__.py
index 11bb865..9e96606 100644
--- a/tabulate/__init__.py
+++ b/tabulate/__init__.py
@@ -1229,6 +1229,17 @@ def _format(val, valtype, floatfmt, intfmt, missingval="", has_invisible=True):
     if valtype is str:
         return f"{val}"
     elif valtype is int:
+        if isinstance(val, str):
+            val_striped = val.encode('unicode_escape').decode('utf-8')
+            colored = re.search(r'(\\[xX]+[0-9a-fA-F]+\[\d+[mM]+)([0-9.]+)(\\.*)$', val_striped)
+            if colored:
+                total_groups = len(colored.groups())
+                if total_groups == 3:
+                    digits = colored.group(2)
+                    if digits.isdigit():
+                        val_new = colored.group(1) + format(int(digits), intfmt) + colored.group(3)
+                        val = val_new.encode('utf-8').decode('unicode_escape')
+            intfmt = ""
         return format(val, intfmt)
     elif valtype is bytes:
         try:


Test patch:
diff --git a/test/test_output.py b/test/test_output.py
index d572498..8d0207c 100644
--- a/test/test_output.py
+++ b/test/test_output.py
@@ -1,4 +1,5 @@
 """Test output of the various forms of tabular data."""
+from pytest import mark
 
 import tabulate as tabulate_module
 from common import assert_equal, raises, skip, check_warnings
@@ -2638,6 +2639,44 @@ def test_intfmt():
     assert_equal(expected, result)
 
 
+def test_intfmt_with_string_as_integer():
+    "Output: integer format"
+    result = tabulate([[82642], ["1500"], [2463]], intfmt=",", tablefmt="plain")
+    expected = "82,642\n  1500\n 2,463"
+    assert_equal(expected, result)
+
+
+@mark.skip(reason="It detects all values as floats but there are strings and integers.")
+def test_intfmt_with_string_with_floats():
+    "Output: integer format"
+    result = tabulate([[82000.38], ["1500.47"], ["2463"], [92165]], intfmt=",", tablefmt="plain")
+    expected = "82000.4\n 1500.47\n 2463\n92,165"
+    assert_equal(expected, result)
+
+
+def test_intfmt_with_colors():
+    "Regression: Align ANSI-colored values as if they were colorless."
+    colortable = [
+        ("\x1b[33mabc\x1b[0m", 42, "\x1b[31m42\x1b[0m"),
+        ("\x1b[35mdef\x1b[0m", 987654321, "\x1b[32m987654321\x1b[0m"),
+    ]
+    colorheaders = ("test", "\x1b[34mtest\x1b[0m", "test")
+    formatted = tabulate(colortable, colorheaders, "grid", intfmt=",")
+    expected = "\n".join(
+        [
+            "+--------+-------------+-------------+",
+            "| test   |        \x1b[34mtest\x1b[0m |        test |",
+            "+========+=============+=============+",
+            "| \x1b[33mabc\x1b[0m    |          42 |          \x1b[31m42\x1b[0m |",
+            "+--------+-------------+-------------+",
+            "| \x1b[35mdef\x1b[0m    | 987,654,321 | \x1b[32m987,654,321\x1b[0m |",
+            "+--------+-------------+-------------+",
+        ]
+    )
+    print(f"expected: {expected!r}\n\ngot:      {formatted!r}\n")
+    assert_equal(expected, formatted)
+
+
 def test_empty_data_with_headers():
     "Output: table with empty data and headers as firstrow"
     expected = ""