Skip to content

feat: Support for auto-sizing specific columns using None #38

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

Merged
merged 2 commits into from
Jun 26, 2022
Merged
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
2 changes: 1 addition & 1 deletion table2ascii/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ class Options:

first_col_heading: bool
last_col_heading: bool
column_widths: Optional[List[int]]
column_widths: Optional[List[Optional[int]]]
alignments: Optional[List[Alignment]]
style: TableStyle
4 changes: 2 additions & 2 deletions table2ascii/table_style.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,10 @@ def from_string(cls, string: str) -> "TableStyle":
Create a TableStyle from a string

Args:
string: The string to create the TableStyle from
string (:class:`str`): The string to create the TableStyle from

Returns:
TableStyle: A TableStyle object
:class:`TableStyle`: A TableStyle object

Example::

Expand Down
36 changes: 24 additions & 12 deletions table2ascii/table_to_ascii.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,13 @@ def __init__(
for i in range(len(options.column_widths)):
option = options.column_widths[i]
minimum = self.__column_widths[i]
if option < minimum:
if option is None:
option = minimum
elif option < minimum:
raise ValueError(
f"The value at index {i} of `column_widths` is {option} which is less than the minimum {minimum}."
)
self.__column_widths = options.column_widths
self.__column_widths[i] = option

self.__alignments = options.alignments or [Alignment.CENTER] * self.__columns

Expand Down Expand Up @@ -314,25 +316,35 @@ def table2ascii(
*,
first_col_heading: bool = False,
last_col_heading: bool = False,
column_widths: Optional[List[int]] = None,
column_widths: Optional[List[Optional[int]]] = None,
alignments: Optional[List[Alignment]] = None,
style: TableStyle = PresetStyle.double_thin_compact,
) -> str:
"""
Convert a 2D Python table to ASCII text

Args:
header (:class:`Optional[List[Any]]`): List of column values in the table's header row
body (:class:`Optional[List[List[Any]]]`): 2-dimensional list of values in the table's body
footer (:class:`Optional[List[Any]]`): List of column values in the table's footer row
first_col_heading (:class:`bool`): Whether to add a header column separator after the first column
last_col_heading (:class:`bool`): Whether to add a header column separator before the last column
column_widths (:class:`Optional[List[int]]`): List of widths in characters for each column (``None`` for auto-sizing)
alignments (:class:`List[Alignment]`): List of alignments (ex. `[Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT]`)
style (:class:`TableStyle`): Table style to use for styling (preset styles can be imported)
header (Optional[List[Any]]): List of column values in the table's header row.
If not specified, the table will not have a header row.
body (Optional[List[List[Any]]]): 2-dimensional list of values in the table's body.
If not specified, the table will not have a body.
footer (Optional[List[Any]]): List of column values in the table's footer row.
If not specified, the table will not have a footer row.
first_col_heading (:class:`bool`): Whether to add a header column separator after the first
column. Defaults to ``False``.
last_col_heading (:class:`bool`): Whether to add a header column separator before the last
column. Defaults to ``False``.
column_widths (Optional[List[Optional[:class:`int`]]]): List of widths in characters for each
column. Any value of ``None`` indicates that the column width should be determined automatically.
If ``column_widths`` is set to ``None``, all columns will be automatically sized. Defaults to ``None``.
alignments (Optional[List[:class:`Alignment`]]): List of alignments for each column
(ex. ``[Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT]``). If not specified or set to ``None``,
all columns will be center-aligned. Defaults to ``None``.
style (:class:`TableStyle`): Table style to use for styling (preset styles can be imported).
Defaults to :data:`PresetStyle.double_thin_compact`.

Returns:
str: The generated ASCII table
:class:`str`: The generated ASCII table
"""
return TableToAscii(
header,
Expand Down
22 changes: 22 additions & 0 deletions tests/test_column_widths.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,28 @@ def test_column_widths_none():
assert text == expected


def test_column_widths_contains_none():
text = t2a(
header=["#", "G", "H", "R", "S"],
body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]],
footer=["TOTL", "130", "140", "135", "130"],
first_col_heading=True,
last_col_heading=True,
column_widths=[7, None, 5, 5, None],
)
expected = (
"╔═══════╦═════════════════╦═════╗\n"
"║ # ║ G H R ║ S ║\n"
"╟───────╫─────────────────╫─────╢\n"
"║ 1 ║ 30 40 35 ║ 30 ║\n"
"║ 2 ║ 30 40 35 ║ 30 ║\n"
"╟───────╫─────────────────╫─────╢\n"
"║ TOTL ║ 130 140 135 ║ 130 ║\n"
"╚═══════╩═════════════════╩═════╝"
)
assert text == expected


def test_wrong_number_column_widths():
with pytest.raises(ValueError):
t2a(
Expand Down