diff --git a/README.md b/README.md
index de9e288..ca0e1c6 100644
--- a/README.md
+++ b/README.md
@@ -123,7 +123,7 @@ output = table2ascii(
body=[["10", "30", "40", "35"], ["20", "10", "20", "5"]],
style=PresetStyle.plain,
cell_padding=0,
- alignments=[Alignment.LEFT] * 4,
+ alignments=Alignment.LEFT,
)
print(output)
@@ -203,18 +203,18 @@ All parameters are optional. At least one of `header`, `body`, and `footer` must
Refer to the [documentation](https://table2ascii.readthedocs.io/en/stable/api.html#table2ascii) for more information.
-| Option | Type | Default | Description |
-| :-----------------: | :----------------------------: | :-------------------: | :--------------------------------------------------------------------------------------------------: |
-| `header` | `Sequence[SupportsStr]` | `None` | First table row seperated by header row separator. Values should support `str()` |
-| `body` | `Sequence[Sequence[Sequence]]` | `None` | 2D List of rows for the main section of the table. Values should support `str()` |
-| `footer` | `Sequence[Sequence]` | `None` | Last table row seperated by header row separator. Values should support `str()` |
-| `column_widths` | `Sequence[Optional[int]]` | `None` (automatic) | List of column widths in characters for each column |
-| `alignments` | `Sequence[Alignment]` | `None` (all centered) | Column alignments
(ex. `[Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT, Alignment.DECIMAL]`) |
-| `style` | `TableStyle` | `double_thin_compact` | Table style to use for the table\* |
-| `first_col_heading` | `bool` | `False` | Whether to add a heading column separator after the first column |
-| `last_col_heading` | `bool` | `False` | Whether to add a heading column separator before the last column |
-| `cell_padding` | `int` | `1` | The minimum number of spaces to add between the cell content and the cell border |
-| `use_wcwidth` | `bool` | `True` | Whether to use [wcwidth][wcwidth] instead of `len()` to calculate cell width |
+| Option | Supported Types | Description |
+| :-----------------: | :-----------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------: |
+| `header` | `Sequence[SupportsStr]`, `None`
(Default: `None`) | First table row seperated by header row separator. Values should support `str()` |
+| `body` | `Sequence[Sequence[SupportsStr]]`, `None`
(Default: `None`) | 2D List of rows for the main section of the table. Values should support `str()` |
+| `footer` | `Sequence[SupportsStr]`, `None`
(Default: `None`) | Last table row seperated by header row separator. Values should support `str()` |
+| `column_widths` | `Sequence[Optional[int]]`, `None`
(Default: `None` / automatic) | List of column widths in characters for each column |
+| `alignments` | `Sequence[Alignment]`, `Alignment`, `None`
(Default: `None` / all centered) | Column alignments
(ex. `[Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT, Alignment.DECIMAL]`) |
+| `style` | `TableStyle`
(Default: `double_thin_compact`) | Table style to use for the table\* |
+| `first_col_heading` | `bool`
(Default: `False`) | Whether to add a heading column separator after the first column |
+| `last_col_heading` | `bool`
(Default: `False`) | Whether to add a heading column separator before the last column |
+| `cell_padding` | `int`
(Default: `1`) | The minimum number of spaces to add between the cell content and the cell border |
+| `use_wcwidth` | `bool`
(Default: `True`) | Whether to use [wcwidth][wcwidth] instead of `len()` to calculate cell width |
[wcwidth]: https://pypi.org/project/wcwidth/
diff --git a/docs/source/usage.rst b/docs/source/usage.rst
index 823c23e..d1eb820 100644
--- a/docs/source/usage.rst
+++ b/docs/source/usage.rst
@@ -109,7 +109,7 @@ Use a preset style
body=[["10", "30", "40", "35"], ["20", "10", "20", "5"]],
style=PresetStyle.plain,
cell_padding=0,
- alignments=[Alignment.LEFT] * 4,
+ alignments=Alignment.LEFT,
)
print(output)
diff --git a/table2ascii/alignment.py b/table2ascii/alignment.py
index 2ae487f..041d167 100644
--- a/table2ascii/alignment.py
+++ b/table2ascii/alignment.py
@@ -4,7 +4,7 @@
class Alignment(IntEnum):
"""Enum for text alignment types within a table cell
- Example::
+ A list of alignment types can be used to align each column individually::
from table2ascii import Alignment, table2ascii
@@ -15,6 +15,8 @@ class Alignment(IntEnum):
["Cheese", "Dairy", "$10.99", "8.2"],
["Apples", "Produce", "$0.99", "10.00"],
],
+ # Align the first column to the left, the second to the center,
+ # the third to the right, and the fourth to the decimal point
alignments=[Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT, Alignment.DECIMAL],
)
@@ -28,6 +30,27 @@ class Alignment(IntEnum):
╚════════════════════════════════════════╝
\"\"\"
+ A single alignment type can be used for all columns::
+
+ table2ascii(
+ header=["First Name", "Last Name", "Age"],
+ body=[
+ ["John", "Smith", 30],
+ ["Jane", "Doe", 28],
+ ],
+ # Align all columns to the left
+ alignments=Alignment.LEFT,
+ )
+
+ \"\"\"
+ ╔══════════════════════════════╗
+ ║ First Name Last Name Age ║
+ ╟──────────────────────────────╢
+ ║ John Smith 30 ║
+ ║ Jane Doe 28 ║
+ ╚══════════════════════════════╝
+ \"\"\"
+
.. note::
If the :attr:`DECIMAL` alignment type is used, any cell values that are
diff --git a/table2ascii/options.py b/table2ascii/options.py
index 36f6ee0..e88bd44 100644
--- a/table2ascii/options.py
+++ b/table2ascii/options.py
@@ -19,7 +19,7 @@ class Options:
first_col_heading: bool
last_col_heading: bool
column_widths: Sequence[int | None] | None
- alignments: Sequence[Alignment] | None
+ alignments: Sequence[Alignment] | Alignment | None
cell_padding: int
style: TableStyle
use_wcwidth: bool
diff --git a/table2ascii/table_to_ascii.py b/table2ascii/table_to_ascii.py
index 0510bd1..46603d7 100644
--- a/table2ascii/table_to_ascii.py
+++ b/table2ascii/table_to_ascii.py
@@ -67,11 +67,16 @@ def __init__(
if not header and not body and not footer:
raise NoHeaderBodyOrFooterError()
- self.__alignments = options.alignments or [Alignment.CENTER] * self.__columns
+ alignments = options.alignments if options.alignments is not None else Alignment.CENTER
+
+ # if alignments is a single Alignment, convert it to a list of that Alignment
+ self.__alignments: list[Alignment] = (
+ [alignments] * self.__columns if isinstance(alignments, Alignment) else list(alignments)
+ )
# check if alignments specified have a different number of columns
- if options.alignments and len(options.alignments) != self.__columns:
- raise AlignmentCountMismatchError(options.alignments, self.__columns)
+ if len(self.__alignments) != self.__columns:
+ raise AlignmentCountMismatchError(self.__alignments, self.__columns)
# keep track of the number widths and positions of the decimal points for decimal alignment
decimal_widths, decimal_positions = self.__calculate_decimal_widths_and_positions()
@@ -634,16 +639,13 @@ def table2ascii(
first_col_heading: bool = False,
last_col_heading: bool = False,
column_widths: Sequence[int | None] | None = None,
- alignments: Sequence[Alignment] | None = None,
+ alignments: Sequence[Alignment] | Alignment | None = None,
cell_padding: int = 1,
style: TableStyle = PresetStyle.double_thin_compact,
use_wcwidth: bool = True,
) -> str:
"""Convert a 2D Python table to ASCII text
- .. versionchanged:: 1.0.0
- Added the ``use_wcwidth`` parameter defaulting to :py:obj:`True`.
-
Args:
header: List of column values in the table's header row. All values should be :class:`str`
or support :class:`str` conversion. If not specified, the table will not have a header row.
@@ -660,8 +662,10 @@ def table2ascii(
is passed instead of a :class:`~collections.abc.Sequence`, all columns will be automatically
sized. Defaults to :py:obj:`None`.
alignments: List of alignments for each column
- (ex. ``[Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT]``). If not specified or set to
- :py:obj:`None`, all columns will be center-aligned. Defaults to :py:obj:`None`.
+ (ex. ``[Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT, Alignment.DECIMAL]``)
+ or a single alignment to apply to all columns (ex. ``Alignment.LEFT``).
+ If not specified or set to :py:obj:`None`, all columns will be center-aligned.
+ Defaults to :py:obj:`None`.
cell_padding: The minimum number of spaces to add between the cell content and the column
separator. If set to ``0``, the cell content will be flush against the column separator.
Defaults to ``1``.
@@ -673,6 +677,14 @@ def table2ascii(
zero-width space, etc.), whereas :func:`len` determines the width solely based on the number of
characters in the string. Defaults to :py:obj:`True`.
+ .. versionchanged:: 1.1.0
+
+ ``alignments`` can now also be specified as a single :class:`Alignment` value to apply to all columns.
+
+ .. versionchanged:: 1.0.0
+
+ Added the ``use_wcwidth`` parameter defaulting to :py:obj:`True`.
+
Returns:
The generated ASCII table
"""
diff --git a/tests/test_alignments.py b/tests/test_alignments.py
index 107c32b..ff684e1 100644
--- a/tests/test_alignments.py
+++ b/tests/test_alignments.py
@@ -120,3 +120,37 @@ def test_decimal_alignment():
"╚═════════════╩═══════╧═════════════╧════╧════╧═════════╝"
)
assert text == expected
+
+
+def test_single_decimal_alignment():
+ text = t2a(
+ header=["1.1.1", "G", "Long Header"],
+ body=[[100.00001, 2, 3.14], [10.0001, 22.0, 2.718]],
+ alignments=Alignment.DECIMAL,
+ )
+ expected = (
+ "╔════════════════════════════════╗\n"
+ "║ 1.1.1 G Long Header ║\n"
+ "╟────────────────────────────────╢\n"
+ "║ 100.00001 2 3.14 ║\n"
+ "║ 10.0001 22.0 2.718 ║\n"
+ "╚════════════════════════════════╝"
+ )
+ assert text == expected
+
+
+def test_single_left_alignment():
+ text = t2a(
+ header=["1.1.1", "G", "Long Header"],
+ body=[[100.00001, 2, 3.14], [10.0001, 22.0, 2.718]],
+ alignments=Alignment.LEFT,
+ )
+ expected = (
+ "╔════════════════════════════════╗\n"
+ "║ 1.1.1 G Long Header ║\n"
+ "╟────────────────────────────────╢\n"
+ "║ 100.00001 2 3.14 ║\n"
+ "║ 10.0001 22.0 2.718 ║\n"
+ "╚════════════════════════════════╝"
+ )
+ assert text == expected