Skip to content

Commit

Permalink
Merge pull request #342 from astanin/pr-79
Browse files Browse the repository at this point in the history
Merge changes from Pull Request #79 (preserve_whitespace as an argument to tabulate())
  • Loading branch information
astanin authored Sep 26, 2024
2 parents ee0472e + 0d5d30e commit 541afc6
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 31 deletions.
11 changes: 3 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ When data is a list of dictionaries, a dictionary can be passed as `headers`
to replace the keys with other column labels:

```pycon
>>> print(tabulate([{1: "Alice", 2: 24}, {1: "Bob", 2: 19}],
>>> print(tabulate([{1: "Alice", 2: 24}, {1: "Bob", 2: 19}],
... headers={1: "Name", 2: "Age"}))
Name Age
------ -----
Expand Down Expand Up @@ -739,13 +739,8 @@ column, in which case every column may have different number formatting:
### Text formatting

By default, `tabulate` removes leading and trailing whitespace from text
columns. To disable whitespace removal, set the global module-level flag
`PRESERVE_WHITESPACE`:

```python
import tabulate
tabulate.PRESERVE_WHITESPACE = True
```
columns. To disable whitespace removal, pass `preserve_whitespace=True`.
Older versions of the library used a global module-level flag PRESERVE_WHITESPACE.

### Wide (fullwidth CJK) symbols

Expand Down
53 changes: 38 additions & 15 deletions tabulate/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@ def _is_file(f):
# minimum extra space in headers
MIN_PADDING = 2

# Whether or not to preserve leading/trailing whitespace in data.
PRESERVE_WHITESPACE = False

_DEFAULT_FLOATFMT = "g"
_DEFAULT_INTFMT = ""
_DEFAULT_MISSINGVAL = ""
Expand Down Expand Up @@ -163,7 +160,6 @@ def _grid_line_with_colons(colwidths, colaligns):
return "+" + "+".join(segments) + "+"



def _mediawiki_row_with_attrs(separator, cell_values, colwidths, colaligns):
alignment = {
"left": "",
Expand Down Expand Up @@ -1100,13 +1096,13 @@ def _choose_width_fn(has_invisible, enable_widechars, is_multiline):
return width_fn


def _align_column_choose_padfn(strings, alignment, has_invisible):
def _align_column_choose_padfn(strings, alignment, has_invisible, preserve_whitespace):
if alignment == "right":
if not PRESERVE_WHITESPACE:
if not preserve_whitespace:
strings = [s.strip() for s in strings]
padfn = _padleft
elif alignment == "center":
if not PRESERVE_WHITESPACE:
if not preserve_whitespace:
strings = [s.strip() for s in strings]
padfn = _padboth
elif alignment == "decimal":
Expand All @@ -1120,7 +1116,7 @@ def _align_column_choose_padfn(strings, alignment, has_invisible):
elif not alignment:
padfn = _padnone
else:
if not PRESERVE_WHITESPACE:
if not preserve_whitespace:
strings = [s.strip() for s in strings]
padfn = _padright
return strings, padfn
Expand Down Expand Up @@ -1163,9 +1159,12 @@ def _align_column(
has_invisible=True,
enable_widechars=False,
is_multiline=False,
preserve_whitespace=False,
):
"""[string] -> [padded_string]"""
strings, padfn = _align_column_choose_padfn(strings, alignment, has_invisible)
strings, padfn = _align_column_choose_padfn(
strings, alignment, has_invisible, preserve_whitespace
)
width_fn = _align_column_choose_width_fn(
has_invisible, enable_widechars, is_multiline
)
Expand Down Expand Up @@ -1271,15 +1270,21 @@ def _format(val, valtype, floatfmt, intfmt, missingval="", has_invisible=True):
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)
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')
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:
Expand Down Expand Up @@ -1645,6 +1650,7 @@ def tabulate(
disable_numparse=False,
colglobalalign=None,
colalign=None,
preserve_whitespace=False,
maxcolwidths=None,
headersglobalalign=None,
headersalign=None,
Expand Down Expand Up @@ -2323,7 +2329,15 @@ def tabulate(
if tablefmt == "colon_grid":
aligns_copy = ["left"] * len(cols)
cols = [
_align_column(c, a, minw, has_invisible, enable_widechars, is_multiline)
_align_column(
c,
a,
minw,
has_invisible,
enable_widechars,
is_multiline,
preserve_whitespace,
)
for c, a, minw in zip(cols, aligns_copy, minwidths)
]

Expand Down Expand Up @@ -2820,7 +2834,16 @@ def _main():
opts, args = getopt.getopt(
sys.argv[1:],
"h1o:s:F:I:f:",
["help", "header", "output=", "sep=", "float=", "int=", "colalign=", "format="],
[
"help",
"header",
"output=",
"sep=",
"float=",
"int=",
"colalign=",
"format=",
],
)
except getopt.GetoptError as e:
print(e)
Expand Down
2 changes: 2 additions & 0 deletions test/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
from pytest import skip, raises # noqa
import warnings


def assert_equal(expected, result):
print("Expected:\n%s\n" % expected)
print("Got:\n%s\n" % result)
assert expected == result


def assert_in(result, expected_set):
nums = range(1, len(expected_set) + 1)
for i, expected in zip(nums, expected_set):
Expand Down
1 change: 1 addition & 0 deletions test/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ def test_tabulate_signature():
("disable_numparse", False),
("colglobalalign", None),
("colalign", None),
("preserve_whitespace", False),
("maxcolwidths", None),
("headersglobalalign", None),
("headersalign", None),
Expand Down
22 changes: 14 additions & 8 deletions test/test_output.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""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
from tabulate import tabulate, simple_separated_format, SEPARATING_LINE

Expand Down Expand Up @@ -1459,7 +1458,12 @@ def test_colon_grid():
"+------+------+",
]
)
result = tabulate([[3, 4]], headers=("H1", "H2"), tablefmt="colon_grid", colalign=["right", "center"])
result = tabulate(
[[3, 4]],
headers=("H1", "H2"),
tablefmt="colon_grid",
colalign=["right", "center"],
)
assert_equal(expected, result)


Expand All @@ -1482,7 +1486,9 @@ def test_colon_grid_wide_characters():
"+-----------+---------+",
]
)
result = tabulate(_test_table, headers, tablefmt="colon_grid", colalign=["left", "right"])
result = tabulate(
_test_table, headers, tablefmt="colon_grid", colalign=["left", "right"]
)
assert_equal(expected, result)


Expand Down Expand Up @@ -2773,7 +2779,9 @@ def test_intfmt_with_string_as_integer():
@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")
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)

Expand Down Expand Up @@ -3208,18 +3216,16 @@ def test_disable_numparse_list():

def test_preserve_whitespace():
"Output: Default table output, but with preserved leading whitespace."
tabulate_module.PRESERVE_WHITESPACE = True
table_headers = ["h1", "h2", "h3"]
test_table = [[" foo", " bar ", "foo"]]
expected = "\n".join(
["h1 h2 h3", "----- ------- ----", " foo bar foo"]
)
result = tabulate(test_table, table_headers)
result = tabulate(test_table, table_headers, preserve_whitespace=True)
assert_equal(expected, result)

tabulate_module.PRESERVE_WHITESPACE = False
table_headers = ["h1", "h2", "h3"]
test_table = [[" foo", " bar ", "foo"]]
expected = "\n".join(["h1 h2 h3", "---- ---- ----", "foo bar foo"])
result = tabulate(test_table, table_headers)
result = tabulate(test_table, table_headers, preserve_whitespace=False)
assert_equal(expected, result)
1 change: 1 addition & 0 deletions test/test_regression.py
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,7 @@ def test_numpy_int64_as_integer():
except ImportError:
raise skip("")


def test_empty_table_with_colalign():
"Regression: empty table with colalign kwarg"
table = tabulate([], ["a", "b", "c"], colalign=("center", "left", "left", "center"))
Expand Down

0 comments on commit 541afc6

Please sign in to comment.