Skip to content

Commit 1c6d431

Browse files
authored
Merge pull request #78 from DenverCoder1/refactor
2 parents ea432b5 + 08e59cf commit 1c6d431

File tree

8 files changed

+107
-73
lines changed

8 files changed

+107
-73
lines changed

Diff for: README.md

+16-14
Original file line numberDiff line numberDiff line change
@@ -195,20 +195,22 @@ print(output)
195195

196196
## ⚙️ Options
197197

198-
All parameters are optional.
199-
200-
| Option | Type | Default | Description |
201-
| :-----------------: | :-------------------: | :-------------------: | :-------------------------------------------------------------------------------: |
202-
| `header` | `List[Any]` | `None` | First table row seperated by header row separator. Values should support `str()` |
203-
| `body` | `List[List[Any]]` | `None` | List of rows for the main section of the table. Values should support `str()` |
204-
| `footer` | `List[Any]` | `None` | Last table row seperated by header row separator. Values should support `str()` |
205-
| `column_widths` | `List[Optional[int]]` | `None` (automatic) | List of column widths in characters for each column |
206-
| `alignments` | `List[Alignment]` | `None` (all centered) | Column alignments<br/>(ex. `[Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT]`) |
207-
| `style` | `TableStyle` | `double_thin_compact` | Table style to use for the table\* |
208-
| `first_col_heading` | `bool` | `False` | Whether to add a heading column separator after the first column |
209-
| `last_col_heading` | `bool` | `False` | Whether to add a heading column separator before the last column |
210-
| `cell_padding` | `int` | `1` | The minimum number of spaces to add between the cell content and the cell border |
211-
| `use_wcwidth` | `bool` | `True` | Whether to use [wcwidth][wcwidth] instead of `len()` to calculate cell width |
198+
All parameters are optional. At least one of `header`, `body`, and `footer` must be provided.
199+
200+
Refer to the [documentation](https://table2ascii.readthedocs.io/en/stable/api.html#table2ascii) for more information.
201+
202+
| Option | Type | Default | Description |
203+
| :-----------------: | :----------------------------: | :-------------------: | :-------------------------------------------------------------------------------: |
204+
| `header` | `Sequence[SupportsStr]` | `None` | First table row seperated by header row separator. Values should support `str()` |
205+
| `body` | `Sequence[Sequence[Sequence]]` | `None` | 2D List of rows for the main section of the table. Values should support `str()` |
206+
| `footer` | `Sequence[Sequence]` | `None` | Last table row seperated by header row separator. Values should support `str()` |
207+
| `column_widths` | `Sequence[Optional[int]]` | `None` (automatic) | List of column widths in characters for each column |
208+
| `alignments` | `Sequence[Alignment]` | `None` (all centered) | Column alignments<br/>(ex. `[Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT]`) |
209+
| `style` | `TableStyle` | `double_thin_compact` | Table style to use for the table\* |
210+
| `first_col_heading` | `bool` | `False` | Whether to add a heading column separator after the first column |
211+
| `last_col_heading` | `bool` | `False` | Whether to add a heading column separator before the last column |
212+
| `cell_padding` | `int` | `1` | The minimum number of spaces to add between the cell content and the cell border |
213+
| `use_wcwidth` | `bool` | `True` | Whether to use [wcwidth][wcwidth] instead of `len()` to calculate cell width |
212214

213215
[wcwidth]: https://pypi.org/project/wcwidth/
214216

Diff for: docs/source/generate_style_list.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44
from table2ascii import PresetStyle, table2ascii
55

66

7-
def indent_all_lines(text, number_of_spaces=3):
7+
def indent_all_lines(text: str, number_of_spaces: int = 3) -> str:
88
"""Indent all lines in a string by a certain number of spaces"""
99
return "\n".join(number_of_spaces * " " + line for line in text.split("\n"))
1010

1111

12-
def generate_style_list():
12+
def generate_style_list() -> str:
1313
"""Generate README.rst the style list"""
1414
# get attributes in PresetStyle
1515
attribute_names = [attr for attr in dir(PresetStyle) if not attr.startswith("__")]
@@ -43,7 +43,7 @@ def generate_style_list():
4343
return f"{heading}\n\n{table_of_contents}\n{style_list}"
4444

4545

46-
def write_to_file(filename, content):
46+
def write_to_file(filename: str, content: str) -> None:
4747
"""Write content to filename"""
4848
with open(filename, "w") as f:
4949
f.write(content)

Diff for: table2ascii/exceptions.py

+34-20
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
from __future__ import annotations
2+
3+
from collections.abc import Sequence
24
from typing import Any
35

46
from .alignment import Alignment
5-
67
from .annotations import SupportsStr
78

89

910
class Table2AsciiError(Exception):
1011
"""Base class for all table2ascii exceptions"""
1112

12-
def _message(self):
13+
def _message(self) -> str:
1314
"""Return the error message"""
1415
raise NotImplementedError
1516

@@ -39,16 +40,16 @@ class FooterColumnCountMismatchError(ColumnCountMismatchError):
3940
This class is a subclass of :class:`ColumnCountMismatchError`.
4041
4142
Attributes:
42-
footer (list[SupportsStr]): The footer that caused the error
43+
footer (Sequence[SupportsStr]): The footer that caused the error
4344
expected_columns (int): The number of columns that were expected
4445
"""
4546

46-
def __init__(self, footer: list[SupportsStr], expected_columns: int):
47+
def __init__(self, footer: Sequence[SupportsStr], expected_columns: int):
4748
self.footer = footer
4849
self.expected_columns = expected_columns
4950
super().__init__(self._message())
5051

51-
def _message(self):
52+
def _message(self) -> str:
5253
return (
5354
f"Footer column count mismatch: {len(self.footer)} columns "
5455
f"found, expected {self.expected_columns}."
@@ -62,20 +63,20 @@ class BodyColumnCountMismatchError(ColumnCountMismatchError):
6263
This class is a subclass of :class:`ColumnCountMismatchError`.
6364
6465
Attributes:
65-
body (list[list[SupportsStr]]): The body that caused the error
66+
body (Sequence[Sequence[SupportsStr]]): The body that caused the error
6667
expected_columns (int): The number of columns that were expected
67-
first_invalid_row (list[SupportsStr]): The first row with an invalid column count
68+
first_invalid_row (Sequence[SupportsStr]): The first row with an invalid column count
6869
"""
6970

70-
def __init__(self, body: list[list[SupportsStr]], expected_columns: int):
71+
def __init__(self, body: Sequence[Sequence[SupportsStr]], expected_columns: int):
7172
self.body = body
7273
self.expected_columns = expected_columns
7374
self.first_invalid_row = next(
7475
(row for row in self.body if len(row) != self.expected_columns)
7576
)
7677
super().__init__(self._message())
7778

78-
def _message(self):
79+
def _message(self) -> str:
7980
return (
8081
f"Body column count mismatch: A row with {len(self.first_invalid_row)} "
8182
f"columns was found, expected {self.expected_columns}."
@@ -89,16 +90,16 @@ class AlignmentCountMismatchError(ColumnCountMismatchError):
8990
This class is a subclass of :class:`ColumnCountMismatchError`.
9091
9192
Attributes:
92-
alignments (list[Alignment]): The alignments that caused the error
93+
alignments (Sequence[Alignment]): The alignments that caused the error
9394
expected_columns (int): The number of columns that were expected
9495
"""
9596

96-
def __init__(self, alignments: list[Alignment], expected_columns: int):
97+
def __init__(self, alignments: Sequence[Alignment], expected_columns: int):
9798
self.alignments = alignments
9899
self.expected_columns = expected_columns
99100
super().__init__(self._message())
100101

101-
def _message(self):
102+
def _message(self) -> str:
102103
return (
103104
f"Alignment count mismatch: {len(self.alignments)} alignments "
104105
f"found, expected {self.expected_columns}."
@@ -112,22 +113,35 @@ class ColumnWidthsCountMismatchError(ColumnCountMismatchError):
112113
This class is a subclass of :class:`ColumnCountMismatchError`.
113114
114115
Attributes:
115-
column_widths (list[Optional[int]]): The column widths that caused the error
116+
column_widths (Sequence[Optional[int]]): The column widths that caused the error
116117
expected_columns (int): The number of columns that were expected
117118
"""
118119

119-
def __init__(self, column_widths: list[int | None], expected_columns: int):
120+
def __init__(self, column_widths: Sequence[int | None], expected_columns: int):
120121
self.column_widths = column_widths
121122
self.expected_columns = expected_columns
122123
super().__init__(self._message())
123124

124-
def _message(self):
125+
def _message(self) -> str:
125126
return (
126127
f"Column widths count mismatch: {len(self.column_widths)} column widths "
127128
f"found, expected {self.expected_columns}."
128129
)
129130

130131

132+
class NoHeaderBodyOrFooterError(TableOptionError):
133+
"""Exception raised when no header, body or footer is provided
134+
135+
This class is a subclass of :class:`TableOptionError`.
136+
"""
137+
138+
def __init__(self):
139+
super().__init__(self._message())
140+
141+
def _message(self) -> str:
142+
return "At least one of header, body or footer must be provided."
143+
144+
131145
class InvalidCellPaddingError(TableOptionError):
132146
"""Exception raised when the cell padding is invalid
133147
@@ -141,7 +155,7 @@ def __init__(self, padding: int):
141155
self.padding = padding
142156
super().__init__(self._message())
143157

144-
def _message(self):
158+
def _message(self) -> str:
145159
return f"Invalid cell padding: {self.padding} is not a positive integer."
146160

147161

@@ -163,7 +177,7 @@ def __init__(self, column_index: int, column_width: int, min_width: int):
163177
self.min_width = min_width
164178
super().__init__(self._message())
165179

166-
def _message(self):
180+
def _message(self) -> str:
167181
return (
168182
f"Column width too small: The column width for column index {self.column_index} "
169183
f" of `column_widths` is {self.column_width}, but the minimum width "
@@ -184,7 +198,7 @@ def __init__(self, alignment: Any):
184198
self.alignment = alignment
185199
super().__init__(self._message())
186200

187-
def _message(self):
201+
def _message(self) -> str:
188202
return (
189203
f"Invalid alignment: {self.alignment!r} is not a valid alignment. "
190204
f"Valid alignments are: {', '.join(a.__repr__() for a in Alignment)}"
@@ -208,7 +222,7 @@ def __init__(self, string: str, max_characters: int):
208222
self.max_characters = max_characters
209223
super().__init__(self._message())
210224

211-
def _message(self):
225+
def _message(self) -> str:
212226
return (
213227
f"Too many characters for table style: {len(self.string)} characters "
214228
f"found, but the maximum number of characters allowed is {self.max_characters}."
@@ -234,7 +248,7 @@ def __init__(self, string: str, max_characters: int):
234248
self.max_characters = max_characters
235249
super().__init__(self._message())
236250

237-
def _message(self):
251+
def _message(self) -> str:
238252
return (
239253
f"Too few characters for table style: {len(self.string)} characters "
240254
f"found, but table styles can accept {self.max_characters} characters. "

Diff for: table2ascii/merge.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,5 @@ class Merge(Enum):
3939

4040
LEFT = 0
4141

42-
def __str__(self):
42+
def __str__(self) -> str:
4343
return ""

Diff for: table2ascii/options.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
from collections.abc import Sequence
34
from dataclasses import dataclass
45

56
from .alignment import Alignment
@@ -17,8 +18,8 @@ class Options:
1718

1819
first_col_heading: bool
1920
last_col_heading: bool
20-
column_widths: list[int | None] | None
21-
alignments: list[Alignment] | None
21+
column_widths: Sequence[int | None] | None
22+
alignments: Sequence[Alignment] | None
2223
cell_padding: int
2324
style: TableStyle
2425
use_wcwidth: bool

Diff for: table2ascii/table_style.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,11 @@ def from_string(cls, string: str) -> "TableStyle":
128128
raise TableStyleTooLongError(string, num_params)
129129
# if the string is too short, show a warning and pad it with spaces
130130
elif len(string) < num_params:
131-
string += " " * (num_params - len(string))
132131
warnings.warn(TableStyleTooShortWarning(string, num_params), stacklevel=2)
132+
string += " " * (num_params - len(string))
133133
return cls(*string)
134134

135-
def set(self, **kwargs) -> "TableStyle":
135+
def set(self, **kwargs: str) -> "TableStyle":
136136
"""Set attributes of the TableStyle
137137
138138
Args:

0 commit comments

Comments
 (0)