Skip to content

Commit 5414b4d

Browse files
committed
Move all parameters to Options and simplified code
1 parent 7e642ae commit 5414b4d

File tree

2 files changed

+38
-50
lines changed

2 files changed

+38
-50
lines changed

table2ascii/__init__.py

Lines changed: 37 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,6 @@
44
from typing import List, Optional, Union
55

66

7-
@dataclass
8-
class Options:
9-
"""Class for storing options that the user sets"""
10-
11-
first_col_heading: bool = False
12-
last_col_heading: bool = False
13-
14-
157
class Alignment(enum.Enum):
168
"""Enum for alignment types"""
179

@@ -20,57 +12,63 @@ class Alignment(enum.Enum):
2012
RIGHT = 2
2113

2214

15+
@dataclass
16+
class Options:
17+
"""Class for storing options that the user sets"""
18+
19+
header: Optional[List] = None
20+
body: Optional[List[List]] = None
21+
footer: Optional[List] = None
22+
first_col_heading: bool = False
23+
last_col_heading: bool = False
24+
column_widths: Optional[List[int]] = None
25+
alignments: Optional[List[Alignment]] = None
26+
27+
2328
class TableToAscii:
2429
"""Class used to convert a 2D Python table to ASCII text"""
2530

26-
def __init__(
27-
self,
28-
header: Optional[List],
29-
body: Optional[List[List]],
30-
footer: Optional[List],
31-
column_widths: Optional[List[int]],
32-
alignments: Optional[List[Alignment]],
33-
options: Options,
34-
):
31+
def __init__(self, options: Options):
3532
"""Validate arguments and initialize fields"""
3633
# initialize fields
37-
self.__header = header
38-
self.__body = body
39-
self.__footer = footer
40-
self.__options = options
34+
self.__header = options.header
35+
self.__body = options.body
36+
self.__footer = options.footer
37+
self.__first_col_heading = options.first_col_heading
38+
self.__last_col_heading = options.last_col_heading
4139

4240
# calculate number of columns
4341
self.__columns = self.__count_columns()
4442

4543
# check if footer has a different number of columns
46-
if footer and len(footer) != self.__columns:
44+
if options.footer and len(options.footer) != self.__columns:
4745
raise ValueError(
4846
"Footer must have the same number of columns as the other rows"
4947
)
5048
# check if any rows in body have a different number of columns
51-
if body and tuple(filter(lambda r: len(r) != self.__columns, body)):
49+
if options.body and any(len(row) != self.__columns for row in options.body):
5250
raise ValueError(
5351
"All rows in body must have the same number of columns as the other rows"
5452
)
5553

5654
# calculate or use given column widths
57-
self.__column_widths = column_widths or self.__auto_column_widths()
55+
self.__column_widths = options.column_widths or self.__auto_column_widths()
5856

5957
# check if column widths specified have a different number of columns
60-
if column_widths and len(column_widths) != self.__columns:
58+
if options.column_widths and len(options.column_widths) != self.__columns:
6159
raise ValueError(
6260
"Length of `column_widths` list must equal the number of columns"
6361
)
6462
# check if column widths are not all at least 2
65-
if column_widths and min(column_widths) < 2:
63+
if options.column_widths and min(options.column_widths) < 2:
6664
raise ValueError(
6765
"All values in `column_widths` must be greater than or equal to 2"
6866
)
6967

70-
self.__alignments = alignments or [Alignment.CENTER] * self.__columns
68+
self.__alignments = options.alignments or [Alignment.CENTER] * self.__columns
7169

7270
# check if alignments specified have a different number of columns
73-
if alignments and len(alignments) != self.__columns:
71+
if options.alignments and len(options.alignments) != self.__columns:
7472
raise ValueError(
7573
"Length of `alignments` list must equal the number of columns"
7674
)
@@ -162,8 +160,6 @@ def __row_to_ascii(
162160
filler: Union[str, List],
163161
) -> str:
164162
"""Assembles a row of the ascii table"""
165-
first_heading = self.__options.first_col_heading
166-
last_heading = self.__options.last_col_heading
167163
# left edge of the row
168164
output = left_edge
169165
# add columns
@@ -180,8 +176,11 @@ def __row_to_ascii(
180176
)
181177
# column seperator
182178
sep = column_seperator
183-
if (i == 0 and first_heading) or (i == self.__columns - 2 and last_heading):
184-
# use column heading if option is specified
179+
if i == 0 and self.__first_col_heading:
180+
# use column heading if first column option is specified
181+
sep = heading_col_sep
182+
elif i == self.__columns - 2 and self.__last_col_heading:
183+
# use column heading if last column option is specified
185184
sep = heading_col_sep
186185
elif i == self.__columns - 1:
187186
# replace last seperator with symbol for edge of the row
@@ -250,16 +249,16 @@ def __footer_sep_to_ascii(self) -> str:
250249
)
251250

252251
def __body_to_ascii(self) -> str:
253-
output: str = ""
254-
for row in self.__body:
255-
output += self.__row_to_ascii(
252+
return "".join(
253+
self.__row_to_ascii(
256254
left_edge=self.__parts["left_and_right_edge"],
257255
heading_col_sep=self.__parts["heading_col_sep"],
258256
column_seperator=self.__parts["middle_edge"],
259257
right_edge=self.__parts["left_and_right_edge"],
260258
filler=row,
261259
)
262-
return output
260+
for row in self.__body
261+
)
263262

264263
def to_ascii(self) -> str:
265264
# top row of table
@@ -281,14 +280,7 @@ def to_ascii(self) -> str:
281280
return table
282281

283282

284-
def table2ascii(
285-
header: Optional[List] = None,
286-
body: Optional[List[List]] = None,
287-
footer: Optional[List] = None,
288-
column_widths: Optional[List[int]] = None,
289-
alignments: Optional[List[Alignment]] = None,
290-
**options,
291-
) -> str:
283+
def table2ascii(**options) -> str:
292284
"""Convert a 2D Python table to ASCII text
293285
294286
### Arguments
@@ -297,11 +289,7 @@ def table2ascii(
297289
:param footer: :class:`Optional[List]` List of column values in the table's footer row
298290
:param column_widths: :class:`Optional[List[int]]` List of widths in characters for each column (defaults to auto-sizing)
299291
:param alignments: :class:`Optional[List[Alignment]]` List of alignments (ex. `[Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT]`)
300-
301-
### Additional options
302292
:param first_col_heading: :class:`Optional[bool]` Whether to add a header column separator after the first column
303293
:param last_col_heading: :class:`Optional[bool]` Whether to add a header column separator before the last column
304294
"""
305-
return TableToAscii(
306-
header, body, footer, column_widths, alignments, Options(**options)
307-
).to_ascii()
295+
return TableToAscii(Options(**options)).to_ascii()

tests/test_alignments.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,5 +42,5 @@ def test_invalid_alignments():
4242
body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]],
4343
footer=["SUM", "130", "140", "135", "130"],
4444
first_col_heading=True,
45-
alignments=[9999, -1, Alignment.RIGHT],
45+
alignments=[9999, -1, Alignment.RIGHT, Alignment.CENTER, Alignment.RIGHT],
4646
)

0 commit comments

Comments
 (0)