From bce515ca7862121f58a17ec00afbedf6be0cfc00 Mon Sep 17 00:00:00 2001 From: Jonah Lawrence Date: Wed, 28 Apr 2021 01:17:08 +0300 Subject: [PATCH 01/22] separated files and added preset styles --- table2ascii/__init__.py | 300 +---------------------- table2ascii/alignment.py | 9 + table2ascii/options.py | 20 ++ table2ascii/style.py | 56 +++++ table2ascii/styles.py | 440 ++++++++++++++++++++++++++++++++++ table2ascii/table_to_ascii.py | 241 +++++++++++++++++++ tests/test_styles.py | 134 +++++++++++ 7 files changed, 906 insertions(+), 294 deletions(-) create mode 100644 table2ascii/alignment.py create mode 100644 table2ascii/options.py create mode 100644 table2ascii/style.py create mode 100644 table2ascii/styles.py create mode 100644 table2ascii/table_to_ascii.py create mode 100644 tests/test_styles.py diff --git a/table2ascii/__init__.py b/table2ascii/__init__.py index dc29de7..4aa2b25 100644 --- a/table2ascii/__init__.py +++ b/table2ascii/__init__.py @@ -1,295 +1,7 @@ -import enum -from dataclasses import dataclass -from math import ceil, floor -from typing import List, Optional, Union +from .table_to_ascii import table2ascii +from .alignment import Alignment - -class Alignment(enum.Enum): - """Enum for alignment types""" - - LEFT = 0 - CENTER = 1 - RIGHT = 2 - - -@dataclass -class Options: - """Class for storing options that the user sets""" - - header: Optional[List] = None - body: Optional[List[List]] = None - footer: Optional[List] = None - first_col_heading: bool = False - last_col_heading: bool = False - column_widths: Optional[List[int]] = None - alignments: Optional[List[Alignment]] = None - - -class TableToAscii: - """Class used to convert a 2D Python table to ASCII text""" - - def __init__(self, options: Options): - """Validate arguments and initialize fields""" - # initialize fields - self.__header = options.header - self.__body = options.body - self.__footer = options.footer - self.__first_col_heading = options.first_col_heading - self.__last_col_heading = options.last_col_heading - - # calculate number of columns - self.__columns = self.__count_columns() - - # check if footer has a different number of columns - if options.footer and len(options.footer) != self.__columns: - raise ValueError( - "Footer must have the same number of columns as the other rows" - ) - # check if any rows in body have a different number of columns - if options.body and any(len(row) != self.__columns for row in options.body): - raise ValueError( - "All rows in body must have the same number of columns as the other rows" - ) - - # calculate or use given column widths - self.__column_widths = options.column_widths or self.__auto_column_widths() - - # check if column widths specified have a different number of columns - if options.column_widths and len(options.column_widths) != self.__columns: - raise ValueError( - "Length of `column_widths` list must equal the number of columns" - ) - # check if column widths are not all at least 2 - if options.column_widths and min(options.column_widths) < 2: - raise ValueError( - "All values in `column_widths` must be greater than or equal to 2" - ) - - self.__alignments = options.alignments or [Alignment.CENTER] * self.__columns - - # check if alignments specified have a different number of columns - if options.alignments and len(options.alignments) != self.__columns: - raise ValueError( - "Length of `alignments` list must equal the number of columns" - ) - - """ - ╔═════╦═══════════════════════╗ ABBBBBCBBBBBDBBBBBDBBBBBDBBBBBE - ║ # ║ G H R S ║ F G H H H F - ╟─────╫───────────────────────╢ IJJJJJKJJJJJLJJJJJLJJJJJLJJJJJM - ║ 1 ║ 30 40 35 30 ║ F G H H H F - ║ 2 ║ 30 40 35 30 ║ F G H H H F - ╟─────╫───────────────────────╢ NOOOOOPOOOOOQOOOOOQOOOOOQOOOOOR - ║ SUM ║ 130 140 135 130 ║ F G H H H F - ╚═════╩═══════════════════════╝ SBBBBBTBBBBBUBBBBBUBBBBBUBBBBBV - """ - self.__parts = { - "top_left_corner": "╔", # A - "top_and_bottom_edge": "═", # B - "heading_col_top_tee": "╦", # C - "top_tee": "═", # D - "top_right_corner": "╗", # E - "left_and_right_edge": "║", # F - "heading_col_sep": "║", # G - "middle_edge": " ", # H - "header_left_tee": "╟", # I - "header_row_sep": "─", # J - "heading_col_header_cross": "╫", # K - "header_row_cross": "─", # L - "header_right_tee": "╢", # M - "footer_left_tee": "╟", # N - "footer_row_sep": "─", # O - "heading_col_footer_cross": "╫", # P - "footer_row_cross": "─", # Q - "footer_right_tee": "╢", # R - "bottom_left_corner": "╚", # S - "heading_col_bottom_tee": "╩", # T - "bottom_tee": "═", # U - "bottom_right_corner": "╝", # V - } - - def __count_columns(self) -> int: - """Get the number of columns in the table - based on the provided header, footer, and body lists. - """ - if self.__header: - return len(self.__header) - if self.__footer: - return len(self.__footer) - if self.__body and len(self.__body) > 0: - return len(self.__body[0]) - return 0 - - def __auto_column_widths(self) -> List[int]: - """Get the minimum number of characters needed for the values - in each column in the table with 1 space of padding on each side. - """ - column_widths = [] - for i in range(self.__columns): - # number of characters in column of i of header, each body row, and footer - header_size = len(self.__header[i]) if self.__header else 0 - body_size = ( - map(lambda row, i=i: len(row[i]), self.__body) if self.__body else [0] - ) - footer_size = len(self.__footer[i]) if self.__footer else 0 - # get the max and add 2 for padding each side with a space - column_widths.append(max(header_size, *body_size, footer_size) + 2) - return column_widths - - def __pad(self, text: str, width: int, alignment: Alignment): - """Pad a string of text to a given width with specified alignment""" - if alignment == Alignment.LEFT: - # pad with spaces on the end - return f" {text} " + (" " * (width - len(text) - 2)) - if alignment == Alignment.CENTER: - # pad with spaces, half on each side - before = " " * floor((width - len(text) - 2) / 2) - after = " " * ceil((width - len(text) - 2) / 2) - return before + f" {text} " + after - if alignment == Alignment.RIGHT: - # pad with spaces at the beginning - return (" " * (width - len(text) - 2)) + f" {text} " - raise ValueError(f"The value '{alignment}' is not valid for alignment.") - - def __row_to_ascii( - self, - left_edge: str, - heading_col_sep: str, - column_seperator: str, - right_edge: str, - filler: Union[str, List], - ) -> str: - """Assembles a row of the ascii table""" - # left edge of the row - output = left_edge - # add columns - for i in range(self.__columns): - # content between separators - output += ( - # edge or row separator if filler is a specific character - filler * self.__column_widths[i] - if isinstance(filler, str) - # otherwise, use the column content - else self.__pad( - str(filler[i]), self.__column_widths[i], self.__alignments[i] - ) - ) - # column seperator - sep = column_seperator - if i == 0 and self.__first_col_heading: - # use column heading if first column option is specified - sep = heading_col_sep - elif i == self.__columns - 2 and self.__last_col_heading: - # use column heading if last column option is specified - sep = heading_col_sep - elif i == self.__columns - 1: - # replace last seperator with symbol for edge of the row - sep = right_edge - output += sep - return output + "\n" - - def __top_edge_to_ascii(self) -> str: - """Assembles the top edge of the ascii table""" - return self.__row_to_ascii( - left_edge=self.__parts["top_left_corner"], - heading_col_sep=self.__parts["heading_col_top_tee"], - column_seperator=self.__parts["top_tee"], - right_edge=self.__parts["top_right_corner"], - filler=self.__parts["top_and_bottom_edge"], - ) - - def __bottom_edge_to_ascii(self) -> str: - """Assembles the top edge of the ascii table""" - return self.__row_to_ascii( - left_edge=self.__parts["bottom_left_corner"], - heading_col_sep=self.__parts["heading_col_bottom_tee"], - column_seperator=self.__parts["bottom_tee"], - right_edge=self.__parts["bottom_right_corner"], - filler=self.__parts["top_and_bottom_edge"], - ) - - def __header_row_to_ascii(self) -> str: - """Assembles the header row line of the ascii table""" - return self.__row_to_ascii( - left_edge=self.__parts["left_and_right_edge"], - heading_col_sep=self.__parts["heading_col_sep"], - column_seperator=self.__parts["middle_edge"], - right_edge=self.__parts["left_and_right_edge"], - filler=self.__header, - ) - - def __footer_row_to_ascii(self) -> str: - """Assembles the header row line of the ascii table""" - return self.__row_to_ascii( - left_edge=self.__parts["left_and_right_edge"], - heading_col_sep=self.__parts["heading_col_sep"], - column_seperator=self.__parts["middle_edge"], - right_edge=self.__parts["left_and_right_edge"], - filler=self.__footer, - ) - - def __header_sep_to_ascii(self) -> str: - """Assembles the seperator below the header of the ascii table""" - return self.__row_to_ascii( - left_edge=self.__parts["header_left_tee"], - heading_col_sep=self.__parts["heading_col_header_cross"], - column_seperator=self.__parts["header_row_cross"], - right_edge=self.__parts["header_right_tee"], - filler=self.__parts["header_row_sep"], - ) - - def __footer_sep_to_ascii(self) -> str: - """Assembles the seperator below the header of the ascii table""" - return self.__row_to_ascii( - left_edge=self.__parts["footer_left_tee"], - heading_col_sep=self.__parts["heading_col_footer_cross"], - column_seperator=self.__parts["footer_row_cross"], - right_edge=self.__parts["footer_right_tee"], - filler=self.__parts["footer_row_sep"], - ) - - def __body_to_ascii(self) -> str: - return "".join( - self.__row_to_ascii( - left_edge=self.__parts["left_and_right_edge"], - heading_col_sep=self.__parts["heading_col_sep"], - column_seperator=self.__parts["middle_edge"], - right_edge=self.__parts["left_and_right_edge"], - filler=row, - ) - for row in self.__body - ) - - def to_ascii(self) -> str: - # top row of table - table = self.__top_edge_to_ascii() - # add table header - if self.__header: - table += self.__header_row_to_ascii() - table += self.__header_sep_to_ascii() - # add table body - if self.__body: - table += self.__body_to_ascii() - # add table footer - if self.__footer: - table += self.__footer_sep_to_ascii() - table += self.__footer_row_to_ascii() - # bottom row of table - table += self.__bottom_edge_to_ascii() - # reurn ascii table - return table - - -def table2ascii(**options) -> str: - """Convert a 2D Python table to ASCII text - - ### Arguments - :param header: :class:`Optional[List]` List of column values in the table's header row - :param body: :class:`Optional[List[List]]` 2-dimensional list of values in the table's body - :param footer: :class:`Optional[List]` List of column values in the table's footer row - :param column_widths: :class:`Optional[List[int]]` List of widths in characters for each column (defaults to auto-sizing) - :param alignments: :class:`Optional[List[Alignment]]` List of alignments (ex. `[Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT]`) - :param first_col_heading: :class:`Optional[bool]` Whether to add a header column separator after the first column - :param last_col_heading: :class:`Optional[bool]` Whether to add a header column separator before the last column - """ - return TableToAscii(Options(**options)).to_ascii() +__all__ = [ + "table2ascii", + "Alignment", +] diff --git a/table2ascii/alignment.py b/table2ascii/alignment.py new file mode 100644 index 0000000..0f677ce --- /dev/null +++ b/table2ascii/alignment.py @@ -0,0 +1,9 @@ +import enum + + +class Alignment(enum.Enum): + """Enum for alignment types""" + + LEFT = 0 + CENTER = 1 + RIGHT = 2 diff --git a/table2ascii/options.py b/table2ascii/options.py new file mode 100644 index 0000000..9b2c22a --- /dev/null +++ b/table2ascii/options.py @@ -0,0 +1,20 @@ +from dataclasses import dataclass +from typing import List, Optional + +from . import styles +from .alignment import Alignment +from .style import Style + + +@dataclass +class Options: + """Class for storing options that the user sets""" + + header: Optional[List] = None + body: Optional[List[List]] = None + footer: Optional[List] = None + first_col_heading: bool = False + last_col_heading: bool = False + column_widths: Optional[List[int]] = None + alignments: Optional[List[Alignment]] = None + style: Style = styles.double_thin diff --git a/table2ascii/style.py b/table2ascii/style.py new file mode 100644 index 0000000..c478f8f --- /dev/null +++ b/table2ascii/style.py @@ -0,0 +1,56 @@ +from dataclasses import dataclass + + +@dataclass +class Style: + """Class for storing information about a table style + + **Parts of the table labeled alphabetically** + + ```text + ABBBBBCBBBBBDBBBBBDBBBBBDBBBBBE + F G H H H F + IJJJJJKJJJJJLJJJJJLJJJJJLJJJJJM + F G H H H F + F G H H H F + NOOOOOPOOOOOQOOOOOQOOOOOQOOOOOR + F G H H H F + SBBBBBTBBBBBUBBBBBUBBBBBUBBBBBV + ``` + + **How the default theme is displayed** + + ```text + ╔═════╦═══════════════════════╗ + ║ # ║ G H R S ║ + ╟─────╫───────────────────────╢ + ║ 1 ║ 30 40 35 30 ║ + ║ 2 ║ 30 40 35 30 ║ + ╟─────╫───────────────────────╢ + ║ SUM ║ 130 140 135 130 ║ + ╚═════╩═══════════════════════╝ + ``` + """ + + top_left_corner: str # A + top_and_bottom_edge: str # B + heading_col_top_tee: str # C + top_tee: str # D + top_right_corner: str # E + left_and_right_edge: str # F + heading_col_sep: str # G + middle_edge: str # H + header_left_tee: str # I + header_row_sep: str # J + heading_col_header_cross: str # K + header_row_cross: str # L + header_right_tee: str # M + footer_left_tee: str # N + footer_row_sep: str # O + heading_col_footer_cross: str # P + footer_row_cross: str # Q + footer_right_tee: str # R + bottom_left_corner: str # S + heading_col_bottom_tee: str # T + bottom_tee: str # U + bottom_right_corner: str # V diff --git a/table2ascii/styles.py b/table2ascii/styles.py new file mode 100644 index 0000000..df8e980 --- /dev/null +++ b/table2ascii/styles.py @@ -0,0 +1,440 @@ +from .style import Style + + +double_thin = Style( + top_left_corner="╔", + top_and_bottom_edge="═", + heading_col_top_tee="╦", + top_tee="═", + top_right_corner="╗", + left_and_right_edge="║", + heading_col_sep="║", + middle_edge=" ", + header_left_tee="╟", + header_row_sep="─", + heading_col_header_cross="╫", + header_row_cross="─", + header_right_tee="╢", + footer_left_tee="╟", + footer_row_sep="─", + heading_col_footer_cross="╫", + footer_row_cross="─", + footer_right_tee="╢", + bottom_left_corner="╚", + heading_col_bottom_tee="╩", + bottom_tee="═", + bottom_right_corner="╝", +) + +thin = Style( + top_left_corner="┌", + top_and_bottom_edge="─", + heading_col_top_tee="┬", + top_tee="─", + top_right_corner="┐", + left_and_right_edge="│", + heading_col_sep="│", + middle_edge=" ", + header_left_tee="├", + header_row_sep="─", + heading_col_header_cross="┼", + header_row_cross="─", + header_right_tee="┤", + footer_left_tee="├", + footer_row_sep="─", + heading_col_footer_cross="┼", + footer_row_cross="─", + footer_right_tee="┤", + bottom_left_corner="└", + heading_col_bottom_tee="┴", + bottom_tee="─", + bottom_right_corner="┘", +) + +thin_thick = Style( + top_left_corner="┌", + top_and_bottom_edge="─", + heading_col_top_tee="┬", + top_tee="─", + top_right_corner="┐", + left_and_right_edge="│", + heading_col_sep="│", + middle_edge=" ", + header_left_tee="┝", + header_row_sep="━", + heading_col_header_cross="┿", + header_row_cross="━", + header_right_tee="┥", + footer_left_tee="┝", + footer_row_sep="━", + heading_col_footer_cross="┿", + footer_row_cross="━", + footer_right_tee="┥", + bottom_left_corner="└", + heading_col_bottom_tee="┴", + bottom_tee="─", + bottom_right_corner="┘", +) + +thin_double = Style( + top_left_corner="┌", + top_and_bottom_edge="─", + heading_col_top_tee="┬", + top_tee="─", + top_right_corner="┐", + left_and_right_edge="│", + heading_col_sep="│", + middle_edge=" ", + header_left_tee="╞", + header_row_sep="═", + heading_col_header_cross="╪", + header_row_cross="═", + header_right_tee="╡", + footer_left_tee="╞", + footer_row_sep="═", + heading_col_footer_cross="╪", + footer_row_cross="═", + footer_right_tee="╡", + bottom_left_corner="└", + heading_col_bottom_tee="┴", + bottom_tee="─", + bottom_right_corner="┘", +) + +thin_rounded = Style( + top_left_corner="╭", + top_and_bottom_edge="─", + heading_col_top_tee="┬", + top_tee="─", + top_right_corner="╮", + left_and_right_edge="│", + heading_col_sep="│", + middle_edge=" ", + header_left_tee="├", + header_row_sep="─", + heading_col_header_cross="┼", + header_row_cross="─", + header_right_tee="┤", + footer_left_tee="├", + footer_row_sep="─", + heading_col_footer_cross="┼", + footer_row_cross="─", + footer_right_tee="┤", + bottom_left_corner="╰", + heading_col_bottom_tee="┴", + bottom_tee="─", + bottom_right_corner="╯", +) + +thin_thick_rounded = Style( + top_left_corner="╭", + top_and_bottom_edge="─", + heading_col_top_tee="┬", + top_tee="─", + top_right_corner="╮", + left_and_right_edge="│", + heading_col_sep="│", + middle_edge=" ", + header_left_tee="┝", + header_row_sep="━", + heading_col_header_cross="┿", + header_row_cross="━", + header_right_tee="┥", + footer_left_tee="┝", + footer_row_sep="━", + heading_col_footer_cross="┿", + footer_row_cross="━", + footer_right_tee="┥", + bottom_left_corner="╰", + heading_col_bottom_tee="┴", + bottom_tee="─", + bottom_right_corner="╯", +) +f = Style( + top_left_corner="╭", + top_and_bottom_edge="─", + heading_col_top_tee="┬", + top_tee="─", + top_right_corner="╮", + left_and_right_edge="│", + heading_col_sep="│", + middle_edge=" ", + header_left_tee="╞", + header_row_sep="═", + heading_col_header_cross="╪", + header_row_cross="═", + header_right_tee="╡", + footer_left_tee="├", + footer_row_sep="─", + heading_col_footer_cross="┼", + footer_row_cross="─", + footer_right_tee="┤", + bottom_left_corner="╰", + heading_col_bottom_tee="┴", + bottom_tee="─", + bottom_right_corner="╯", +) +g = Style( + top_left_corner="┏", + top_and_bottom_edge="━", + heading_col_top_tee="┳", + top_tee="━", + top_right_corner="┓", + left_and_right_edge="┃", + heading_col_sep="┃", + middle_edge=" ", + header_left_tee="", + header_row_sep="", + heading_col_header_cross="", + header_row_cross="", + header_right_tee="", + footer_left_tee="┣", + footer_row_sep="━", + heading_col_footer_cross="╋", + footer_row_cross="━", + footer_right_tee="┫", + bottom_left_corner="┗", + heading_col_bottom_tee="┻", + bottom_tee="━", + bottom_right_corner="┛", +) +h = Style( + top_left_corner="┌", + top_and_bottom_edge="─", + heading_col_top_tee="┬", + top_tee="─", + top_right_corner="┐", + left_and_right_edge="│", + heading_col_sep="│", + middle_edge=" ", + header_left_tee="┠", + header_row_sep="─", + heading_col_header_cross="╂", + header_row_cross="─", + header_right_tee="┨", + footer_left_tee="├", + footer_row_sep="─", + heading_col_footer_cross="┼", + footer_row_cross="─", + footer_right_tee="┤", + bottom_left_corner="└", + heading_col_bottom_tee="┴", + bottom_tee="─", + bottom_right_corner="┘", +) +i = Style( + top_left_corner="╔", + top_and_bottom_edge="═", + heading_col_top_tee="╦", + top_tee="═", + top_right_corner="╗", + left_and_right_edge="║", + heading_col_sep="║", + middle_edge=" ", + header_left_tee="", + header_row_sep="", + heading_col_header_cross="", + header_row_cross="", + header_right_tee="", + footer_left_tee="╠", + footer_row_sep="═", + heading_col_footer_cross="╬", + footer_row_cross="═", + footer_right_tee="╣", + bottom_left_corner="╚", + heading_col_bottom_tee="╩", + bottom_tee="═", + bottom_right_corner="╝", +) +j = Style( + top_left_corner="╔", + top_and_bottom_edge="═", + heading_col_top_tee="╦", + top_tee="═", + top_right_corner="╗", + left_and_right_edge="║", + heading_col_sep="║", + middle_edge=" ", + header_left_tee="╟", + header_row_sep="─", + heading_col_header_cross="╫", + header_row_cross="─", + header_right_tee="╢", + footer_left_tee="╠", + footer_row_sep="═", + heading_col_footer_cross="╬", + footer_row_cross="═", + footer_right_tee="╣", + bottom_left_corner="╚", + heading_col_bottom_tee="╩", + bottom_tee="═", + bottom_right_corner="╝", +) +k = Style( + top_left_corner=" ", + top_and_bottom_edge="─", + heading_col_top_tee="─", + top_tee="─", + top_right_corner=" ", + left_and_right_edge=" ", + heading_col_sep="", + middle_edge=" ", + header_left_tee="", + header_row_sep="━", + heading_col_header_cross="━", + header_row_cross="━", + header_right_tee="", + footer_left_tee=" ", + footer_row_sep="─", + heading_col_footer_cross="─", + footer_row_cross="─", + footer_right_tee=" ", + bottom_left_corner=" ", + heading_col_bottom_tee="─", + bottom_tee="─", + bottom_right_corner=" ", +) +l = Style( + top_left_corner="+", + top_and_bottom_edge="-", + heading_col_top_tee="+", + top_tee="-", + top_right_corner="+", + left_and_right_edge="|", + heading_col_sep="|", + middle_edge=" ", + header_left_tee="", + header_row_sep="", + heading_col_header_cross="", + header_row_cross="", + header_right_tee="", + footer_left_tee="+", + footer_row_sep="-", + heading_col_footer_cross="+", + footer_row_cross="-", + footer_right_tee="+", + bottom_left_corner="+", + heading_col_bottom_tee="+", + bottom_tee="-", + bottom_right_corner="+", +) +m = Style( + top_left_corner="+", + top_and_bottom_edge="-", + heading_col_top_tee="+", + top_tee="-", + top_right_corner="+", + left_and_right_edge="|", + heading_col_sep="|", + middle_edge=" ", + header_left_tee="+", + header_row_sep="=", + heading_col_header_cross="+", + header_row_cross="=", + header_right_tee="+", + footer_left_tee="+", + footer_row_sep="-", + heading_col_footer_cross="+", + footer_row_cross="-", + footer_right_tee="+", + bottom_left_corner="+", + heading_col_bottom_tee="+", + bottom_tee="-", + bottom_right_corner="+", +) +n = Style( + top_left_corner="+", + top_and_bottom_edge="=", + heading_col_top_tee="+", + top_tee="=", + top_right_corner="+", + left_and_right_edge="H", + heading_col_sep="H", + middle_edge=" ", + header_left_tee="", + header_row_sep="", + heading_col_header_cross="", + header_row_cross="", + header_right_tee="", + footer_left_tee="+", + footer_row_sep="=", + heading_col_footer_cross="+", + footer_row_cross="=", + footer_right_tee="+", + bottom_left_corner="+", + heading_col_bottom_tee="+", + bottom_tee="=", + bottom_right_corner="+", +) +o = Style( + top_left_corner="+", + top_and_bottom_edge="=", + heading_col_top_tee="+", + top_tee="=", + top_right_corner="+", + left_and_right_edge="H", + heading_col_sep="H", + middle_edge=" ", + header_left_tee="+", + header_row_sep="-", + heading_col_header_cross="+", + header_row_cross="-", + header_right_tee="+", + footer_left_tee="+", + footer_row_sep="=", + heading_col_footer_cross="+", + footer_row_cross="=", + footer_right_tee="+", + bottom_left_corner="+", + heading_col_bottom_tee="+", + bottom_tee="=", + bottom_right_corner="+", +) +p = Style( + top_left_corner=" ", + top_and_bottom_edge="-", + heading_col_top_tee="-", + top_tee="-", + top_right_corner=" ", + left_and_right_edge=" ", + heading_col_sep="", + middle_edge=" ", + header_left_tee="", + header_row_sep="=", + heading_col_header_cross="=", + header_row_cross="=", + header_right_tee="", + footer_left_tee=" ", + footer_row_sep="-", + heading_col_footer_cross="-", + footer_row_cross="-", + footer_right_tee=" ", + bottom_left_corner=" ", + heading_col_bottom_tee="-", + bottom_tee="-", + bottom_right_corner=" ", +) +q = Style( + top_left_corner=" ", + top_and_bottom_edge=" ", + heading_col_top_tee="", + top_tee=" ", + top_right_corner=" ", + left_and_right_edge="|", + heading_col_sep="|", + middle_edge=" ", + header_left_tee="|", + header_row_sep="-", + heading_col_header_cross="|", + header_row_cross="-", + header_right_tee="|", + footer_left_tee=" ", + footer_row_sep=" ", + heading_col_footer_cross="", + footer_row_cross=" ", + footer_right_tee=" ", + bottom_left_corner=" ", + heading_col_bottom_tee="", + bottom_tee=" ", + bottom_right_corner=" ", +) diff --git a/table2ascii/table_to_ascii.py b/table2ascii/table_to_ascii.py new file mode 100644 index 0000000..eaecfc3 --- /dev/null +++ b/table2ascii/table_to_ascii.py @@ -0,0 +1,241 @@ +from math import ceil, floor +from typing import List, Union + +from .alignment import Alignment +from .options import Options + + +class TableToAscii: + """Class used to convert a 2D Python table to ASCII text""" + + def __init__(self, options: Options): + """Validate arguments and initialize fields""" + # initialize fields + self.__header = options.header + self.__body = options.body + self.__footer = options.footer + self.__style = options.style + self.__first_col_heading = options.first_col_heading + self.__last_col_heading = options.last_col_heading + + # calculate number of columns + self.__columns = self.__count_columns() + + # check if footer has a different number of columns + if options.footer and len(options.footer) != self.__columns: + raise ValueError( + "Footer must have the same number of columns as the other rows" + ) + # check if any rows in body have a different number of columns + if options.body and any(len(row) != self.__columns for row in options.body): + raise ValueError( + "All rows in body must have the same number of columns as the other rows" + ) + + # calculate or use given column widths + self.__column_widths = options.column_widths or self.__auto_column_widths() + + # check if column widths specified have a different number of columns + if options.column_widths and len(options.column_widths) != self.__columns: + raise ValueError( + "Length of `column_widths` list must equal the number of columns" + ) + # check if column widths are not all at least 2 + if options.column_widths and min(options.column_widths) < 2: + raise ValueError( + "All values in `column_widths` must be greater than or equal to 2" + ) + + self.__alignments = options.alignments or [Alignment.CENTER] * self.__columns + + # check if alignments specified have a different number of columns + if options.alignments and len(options.alignments) != self.__columns: + raise ValueError( + "Length of `alignments` list must equal the number of columns" + ) + + def __count_columns(self) -> int: + """Get the number of columns in the table + based on the provided header, footer, and body lists. + """ + if self.__header: + return len(self.__header) + if self.__footer: + return len(self.__footer) + if self.__body and len(self.__body) > 0: + return len(self.__body[0]) + return 0 + + def __auto_column_widths(self) -> List[int]: + """Get the minimum number of characters needed for the values + in each column in the table with 1 space of padding on each side. + """ + column_widths = [] + for i in range(self.__columns): + # number of characters in column of i of header, each body row, and footer + header_size = len(self.__header[i]) if self.__header else 0 + body_size = ( + map(lambda row, i=i: len(row[i]), self.__body) if self.__body else [0] + ) + footer_size = len(self.__footer[i]) if self.__footer else 0 + # get the max and add 2 for padding each side with a space + column_widths.append(max(header_size, *body_size, footer_size) + 2) + return column_widths + + def __pad(self, text: str, width: int, alignment: Alignment): + """Pad a string of text to a given width with specified alignment""" + if alignment == Alignment.LEFT: + # pad with spaces on the end + return f" {text} " + (" " * (width - len(text) - 2)) + if alignment == Alignment.CENTER: + # pad with spaces, half on each side + before = " " * floor((width - len(text) - 2) / 2) + after = " " * ceil((width - len(text) - 2) / 2) + return before + f" {text} " + after + if alignment == Alignment.RIGHT: + # pad with spaces at the beginning + return (" " * (width - len(text) - 2)) + f" {text} " + raise ValueError(f"The value '{alignment}' is not valid for alignment.") + + def __row_to_ascii( + self, + left_edge: str, + heading_col_sep: str, + column_seperator: str, + right_edge: str, + filler: Union[str, List], + ) -> str: + """Assembles a row of the ascii table""" + # left edge of the row + output = left_edge + # add columns + for i in range(self.__columns): + # content between separators + output += ( + # edge or row separator if filler is a specific character + filler * self.__column_widths[i] + if isinstance(filler, str) + # otherwise, use the column content + else self.__pad( + str(filler[i]), self.__column_widths[i], self.__alignments[i] + ) + ) + # column seperator + sep = column_seperator + if i == 0 and self.__first_col_heading: + # use column heading if first column option is specified + sep = heading_col_sep + elif i == self.__columns - 2 and self.__last_col_heading: + # use column heading if last column option is specified + sep = heading_col_sep + elif i == self.__columns - 1: + # replace last seperator with symbol for edge of the row + sep = right_edge + output += sep + return output + "\n" + + def __top_edge_to_ascii(self) -> str: + """Assembles the top edge of the ascii table""" + return self.__row_to_ascii( + left_edge=self.__style.top_left_corner, + heading_col_sep=self.__style.heading_col_top_tee, + column_seperator=self.__style.top_tee, + right_edge=self.__style.top_right_corner, + filler=self.__style.top_and_bottom_edge, + ) + + def __bottom_edge_to_ascii(self) -> str: + """Assembles the top edge of the ascii table""" + return self.__row_to_ascii( + left_edge=self.__style.bottom_left_corner, + heading_col_sep=self.__style.heading_col_bottom_tee, + column_seperator=self.__style.bottom_tee, + right_edge=self.__style.bottom_right_corner, + filler=self.__style.top_and_bottom_edge, + ) + + def __header_row_to_ascii(self) -> str: + """Assembles the header row line of the ascii table""" + return self.__row_to_ascii( + left_edge=self.__style.left_and_right_edge, + heading_col_sep=self.__style.heading_col_sep, + column_seperator=self.__style.middle_edge, + right_edge=self.__style.left_and_right_edge, + filler=self.__header, + ) + + def __footer_row_to_ascii(self) -> str: + """Assembles the header row line of the ascii table""" + return self.__row_to_ascii( + left_edge=self.__style.left_and_right_edge, + heading_col_sep=self.__style.heading_col_sep, + column_seperator=self.__style.middle_edge, + right_edge=self.__style.left_and_right_edge, + filler=self.__footer, + ) + + def __header_sep_to_ascii(self) -> str: + """Assembles the seperator below the header of the ascii table""" + return self.__row_to_ascii( + left_edge=self.__style.header_left_tee, + heading_col_sep=self.__style.heading_col_header_cross, + column_seperator=self.__style.header_row_cross, + right_edge=self.__style.header_right_tee, + filler=self.__style.header_row_sep, + ) + + def __footer_sep_to_ascii(self) -> str: + """Assembles the seperator below the header of the ascii table""" + return self.__row_to_ascii( + left_edge=self.__style.footer_left_tee, + heading_col_sep=self.__style.heading_col_footer_cross, + column_seperator=self.__style.footer_row_cross, + right_edge=self.__style.footer_right_tee, + filler=self.__style.footer_row_sep, + ) + + def __body_to_ascii(self) -> str: + return "".join( + self.__row_to_ascii( + left_edge=self.__style.left_and_right_edge, + heading_col_sep=self.__style.heading_col_sep, + column_seperator=self.__style.middle_edge, + right_edge=self.__style.left_and_right_edge, + filler=row, + ) + for row in self.__body + ) + + def to_ascii(self) -> str: + # top row of table + table = self.__top_edge_to_ascii() + # add table header + if self.__header: + table += self.__header_row_to_ascii() + table += self.__header_sep_to_ascii() + # add table body + if self.__body: + table += self.__body_to_ascii() + # add table footer + if self.__footer: + table += self.__footer_sep_to_ascii() + table += self.__footer_row_to_ascii() + # bottom row of table + table += self.__bottom_edge_to_ascii() + # reurn ascii table + return table + + +def table2ascii(**options) -> str: + """Convert a 2D Python table to ASCII text + + ### Arguments + :param header: :class:`Optional[List]` List of column values in the table's header row + :param body: :class:`Optional[List[List]]` 2-dimensional list of values in the table's body + :param footer: :class:`Optional[List]` List of column values in the table's footer row + :param column_widths: :class:`Optional[List[int]]` List of widths in characters for each column (defaults to auto-sizing) + :param alignments: :class:`Optional[List[Alignment]]` List of alignments (ex. `[Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT]`) + :param first_col_heading: :class:`Optional[bool]` Whether to add a header column separator after the first column + :param last_col_heading: :class:`Optional[bool]` Whether to add a header column separator before the last column + """ + return TableToAscii(Options(**options)).to_ascii() diff --git a/tests/test_styles.py b/tests/test_styles.py new file mode 100644 index 0000000..268789a --- /dev/null +++ b/tests/test_styles.py @@ -0,0 +1,134 @@ +from table2ascii import table2ascii as t2a, styles + + +def test_double_thin(): + text = t2a( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=styles.double_thin, + ) + expected = ( + "╔═════╦═══════════════════════╗\n" + "║ # ║ G H R S ║\n" + "╟─────╫───────────────────────╢\n" + "║ 1 ║ 30 40 35 30 ║\n" + "║ 2 ║ 30 40 35 30 ║\n" + "╟─────╫───────────────────────╢\n" + "║ SUM ║ 130 140 135 130 ║\n" + "╚═════╩═══════════════════════╝\n" + ) + assert text == expected + + +def test_thin(): + text = t2a( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=styles.thin, + ) + expected = ( + "┌─────┬───────────────────────┐\n" + "│ # │ G H R S │\n" + "├─────┼───────────────────────┤\n" + "│ 1 │ 30 40 35 30 │\n" + "│ 2 │ 30 40 35 30 │\n" + "├─────┼───────────────────────┤\n" + "│ SUM │ 130 140 135 130 │\n" + "└─────┴───────────────────────┘\n" + "" + ) + assert text == expected + + +def test_thin_thick(): + text = t2a( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=styles.thin_thick, + ) + expected = ( + "┌─────┬───────────────────────┐\n" + "│ # │ G H R S │\n" + "┝━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━┥\n" + "│ 1 │ 30 40 35 30 │\n" + "│ 2 │ 30 40 35 30 │\n" + "┝━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━┥\n" + "│ SUM │ 130 140 135 130 │\n" + "└─────┴───────────────────────┘\n" + ) + assert text == expected + + +def test_thin_double(): + text = t2a( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=styles.thin_double, + ) + expected = ( + "┌─────┬───────────────────────┐\n" + "│ # │ G H R S │\n" + "╞═════╪═══════════════════════╡\n" + "│ 1 │ 30 40 35 30 │\n" + "│ 2 │ 30 40 35 30 │\n" + "╞═════╪═══════════════════════╡\n" + "│ SUM │ 130 140 135 130 │\n" + "└─────┴───────────────────────┘\n" + ) + assert text == expected + + +def test_thin_rounded(): + text = t2a( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=styles.thin_rounded, + ) + expected = ( + "╭─────┬───────────────────────╮\n" + "│ # │ G H R S │\n" + "├─────┼───────────────────────┤\n" + "│ 1 │ 30 40 35 30 │\n" + "│ 2 │ 30 40 35 30 │\n" + "├─────┼───────────────────────┤\n" + "│ SUM │ 130 140 135 130 │\n" + "╰─────┴───────────────────────╯\n" + ) + assert text == expected + + +def test_thin_thick_rounded(): + text = t2a( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=styles.thin_thick_rounded, + ) + expected = ( + "╭─────┬───────────────────────╮\n" + "│ # │ G H R S │\n" + "┝━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━┥\n" + "│ 1 │ 30 40 35 30 │\n" + "│ 2 │ 30 40 35 30 │\n" + "┝━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━┥\n" + "│ SUM │ 130 140 135 130 │\n" + "╰─────┴───────────────────────╯\n" + ) + assert text == expected From 72c17c93c8cc537145871297037c38e42387208b Mon Sep 17 00:00:00 2001 From: Jonah Lawrence Date: Thu, 29 Apr 2021 01:56:17 +0300 Subject: [PATCH 02/22] Setup for easier adding of styles --- table2ascii/options.py | 4 +- table2ascii/style.py | 56 ----- table2ascii/styles.py | 456 ++-------------------------------- table2ascii/table_style.py | 64 +++++ table2ascii/table_to_ascii.py | 48 ++-- 5 files changed, 98 insertions(+), 530 deletions(-) delete mode 100644 table2ascii/style.py create mode 100644 table2ascii/table_style.py diff --git a/table2ascii/options.py b/table2ascii/options.py index 9b2c22a..fab9c0b 100644 --- a/table2ascii/options.py +++ b/table2ascii/options.py @@ -3,7 +3,7 @@ from . import styles from .alignment import Alignment -from .style import Style +from .table_style import TableStyle @dataclass @@ -17,4 +17,4 @@ class Options: last_col_heading: bool = False column_widths: Optional[List[int]] = None alignments: Optional[List[Alignment]] = None - style: Style = styles.double_thin + style: TableStyle = styles.double_thin diff --git a/table2ascii/style.py b/table2ascii/style.py deleted file mode 100644 index c478f8f..0000000 --- a/table2ascii/style.py +++ /dev/null @@ -1,56 +0,0 @@ -from dataclasses import dataclass - - -@dataclass -class Style: - """Class for storing information about a table style - - **Parts of the table labeled alphabetically** - - ```text - ABBBBBCBBBBBDBBBBBDBBBBBDBBBBBE - F G H H H F - IJJJJJKJJJJJLJJJJJLJJJJJLJJJJJM - F G H H H F - F G H H H F - NOOOOOPOOOOOQOOOOOQOOOOOQOOOOOR - F G H H H F - SBBBBBTBBBBBUBBBBBUBBBBBUBBBBBV - ``` - - **How the default theme is displayed** - - ```text - ╔═════╦═══════════════════════╗ - ║ # ║ G H R S ║ - ╟─────╫───────────────────────╢ - ║ 1 ║ 30 40 35 30 ║ - ║ 2 ║ 30 40 35 30 ║ - ╟─────╫───────────────────────╢ - ║ SUM ║ 130 140 135 130 ║ - ╚═════╩═══════════════════════╝ - ``` - """ - - top_left_corner: str # A - top_and_bottom_edge: str # B - heading_col_top_tee: str # C - top_tee: str # D - top_right_corner: str # E - left_and_right_edge: str # F - heading_col_sep: str # G - middle_edge: str # H - header_left_tee: str # I - header_row_sep: str # J - heading_col_header_cross: str # K - header_row_cross: str # L - header_right_tee: str # M - footer_left_tee: str # N - footer_row_sep: str # O - heading_col_footer_cross: str # P - footer_row_cross: str # Q - footer_right_tee: str # R - bottom_left_corner: str # S - heading_col_bottom_tee: str # T - bottom_tee: str # U - bottom_right_corner: str # V diff --git a/table2ascii/styles.py b/table2ascii/styles.py index df8e980..f859d18 100644 --- a/table2ascii/styles.py +++ b/table2ascii/styles.py @@ -1,440 +1,20 @@ -from .style import Style +from .table_style import TableStyle -double_thin = Style( - top_left_corner="╔", - top_and_bottom_edge="═", - heading_col_top_tee="╦", - top_tee="═", - top_right_corner="╗", - left_and_right_edge="║", - heading_col_sep="║", - middle_edge=" ", - header_left_tee="╟", - header_row_sep="─", - heading_col_header_cross="╫", - header_row_cross="─", - header_right_tee="╢", - footer_left_tee="╟", - footer_row_sep="─", - heading_col_footer_cross="╫", - footer_row_cross="─", - footer_right_tee="╢", - bottom_left_corner="╚", - heading_col_bottom_tee="╩", - bottom_tee="═", - bottom_right_corner="╝", -) - -thin = Style( - top_left_corner="┌", - top_and_bottom_edge="─", - heading_col_top_tee="┬", - top_tee="─", - top_right_corner="┐", - left_and_right_edge="│", - heading_col_sep="│", - middle_edge=" ", - header_left_tee="├", - header_row_sep="─", - heading_col_header_cross="┼", - header_row_cross="─", - header_right_tee="┤", - footer_left_tee="├", - footer_row_sep="─", - heading_col_footer_cross="┼", - footer_row_cross="─", - footer_right_tee="┤", - bottom_left_corner="└", - heading_col_bottom_tee="┴", - bottom_tee="─", - bottom_right_corner="┘", -) - -thin_thick = Style( - top_left_corner="┌", - top_and_bottom_edge="─", - heading_col_top_tee="┬", - top_tee="─", - top_right_corner="┐", - left_and_right_edge="│", - heading_col_sep="│", - middle_edge=" ", - header_left_tee="┝", - header_row_sep="━", - heading_col_header_cross="┿", - header_row_cross="━", - header_right_tee="┥", - footer_left_tee="┝", - footer_row_sep="━", - heading_col_footer_cross="┿", - footer_row_cross="━", - footer_right_tee="┥", - bottom_left_corner="└", - heading_col_bottom_tee="┴", - bottom_tee="─", - bottom_right_corner="┘", -) - -thin_double = Style( - top_left_corner="┌", - top_and_bottom_edge="─", - heading_col_top_tee="┬", - top_tee="─", - top_right_corner="┐", - left_and_right_edge="│", - heading_col_sep="│", - middle_edge=" ", - header_left_tee="╞", - header_row_sep="═", - heading_col_header_cross="╪", - header_row_cross="═", - header_right_tee="╡", - footer_left_tee="╞", - footer_row_sep="═", - heading_col_footer_cross="╪", - footer_row_cross="═", - footer_right_tee="╡", - bottom_left_corner="└", - heading_col_bottom_tee="┴", - bottom_tee="─", - bottom_right_corner="┘", -) - -thin_rounded = Style( - top_left_corner="╭", - top_and_bottom_edge="─", - heading_col_top_tee="┬", - top_tee="─", - top_right_corner="╮", - left_and_right_edge="│", - heading_col_sep="│", - middle_edge=" ", - header_left_tee="├", - header_row_sep="─", - heading_col_header_cross="┼", - header_row_cross="─", - header_right_tee="┤", - footer_left_tee="├", - footer_row_sep="─", - heading_col_footer_cross="┼", - footer_row_cross="─", - footer_right_tee="┤", - bottom_left_corner="╰", - heading_col_bottom_tee="┴", - bottom_tee="─", - bottom_right_corner="╯", -) - -thin_thick_rounded = Style( - top_left_corner="╭", - top_and_bottom_edge="─", - heading_col_top_tee="┬", - top_tee="─", - top_right_corner="╮", - left_and_right_edge="│", - heading_col_sep="│", - middle_edge=" ", - header_left_tee="┝", - header_row_sep="━", - heading_col_header_cross="┿", - header_row_cross="━", - header_right_tee="┥", - footer_left_tee="┝", - footer_row_sep="━", - heading_col_footer_cross="┿", - footer_row_cross="━", - footer_right_tee="┥", - bottom_left_corner="╰", - heading_col_bottom_tee="┴", - bottom_tee="─", - bottom_right_corner="╯", -) -f = Style( - top_left_corner="╭", - top_and_bottom_edge="─", - heading_col_top_tee="┬", - top_tee="─", - top_right_corner="╮", - left_and_right_edge="│", - heading_col_sep="│", - middle_edge=" ", - header_left_tee="╞", - header_row_sep="═", - heading_col_header_cross="╪", - header_row_cross="═", - header_right_tee="╡", - footer_left_tee="├", - footer_row_sep="─", - heading_col_footer_cross="┼", - footer_row_cross="─", - footer_right_tee="┤", - bottom_left_corner="╰", - heading_col_bottom_tee="┴", - bottom_tee="─", - bottom_right_corner="╯", -) -g = Style( - top_left_corner="┏", - top_and_bottom_edge="━", - heading_col_top_tee="┳", - top_tee="━", - top_right_corner="┓", - left_and_right_edge="┃", - heading_col_sep="┃", - middle_edge=" ", - header_left_tee="", - header_row_sep="", - heading_col_header_cross="", - header_row_cross="", - header_right_tee="", - footer_left_tee="┣", - footer_row_sep="━", - heading_col_footer_cross="╋", - footer_row_cross="━", - footer_right_tee="┫", - bottom_left_corner="┗", - heading_col_bottom_tee="┻", - bottom_tee="━", - bottom_right_corner="┛", -) -h = Style( - top_left_corner="┌", - top_and_bottom_edge="─", - heading_col_top_tee="┬", - top_tee="─", - top_right_corner="┐", - left_and_right_edge="│", - heading_col_sep="│", - middle_edge=" ", - header_left_tee="┠", - header_row_sep="─", - heading_col_header_cross="╂", - header_row_cross="─", - header_right_tee="┨", - footer_left_tee="├", - footer_row_sep="─", - heading_col_footer_cross="┼", - footer_row_cross="─", - footer_right_tee="┤", - bottom_left_corner="└", - heading_col_bottom_tee="┴", - bottom_tee="─", - bottom_right_corner="┘", -) -i = Style( - top_left_corner="╔", - top_and_bottom_edge="═", - heading_col_top_tee="╦", - top_tee="═", - top_right_corner="╗", - left_and_right_edge="║", - heading_col_sep="║", - middle_edge=" ", - header_left_tee="", - header_row_sep="", - heading_col_header_cross="", - header_row_cross="", - header_right_tee="", - footer_left_tee="╠", - footer_row_sep="═", - heading_col_footer_cross="╬", - footer_row_cross="═", - footer_right_tee="╣", - bottom_left_corner="╚", - heading_col_bottom_tee="╩", - bottom_tee="═", - bottom_right_corner="╝", -) -j = Style( - top_left_corner="╔", - top_and_bottom_edge="═", - heading_col_top_tee="╦", - top_tee="═", - top_right_corner="╗", - left_and_right_edge="║", - heading_col_sep="║", - middle_edge=" ", - header_left_tee="╟", - header_row_sep="─", - heading_col_header_cross="╫", - header_row_cross="─", - header_right_tee="╢", - footer_left_tee="╠", - footer_row_sep="═", - heading_col_footer_cross="╬", - footer_row_cross="═", - footer_right_tee="╣", - bottom_left_corner="╚", - heading_col_bottom_tee="╩", - bottom_tee="═", - bottom_right_corner="╝", -) -k = Style( - top_left_corner=" ", - top_and_bottom_edge="─", - heading_col_top_tee="─", - top_tee="─", - top_right_corner=" ", - left_and_right_edge=" ", - heading_col_sep="", - middle_edge=" ", - header_left_tee="", - header_row_sep="━", - heading_col_header_cross="━", - header_row_cross="━", - header_right_tee="", - footer_left_tee=" ", - footer_row_sep="─", - heading_col_footer_cross="─", - footer_row_cross="─", - footer_right_tee=" ", - bottom_left_corner=" ", - heading_col_bottom_tee="─", - bottom_tee="─", - bottom_right_corner=" ", -) -l = Style( - top_left_corner="+", - top_and_bottom_edge="-", - heading_col_top_tee="+", - top_tee="-", - top_right_corner="+", - left_and_right_edge="|", - heading_col_sep="|", - middle_edge=" ", - header_left_tee="", - header_row_sep="", - heading_col_header_cross="", - header_row_cross="", - header_right_tee="", - footer_left_tee="+", - footer_row_sep="-", - heading_col_footer_cross="+", - footer_row_cross="-", - footer_right_tee="+", - bottom_left_corner="+", - heading_col_bottom_tee="+", - bottom_tee="-", - bottom_right_corner="+", -) -m = Style( - top_left_corner="+", - top_and_bottom_edge="-", - heading_col_top_tee="+", - top_tee="-", - top_right_corner="+", - left_and_right_edge="|", - heading_col_sep="|", - middle_edge=" ", - header_left_tee="+", - header_row_sep="=", - heading_col_header_cross="+", - header_row_cross="=", - header_right_tee="+", - footer_left_tee="+", - footer_row_sep="-", - heading_col_footer_cross="+", - footer_row_cross="-", - footer_right_tee="+", - bottom_left_corner="+", - heading_col_bottom_tee="+", - bottom_tee="-", - bottom_right_corner="+", -) -n = Style( - top_left_corner="+", - top_and_bottom_edge="=", - heading_col_top_tee="+", - top_tee="=", - top_right_corner="+", - left_and_right_edge="H", - heading_col_sep="H", - middle_edge=" ", - header_left_tee="", - header_row_sep="", - heading_col_header_cross="", - header_row_cross="", - header_right_tee="", - footer_left_tee="+", - footer_row_sep="=", - heading_col_footer_cross="+", - footer_row_cross="=", - footer_right_tee="+", - bottom_left_corner="+", - heading_col_bottom_tee="+", - bottom_tee="=", - bottom_right_corner="+", -) -o = Style( - top_left_corner="+", - top_and_bottom_edge="=", - heading_col_top_tee="+", - top_tee="=", - top_right_corner="+", - left_and_right_edge="H", - heading_col_sep="H", - middle_edge=" ", - header_left_tee="+", - header_row_sep="-", - heading_col_header_cross="+", - header_row_cross="-", - header_right_tee="+", - footer_left_tee="+", - footer_row_sep="=", - heading_col_footer_cross="+", - footer_row_cross="=", - footer_right_tee="+", - bottom_left_corner="+", - heading_col_bottom_tee="+", - bottom_tee="=", - bottom_right_corner="+", -) -p = Style( - top_left_corner=" ", - top_and_bottom_edge="-", - heading_col_top_tee="-", - top_tee="-", - top_right_corner=" ", - left_and_right_edge=" ", - heading_col_sep="", - middle_edge=" ", - header_left_tee="", - header_row_sep="=", - heading_col_header_cross="=", - header_row_cross="=", - header_right_tee="", - footer_left_tee=" ", - footer_row_sep="-", - heading_col_footer_cross="-", - footer_row_cross="-", - footer_right_tee=" ", - bottom_left_corner=" ", - heading_col_bottom_tee="-", - bottom_tee="-", - bottom_right_corner=" ", -) -q = Style( - top_left_corner=" ", - top_and_bottom_edge=" ", - heading_col_top_tee="", - top_tee=" ", - top_right_corner=" ", - left_and_right_edge="|", - heading_col_sep="|", - middle_edge=" ", - header_left_tee="|", - header_row_sep="-", - heading_col_header_cross="|", - header_row_cross="-", - header_right_tee="|", - footer_left_tee=" ", - footer_row_sep=" ", - heading_col_footer_cross="", - footer_row_cross=" ", - footer_right_tee=" ", - bottom_left_corner=" ", - heading_col_bottom_tee="", - bottom_tee=" ", - bottom_right_corner=" ", -) +a = TableStyle.from_string("┌─┬─┐││ ├─┼─┤└┴─┘") +b = TableStyle.from_string("┌─┬─┐││┝━┿━┥├─┼─┤└┴─┘") +c = TableStyle.from_string("┌─┬─┐││╞═╪═╡├─┼─┤└┴─┘") +d = TableStyle.from_string("╭─┬─╮││ ├─┼─┤╰┴─╯") +e = TableStyle.from_string("╭─┬─╮││┝━┿━┥├─┼─┤╰┴─╯") +f = TableStyle.from_string("╭─┬─╮││╞═╪═╡├─┼─┤╰┴─╯") +g = TableStyle.from_string("┏━┳━┓┃┃ ┣━╋━┫┗┻━┛") +h = TableStyle.from_string("┌─┬─┐││┠─╂─┨├─┼─┤└┴─┘") +i = TableStyle.from_string("╔═╦═╗║║ ╠═╬═╣╚╩═╝") +j = TableStyle.from_string("╔═╦═╗║║╟─╫─╢╠═╬═╣╚╩═╝") +k = TableStyle.from_string(" ─── ━━━ ─── ── ") +l = TableStyle.from_string("+-+-+|| +-+-+++-+") +m = TableStyle.from_string("+-+-+||+=+=++-+-+++-+") +n = TableStyle.from_string("+=+=+HH +=+=+++=+") +o = TableStyle.from_string("+=+=+HH+-+-++=+=+++=+") +p = TableStyle.from_string(" --- === --- -- ") +q = TableStyle.from_string(" |||-|-| ") diff --git a/table2ascii/table_style.py b/table2ascii/table_style.py new file mode 100644 index 0000000..f859c91 --- /dev/null +++ b/table2ascii/table_style.py @@ -0,0 +1,64 @@ +import enum +from dataclasses import dataclass + + +@dataclass +class TableStyle: + """Class for storing information about a table style + + **Parts of the table labeled alphabetically** + + ```text + ABBBBBCBBBBBDBBBBBDBBBBBDBBBBBE + F G H H H F + IJJJJJKJJJJJLJJJJJLJJJJJLJJJJJM + F G H H H F + NOOOOOPOOOOOQOOOOOQOOOOOQOOOOOR + F G H H H F + IJJJJJKJJJJJLJJJJJLJJJJJLJJJJJM + F G H H H F + SBBBBBTBBBBBUBBBBBUBBBBBUBBBBBV + ``` + + **How the theme is displayed with double thickness for + heading rows and columns and thin for normal rows and columns** + + ```text + ╔═════╦═════╦═════╦═════╦═════╗ + ║ # ║ G │ H │ R │ S ║ + ╠═════╬═════╪═════╪═════╪═════╣ + ║ 1 ║ 30 │ 40 │ 35 │ 30 ║ + ╟─────╫─────┼─────┼─────┼─────╢ + ║ 2 ║ 30 │ 40 │ 35 │ 30 ║ + ╠═════╬═════╪═════╪═════╪═════╣ + ║ SUM ║ 130 │ 140 │ 135 │ 130 ║ + ╚═════╩═════╩═════╩═════╩═════╝ + ``` + """ + + top_left_corner: str # A + top_and_bottom_edge: str # B + heading_col_top_tee: str # C + top_tee: str # D + top_right_corner: str # E + left_and_right_edge: str # F + heading_col_sep: str # G + middle_edge: str # H + heading_row_left_tee: str # I + heading_row_sep: str # J + heading_col_row_cross: str # K + heading_row_cross: str # L + heading_row_right_tee: str # M + row_left_tee: str # N + normalrow_sep: str # O + col_row_cross: str # P + row_cross: str # Q + row_right_tee: str # R + bottom_left_corner: str # S + heading_col_bottom_tee: str # T + bottom_tee: str # U + bottom_right_corner: str # V + + @classmethod + def from_string(cls, string: str) -> "TableStyle": + return cls(*string) diff --git a/table2ascii/table_to_ascii.py b/table2ascii/table_to_ascii.py index eaecfc3..8a88c72 100644 --- a/table2ascii/table_to_ascii.py +++ b/table2ascii/table_to_ascii.py @@ -154,44 +154,24 @@ def __bottom_edge_to_ascii(self) -> str: filler=self.__style.top_and_bottom_edge, ) - def __header_row_to_ascii(self) -> str: - """Assembles the header row line of the ascii table""" + def __heading_row_to_ascii(self, row: List) -> str: + """Assembles the header or footer row line of the ascii table""" return self.__row_to_ascii( left_edge=self.__style.left_and_right_edge, heading_col_sep=self.__style.heading_col_sep, column_seperator=self.__style.middle_edge, right_edge=self.__style.left_and_right_edge, - filler=self.__header, + filler=row, ) - def __footer_row_to_ascii(self) -> str: - """Assembles the header row line of the ascii table""" + def __heading_sep_to_ascii(self) -> str: + """Assembles the seperator below the header or above footer of the ascii table""" return self.__row_to_ascii( - left_edge=self.__style.left_and_right_edge, - heading_col_sep=self.__style.heading_col_sep, - column_seperator=self.__style.middle_edge, - right_edge=self.__style.left_and_right_edge, - filler=self.__footer, - ) - - def __header_sep_to_ascii(self) -> str: - """Assembles the seperator below the header of the ascii table""" - return self.__row_to_ascii( - left_edge=self.__style.header_left_tee, - heading_col_sep=self.__style.heading_col_header_cross, - column_seperator=self.__style.header_row_cross, - right_edge=self.__style.header_right_tee, - filler=self.__style.header_row_sep, - ) - - def __footer_sep_to_ascii(self) -> str: - """Assembles the seperator below the header of the ascii table""" - return self.__row_to_ascii( - left_edge=self.__style.footer_left_tee, - heading_col_sep=self.__style.heading_col_footer_cross, - column_seperator=self.__style.footer_row_cross, - right_edge=self.__style.footer_right_tee, - filler=self.__style.footer_row_sep, + left_edge=self.__style.heading_row_left_tee, + heading_col_sep=self.__style.heading_col_row_cross, + column_seperator=self.__style.heading_row_cross, + right_edge=self.__style.heading_row_right_tee, + filler=self.__style.heading_row_sep, ) def __body_to_ascii(self) -> str: @@ -211,15 +191,15 @@ def to_ascii(self) -> str: table = self.__top_edge_to_ascii() # add table header if self.__header: - table += self.__header_row_to_ascii() - table += self.__header_sep_to_ascii() + table += self.__heading_row_to_ascii(self.__header) + table += self.__heading_sep_to_ascii() # add table body if self.__body: table += self.__body_to_ascii() # add table footer if self.__footer: - table += self.__footer_sep_to_ascii() - table += self.__footer_row_to_ascii() + table += self.__heading_sep_to_ascii() + table += self.__heading_row_to_ascii(self.__footer) # bottom row of table table += self.__bottom_edge_to_ascii() # reurn ascii table From 5d0a24c0dad36f344cfd161690d89263666f0bcd Mon Sep 17 00:00:00 2001 From: Jonah Lawrence Date: Thu, 29 Apr 2021 03:37:03 +0300 Subject: [PATCH 03/22] Support separators between body rows --- table2ascii/styles.py | 73 +++++++++++++++++++++++++++-------- table2ascii/table_style.py | 10 ++--- table2ascii/table_to_ascii.py | 18 +++++++-- 3 files changed, 75 insertions(+), 26 deletions(-) diff --git a/table2ascii/styles.py b/table2ascii/styles.py index f859d18..b26ad5b 100644 --- a/table2ascii/styles.py +++ b/table2ascii/styles.py @@ -1,20 +1,59 @@ from .table_style import TableStyle +thin = TableStyle.from_string("┌─┬─┐││ ├─┼─┤├─┼─┤└┴─┘") +thin_rounded = TableStyle.from_string("╭─┬─╮││ ├─┼─┤├─┼─┤╰┴─╯") +thin_compact = TableStyle.from_string("┌─┬─┐││ ├─┼─┤ └┴─┘") +thin_compact_rounded = TableStyle.from_string("╭─┬─╮││ ├─┼─┤ ╰┴─╯") +thin_thick = TableStyle.from_string("┌─┬─┐││ ┝━┿━┥├─┼─┤└┴─┘") +thin_thick_rounded = TableStyle.from_string("╭─┬─╮││ ┝━┿━┥├─┼─┤╰┴─╯") +thin_double = TableStyle.from_string("┌─┬─┐││ ╞═╪═╡├─┼─┤└┴─┘") +thin_double_rounded = TableStyle.from_string("╭─┬─╮││ ╞═╪═╡├─┼─┤╰┴─╯") +thick_compact = TableStyle.from_string("┏━┳━┓┃┃ ┣━╋━┫ ┗┻━┛") +double = TableStyle.from_string("╔═╦═╗║║ ╠═╬═╣╠═╬═╣╚╩═╝") +double_compact = TableStyle.from_string("╔═╦═╗║║ ╠═╬═╣ ╚╩═╝") +double_thin = TableStyle.from_string("╔═╦═╗║║ ╟─╫─╢╠═╬═╣╚╩═╝") +minimalist = TableStyle.from_string(" ─── ━━━ ─── ── ") +ascii_compact = TableStyle.from_string("+-+-+|| +-+-+ ++-+") +ascii_double = TableStyle.from_string("+-+-+|| +=+=++-+-+++-+") +ascii_minimalist = TableStyle.from_string(" --- === --- -- ") +markdown = TableStyle.from_string(" ||||-||| ") -a = TableStyle.from_string("┌─┬─┐││ ├─┼─┤└┴─┘") -b = TableStyle.from_string("┌─┬─┐││┝━┿━┥├─┼─┤└┴─┘") -c = TableStyle.from_string("┌─┬─┐││╞═╪═╡├─┼─┤└┴─┘") -d = TableStyle.from_string("╭─┬─╮││ ├─┼─┤╰┴─╯") -e = TableStyle.from_string("╭─┬─╮││┝━┿━┥├─┼─┤╰┴─╯") -f = TableStyle.from_string("╭─┬─╮││╞═╪═╡├─┼─┤╰┴─╯") -g = TableStyle.from_string("┏━┳━┓┃┃ ┣━╋━┫┗┻━┛") -h = TableStyle.from_string("┌─┬─┐││┠─╂─┨├─┼─┤└┴─┘") -i = TableStyle.from_string("╔═╦═╗║║ ╠═╬═╣╚╩═╝") -j = TableStyle.from_string("╔═╦═╗║║╟─╫─╢╠═╬═╣╚╩═╝") -k = TableStyle.from_string(" ─── ━━━ ─── ── ") -l = TableStyle.from_string("+-+-+|| +-+-+++-+") -m = TableStyle.from_string("+-+-+||+=+=++-+-+++-+") -n = TableStyle.from_string("+=+=+HH +=+=+++=+") -o = TableStyle.from_string("+=+=+HH+-+-++=+=+++=+") -p = TableStyle.from_string(" --- === --- -- ") -q = TableStyle.from_string(" |||-|-| ") +# prints all themes with previews +if __name__ == "__main__": + from .table_to_ascii import table2ascii + + styles = { + "thin": thin, + "thin_rounded": thin_rounded, + "thin_compact": thin_compact, + "thin_compact_rounded": thin_compact_rounded, + "thin_thick": thin_thick, + "thin_thick_rounded": thin_thick_rounded, + "thin_double": thin_double, + "thin_double_rounded": thin_double_rounded, + "thick_compact": thick_compact, + "double": double, + "double_compact": double_compact, + "double_thin": double_thin, + "minimalist": minimalist, + "ascii_compact": ascii_compact, + "ascii_double": ascii_double, + "ascii_minimalist": ascii_minimalist, + "markdown": markdown, + } + for style in list(styles.keys()): + full = table2ascii( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=styles[style], + ) + body_only = table2ascii( + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + first_col_heading=True, + last_col_heading=False, + style=styles[style], + ) + print(f"### `{style}`\n\n```\n{full}\n{body_only}```\n") diff --git a/table2ascii/table_style.py b/table2ascii/table_style.py index f859c91..753b25b 100644 --- a/table2ascii/table_style.py +++ b/table2ascii/table_style.py @@ -43,16 +43,16 @@ class TableStyle: top_right_corner: str # E left_and_right_edge: str # F heading_col_sep: str # G - middle_edge: str # H + col_sep: str # H heading_row_left_tee: str # I heading_row_sep: str # J - heading_col_row_cross: str # K + heading_col_heading_row_cross: str # K heading_row_cross: str # L heading_row_right_tee: str # M row_left_tee: str # N - normalrow_sep: str # O - col_row_cross: str # P - row_cross: str # Q + row_sep: str # O + heading_col_row_cross: str # P + col_row_cross: str # Q row_right_tee: str # R bottom_left_corner: str # S heading_col_bottom_tee: str # T diff --git a/table2ascii/table_to_ascii.py b/table2ascii/table_to_ascii.py index 8a88c72..68b2f22 100644 --- a/table2ascii/table_to_ascii.py +++ b/table2ascii/table_to_ascii.py @@ -159,7 +159,7 @@ def __heading_row_to_ascii(self, row: List) -> str: return self.__row_to_ascii( left_edge=self.__style.left_and_right_edge, heading_col_sep=self.__style.heading_col_sep, - column_seperator=self.__style.middle_edge, + column_seperator=self.__style.col_sep, right_edge=self.__style.left_and_right_edge, filler=row, ) @@ -168,18 +168,28 @@ def __heading_sep_to_ascii(self) -> str: """Assembles the seperator below the header or above footer of the ascii table""" return self.__row_to_ascii( left_edge=self.__style.heading_row_left_tee, - heading_col_sep=self.__style.heading_col_row_cross, + heading_col_sep=self.__style.heading_col_heading_row_cross, column_seperator=self.__style.heading_row_cross, right_edge=self.__style.heading_row_right_tee, filler=self.__style.heading_row_sep, ) def __body_to_ascii(self) -> str: - return "".join( + separation_row = self.__row_to_ascii( + left_edge=self.__style.row_left_tee, + heading_col_sep=self.__style.heading_col_row_cross, + column_seperator=self.__style.col_row_cross, + right_edge=self.__style.row_right_tee, + filler=self.__style.row_sep, + ) + # don't use separation row if it's only space + if separation_row.strip() == "": + separation_row = "" + return separation_row.join( self.__row_to_ascii( left_edge=self.__style.left_and_right_edge, heading_col_sep=self.__style.heading_col_sep, - column_seperator=self.__style.middle_edge, + column_seperator=self.__style.col_sep, right_edge=self.__style.left_and_right_edge, filler=row, ) From c087d8d4883ea81d7d1f39148f4a12a75fee5854 Mon Sep 17 00:00:00 2001 From: Jonah Lawrence Date: Thu, 29 Apr 2021 06:06:04 +0300 Subject: [PATCH 04/22] More themes --- table2ascii/styles.py | 26 +++++++++++++++++++++++--- table2ascii/table_to_ascii.py | 9 +++++---- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/table2ascii/styles.py b/table2ascii/styles.py index b26ad5b..0e112cf 100644 --- a/table2ascii/styles.py +++ b/table2ascii/styles.py @@ -1,6 +1,7 @@ from .table_style import TableStyle thin = TableStyle.from_string("┌─┬─┐││ ├─┼─┤├─┼─┤└┴─┘") +thin_box = TableStyle.from_string("┌─┬┬┐│││├─┼┼┤├─┼┼┤└┴┴┘") thin_rounded = TableStyle.from_string("╭─┬─╮││ ├─┼─┤├─┼─┤╰┴─╯") thin_compact = TableStyle.from_string("┌─┬─┐││ ├─┼─┤ └┴─┘") thin_compact_rounded = TableStyle.from_string("╭─┬─╮││ ├─┼─┤ ╰┴─╯") @@ -8,14 +9,23 @@ thin_thick_rounded = TableStyle.from_string("╭─┬─╮││ ┝━┿━┥├─┼─┤╰┴─╯") thin_double = TableStyle.from_string("┌─┬─┐││ ╞═╪═╡├─┼─┤└┴─┘") thin_double_rounded = TableStyle.from_string("╭─┬─╮││ ╞═╪═╡├─┼─┤╰┴─╯") +thick = TableStyle.from_string("┏━┳━┓┃┃ ┣━╋━┫┣━╋━┫┗┻━┛") +thick_box = TableStyle.from_string("┏━┳┳┓┃┃┃┣━╋╋┫┣━╋╋┫┗┻┻┛") thick_compact = TableStyle.from_string("┏━┳━┓┃┃ ┣━╋━┫ ┗┻━┛") double = TableStyle.from_string("╔═╦═╗║║ ╠═╬═╣╠═╬═╣╚╩═╝") +double_box = TableStyle.from_string("╔═╦╦╗║║║╠═╬╬╣╠═╬╬╣╚╩╩╝") double_compact = TableStyle.from_string("╔═╦═╗║║ ╠═╬═╣ ╚╩═╝") double_thin = TableStyle.from_string("╔═╦═╗║║ ╟─╫─╢╠═╬═╣╚╩═╝") -minimalist = TableStyle.from_string(" ─── ━━━ ─── ── ") +double_thin_compact = TableStyle.from_string("╔═╦═╗║║ ╟─╫─╢╠═╬═╣╚╩═╝") +minimalist = TableStyle.from_string(" ─── │ ━━━ ─── ── ") +borderless = TableStyle.from_string(" ┃ ━ ") +ascii = TableStyle.from_string("+-+-+|| +-+-++-+-+++-+") +ascii_box = TableStyle.from_string("+-+++|||+-++++-+++++++") ascii_compact = TableStyle.from_string("+-+-+|| +-+-+ ++-+") ascii_double = TableStyle.from_string("+-+-+|| +=+=++-+-+++-+") -ascii_minimalist = TableStyle.from_string(" --- === --- -- ") +ascii_minimalist = TableStyle.from_string(" --- | === --- -- ") +ascii_borderless = TableStyle.from_string(" | - ") +ascii_simple = TableStyle.from_string(" = | = ") markdown = TableStyle.from_string(" ||||-||| ") # prints all themes with previews @@ -24,6 +34,7 @@ styles = { "thin": thin, + "thin_box": thin_box, "thin_rounded": thin_rounded, "thin_compact": thin_compact, "thin_compact_rounded": thin_compact_rounded, @@ -31,14 +42,23 @@ "thin_thick_rounded": thin_thick_rounded, "thin_double": thin_double, "thin_double_rounded": thin_double_rounded, + "thick": thick, + "thick_box": thick_box, "thick_compact": thick_compact, "double": double, + "double_box": double_box, "double_compact": double_compact, "double_thin": double_thin, + "double_thin_compact": double_thin_compact, "minimalist": minimalist, + "borderless": borderless, + "ascii": ascii, + "ascii_box": ascii_box, "ascii_compact": ascii_compact, "ascii_double": ascii_double, "ascii_minimalist": ascii_minimalist, + "ascii_borderless": ascii_borderless, + "ascii_simple": ascii_simple, "markdown": markdown, } for style in list(styles.keys()): @@ -56,4 +76,4 @@ last_col_heading=False, style=styles[style], ) - print(f"### `{style}`\n\n```\n{full}\n{body_only}```\n") + print(f"### `{style}`\n\n```\n{full}\n\n{body_only}\n```\n") diff --git a/table2ascii/table_to_ascii.py b/table2ascii/table_to_ascii.py index 68b2f22..fe0c12d 100644 --- a/table2ascii/table_to_ascii.py +++ b/table2ascii/table_to_ascii.py @@ -132,6 +132,10 @@ def __row_to_ascii( # replace last seperator with symbol for edge of the row sep = right_edge output += sep + # don't use separation row if it's only space + if output.strip() == "": + return "" + # otherwise, return the row followed by newline return output + "\n" def __top_edge_to_ascii(self) -> str: @@ -182,9 +186,6 @@ def __body_to_ascii(self) -> str: right_edge=self.__style.row_right_tee, filler=self.__style.row_sep, ) - # don't use separation row if it's only space - if separation_row.strip() == "": - separation_row = "" return separation_row.join( self.__row_to_ascii( left_edge=self.__style.left_and_right_edge, @@ -213,7 +214,7 @@ def to_ascii(self) -> str: # bottom row of table table += self.__bottom_edge_to_ascii() # reurn ascii table - return table + return table.strip("\n") def table2ascii(**options) -> str: From f48d7ee8e11b25111f4dabf898fc7b35af66956f Mon Sep 17 00:00:00 2001 From: Jonah Lawrence Date: Thu, 29 Apr 2021 06:11:34 +0300 Subject: [PATCH 05/22] Move printing styles to scripts folder --- scripts/style_list.py | 50 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 scripts/style_list.py diff --git a/scripts/style_list.py b/scripts/style_list.py new file mode 100644 index 0000000..24340f2 --- /dev/null +++ b/scripts/style_list.py @@ -0,0 +1,50 @@ +from table2ascii import styles +from table2ascii.table_to_ascii import table2ascii + +# prints all themes with previews +if __name__ == "__main__": + styles = { + "thin": styles.thin, + "thin_box": styles.thin_box, + "thin_rounded": styles.thin_rounded, + "thin_compact": styles.thin_compact, + "thin_compact_rounded": styles.thin_compact_rounded, + "thin_thick": styles.thin_thick, + "thin_thick_rounded": styles.thin_thick_rounded, + "thin_double": styles.thin_double, + "thin_double_rounded": styles.thin_double_rounded, + "thick": styles.thick, + "thick_box": styles.thick_box, + "thick_compact": styles.thick_compact, + "double": styles.double, + "double_box": styles.double_box, + "double_compact": styles.double_compact, + "double_thin": styles.double_thin, + "double_thin_compact": styles.double_thin_compact, + "minimalist": styles.minimalist, + "borderless": styles.borderless, + "ascii": styles.ascii, + "ascii_box": styles.ascii_box, + "ascii_compact": styles.ascii_compact, + "ascii_double": styles.ascii_double, + "ascii_minimalist": styles.ascii_minimalist, + "ascii_borderless": styles.ascii_borderless, + "ascii_simple": styles.ascii_simple, + "markdown": styles.markdown, + } + for style in list(styles.keys()): + full = table2ascii( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=styles[style], + ) + body_only = table2ascii( + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + first_col_heading=True, + last_col_heading=False, + style=styles[style], + ) + print(f"### `{style}`\n\n```\n{full}\n\n{body_only}\n```\n") From 4afb30613e066b33d0c3cdf6c332bf5b902455f0 Mon Sep 17 00:00:00 2001 From: Jonah Lawrence Date: Thu, 29 Apr 2021 06:22:11 +0300 Subject: [PATCH 06/22] Generate README.md for style_list --- README.md | 2 + style_list/README.md | 485 ++++++++++++++++++++++++++ {scripts => style_list}/style_list.py | 10 +- table2ascii/styles.py | 52 +-- 4 files changed, 496 insertions(+), 53 deletions(-) create mode 100644 style_list/README.md rename {scripts => style_list}/style_list.py (87%) diff --git a/README.md b/README.md index 611d56c..f73ba81 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,8 @@ Module for converting 2D Python lists to a fancy ASCII/Unicode tables - [🧑‍💻 Usage](#-usage) - [⚙️ Options](#️-options) - [👨‍🎨 Use cases](#-use-cases) + - [Discord messages and embeds](#discord-messages-and-embeds) + - [Terminal outputs](#terminal-outputs) - [🧰 Development](#-development) diff --git a/style_list/README.md b/style_list/README.md new file mode 100644 index 0000000..b949c82 --- /dev/null +++ b/style_list/README.md @@ -0,0 +1,485 @@ +## Preset styles + +### `thin` + +``` +┌─────┬───────────────────────┐ +│ # │ G H R S │ +├─────┼───────────────────────┤ +│ 1 │ 30 40 35 30 │ +├─────┼───────────────────────┤ +│ 2 │ 30 40 35 30 │ +├─────┼───────────────────────┤ +│ SUM │ 130 140 135 130 │ +└─────┴───────────────────────┘ + +┌───┬───────────────────┐ +│ 1 │ 30 40 35 30 │ +├───┼───────────────────┤ +│ 2 │ 30 40 35 30 │ +└───┴───────────────────┘ +``` +### `thin_box` + +``` +┌─────┬─────┬─────┬─────┬─────┐ +│ # │ G │ H │ R │ S │ +├─────┼─────┼─────┼─────┼─────┤ +│ 1 │ 30 │ 40 │ 35 │ 30 │ +├─────┼─────┼─────┼─────┼─────┤ +│ 2 │ 30 │ 40 │ 35 │ 30 │ +├─────┼─────┼─────┼─────┼─────┤ +│ SUM │ 130 │ 140 │ 135 │ 130 │ +└─────┴─────┴─────┴─────┴─────┘ + +┌───┬────┬────┬────┬────┐ +│ 1 │ 30 │ 40 │ 35 │ 30 │ +├───┼────┼────┼────┼────┤ +│ 2 │ 30 │ 40 │ 35 │ 30 │ +└───┴────┴────┴────┴────┘ +``` +### `thin_rounded` + +``` +╭─────┬───────────────────────╮ +│ # │ G H R S │ +├─────┼───────────────────────┤ +│ 1 │ 30 40 35 30 │ +├─────┼───────────────────────┤ +│ 2 │ 30 40 35 30 │ +├─────┼───────────────────────┤ +│ SUM │ 130 140 135 130 │ +╰─────┴───────────────────────╯ + +╭───┬───────────────────╮ +│ 1 │ 30 40 35 30 │ +├───┼───────────────────┤ +│ 2 │ 30 40 35 30 │ +╰───┴───────────────────╯ +``` +### `thin_compact` + +``` +┌─────┬───────────────────────┐ +│ # │ G H R S │ +├─────┼───────────────────────┤ +│ 1 │ 30 40 35 30 │ +│ 2 │ 30 40 35 30 │ +├─────┼───────────────────────┤ +│ SUM │ 130 140 135 130 │ +└─────┴───────────────────────┘ + +┌───┬───────────────────┐ +│ 1 │ 30 40 35 30 │ +│ 2 │ 30 40 35 30 │ +└───┴───────────────────┘ +``` +### `thin_compact_rounded` + +``` +╭─────┬───────────────────────╮ +│ # │ G H R S │ +├─────┼───────────────────────┤ +│ 1 │ 30 40 35 30 │ +│ 2 │ 30 40 35 30 │ +├─────┼───────────────────────┤ +│ SUM │ 130 140 135 130 │ +╰─────┴───────────────────────╯ + +╭───┬───────────────────╮ +│ 1 │ 30 40 35 30 │ +│ 2 │ 30 40 35 30 │ +╰───┴───────────────────╯ +``` +### `thin_thick` + +``` +┌─────┬───────────────────────┐ +│ # │ G H R S │ +┝━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━┥ +│ 1 │ 30 40 35 30 │ +├─────┼───────────────────────┤ +│ 2 │ 30 40 35 30 │ +┝━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━┥ +│ SUM │ 130 140 135 130 │ +└─────┴───────────────────────┘ + +┌───┬───────────────────┐ +│ 1 │ 30 40 35 30 │ +├───┼───────────────────┤ +│ 2 │ 30 40 35 30 │ +└───┴───────────────────┘ +``` +### `thin_thick_rounded` + +``` +╭─────┬───────────────────────╮ +│ # │ G H R S │ +┝━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━┥ +│ 1 │ 30 40 35 30 │ +├─────┼───────────────────────┤ +│ 2 │ 30 40 35 30 │ +┝━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━┥ +│ SUM │ 130 140 135 130 │ +╰─────┴───────────────────────╯ + +╭───┬───────────────────╮ +│ 1 │ 30 40 35 30 │ +├───┼───────────────────┤ +│ 2 │ 30 40 35 30 │ +╰───┴───────────────────╯ +``` +### `thin_double` + +``` +┌─────┬───────────────────────┐ +│ # │ G H R S │ +╞═════╪═══════════════════════╡ +│ 1 │ 30 40 35 30 │ +├─────┼───────────────────────┤ +│ 2 │ 30 40 35 30 │ +╞═════╪═══════════════════════╡ +│ SUM │ 130 140 135 130 │ +└─────┴───────────────────────┘ + +┌───┬───────────────────┐ +│ 1 │ 30 40 35 30 │ +├───┼───────────────────┤ +│ 2 │ 30 40 35 30 │ +└───┴───────────────────┘ +``` +### `thin_double_rounded` + +``` +╭─────┬───────────────────────╮ +│ # │ G H R S │ +╞═════╪═══════════════════════╡ +│ 1 │ 30 40 35 30 │ +├─────┼───────────────────────┤ +│ 2 │ 30 40 35 30 │ +╞═════╪═══════════════════════╡ +│ SUM │ 130 140 135 130 │ +╰─────┴───────────────────────╯ + +╭───┬───────────────────╮ +│ 1 │ 30 40 35 30 │ +├───┼───────────────────┤ +│ 2 │ 30 40 35 30 │ +╰───┴───────────────────╯ +``` +### `thick` + +``` +┏━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓ +┃ # ┃ G H R S ┃ +┣━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━┫ +┃ 1 ┃ 30 40 35 30 ┃ +┣━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━┫ +┃ 2 ┃ 30 40 35 30 ┃ +┣━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━┫ +┃ SUM ┃ 130 140 135 130 ┃ +┗━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━┛ + +┏━━━┳━━━━━━━━━━━━━━━━━━━┓ +┃ 1 ┃ 30 40 35 30 ┃ +┣━━━╋━━━━━━━━━━━━━━━━━━━┫ +┃ 2 ┃ 30 40 35 30 ┃ +┗━━━┻━━━━━━━━━━━━━━━━━━━┛ +``` +### `thick_box` + +``` +┏━━━━━┳━━━━━┳━━━━━┳━━━━━┳━━━━━┓ +┃ # ┃ G ┃ H ┃ R ┃ S ┃ +┣━━━━━╋━━━━━╋━━━━━╋━━━━━╋━━━━━┫ +┃ 1 ┃ 30 ┃ 40 ┃ 35 ┃ 30 ┃ +┣━━━━━╋━━━━━╋━━━━━╋━━━━━╋━━━━━┫ +┃ 2 ┃ 30 ┃ 40 ┃ 35 ┃ 30 ┃ +┣━━━━━╋━━━━━╋━━━━━╋━━━━━╋━━━━━┫ +┃ SUM ┃ 130 ┃ 140 ┃ 135 ┃ 130 ┃ +┗━━━━━┻━━━━━┻━━━━━┻━━━━━┻━━━━━┛ + +┏━━━┳━━━━┳━━━━┳━━━━┳━━━━┓ +┃ 1 ┃ 30 ┃ 40 ┃ 35 ┃ 30 ┃ +┣━━━╋━━━━╋━━━━╋━━━━╋━━━━┫ +┃ 2 ┃ 30 ┃ 40 ┃ 35 ┃ 30 ┃ +┗━━━┻━━━━┻━━━━┻━━━━┻━━━━┛ +``` +### `thick_compact` + +``` +┏━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓ +┃ # ┃ G H R S ┃ +┣━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━┫ +┃ 1 ┃ 30 40 35 30 ┃ +┃ 2 ┃ 30 40 35 30 ┃ +┣━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━┫ +┃ SUM ┃ 130 140 135 130 ┃ +┗━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━┛ + +┏━━━┳━━━━━━━━━━━━━━━━━━━┓ +┃ 1 ┃ 30 40 35 30 ┃ +┃ 2 ┃ 30 40 35 30 ┃ +┗━━━┻━━━━━━━━━━━━━━━━━━━┛ +``` +### `double` + +``` +╔═════╦═══════════════════════╗ +║ # ║ G H R S ║ +╠═════╬═══════════════════════╣ +║ 1 ║ 30 40 35 30 ║ +╠═════╬═══════════════════════╣ +║ 2 ║ 30 40 35 30 ║ +╠═════╬═══════════════════════╣ +║ SUM ║ 130 140 135 130 ║ +╚═════╩═══════════════════════╝ + +╔═══╦═══════════════════╗ +║ 1 ║ 30 40 35 30 ║ +╠═══╬═══════════════════╣ +║ 2 ║ 30 40 35 30 ║ +╚═══╩═══════════════════╝ +``` +### `double_box` + +``` +╔═════╦═════╦═════╦═════╦═════╗ +║ # ║ G ║ H ║ R ║ S ║ +╠═════╬═════╬═════╬═════╬═════╣ +║ 1 ║ 30 ║ 40 ║ 35 ║ 30 ║ +╠═════╬═════╬═════╬═════╬═════╣ +║ 2 ║ 30 ║ 40 ║ 35 ║ 30 ║ +╠═════╬═════╬═════╬═════╬═════╣ +║ SUM ║ 130 ║ 140 ║ 135 ║ 130 ║ +╚═════╩═════╩═════╩═════╩═════╝ + +╔═══╦════╦════╦════╦════╗ +║ 1 ║ 30 ║ 40 ║ 35 ║ 30 ║ +╠═══╬════╬════╬════╬════╣ +║ 2 ║ 30 ║ 40 ║ 35 ║ 30 ║ +╚═══╩════╩════╩════╩════╝ +``` +### `double_compact` + +``` +╔═════╦═══════════════════════╗ +║ # ║ G H R S ║ +╠═════╬═══════════════════════╣ +║ 1 ║ 30 40 35 30 ║ +║ 2 ║ 30 40 35 30 ║ +╠═════╬═══════════════════════╣ +║ SUM ║ 130 140 135 130 ║ +╚═════╩═══════════════════════╝ + +╔═══╦═══════════════════╗ +║ 1 ║ 30 40 35 30 ║ +║ 2 ║ 30 40 35 30 ║ +╚═══╩═══════════════════╝ +``` +### `double_thin` + +``` +╔═════╦═══════════════════════╗ +║ # ║ G H R S ║ +╟─────╫───────────────────────╢ +║ 1 ║ 30 40 35 30 ║ +╠═════╬═══════════════════════╣ +║ 2 ║ 30 40 35 30 ║ +╟─────╫───────────────────────╢ +║ SUM ║ 130 140 135 130 ║ +╚═════╩═══════════════════════╝ + +╔═══╦═══════════════════╗ +║ 1 ║ 30 40 35 30 ║ +╠═══╬═══════════════════╣ +║ 2 ║ 30 40 35 30 ║ +╚═══╩═══════════════════╝ +``` +### `double_thin_compact` + +``` +╔═════╦═══════════════════════╗ +║ # ║ G H R S ║ +╟─────╫───────────────────────╢ +║ 1 ║ 30 40 35 30 ║ +╠═════╬═══════════════════════╣ +║ 2 ║ 30 40 35 30 ║ +╟─────╫───────────────────────╢ +║ SUM ║ 130 140 135 130 ║ +╚═════╩═══════════════════════╝ + +╔═══╦═══════════════════╗ +║ 1 ║ 30 40 35 30 ║ +╠═══╬═══════════════════╣ +║ 2 ║ 30 40 35 30 ║ +╚═══╩═══════════════════╝ +``` +### `minimalist` + +``` + ───────────────────────────── + # │ G H R S + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + 1 │ 30 40 35 30 + ───────────────────────────── + 2 │ 30 40 35 30 + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + SUM │ 130 140 135 130 + ───────────────────────────── + + ─────────────────────── + 1 │ 30 40 35 30 + ─────────────────────── + 2 │ 30 40 35 30 + ─────────────────────── +``` +### `borderless` + +``` + # ┃ G H R S + ━━━━━ ━━━━━ ━━━━━ ━━━━━ ━━━━━ + 1 ┃ 30 40 35 30 + 2 ┃ 30 40 35 30 + ━━━━━ ━━━━━ ━━━━━ ━━━━━ ━━━━━ + SUM ┃ 130 140 135 130 + + 1 ┃ 30 40 35 30 + 2 ┃ 30 40 35 30 +``` +### `ascii` + +``` ++-----+-----------------------+ +| # | G H R S | ++-----+-----------------------+ +| 1 | 30 40 35 30 | ++-----+-----------------------+ +| 2 | 30 40 35 30 | ++-----+-----------------------+ +| SUM | 130 140 135 130 | ++-----+-----------------------+ + ++---+-------------------+ +| 1 | 30 40 35 30 | ++---+-------------------+ +| 2 | 30 40 35 30 | ++---+-------------------+ +``` +### `ascii_box` + +``` ++-----+-----+-----+-----+-----+ +| # | G | H | R | S | ++-----+-----+-----+-----+-----+ +| 1 | 30 | 40 | 35 | 30 | ++-----+-----+-----+-----+-----+ +| 2 | 30 | 40 | 35 | 30 | ++-----+-----+-----+-----+-----+ +| SUM | 130 | 140 | 135 | 130 | ++-----+-----+-----+-----+-----+ + ++---+----+----+----+----+ +| 1 | 30 | 40 | 35 | 30 | ++---+----+----+----+----+ +| 2 | 30 | 40 | 35 | 30 | ++---+----+----+----+----+ +``` +### `ascii_compact` + +``` ++-----+-----------------------+ +| # | G H R S | ++-----+-----------------------+ +| 1 | 30 40 35 30 | +| 2 | 30 40 35 30 | ++-----+-----------------------+ +| SUM | 130 140 135 130 | ++-----+-----------------------+ + ++---+-------------------+ +| 1 | 30 40 35 30 | +| 2 | 30 40 35 30 | ++---+-------------------+ +``` +### `ascii_double` + +``` ++-----+-----------------------+ +| # | G H R S | ++=====+=======================+ +| 1 | 30 40 35 30 | ++-----+-----------------------+ +| 2 | 30 40 35 30 | ++=====+=======================+ +| SUM | 130 140 135 130 | ++-----+-----------------------+ + ++---+-------------------+ +| 1 | 30 40 35 30 | ++---+-------------------+ +| 2 | 30 40 35 30 | ++---+-------------------+ +``` +### `ascii_minimalist` + +``` + ----------------------------- + # | G H R S + ============================= + 1 | 30 40 35 30 + ----------------------------- + 2 | 30 40 35 30 + ============================= + SUM | 130 140 135 130 + ----------------------------- + + ----------------------- + 1 | 30 40 35 30 + ----------------------- + 2 | 30 40 35 30 + ----------------------- +``` +### `ascii_borderless` + +``` + # | G H R S + ----- ----- ----- ----- ----- + 1 | 30 40 35 30 + 2 | 30 40 35 30 + ----- ----- ----- ----- ----- + SUM | 130 140 135 130 + + 1 | 30 40 35 30 + 2 | 30 40 35 30 +``` +### `ascii_simple` + +``` + ===== ===== ===== ===== ===== + # | G H R S + ===== ===== ===== ===== ===== + 1 | 30 40 35 30 + 2 | 30 40 35 30 + ===== ===== ===== ===== ===== + SUM | 130 140 135 130 + ===== ===== ===== ===== ===== + + === ==== ==== ==== ==== + 1 | 30 40 35 30 + 2 | 30 40 35 30 + === ==== ==== ==== ==== +``` +### `markdown` + +``` +| # | G | H | R | S | +|-----|-----|-----|-----|-----| +| 1 | 30 | 40 | 35 | 30 | +| 2 | 30 | 40 | 35 | 30 | +|-----|-----|-----|-----|-----| +| SUM | 130 | 140 | 135 | 130 | + +| 1 | 30 | 40 | 35 | 30 | +| 2 | 30 | 40 | 35 | 30 | +``` diff --git a/scripts/style_list.py b/style_list/style_list.py similarity index 87% rename from scripts/style_list.py rename to style_list/style_list.py index 24340f2..cd801dc 100644 --- a/scripts/style_list.py +++ b/style_list/style_list.py @@ -1,7 +1,8 @@ +import os from table2ascii import styles from table2ascii.table_to_ascii import table2ascii -# prints all themes with previews +# generate README.md containing all themes with previews if __name__ == "__main__": styles = { "thin": styles.thin, @@ -32,6 +33,7 @@ "ascii_simple": styles.ascii_simple, "markdown": styles.markdown, } + output = "## Preset styles\n\n" for style in list(styles.keys()): full = table2ascii( header=["#", "G", "H", "R", "S"], @@ -47,4 +49,8 @@ last_col_heading=False, style=styles[style], ) - print(f"### `{style}`\n\n```\n{full}\n\n{body_only}\n```\n") + output += f"### `{style}`\n\n```\n{full}\n\n{body_only}\n```\n" + + f = open(os.path.join("style_list", "README.md"), "w") + f.write(output) + f.close() diff --git a/table2ascii/styles.py b/table2ascii/styles.py index 0e112cf..511398f 100644 --- a/table2ascii/styles.py +++ b/table2ascii/styles.py @@ -26,54 +26,4 @@ ascii_minimalist = TableStyle.from_string(" --- | === --- -- ") ascii_borderless = TableStyle.from_string(" | - ") ascii_simple = TableStyle.from_string(" = | = ") -markdown = TableStyle.from_string(" ||||-||| ") - -# prints all themes with previews -if __name__ == "__main__": - from .table_to_ascii import table2ascii - - styles = { - "thin": thin, - "thin_box": thin_box, - "thin_rounded": thin_rounded, - "thin_compact": thin_compact, - "thin_compact_rounded": thin_compact_rounded, - "thin_thick": thin_thick, - "thin_thick_rounded": thin_thick_rounded, - "thin_double": thin_double, - "thin_double_rounded": thin_double_rounded, - "thick": thick, - "thick_box": thick_box, - "thick_compact": thick_compact, - "double": double, - "double_box": double_box, - "double_compact": double_compact, - "double_thin": double_thin, - "double_thin_compact": double_thin_compact, - "minimalist": minimalist, - "borderless": borderless, - "ascii": ascii, - "ascii_box": ascii_box, - "ascii_compact": ascii_compact, - "ascii_double": ascii_double, - "ascii_minimalist": ascii_minimalist, - "ascii_borderless": ascii_borderless, - "ascii_simple": ascii_simple, - "markdown": markdown, - } - for style in list(styles.keys()): - full = table2ascii( - header=["#", "G", "H", "R", "S"], - body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], - footer=["SUM", "130", "140", "135", "130"], - first_col_heading=True, - last_col_heading=False, - style=styles[style], - ) - body_only = table2ascii( - body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], - first_col_heading=True, - last_col_heading=False, - style=styles[style], - ) - print(f"### `{style}`\n\n```\n{full}\n\n{body_only}\n```\n") +markdown = TableStyle.from_string(" ||||-||| ") \ No newline at end of file From 9f29aa1e7736d2ce6fd67f25a023a767952758e7 Mon Sep 17 00:00:00 2001 From: Jonah Lawrence Date: Thu, 29 Apr 2021 06:41:35 +0300 Subject: [PATCH 07/22] Add themes --- style_list/README.md | 38 +++++++++---------- .../{style_list.py => generate_style_list.py} | 2 +- table2ascii/options.py | 2 +- table2ascii/styles.py | 4 +- 4 files changed, 21 insertions(+), 25 deletions(-) rename style_list/{style_list.py => generate_style_list.py} (98%) diff --git a/style_list/README.md b/style_list/README.md index b949c82..3efc9c0 100644 --- a/style_list/README.md +++ b/style_list/README.md @@ -277,25 +277,6 @@ ║ 2 ║ 30 40 35 30 ║ ╚═══╩═══════════════════╝ ``` -### `double_thin` - -``` -╔═════╦═══════════════════════╗ -║ # ║ G H R S ║ -╟─────╫───────────────────────╢ -║ 1 ║ 30 40 35 30 ║ -╠═════╬═══════════════════════╣ -║ 2 ║ 30 40 35 30 ║ -╟─────╫───────────────────────╢ -║ SUM ║ 130 140 135 130 ║ -╚═════╩═══════════════════════╝ - -╔═══╦═══════════════════╗ -║ 1 ║ 30 40 35 30 ║ -╠═══╬═══════════════════╣ -║ 2 ║ 30 40 35 30 ║ -╚═══╩═══════════════════╝ -``` ### `double_thin_compact` ``` @@ -303,7 +284,6 @@ ║ # ║ G H R S ║ ╟─────╫───────────────────────╢ ║ 1 ║ 30 40 35 30 ║ -╠═════╬═══════════════════════╣ ║ 2 ║ 30 40 35 30 ║ ╟─────╫───────────────────────╢ ║ SUM ║ 130 140 135 130 ║ @@ -311,7 +291,6 @@ ╔═══╦═══════════════════╗ ║ 1 ║ 30 40 35 30 ║ -╠═══╬═══════════════════╣ ║ 2 ║ 30 40 35 30 ║ ╚═══╩═══════════════════╝ ``` @@ -347,6 +326,23 @@ 1 ┃ 30 40 35 30 2 ┃ 30 40 35 30 ``` +### `simple` + +``` + ═════ ═════ ═════ ═════ ═════ + # │ G H R S + ═════ ═════ ═════ ═════ ═════ + 1 │ 30 40 35 30 + 2 │ 30 40 35 30 + ═════ ═════ ═════ ═════ ═════ + SUM │ 130 140 135 130 + ═════ ═════ ═════ ═════ ═════ + + ═══ ════ ════ ════ ════ + 1 │ 30 40 35 30 + 2 │ 30 40 35 30 + ═══ ════ ════ ════ ════ +``` ### `ascii` ``` diff --git a/style_list/style_list.py b/style_list/generate_style_list.py similarity index 98% rename from style_list/style_list.py rename to style_list/generate_style_list.py index cd801dc..ff0202d 100644 --- a/style_list/style_list.py +++ b/style_list/generate_style_list.py @@ -20,10 +20,10 @@ "double": styles.double, "double_box": styles.double_box, "double_compact": styles.double_compact, - "double_thin": styles.double_thin, "double_thin_compact": styles.double_thin_compact, "minimalist": styles.minimalist, "borderless": styles.borderless, + "simple": styles.simple, "ascii": styles.ascii, "ascii_box": styles.ascii_box, "ascii_compact": styles.ascii_compact, diff --git a/table2ascii/options.py b/table2ascii/options.py index fab9c0b..e9048e4 100644 --- a/table2ascii/options.py +++ b/table2ascii/options.py @@ -17,4 +17,4 @@ class Options: last_col_heading: bool = False column_widths: Optional[List[int]] = None alignments: Optional[List[Alignment]] = None - style: TableStyle = styles.double_thin + style: TableStyle = styles.double_thin_compact diff --git a/table2ascii/styles.py b/table2ascii/styles.py index 511398f..debfcde 100644 --- a/table2ascii/styles.py +++ b/table2ascii/styles.py @@ -15,10 +15,10 @@ double = TableStyle.from_string("╔═╦═╗║║ ╠═╬═╣╠═╬═╣╚╩═╝") double_box = TableStyle.from_string("╔═╦╦╗║║║╠═╬╬╣╠═╬╬╣╚╩╩╝") double_compact = TableStyle.from_string("╔═╦═╗║║ ╠═╬═╣ ╚╩═╝") -double_thin = TableStyle.from_string("╔═╦═╗║║ ╟─╫─╢╠═╬═╣╚╩═╝") -double_thin_compact = TableStyle.from_string("╔═╦═╗║║ ╟─╫─╢╠═╬═╣╚╩═╝") +double_thin_compact = TableStyle.from_string("╔═╦═╗║║ ╟─╫─╢ ╚╩═╝") minimalist = TableStyle.from_string(" ─── │ ━━━ ─── ── ") borderless = TableStyle.from_string(" ┃ ━ ") +simple = TableStyle.from_string(" ═ │ ═ ") ascii = TableStyle.from_string("+-+-+|| +-+-++-+-+++-+") ascii_box = TableStyle.from_string("+-+++|||+-++++-+++++++") ascii_compact = TableStyle.from_string("+-+-+|| +-+-+ ++-+") From 9c5cb5ee1bc69aafcce5aa207eb5fb25873ad550 Mon Sep 17 00:00:00 2001 From: Jonah Lawrence Date: Thu, 29 Apr 2021 06:42:21 +0300 Subject: [PATCH 08/22] Move header, body, footer back as positional arguments --- table2ascii/table_to_ascii.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/table2ascii/table_to_ascii.py b/table2ascii/table_to_ascii.py index fe0c12d..e2758e4 100644 --- a/table2ascii/table_to_ascii.py +++ b/table2ascii/table_to_ascii.py @@ -8,12 +8,12 @@ class TableToAscii: """Class used to convert a 2D Python table to ASCII text""" - def __init__(self, options: Options): + def __init__(self, header: List, body: List[List], footer: List, options: Options): """Validate arguments and initialize fields""" # initialize fields - self.__header = options.header - self.__body = options.body - self.__footer = options.footer + self.__header = header + self.__body = body + self.__footer = footer self.__style = options.style self.__first_col_heading = options.first_col_heading self.__last_col_heading = options.last_col_heading @@ -217,16 +217,21 @@ def to_ascii(self) -> str: return table.strip("\n") -def table2ascii(**options) -> str: +def table2ascii( + header: List = None, body: List[List] = None, footer: List = None, **options +) -> str: """Convert a 2D Python table to ASCII text ### Arguments :param header: :class:`Optional[List]` List of column values in the table's header row :param body: :class:`Optional[List[List]]` 2-dimensional list of values in the table's body :param footer: :class:`Optional[List]` List of column values in the table's footer row + + ### Keyword required + :param style: :class:`Optional[TableStyle]` Table style to use for styling (preset styles can be imported) :param column_widths: :class:`Optional[List[int]]` List of widths in characters for each column (defaults to auto-sizing) :param alignments: :class:`Optional[List[Alignment]]` List of alignments (ex. `[Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT]`) :param first_col_heading: :class:`Optional[bool]` Whether to add a header column separator after the first column :param last_col_heading: :class:`Optional[bool]` Whether to add a header column separator before the last column """ - return TableToAscii(Options(**options)).to_ascii() + return TableToAscii(header, body, footer, Options(**options)).to_ascii() From e787a1c9341251c3f5988cfa39b5fb578e143843 Mon Sep 17 00:00:00 2001 From: Jonah Lawrence Date: Thu, 29 Apr 2021 07:44:38 +0300 Subject: [PATCH 09/22] Created class for preset styles --- style_list/generate_style_list.py | 56 ++-- table2ascii/__init__.py | 6 +- table2ascii/options.py | 4 +- table2ascii/styles.py | 58 ++-- table2ascii/table_style.py | 3 +- table2ascii/table_to_ascii.py | 4 +- tests/test_alignments.py | 2 +- tests/test_column_widths.py | 2 +- tests/test_convert.py | 18 +- tests/test_heading_cols.py | 12 +- tests/test_styles.py | 539 ++++++++++++++++++++++++++++-- 11 files changed, 592 insertions(+), 112 deletions(-) diff --git a/style_list/generate_style_list.py b/style_list/generate_style_list.py index ff0202d..8554220 100644 --- a/style_list/generate_style_list.py +++ b/style_list/generate_style_list.py @@ -1,37 +1,37 @@ import os -from table2ascii import styles +from table2ascii import Styles from table2ascii.table_to_ascii import table2ascii # generate README.md containing all themes with previews if __name__ == "__main__": styles = { - "thin": styles.thin, - "thin_box": styles.thin_box, - "thin_rounded": styles.thin_rounded, - "thin_compact": styles.thin_compact, - "thin_compact_rounded": styles.thin_compact_rounded, - "thin_thick": styles.thin_thick, - "thin_thick_rounded": styles.thin_thick_rounded, - "thin_double": styles.thin_double, - "thin_double_rounded": styles.thin_double_rounded, - "thick": styles.thick, - "thick_box": styles.thick_box, - "thick_compact": styles.thick_compact, - "double": styles.double, - "double_box": styles.double_box, - "double_compact": styles.double_compact, - "double_thin_compact": styles.double_thin_compact, - "minimalist": styles.minimalist, - "borderless": styles.borderless, - "simple": styles.simple, - "ascii": styles.ascii, - "ascii_box": styles.ascii_box, - "ascii_compact": styles.ascii_compact, - "ascii_double": styles.ascii_double, - "ascii_minimalist": styles.ascii_minimalist, - "ascii_borderless": styles.ascii_borderless, - "ascii_simple": styles.ascii_simple, - "markdown": styles.markdown, + "thin": Styles.thin, + "thin_box": Styles.thin_box, + "thin_rounded": Styles.thin_rounded, + "thin_compact": Styles.thin_compact, + "thin_compact_rounded": Styles.thin_compact_rounded, + "thin_thick": Styles.thin_thick, + "thin_thick_rounded": Styles.thin_thick_rounded, + "thin_double": Styles.thin_double, + "thin_double_rounded": Styles.thin_double_rounded, + "thick": Styles.thick, + "thick_box": Styles.thick_box, + "thick_compact": Styles.thick_compact, + "double": Styles.double, + "double_box": Styles.double_box, + "double_compact": Styles.double_compact, + "double_thin_compact": Styles.double_thin_compact, + "minimalist": Styles.minimalist, + "borderless": Styles.borderless, + "simple": Styles.simple, + "ascii": Styles.ascii, + "ascii_box": Styles.ascii_box, + "ascii_compact": Styles.ascii_compact, + "ascii_double": Styles.ascii_double, + "ascii_minimalist": Styles.ascii_minimalist, + "ascii_borderless": Styles.ascii_borderless, + "ascii_simple": Styles.ascii_simple, + "markdown": Styles.markdown, } output = "## Preset styles\n\n" for style in list(styles.keys()): diff --git a/table2ascii/__init__.py b/table2ascii/__init__.py index 4aa2b25..a7b945d 100644 --- a/table2ascii/__init__.py +++ b/table2ascii/__init__.py @@ -1,7 +1,11 @@ -from .table_to_ascii import table2ascii from .alignment import Alignment +from .styles import Styles +from .table_style import TableStyle +from .table_to_ascii import table2ascii __all__ = [ "table2ascii", "Alignment", + "TableStyle", + "Styles", ] diff --git a/table2ascii/options.py b/table2ascii/options.py index e9048e4..8423e56 100644 --- a/table2ascii/options.py +++ b/table2ascii/options.py @@ -1,7 +1,7 @@ from dataclasses import dataclass from typing import List, Optional -from . import styles +from .styles import Styles from .alignment import Alignment from .table_style import TableStyle @@ -17,4 +17,4 @@ class Options: last_col_heading: bool = False column_widths: Optional[List[int]] = None alignments: Optional[List[Alignment]] = None - style: TableStyle = styles.double_thin_compact + style: TableStyle = Styles.double_thin_compact diff --git a/table2ascii/styles.py b/table2ascii/styles.py index debfcde..89f2923 100644 --- a/table2ascii/styles.py +++ b/table2ascii/styles.py @@ -1,29 +1,33 @@ from .table_style import TableStyle -thin = TableStyle.from_string("┌─┬─┐││ ├─┼─┤├─┼─┤└┴─┘") -thin_box = TableStyle.from_string("┌─┬┬┐│││├─┼┼┤├─┼┼┤└┴┴┘") -thin_rounded = TableStyle.from_string("╭─┬─╮││ ├─┼─┤├─┼─┤╰┴─╯") -thin_compact = TableStyle.from_string("┌─┬─┐││ ├─┼─┤ └┴─┘") -thin_compact_rounded = TableStyle.from_string("╭─┬─╮││ ├─┼─┤ ╰┴─╯") -thin_thick = TableStyle.from_string("┌─┬─┐││ ┝━┿━┥├─┼─┤└┴─┘") -thin_thick_rounded = TableStyle.from_string("╭─┬─╮││ ┝━┿━┥├─┼─┤╰┴─╯") -thin_double = TableStyle.from_string("┌─┬─┐││ ╞═╪═╡├─┼─┤└┴─┘") -thin_double_rounded = TableStyle.from_string("╭─┬─╮││ ╞═╪═╡├─┼─┤╰┴─╯") -thick = TableStyle.from_string("┏━┳━┓┃┃ ┣━╋━┫┣━╋━┫┗┻━┛") -thick_box = TableStyle.from_string("┏━┳┳┓┃┃┃┣━╋╋┫┣━╋╋┫┗┻┻┛") -thick_compact = TableStyle.from_string("┏━┳━┓┃┃ ┣━╋━┫ ┗┻━┛") -double = TableStyle.from_string("╔═╦═╗║║ ╠═╬═╣╠═╬═╣╚╩═╝") -double_box = TableStyle.from_string("╔═╦╦╗║║║╠═╬╬╣╠═╬╬╣╚╩╩╝") -double_compact = TableStyle.from_string("╔═╦═╗║║ ╠═╬═╣ ╚╩═╝") -double_thin_compact = TableStyle.from_string("╔═╦═╗║║ ╟─╫─╢ ╚╩═╝") -minimalist = TableStyle.from_string(" ─── │ ━━━ ─── ── ") -borderless = TableStyle.from_string(" ┃ ━ ") -simple = TableStyle.from_string(" ═ │ ═ ") -ascii = TableStyle.from_string("+-+-+|| +-+-++-+-+++-+") -ascii_box = TableStyle.from_string("+-+++|||+-++++-+++++++") -ascii_compact = TableStyle.from_string("+-+-+|| +-+-+ ++-+") -ascii_double = TableStyle.from_string("+-+-+|| +=+=++-+-+++-+") -ascii_minimalist = TableStyle.from_string(" --- | === --- -- ") -ascii_borderless = TableStyle.from_string(" | - ") -ascii_simple = TableStyle.from_string(" = | = ") -markdown = TableStyle.from_string(" ||||-||| ") \ No newline at end of file + +class Styles: + """Importable preset styles for more easily selecting a table style""" + + thin = TableStyle.from_string("┌─┬─┐││ ├─┼─┤├─┼─┤└┴─┘") + thin_box = TableStyle.from_string("┌─┬┬┐│││├─┼┼┤├─┼┼┤└┴┴┘") + thin_rounded = TableStyle.from_string("╭─┬─╮││ ├─┼─┤├─┼─┤╰┴─╯") + thin_compact = TableStyle.from_string("┌─┬─┐││ ├─┼─┤ └┴─┘") + thin_compact_rounded = TableStyle.from_string("╭─┬─╮││ ├─┼─┤ ╰┴─╯") + thin_thick = TableStyle.from_string("┌─┬─┐││ ┝━┿━┥├─┼─┤└┴─┘") + thin_thick_rounded = TableStyle.from_string("╭─┬─╮││ ┝━┿━┥├─┼─┤╰┴─╯") + thin_double = TableStyle.from_string("┌─┬─┐││ ╞═╪═╡├─┼─┤└┴─┘") + thin_double_rounded = TableStyle.from_string("╭─┬─╮││ ╞═╪═╡├─┼─┤╰┴─╯") + thick = TableStyle.from_string("┏━┳━┓┃┃ ┣━╋━┫┣━╋━┫┗┻━┛") + thick_box = TableStyle.from_string("┏━┳┳┓┃┃┃┣━╋╋┫┣━╋╋┫┗┻┻┛") + thick_compact = TableStyle.from_string("┏━┳━┓┃┃ ┣━╋━┫ ┗┻━┛") + double = TableStyle.from_string("╔═╦═╗║║ ╠═╬═╣╠═╬═╣╚╩═╝") + double_box = TableStyle.from_string("╔═╦╦╗║║║╠═╬╬╣╠═╬╬╣╚╩╩╝") + double_compact = TableStyle.from_string("╔═╦═╗║║ ╠═╬═╣ ╚╩═╝") + double_thin_compact = TableStyle.from_string("╔═╦═╗║║ ╟─╫─╢ ╚╩═╝") + minimalist = TableStyle.from_string(" ─── │ ━━━ ─── ── ") + borderless = TableStyle.from_string(" ┃ ━ ") + simple = TableStyle.from_string(" ═ │ ═ ") + ascii = TableStyle.from_string("+-+-+|| +-+-++-+-+++-+") + ascii_box = TableStyle.from_string("+-+++|||+-++++-+++++++") + ascii_compact = TableStyle.from_string("+-+-+|| +-+-+ ++-+") + ascii_double = TableStyle.from_string("+-+-+|| +=+=++-+-+++-+") + ascii_minimalist = TableStyle.from_string(" --- | === --- -- ") + ascii_borderless = TableStyle.from_string(" | - ") + ascii_simple = TableStyle.from_string(" = | = ") + markdown = TableStyle.from_string(" ||||-||| ") diff --git a/table2ascii/table_style.py b/table2ascii/table_style.py index 753b25b..238d963 100644 --- a/table2ascii/table_style.py +++ b/table2ascii/table_style.py @@ -1,4 +1,3 @@ -import enum from dataclasses import dataclass @@ -36,6 +35,7 @@ class TableStyle: ``` """ + # parts of the table top_left_corner: str # A top_and_bottom_edge: str # B heading_col_top_tee: str # C @@ -59,6 +59,7 @@ class TableStyle: bottom_tee: str # U bottom_right_corner: str # V + # method for splitting string into argument list @classmethod def from_string(cls, string: str) -> "TableStyle": return cls(*string) diff --git a/table2ascii/table_to_ascii.py b/table2ascii/table_to_ascii.py index e2758e4..e18766f 100644 --- a/table2ascii/table_to_ascii.py +++ b/table2ascii/table_to_ascii.py @@ -22,12 +22,12 @@ def __init__(self, header: List, body: List[List], footer: List, options: Option self.__columns = self.__count_columns() # check if footer has a different number of columns - if options.footer and len(options.footer) != self.__columns: + if footer and len(footer) != self.__columns: raise ValueError( "Footer must have the same number of columns as the other rows" ) # check if any rows in body have a different number of columns - if options.body and any(len(row) != self.__columns for row in options.body): + if body and any(len(row) != self.__columns for row in body): raise ValueError( "All rows in body must have the same number of columns as the other rows" ) diff --git a/tests/test_alignments.py b/tests/test_alignments.py index 12667dc..de34d37 100644 --- a/tests/test_alignments.py +++ b/tests/test_alignments.py @@ -19,7 +19,7 @@ def test_first_left_four_right(): "║ 2 ║ 30 40 35 30 ║\n" "╟─────╫───────────────────────╢\n" "║ SUM ║ 130 140 135 130 ║\n" - "╚═════╩═══════════════════════╝\n" + "╚═════╩═══════════════════════╝" ) assert text == expected diff --git a/tests/test_column_widths.py b/tests/test_column_widths.py index 28be80d..cfb7534 100644 --- a/tests/test_column_widths.py +++ b/tests/test_column_widths.py @@ -20,7 +20,7 @@ def test_column_widths(): "║ 2 ║ 30 40 35 ║ 30 ║\n" "╟───────╫─────────────────╫────────╢\n" "║ TOTL ║ 130 140 135 ║ 130 ║\n" - "╚═══════╩═════════════════╩════════╝\n" + "╚═══════╩═════════════════╩════════╝" ) assert text == expected diff --git a/tests/test_convert.py b/tests/test_convert.py index b731988..9142b49 100644 --- a/tests/test_convert.py +++ b/tests/test_convert.py @@ -18,7 +18,7 @@ def test_header_body_footer(): "║ 2 ║ 30 40 35 30 ║\n" "╟─────╫───────────────────────╢\n" "║ SUM ║ 130 140 135 130 ║\n" - "╚═════╩═══════════════════════╝\n" + "╚═════╩═══════════════════════╝" ) assert text == expected @@ -35,7 +35,7 @@ def test_body_footer(): "║ 2 ║ 30 40 35 30 ║\n" "╟─────╫───────────────────────╢\n" "║ SUM ║ 130 140 135 130 ║\n" - "╚═════╩═══════════════════════╝\n" + "╚═════╩═══════════════════════╝" ) assert text == expected @@ -52,7 +52,7 @@ def test_header_body(): "╟───╫───────────────────╢\n" "║ 1 ║ 30 40 35 30 ║\n" "║ 2 ║ 30 40 35 30 ║\n" - "╚═══╩═══════════════════╝\n" + "╚═══╩═══════════════════╝" ) assert text == expected @@ -69,7 +69,7 @@ def test_header_footer(): "╟─────╫───────────────────────╢\n" "╟─────╫───────────────────────╢\n" "║ SUM ║ 130 140 135 130 ║\n" - "╚═════╩═══════════════════════╝\n" + "╚═════╩═══════════════════════╝" ) assert text == expected @@ -83,7 +83,7 @@ def test_header(): "╔═══╦═══════════════╗\n" "║ # ║ G H R S ║\n" "╟───╫───────────────╢\n" - "╚═══╩═══════════════╝\n" + "╚═══╩═══════════════╝" ) assert text == expected @@ -97,7 +97,7 @@ def test_body(): "╔═══╦═══════════════════╗\n" "║ 1 ║ 30 40 35 30 ║\n" "║ 2 ║ 30 40 35 30 ║\n" - "╚═══╩═══════════════════╝\n" + "╚═══╩═══════════════════╝" ) assert text == expected @@ -111,7 +111,7 @@ def test_footer(): "╔═════╦═══════════════════════╗\n" "╟─────╫───────────────────────╢\n" "║ SUM ║ 130 140 135 130 ║\n" - "╚═════╩═══════════════════════╝\n" + "╚═════╩═══════════════════════╝" ) assert text == expected @@ -161,7 +161,7 @@ def test_empty_header(): "╔═══╦═══════════════════╗\n" "║ 1 ║ 30 40 35 30 ║\n" "║ 2 ║ 30 40 35 30 ║\n" - "╚═══╩═══════════════════╝\n" + "╚═══╩═══════════════════╝" ) assert text == expected @@ -176,6 +176,6 @@ def test_empty_body(): "╔═══╦═══════════════╗\n" "║ # ║ G H R S ║\n" "╟───╫───────────────╢\n" - "╚═══╩═══════════════╝\n" + "╚═══╩═══════════════╝" ) assert text == expected diff --git a/tests/test_heading_cols.py b/tests/test_heading_cols.py index 62cf5b5..2a5ccef 100644 --- a/tests/test_heading_cols.py +++ b/tests/test_heading_cols.py @@ -17,7 +17,7 @@ def test_first_column_heading(): "║ 2 ║ 30 40 35 30 ║\n" "╟─────╫───────────────────────╢\n" "║ SUM ║ 130 140 135 130 ║\n" - "╚═════╩═══════════════════════╝\n" + "╚═════╩═══════════════════════╝" ) assert text == expected @@ -31,7 +31,7 @@ def test_first_column_heading_body_only(): "╔═══╦═══════════════════╗\n" "║ 1 ║ 30 40 35 30 ║\n" "║ 2 ║ 30 40 35 30 ║\n" - "╚═══╩═══════════════════╝\n" + "╚═══╩═══════════════════╝" ) assert text == expected @@ -52,7 +52,7 @@ def test_last_column_heading(): "║ 2 30 40 35 ║ 30 ║\n" "╟───────────────────────╫─────╢\n" "║ SUM 130 140 135 ║ 130 ║\n" - "╚═══════════════════════╩═════╝\n" + "╚═══════════════════════╩═════╝" ) assert text == expected @@ -66,7 +66,7 @@ def test_last_column_heading_body_only(): "╔══════════════════╦════╗\n" "║ 1 30 40 35 ║ 30 ║\n" "║ 2 30 40 35 ║ 30 ║\n" - "╚══════════════════╩════╝\n" + "╚══════════════════╩════╝" ) assert text == expected @@ -87,7 +87,7 @@ def test_both_column_heading(): "║ 2 ║ 30 40 35 ║ 30 ║\n" "╟─────╫─────────────────╫─────╢\n" "║ SUM ║ 130 140 135 ║ 130 ║\n" - "╚═════╩═════════════════╩═════╝\n" + "╚═════╩═════════════════╩═════╝" ) assert text == expected @@ -108,6 +108,6 @@ def test_neither_column_heading(): "║ 2 30 40 35 30 ║\n" "╟─────────────────────────────╢\n" "║ SUM 130 140 135 130 ║\n" - "╚═════════════════════════════╝\n" + "╚═════════════════════════════╝" ) assert text == expected diff --git a/tests/test_styles.py b/tests/test_styles.py index 268789a..970cce6 100644 --- a/tests/test_styles.py +++ b/tests/test_styles.py @@ -1,36 +1,83 @@ -from table2ascii import table2ascii as t2a, styles +from table2ascii import table2ascii as t2a, Styles -def test_double_thin(): +def test_thin(): text = t2a( header=["#", "G", "H", "R", "S"], body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=styles.double_thin, + style=Styles.thin, ) expected = ( - "╔═════╦═══════════════════════╗\n" - "║ # ║ G H R S ║\n" - "╟─────╫───────────────────────╢\n" - "║ 1 ║ 30 40 35 30 ║\n" - "║ 2 ║ 30 40 35 30 ║\n" - "╟─────╫───────────────────────╢\n" - "║ SUM ║ 130 140 135 130 ║\n" - "╚═════╩═══════════════════════╝\n" + "┌─────┬───────────────────────┐\n" + "│ # │ G H R S │\n" + "├─────┼───────────────────────┤\n" + "│ 1 │ 30 40 35 30 │\n" + "├─────┼───────────────────────┤\n" + "│ 2 │ 30 40 35 30 │\n" + "├─────┼───────────────────────┤\n" + "│ SUM │ 130 140 135 130 │\n" + "└─────┴───────────────────────┘" ) assert text == expected -def test_thin(): +def test_thin_box(): + text = t2a( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=Styles.thin_box, + ) + expected = ( + "┌─────┬─────┬─────┬─────┬─────┐\n" + "│ # │ G │ H │ R │ S │\n" + "├─────┼─────┼─────┼─────┼─────┤\n" + "│ 1 │ 30 │ 40 │ 35 │ 30 │\n" + "├─────┼─────┼─────┼─────┼─────┤\n" + "│ 2 │ 30 │ 40 │ 35 │ 30 │\n" + "├─────┼─────┼─────┼─────┼─────┤\n" + "│ SUM │ 130 │ 140 │ 135 │ 130 │\n" + "└─────┴─────┴─────┴─────┴─────┘" + ) + assert text == expected + + +def test_thin_rounded(): + text = t2a( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=Styles.thin_rounded, + ) + expected = ( + "╭─────┬───────────────────────╮\n" + "│ # │ G H R S │\n" + "├─────┼───────────────────────┤\n" + "│ 1 │ 30 40 35 30 │\n" + "├─────┼───────────────────────┤\n" + "│ 2 │ 30 40 35 30 │\n" + "├─────┼───────────────────────┤\n" + "│ SUM │ 130 140 135 130 │\n" + "╰─────┴───────────────────────╯" + ) + assert text == expected + + +def test_thin_compact(): text = t2a( header=["#", "G", "H", "R", "S"], body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=styles.thin, + style=Styles.thin_compact, ) expected = ( "┌─────┬───────────────────────┐\n" @@ -40,8 +87,29 @@ def test_thin(): "│ 2 │ 30 40 35 30 │\n" "├─────┼───────────────────────┤\n" "│ SUM │ 130 140 135 130 │\n" - "└─────┴───────────────────────┘\n" - "" + "└─────┴───────────────────────┘" + ) + assert text == expected + + +def test_thin_compact_rounded(): + text = t2a( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=Styles.thin_compact_rounded, + ) + expected = ( + "╭─────┬───────────────────────╮\n" + "│ # │ G H R S │\n" + "├─────┼───────────────────────┤\n" + "│ 1 │ 30 40 35 30 │\n" + "│ 2 │ 30 40 35 30 │\n" + "├─────┼───────────────────────┤\n" + "│ SUM │ 130 140 135 130 │\n" + "╰─────┴───────────────────────╯" ) assert text == expected @@ -53,82 +121,485 @@ def test_thin_thick(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=styles.thin_thick, + style=Styles.thin_thick, ) expected = ( "┌─────┬───────────────────────┐\n" "│ # │ G H R S │\n" "┝━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━┥\n" "│ 1 │ 30 40 35 30 │\n" + "├─────┼───────────────────────┤\n" "│ 2 │ 30 40 35 30 │\n" "┝━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━┥\n" "│ SUM │ 130 140 135 130 │\n" - "└─────┴───────────────────────┘\n" + "└─────┴───────────────────────┘" ) assert text == expected -def test_thin_double(): +def test_thin_thick_rounded(): text = t2a( header=["#", "G", "H", "R", "S"], body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=styles.thin_double, + style=Styles.thin_thick_rounded, ) expected = ( - "┌─────┬───────────────────────┐\n" + "╭─────┬───────────────────────╮\n" "│ # │ G H R S │\n" - "╞═════╪═══════════════════════╡\n" + "┝━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━┥\n" "│ 1 │ 30 40 35 30 │\n" + "├─────┼───────────────────────┤\n" "│ 2 │ 30 40 35 30 │\n" - "╞═════╪═══════════════════════╡\n" + "┝━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━┥\n" "│ SUM │ 130 140 135 130 │\n" - "└─────┴───────────────────────┘\n" + "╰─────┴───────────────────────╯" ) assert text == expected -def test_thin_rounded(): +def test_thin_double(): text = t2a( header=["#", "G", "H", "R", "S"], body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=styles.thin_rounded, + style=Styles.thin_double, ) expected = ( - "╭─────┬───────────────────────╮\n" + "┌─────┬───────────────────────┐\n" "│ # │ G H R S │\n" - "├─────┼───────────────────────┤\n" + "╞═════╪═══════════════════════╡\n" "│ 1 │ 30 40 35 30 │\n" - "│ 2 │ 30 40 35 30 │\n" "├─────┼───────────────────────┤\n" + "│ 2 │ 30 40 35 30 │\n" + "╞═════╪═══════════════════════╡\n" "│ SUM │ 130 140 135 130 │\n" - "╰─────┴───────────────────────╯\n" + "└─────┴───────────────────────┘" ) assert text == expected -def test_thin_thick_rounded(): +def test_thin_double_rounded(): text = t2a( header=["#", "G", "H", "R", "S"], body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=styles.thin_thick_rounded, + style=Styles.thin_double_rounded, ) expected = ( "╭─────┬───────────────────────╮\n" "│ # │ G H R S │\n" - "┝━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━┥\n" + "╞═════╪═══════════════════════╡\n" "│ 1 │ 30 40 35 30 │\n" + "├─────┼───────────────────────┤\n" "│ 2 │ 30 40 35 30 │\n" - "┝━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━┥\n" + "╞═════╪═══════════════════════╡\n" "│ SUM │ 130 140 135 130 │\n" - "╰─────┴───────────────────────╯\n" + "╰─────┴───────────────────────╯" + ) + assert text == expected + + +def test_thick(): + text = t2a( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=Styles.thick, + ) + expected = ( + "┏━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓\n" + "┃ # ┃ G H R S ┃\n" + "┣━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━┫\n" + "┃ 1 ┃ 30 40 35 30 ┃\n" + "┣━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━┫\n" + "┃ 2 ┃ 30 40 35 30 ┃\n" + "┣━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━┫\n" + "┃ SUM ┃ 130 140 135 130 ┃\n" + "┗━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━┛" + ) + assert text == expected + + +def test_thick_box(): + text = t2a( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=Styles.thick_box, + ) + expected = ( + "┏━━━━━┳━━━━━┳━━━━━┳━━━━━┳━━━━━┓\n" + "┃ # ┃ G ┃ H ┃ R ┃ S ┃\n" + "┣━━━━━╋━━━━━╋━━━━━╋━━━━━╋━━━━━┫\n" + "┃ 1 ┃ 30 ┃ 40 ┃ 35 ┃ 30 ┃\n" + "┣━━━━━╋━━━━━╋━━━━━╋━━━━━╋━━━━━┫\n" + "┃ 2 ┃ 30 ┃ 40 ┃ 35 ┃ 30 ┃\n" + "┣━━━━━╋━━━━━╋━━━━━╋━━━━━╋━━━━━┫\n" + "┃ SUM ┃ 130 ┃ 140 ┃ 135 ┃ 130 ┃\n" + "┗━━━━━┻━━━━━┻━━━━━┻━━━━━┻━━━━━┛" + ) + assert text == expected + + +def test_thick_compact(): + text = t2a( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=Styles.thick_compact, + ) + expected = ( + "┏━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓\n" + "┃ # ┃ G H R S ┃\n" + "┣━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━┫\n" + "┃ 1 ┃ 30 40 35 30 ┃\n" + "┃ 2 ┃ 30 40 35 30 ┃\n" + "┣━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━┫\n" + "┃ SUM ┃ 130 140 135 130 ┃\n" + "┗━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━┛" + ) + assert text == expected + + +def test_double(): + text = t2a( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=Styles.double, + ) + expected = ( + "╔═════╦═══════════════════════╗\n" + "║ # ║ G H R S ║\n" + "╠═════╬═══════════════════════╣\n" + "║ 1 ║ 30 40 35 30 ║\n" + "╠═════╬═══════════════════════╣\n" + "║ 2 ║ 30 40 35 30 ║\n" + "╠═════╬═══════════════════════╣\n" + "║ SUM ║ 130 140 135 130 ║\n" + "╚═════╩═══════════════════════╝" + ) + assert text == expected + + +def test_double_box(): + text = t2a( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=Styles.double_box, + ) + expected = ( + "╔═════╦═════╦═════╦═════╦═════╗\n" + "║ # ║ G ║ H ║ R ║ S ║\n" + "╠═════╬═════╬═════╬═════╬═════╣\n" + "║ 1 ║ 30 ║ 40 ║ 35 ║ 30 ║\n" + "╠═════╬═════╬═════╬═════╬═════╣\n" + "║ 2 ║ 30 ║ 40 ║ 35 ║ 30 ║\n" + "╠═════╬═════╬═════╬═════╬═════╣\n" + "║ SUM ║ 130 ║ 140 ║ 135 ║ 130 ║\n" + "╚═════╩═════╩═════╩═════╩═════╝" + ) + assert text == expected + + +def test_double_compact(): + text = t2a( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=Styles.double_compact, + ) + expected = ( + "╔═════╦═══════════════════════╗\n" + "║ # ║ G H R S ║\n" + "╠═════╬═══════════════════════╣\n" + "║ 1 ║ 30 40 35 30 ║\n" + "║ 2 ║ 30 40 35 30 ║\n" + "╠═════╬═══════════════════════╣\n" + "║ SUM ║ 130 140 135 130 ║\n" + "╚═════╩═══════════════════════╝" + ) + assert text == expected + + +def test_double_thin_compact(): + text = t2a( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=Styles.double_thin_compact, + ) + expected = ( + "╔═════╦═══════════════════════╗\n" + "║ # ║ G H R S ║\n" + "╟─────╫───────────────────────╢\n" + "║ 1 ║ 30 40 35 30 ║\n" + "║ 2 ║ 30 40 35 30 ║\n" + "╟─────╫───────────────────────╢\n" + "║ SUM ║ 130 140 135 130 ║\n" + "╚═════╩═══════════════════════╝" + ) + assert text == expected + + +def test_minimalist(): + text = t2a( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=Styles.minimalist, + ) + expected = ( + " ───────────────────────────── \n" + " # │ G H R S \n" + " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ \n" + " 1 │ 30 40 35 30 \n" + " ───────────────────────────── \n" + " 2 │ 30 40 35 30 \n" + " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ \n" + " SUM │ 130 140 135 130 \n" + " ───────────────────────────── " + ) + assert text == expected + + +def test_borderless(): + text = t2a( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=Styles.borderless, + ) + expected = ( + " # ┃ G H R S \n" + " ━━━━━ ━━━━━ ━━━━━ ━━━━━ ━━━━━ \n" + " 1 ┃ 30 40 35 30 \n" + " 2 ┃ 30 40 35 30 \n" + " ━━━━━ ━━━━━ ━━━━━ ━━━━━ ━━━━━ \n" + " SUM ┃ 130 140 135 130 " + ) + assert text == expected + + +def test_simple(): + text = t2a( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=Styles.simple, + ) + expected = ( + " ═════ ═════ ═════ ═════ ═════ \n" + " # │ G H R S \n" + " ═════ ═════ ═════ ═════ ═════ \n" + " 1 │ 30 40 35 30 \n" + " 2 │ 30 40 35 30 \n" + " ═════ ═════ ═════ ═════ ═════ \n" + " SUM │ 130 140 135 130 \n" + " ═════ ═════ ═════ ═════ ═════ " + ) + assert text == expected + + +def test_ascii(): + text = t2a( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=Styles.ascii, + ) + expected = ( + "+-----+-----------------------+\n" + "| # | G H R S |\n" + "+-----+-----------------------+\n" + "| 1 | 30 40 35 30 |\n" + "+-----+-----------------------+\n" + "| 2 | 30 40 35 30 |\n" + "+-----+-----------------------+\n" + "| SUM | 130 140 135 130 |\n" + "+-----+-----------------------+" + ) + assert text == expected + + +def test_ascii_box(): + text = t2a( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=Styles.ascii_box, + ) + expected = ( + "+-----+-----+-----+-----+-----+\n" + "| # | G | H | R | S |\n" + "+-----+-----+-----+-----+-----+\n" + "| 1 | 30 | 40 | 35 | 30 |\n" + "+-----+-----+-----+-----+-----+\n" + "| 2 | 30 | 40 | 35 | 30 |\n" + "+-----+-----+-----+-----+-----+\n" + "| SUM | 130 | 140 | 135 | 130 |\n" + "+-----+-----+-----+-----+-----+" + ) + assert text == expected + + +def test_ascii_compact(): + text = t2a( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=Styles.ascii_compact, + ) + expected = ( + "+-----+-----------------------+\n" + "| # | G H R S |\n" + "+-----+-----------------------+\n" + "| 1 | 30 40 35 30 |\n" + "| 2 | 30 40 35 30 |\n" + "+-----+-----------------------+\n" + "| SUM | 130 140 135 130 |\n" + "+-----+-----------------------+" + ) + assert text == expected + + +def test_ascii_double(): + text = t2a( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=Styles.ascii_double, + ) + expected = ( + "+-----+-----------------------+\n" + "| # | G H R S |\n" + "+=====+=======================+\n" + "| 1 | 30 40 35 30 |\n" + "+-----+-----------------------+\n" + "| 2 | 30 40 35 30 |\n" + "+=====+=======================+\n" + "| SUM | 130 140 135 130 |\n" + "+-----+-----------------------+" + ) + assert text == expected + + +def test_ascii_minimalist(): + text = t2a( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=Styles.ascii_minimalist, + ) + expected = ( + " ----------------------------- \n" + " # | G H R S \n" + " ============================= \n" + " 1 | 30 40 35 30 \n" + " ----------------------------- \n" + " 2 | 30 40 35 30 \n" + " ============================= \n" + " SUM | 130 140 135 130 \n" + " ----------------------------- " + ) + assert text == expected + + +def test_ascii_borderless(): + text = t2a( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=Styles.ascii_borderless, + ) + expected = ( + " # | G H R S \n" + " ----- ----- ----- ----- ----- \n" + " 1 | 30 40 35 30 \n" + " 2 | 30 40 35 30 \n" + " ----- ----- ----- ----- ----- \n" + " SUM | 130 140 135 130 " + ) + assert text == expected + + +def test_ascii_simple(): + text = t2a( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=Styles.ascii_simple, + ) + expected = ( + " ===== ===== ===== ===== ===== \n" + " # | G H R S \n" + " ===== ===== ===== ===== ===== \n" + " 1 | 30 40 35 30 \n" + " 2 | 30 40 35 30 \n" + " ===== ===== ===== ===== ===== \n" + " SUM | 130 140 135 130 \n" + " ===== ===== ===== ===== ===== " + ) + assert text == expected + + +def test_markdown(): + text = t2a( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + first_col_heading=True, + last_col_heading=False, + style=Styles.markdown, + ) + expected = ( + "| # | G | H | R | S |\n" + "|-----|-----|-----|-----|-----|\n" + "| 1 | 30 | 40 | 35 | 30 |\n" + "| 2 | 30 | 40 | 35 | 30 |\n" + "|-----|-----|-----|-----|-----|\n" + "| SUM | 130 | 140 | 135 | 130 |" ) assert text == expected From 0f8dc269c709427f789edf0b7171c2333d488f73 Mon Sep 17 00:00:00 2001 From: Jonah Lawrence Date: Thu, 29 Apr 2021 08:07:05 +0300 Subject: [PATCH 10/22] Added example to readme --- README.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/README.md b/README.md index f73ba81..5bbfaf1 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ Module for converting 2D Python lists to a fancy ASCII/Unicode tables - [table2ascii](#table2ascii) - [📥 Installation](#-installation) - [🧑‍💻 Usage](#-usage) + - [🎨 Styles](#-styles) - [⚙️ Options](#️-options) - [👨‍🎨 Use cases](#-use-cases) - [Discord messages and embeds](#discord-messages-and-embeds) @@ -90,6 +91,35 @@ print(output) """ ``` +```py +from table2ascii import table2ascii, Styles + +output = table2ascii( + header=["#", "G", "H", "R", "S"], + body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], + footer=["SUM", "130", "140", "135", "130"], + style=Styles.ascii_box, +) + +print(output) + +""" ++-----+-----+-----+-----+-----+ +| # | G | H | R | S | ++-----+-----+-----+-----+-----+ +| 1 | 30 | 40 | 35 | 30 | ++-----+-----+-----+-----+-----+ +| 2 | 30 | 40 | 35 | 30 | ++-----+-----+-----+-----+-----+ +| SUM | 130 | 140 | 135 | 130 | ++-----+-----+-----+-----+-----+ +""" +``` + +## 🎨 Styles + +See a list of all preset styles [here](/style_list). + ## ⚙️ Options All parameters are optional. From 939ece4976ee705675f8abbb8bf4efc970f2ccc2 Mon Sep 17 00:00:00 2001 From: Jonah Lawrence Date: Thu, 29 Apr 2021 08:07:18 +0300 Subject: [PATCH 11/22] bump to 0.1.0 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index fec0b7c..c833cd2 100644 --- a/setup.py +++ b/setup.py @@ -59,7 +59,7 @@ def run(self): setup( name="table2ascii", - version="0.0.3", + version="0.1.0", author="Jonah Lawrence", author_email="jonah@freshidea.com", description="Convert 2D Python lists into Unicode/Ascii tables", From c974bc3ec3d91dce01f85838fa4ffbbee1bf1254 Mon Sep 17 00:00:00 2001 From: Jonah Lawrence Date: Thu, 29 Apr 2021 08:11:30 +0300 Subject: [PATCH 12/22] Double column in simple theme --- table2ascii/styles.py | 2 +- tests/test_styles.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/table2ascii/styles.py b/table2ascii/styles.py index 89f2923..181803d 100644 --- a/table2ascii/styles.py +++ b/table2ascii/styles.py @@ -22,7 +22,7 @@ class Styles: double_thin_compact = TableStyle.from_string("╔═╦═╗║║ ╟─╫─╢ ╚╩═╝") minimalist = TableStyle.from_string(" ─── │ ━━━ ─── ── ") borderless = TableStyle.from_string(" ┃ ━ ") - simple = TableStyle.from_string(" ═ │ ═ ") + simple = TableStyle.from_string(" ═ ║ ═ ") ascii = TableStyle.from_string("+-+-+|| +-+-++-+-+++-+") ascii_box = TableStyle.from_string("+-+++|||+-++++-+++++++") ascii_compact = TableStyle.from_string("+-+-+|| +-+-+ ++-+") diff --git a/tests/test_styles.py b/tests/test_styles.py index 970cce6..1f645b4 100644 --- a/tests/test_styles.py +++ b/tests/test_styles.py @@ -418,12 +418,12 @@ def test_simple(): ) expected = ( " ═════ ═════ ═════ ═════ ═════ \n" - " # │ G H R S \n" + " # ║ G H R S \n" " ═════ ═════ ═════ ═════ ═════ \n" - " 1 │ 30 40 35 30 \n" - " 2 │ 30 40 35 30 \n" + " 1 ║ 30 40 35 30 \n" + " 2 ║ 30 40 35 30 \n" " ═════ ═════ ═════ ═════ ═════ \n" - " SUM │ 130 140 135 130 \n" + " SUM ║ 130 140 135 130 \n" " ═════ ═════ ═════ ═════ ═════ " ) assert text == expected From 1d30d3aa0bde381331829631b452fc99b04fd931 Mon Sep 17 00:00:00 2001 From: Jonah Lawrence Date: Thu, 29 Apr 2021 08:12:15 +0300 Subject: [PATCH 13/22] Double column in simple theme --- style_list/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/style_list/README.md b/style_list/README.md index 3efc9c0..34f5e11 100644 --- a/style_list/README.md +++ b/style_list/README.md @@ -330,17 +330,17 @@ ``` ═════ ═════ ═════ ═════ ═════ - # │ G H R S + # ║ G H R S ═════ ═════ ═════ ═════ ═════ - 1 │ 30 40 35 30 - 2 │ 30 40 35 30 + 1 ║ 30 40 35 30 + 2 ║ 30 40 35 30 ═════ ═════ ═════ ═════ ═════ - SUM │ 130 140 135 130 + SUM ║ 130 140 135 130 ═════ ═════ ═════ ═════ ═════ ═══ ════ ════ ════ ════ - 1 │ 30 40 35 30 - 2 │ 30 40 35 30 + 1 ║ 30 40 35 30 + 2 ║ 30 40 35 30 ═══ ════ ════ ════ ════ ``` ### `ascii` From e71e55b7910a589cd44f20e01b29c828e4800c7f Mon Sep 17 00:00:00 2001 From: Jonah Lawrence Date: Thu, 29 Apr 2021 08:14:11 +0300 Subject: [PATCH 14/22] Newline in table --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 5bbfaf1..db37df3 100644 --- a/README.md +++ b/README.md @@ -126,15 +126,15 @@ All parameters are optional. Soon table2ascii will support more options for customization. -| Option | Type | Default | Description | -| :-----------------: | :-------: | :----------: | :------------------------------------------------------------------------------------: | -| `header` | `List` | `None` | First row of table seperated by header row seperator | -| `body` | `2D List` | `None` | List of rows for the main section of the table | -| `footer` | `List` | `None` | Last row of table seperated by header row seperator | -| `column_widths` | `List` | automatic | List of column widths in characters for each column | -| `alignments` | `List` | all centered | Alignments for each column (ex. `[Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT]`) | -| `first_col_heading` | `bool` | `False` | Whether to add a heading column seperator after the first column | -| `last_col_heading` | `bool` | `False` | Whether to add a heading column seperator before the last column | +| Option | Type | Default | Description | +| :-----------------: | :-------: | :----------: | :----------------------------------------------------------------------------------------: | +| `header` | `List` | `None` | First row of table seperated by header row seperator | +| `body` | `2D List` | `None` | List of rows for the main section of the table | +| `footer` | `List` | `None` | Last row of table seperated by header row seperator | +| `column_widths` | `List` | automatic | List of column widths in characters for each column | +| `alignments` | `List` | all centered | Alignments for each column
(ex. `[Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT]`) | +| `first_col_heading` | `bool` | `False` | Whether to add a heading column seperator after the first column | +| `last_col_heading` | `bool` | `False` | Whether to add a heading column seperator before the last column | ## 👨‍🎨 Use cases From f04d1338b0dc8defd0730b19795113bd79219254 Mon Sep 17 00:00:00 2001 From: Jonah Lawrence Date: Thu, 29 Apr 2021 08:16:00 +0300 Subject: [PATCH 15/22] More specific types --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index db37df3..38d32c5 100644 --- a/README.md +++ b/README.md @@ -126,15 +126,15 @@ All parameters are optional. Soon table2ascii will support more options for customization. -| Option | Type | Default | Description | -| :-----------------: | :-------: | :----------: | :----------------------------------------------------------------------------------------: | -| `header` | `List` | `None` | First row of table seperated by header row seperator | -| `body` | `2D List` | `None` | List of rows for the main section of the table | -| `footer` | `List` | `None` | Last row of table seperated by header row seperator | -| `column_widths` | `List` | automatic | List of column widths in characters for each column | -| `alignments` | `List` | all centered | Alignments for each column
(ex. `[Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT]`) | -| `first_col_heading` | `bool` | `False` | Whether to add a heading column seperator after the first column | -| `last_col_heading` | `bool` | `False` | Whether to add a heading column seperator before the last column | +| Option | Type | Default | Description | +| :-----------------: | :---------------: | :----------: | :----------------------------------------------------------------------------------------: | +| `header` | `List[str]` | `None` | First row of table seperated by header row seperator | +| `body` | `List[List[str]]` | `None` | `None` | List of rows for the main section of the table | +| `footer` | `List[str]` | `None` | Last row of table seperated by header row seperator | +| `column_widths` | `List[int]` | automatic | List of column widths in characters for each column | +| `alignments` | `List[int]` | all centered | Alignments for each column
(ex. `[Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT]`) | +| `first_col_heading` | `bool` | `False` | Whether to add a heading column seperator after the first column | +| `last_col_heading` | `bool` | `False` | Whether to add a heading column seperator before the last column | ## 👨‍🎨 Use cases From 209ad8d082d0c67e39f851f972d33de496c86644 Mon Sep 17 00:00:00 2001 From: Jonah Lawrence Date: Thu, 29 Apr 2021 08:54:58 +0300 Subject: [PATCH 16/22] Updated readme example --- README.md | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 38d32c5..8bd1122 100644 --- a/README.md +++ b/README.md @@ -95,24 +95,22 @@ print(output) from table2ascii import table2ascii, Styles output = table2ascii( - header=["#", "G", "H", "R", "S"], - body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]], - footer=["SUM", "130", "140", "135", "130"], - style=Styles.ascii_box, + header=["First", "Second", "Third", "Fourth"], + body=[["10", "30", "40", "35"], ["20", "10", "20", "5"]], + column_widths=[10] * 4, + style=Styles.ascii_box ) print(output) """ -+-----+-----+-----+-----+-----+ -| # | G | H | R | S | -+-----+-----+-----+-----+-----+ -| 1 | 30 | 40 | 35 | 30 | -+-----+-----+-----+-----+-----+ -| 2 | 30 | 40 | 35 | 30 | -+-----+-----+-----+-----+-----+ -| SUM | 130 | 140 | 135 | 130 | -+-----+-----+-----+-----+-----+ ++----------+----------+----------+----------+ +| First | Second | Third | Fourth | ++----------+----------+----------+----------+ +| 10 | 30 | 40 | 35 | ++----------+----------+----------+----------+ +| 20 | 10 | 20 | 5 | ++----------+----------+----------+----------+ """ ``` From 04f25a95b21a6aee65488f18ff6b9803978c5f0d Mon Sep 17 00:00:00 2001 From: Jonah Lawrence Date: Thu, 29 Apr 2021 08:55:24 +0300 Subject: [PATCH 17/22] check column widths too small compared to min --- table2ascii/table_to_ascii.py | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/table2ascii/table_to_ascii.py b/table2ascii/table_to_ascii.py index e18766f..fcfc813 100644 --- a/table2ascii/table_to_ascii.py +++ b/table2ascii/table_to_ascii.py @@ -33,18 +33,22 @@ def __init__(self, header: List, body: List[List], footer: List, options: Option ) # calculate or use given column widths - self.__column_widths = options.column_widths or self.__auto_column_widths() - - # check if column widths specified have a different number of columns - if options.column_widths and len(options.column_widths) != self.__columns: - raise ValueError( - "Length of `column_widths` list must equal the number of columns" - ) - # check if column widths are not all at least 2 - if options.column_widths and min(options.column_widths) < 2: - raise ValueError( - "All values in `column_widths` must be greater than or equal to 2" - ) + self.__column_widths = self.__auto_column_widths() + if options.column_widths: + # check that the right number of columns were specified + if len(options.column_widths) != self.__columns: + raise ValueError( + "Length of `column_widths` list must equal the number of columns" + ) + # check that each column is at least as large as the minimum size + for i in range(len(options.column_widths)): + option = options.column_widths[i] + minimum = self.__column_widths[i] + if 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.__alignments = options.alignments or [Alignment.CENTER] * self.__columns From 31a1c044224dbe35732016dd91e415bc8a669378 Mon Sep 17 00:00:00 2001 From: Jonah Lawrence Date: Thu, 29 Apr 2021 08:55:31 +0300 Subject: [PATCH 18/22] Update test_column_widths.py --- tests/test_column_widths.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/test_column_widths.py b/tests/test_column_widths.py index cfb7534..5ae9ace 100644 --- a/tests/test_column_widths.py +++ b/tests/test_column_widths.py @@ -47,3 +47,15 @@ def test_negative_column_widths(): last_col_heading=True, column_widths=[7, 5, 5, 5, -1], ) + + +def test_column_width_less_than_size(): + with pytest.raises(ValueError): + t2a( + header=["Wide Column", "Another Wide Column", "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=[5, 3, 3, 3, 3], + ) From f8bfd876e6f75061548e69d1ec605a4d2f4da69e Mon Sep 17 00:00:00 2001 From: Jonah Lawrence Date: Thu, 29 Apr 2021 09:22:30 +0300 Subject: [PATCH 19/22] Renamed Styles to PresetStyle and dynamic list generator --- README.md | 8 +- setup.py | 2 +- style_list/README.md | 675 +++++++++++---------- style_list/generate_style_list.py | 48 +- table2ascii/__init__.py | 4 +- table2ascii/options.py | 4 +- table2ascii/{styles.py => preset_style.py} | 2 +- tests/test_styles.py | 56 +- 8 files changed, 406 insertions(+), 393 deletions(-) rename table2ascii/{styles.py => preset_style.py} (99%) diff --git a/README.md b/README.md index 8bd1122..47f1748 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Module for converting 2D Python lists to a fancy ASCII/Unicode tables - [table2ascii](#table2ascii) - [📥 Installation](#-installation) - [🧑‍💻 Usage](#-usage) - - [🎨 Styles](#-styles) + - [🎨 Preset styles](#-preset-styles) - [⚙️ Options](#️-options) - [👨‍🎨 Use cases](#-use-cases) - [Discord messages and embeds](#discord-messages-and-embeds) @@ -92,13 +92,13 @@ print(output) ``` ```py -from table2ascii import table2ascii, Styles +from table2ascii import table2ascii, PresetStyle output = table2ascii( header=["First", "Second", "Third", "Fourth"], body=[["10", "30", "40", "35"], ["20", "10", "20", "5"]], column_widths=[10] * 4, - style=Styles.ascii_box + style=PresetStyle.ascii_box ) print(output) @@ -114,7 +114,7 @@ print(output) """ ``` -## 🎨 Styles +## 🎨 Preset styles See a list of all preset styles [here](/style_list). diff --git a/setup.py b/setup.py index c833cd2..9f146be 100644 --- a/setup.py +++ b/setup.py @@ -59,7 +59,7 @@ def run(self): setup( name="table2ascii", - version="0.1.0", + version="0.1.1", author="Jonah Lawrence", author_email="jonah@freshidea.com", description="Convert 2D Python lists into Unicode/Ascii tables", diff --git a/style_list/README.md b/style_list/README.md index 34f5e11..b92755d 100644 --- a/style_list/README.md +++ b/style_list/README.md @@ -1,247 +1,190 @@ ## Preset styles -### `thin` +- [Preset styles](#preset-styles) + - [`ascii`](#ascii) + - [`ascii_borderless`](#ascii_borderless) + - [`ascii_box`](#ascii_box) + - [`ascii_compact`](#ascii_compact) + - [`ascii_double`](#ascii_double) + - [`ascii_minimalist`](#ascii_minimalist) + - [`ascii_simple`](#ascii_simple) + - [`borderless`](#borderless) + - [`double`](#double) + - [`double_box`](#double_box) + - [`double_compact`](#double_compact) + - [`double_thin_compact`](#double_thin_compact) + - [`markdown`](#markdown) + - [`minimalist`](#minimalist) + - [`simple`](#simple) + - [`thick`](#thick) + - [`thick_box`](#thick_box) + - [`thick_compact`](#thick_compact) + - [`thin`](#thin) + - [`thin_box`](#thin_box) + - [`thin_compact`](#thin_compact) + - [`thin_compact_rounded`](#thin_compact_rounded) + - [`thin_double`](#thin_double) + - [`thin_double_rounded`](#thin_double_rounded) + - [`thin_rounded`](#thin_rounded) + - [`thin_thick`](#thin_thick) + - [`thin_thick_rounded`](#thin_thick_rounded) + +### `ascii` ``` -┌─────┬───────────────────────┐ -│ # │ G H R S │ -├─────┼───────────────────────┤ -│ 1 │ 30 40 35 30 │ -├─────┼───────────────────────┤ -│ 2 │ 30 40 35 30 │ -├─────┼───────────────────────┤ -│ SUM │ 130 140 135 130 │ -└─────┴───────────────────────┘ ++-----+-----------------------+ +| # | G H R S | ++-----+-----------------------+ +| 1 | 30 40 35 30 | ++-----+-----------------------+ +| 2 | 30 40 35 30 | ++-----+-----------------------+ +| SUM | 130 140 135 130 | ++-----+-----------------------+ -┌───┬───────────────────┐ -│ 1 │ 30 40 35 30 │ -├───┼───────────────────┤ -│ 2 │ 30 40 35 30 │ -└───┴───────────────────┘ ++---+-------------------+ +| 1 | 30 40 35 30 | ++---+-------------------+ +| 2 | 30 40 35 30 | ++---+-------------------+ ``` -### `thin_box` +### `ascii_borderless` ``` -┌─────┬─────┬─────┬─────┬─────┐ -│ # │ G │ H │ R │ S │ -├─────┼─────┼─────┼─────┼─────┤ -│ 1 │ 30 │ 40 │ 35 │ 30 │ -├─────┼─────┼─────┼─────┼─────┤ -│ 2 │ 30 │ 40 │ 35 │ 30 │ -├─────┼─────┼─────┼─────┼─────┤ -│ SUM │ 130 │ 140 │ 135 │ 130 │ -└─────┴─────┴─────┴─────┴─────┘ + # | G H R S + ----- ----- ----- ----- ----- + 1 | 30 40 35 30 + 2 | 30 40 35 30 + ----- ----- ----- ----- ----- + SUM | 130 140 135 130 -┌───┬────┬────┬────┬────┐ -│ 1 │ 30 │ 40 │ 35 │ 30 │ -├───┼────┼────┼────┼────┤ -│ 2 │ 30 │ 40 │ 35 │ 30 │ -└───┴────┴────┴────┴────┘ + 1 | 30 40 35 30 + 2 | 30 40 35 30 ``` -### `thin_rounded` +### `ascii_box` ``` -╭─────┬───────────────────────╮ -│ # │ G H R S │ -├─────┼───────────────────────┤ -│ 1 │ 30 40 35 30 │ -├─────┼───────────────────────┤ -│ 2 │ 30 40 35 30 │ -├─────┼───────────────────────┤ -│ SUM │ 130 140 135 130 │ -╰─────┴───────────────────────╯ ++-----+-----+-----+-----+-----+ +| # | G | H | R | S | ++-----+-----+-----+-----+-----+ +| 1 | 30 | 40 | 35 | 30 | ++-----+-----+-----+-----+-----+ +| 2 | 30 | 40 | 35 | 30 | ++-----+-----+-----+-----+-----+ +| SUM | 130 | 140 | 135 | 130 | ++-----+-----+-----+-----+-----+ -╭───┬───────────────────╮ -│ 1 │ 30 40 35 30 │ -├───┼───────────────────┤ -│ 2 │ 30 40 35 30 │ -╰───┴───────────────────╯ ++---+----+----+----+----+ +| 1 | 30 | 40 | 35 | 30 | ++---+----+----+----+----+ +| 2 | 30 | 40 | 35 | 30 | ++---+----+----+----+----+ ``` -### `thin_compact` +### `ascii_compact` ``` -┌─────┬───────────────────────┐ -│ # │ G H R S │ -├─────┼───────────────────────┤ -│ 1 │ 30 40 35 30 │ -│ 2 │ 30 40 35 30 │ -├─────┼───────────────────────┤ -│ SUM │ 130 140 135 130 │ -└─────┴───────────────────────┘ ++-----+-----------------------+ +| # | G H R S | ++-----+-----------------------+ +| 1 | 30 40 35 30 | +| 2 | 30 40 35 30 | ++-----+-----------------------+ +| SUM | 130 140 135 130 | ++-----+-----------------------+ -┌───┬───────────────────┐ -│ 1 │ 30 40 35 30 │ -│ 2 │ 30 40 35 30 │ -└───┴───────────────────┘ ++---+-------------------+ +| 1 | 30 40 35 30 | +| 2 | 30 40 35 30 | ++---+-------------------+ ``` -### `thin_compact_rounded` +### `ascii_double` ``` -╭─────┬───────────────────────╮ -│ # │ G H R S │ -├─────┼───────────────────────┤ -│ 1 │ 30 40 35 30 │ -│ 2 │ 30 40 35 30 │ -├─────┼───────────────────────┤ -│ SUM │ 130 140 135 130 │ -╰─────┴───────────────────────╯ ++-----+-----------------------+ +| # | G H R S | ++=====+=======================+ +| 1 | 30 40 35 30 | ++-----+-----------------------+ +| 2 | 30 40 35 30 | ++=====+=======================+ +| SUM | 130 140 135 130 | ++-----+-----------------------+ -╭───┬───────────────────╮ -│ 1 │ 30 40 35 30 │ -│ 2 │ 30 40 35 30 │ -╰───┴───────────────────╯ ++---+-------------------+ +| 1 | 30 40 35 30 | ++---+-------------------+ +| 2 | 30 40 35 30 | ++---+-------------------+ ``` -### `thin_thick` +### `ascii_minimalist` ``` -┌─────┬───────────────────────┐ -│ # │ G H R S │ -┝━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━┥ -│ 1 │ 30 40 35 30 │ -├─────┼───────────────────────┤ -│ 2 │ 30 40 35 30 │ -┝━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━┥ -│ SUM │ 130 140 135 130 │ -└─────┴───────────────────────┘ + ----------------------------- + # | G H R S + ============================= + 1 | 30 40 35 30 + ----------------------------- + 2 | 30 40 35 30 + ============================= + SUM | 130 140 135 130 + ----------------------------- -┌───┬───────────────────┐ -│ 1 │ 30 40 35 30 │ -├───┼───────────────────┤ -│ 2 │ 30 40 35 30 │ -└───┴───────────────────┘ + ----------------------- + 1 | 30 40 35 30 + ----------------------- + 2 | 30 40 35 30 + ----------------------- ``` -### `thin_thick_rounded` +### `ascii_simple` ``` -╭─────┬───────────────────────╮ -│ # │ G H R S │ -┝━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━┥ -│ 1 │ 30 40 35 30 │ -├─────┼───────────────────────┤ -│ 2 │ 30 40 35 30 │ -┝━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━┥ -│ SUM │ 130 140 135 130 │ -╰─────┴───────────────────────╯ + ===== ===== ===== ===== ===== + # | G H R S + ===== ===== ===== ===== ===== + 1 | 30 40 35 30 + 2 | 30 40 35 30 + ===== ===== ===== ===== ===== + SUM | 130 140 135 130 + ===== ===== ===== ===== ===== -╭───┬───────────────────╮ -│ 1 │ 30 40 35 30 │ -├───┼───────────────────┤ -│ 2 │ 30 40 35 30 │ -╰───┴───────────────────╯ + === ==== ==== ==== ==== + 1 | 30 40 35 30 + 2 | 30 40 35 30 + === ==== ==== ==== ==== ``` -### `thin_double` +### `borderless` ``` -┌─────┬───────────────────────┐ -│ # │ G H R S │ -╞═════╪═══════════════════════╡ -│ 1 │ 30 40 35 30 │ -├─────┼───────────────────────┤ -│ 2 │ 30 40 35 30 │ -╞═════╪═══════════════════════╡ -│ SUM │ 130 140 135 130 │ -└─────┴───────────────────────┘ + # ┃ G H R S + ━━━━━ ━━━━━ ━━━━━ ━━━━━ ━━━━━ + 1 ┃ 30 40 35 30 + 2 ┃ 30 40 35 30 + ━━━━━ ━━━━━ ━━━━━ ━━━━━ ━━━━━ + SUM ┃ 130 140 135 130 -┌───┬───────────────────┐ -│ 1 │ 30 40 35 30 │ -├───┼───────────────────┤ -│ 2 │ 30 40 35 30 │ -└───┴───────────────────┘ + 1 ┃ 30 40 35 30 + 2 ┃ 30 40 35 30 ``` -### `thin_double_rounded` +### `double` ``` -╭─────┬───────────────────────╮ -│ # │ G H R S │ -╞═════╪═══════════════════════╡ -│ 1 │ 30 40 35 30 │ -├─────┼───────────────────────┤ -│ 2 │ 30 40 35 30 │ -╞═════╪═══════════════════════╡ -│ SUM │ 130 140 135 130 │ -╰─────┴───────────────────────╯ +╔═════╦═══════════════════════╗ +║ # ║ G H R S ║ +╠═════╬═══════════════════════╣ +║ 1 ║ 30 40 35 30 ║ +╠═════╬═══════════════════════╣ +║ 2 ║ 30 40 35 30 ║ +╠═════╬═══════════════════════╣ +║ SUM ║ 130 140 135 130 ║ +╚═════╩═══════════════════════╝ -╭───┬───────────────────╮ -│ 1 │ 30 40 35 30 │ -├───┼───────────────────┤ -│ 2 │ 30 40 35 30 │ -╰───┴───────────────────╯ +╔═══╦═══════════════════╗ +║ 1 ║ 30 40 35 30 ║ +╠═══╬═══════════════════╣ +║ 2 ║ 30 40 35 30 ║ +╚═══╩═══════════════════╝ ``` -### `thick` - -``` -┏━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓ -┃ # ┃ G H R S ┃ -┣━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━┫ -┃ 1 ┃ 30 40 35 30 ┃ -┣━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━┫ -┃ 2 ┃ 30 40 35 30 ┃ -┣━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━┫ -┃ SUM ┃ 130 140 135 130 ┃ -┗━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━┛ - -┏━━━┳━━━━━━━━━━━━━━━━━━━┓ -┃ 1 ┃ 30 40 35 30 ┃ -┣━━━╋━━━━━━━━━━━━━━━━━━━┫ -┃ 2 ┃ 30 40 35 30 ┃ -┗━━━┻━━━━━━━━━━━━━━━━━━━┛ -``` -### `thick_box` - -``` -┏━━━━━┳━━━━━┳━━━━━┳━━━━━┳━━━━━┓ -┃ # ┃ G ┃ H ┃ R ┃ S ┃ -┣━━━━━╋━━━━━╋━━━━━╋━━━━━╋━━━━━┫ -┃ 1 ┃ 30 ┃ 40 ┃ 35 ┃ 30 ┃ -┣━━━━━╋━━━━━╋━━━━━╋━━━━━╋━━━━━┫ -┃ 2 ┃ 30 ┃ 40 ┃ 35 ┃ 30 ┃ -┣━━━━━╋━━━━━╋━━━━━╋━━━━━╋━━━━━┫ -┃ SUM ┃ 130 ┃ 140 ┃ 135 ┃ 130 ┃ -┗━━━━━┻━━━━━┻━━━━━┻━━━━━┻━━━━━┛ - -┏━━━┳━━━━┳━━━━┳━━━━┳━━━━┓ -┃ 1 ┃ 30 ┃ 40 ┃ 35 ┃ 30 ┃ -┣━━━╋━━━━╋━━━━╋━━━━╋━━━━┫ -┃ 2 ┃ 30 ┃ 40 ┃ 35 ┃ 30 ┃ -┗━━━┻━━━━┻━━━━┻━━━━┻━━━━┛ -``` -### `thick_compact` - -``` -┏━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓ -┃ # ┃ G H R S ┃ -┣━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━┫ -┃ 1 ┃ 30 40 35 30 ┃ -┃ 2 ┃ 30 40 35 30 ┃ -┣━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━┫ -┃ SUM ┃ 130 140 135 130 ┃ -┗━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━┛ - -┏━━━┳━━━━━━━━━━━━━━━━━━━┓ -┃ 1 ┃ 30 40 35 30 ┃ -┃ 2 ┃ 30 40 35 30 ┃ -┗━━━┻━━━━━━━━━━━━━━━━━━━┛ -``` -### `double` - -``` -╔═════╦═══════════════════════╗ -║ # ║ G H R S ║ -╠═════╬═══════════════════════╣ -║ 1 ║ 30 40 35 30 ║ -╠═════╬═══════════════════════╣ -║ 2 ║ 30 40 35 30 ║ -╠═════╬═══════════════════════╣ -║ SUM ║ 130 140 135 130 ║ -╚═════╩═══════════════════════╝ - -╔═══╦═══════════════════╗ -║ 1 ║ 30 40 35 30 ║ -╠═══╬═══════════════════╣ -║ 2 ║ 30 40 35 30 ║ -╚═══╩═══════════════════╝ -``` -### `double_box` +### `double_box` ``` ╔═════╦═════╦═════╦═════╦═════╗ @@ -294,6 +237,19 @@ ║ 2 ║ 30 40 35 30 ║ ╚═══╩═══════════════════╝ ``` +### `markdown` + +``` +| # | G | H | R | S | +| ----- | ----- | ----- | ----- | ----- | +| 1 | 30 | 40 | 35 | 30 | +| 2 | 30 | 40 | 35 | 30 | +| ----- | ----- | ----- | ----- | ----- | +| SUM | 130 | 140 | 135 | 130 | + +| 1 | 30 | 40 | 35 | 30 | +| 2 | 30 | 40 | 35 | 30 | +``` ### `minimalist` ``` @@ -313,19 +269,6 @@ 2 │ 30 40 35 30 ─────────────────────── ``` -### `borderless` - -``` - # ┃ G H R S - ━━━━━ ━━━━━ ━━━━━ ━━━━━ ━━━━━ - 1 ┃ 30 40 35 30 - 2 ┃ 30 40 35 30 - ━━━━━ ━━━━━ ━━━━━ ━━━━━ ━━━━━ - SUM ┃ 130 140 135 130 - - 1 ┃ 30 40 35 30 - 2 ┃ 30 40 35 30 -``` ### `simple` ``` @@ -343,139 +286,225 @@ 2 ║ 30 40 35 30 ═══ ════ ════ ════ ════ ``` -### `ascii` +### `thick` ``` -+-----+-----------------------+ -| # | G H R S | -+-----+-----------------------+ -| 1 | 30 40 35 30 | -+-----+-----------------------+ -| 2 | 30 40 35 30 | -+-----+-----------------------+ -| SUM | 130 140 135 130 | -+-----+-----------------------+ +┏━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓ +┃ # ┃ G H R S ┃ +┣━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━┫ +┃ 1 ┃ 30 40 35 30 ┃ +┣━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━┫ +┃ 2 ┃ 30 40 35 30 ┃ +┣━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━┫ +┃ SUM ┃ 130 140 135 130 ┃ +┗━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━┛ -+---+-------------------+ -| 1 | 30 40 35 30 | -+---+-------------------+ -| 2 | 30 40 35 30 | -+---+-------------------+ +┏━━━┳━━━━━━━━━━━━━━━━━━━┓ +┃ 1 ┃ 30 40 35 30 ┃ +┣━━━╋━━━━━━━━━━━━━━━━━━━┫ +┃ 2 ┃ 30 40 35 30 ┃ +┗━━━┻━━━━━━━━━━━━━━━━━━━┛ ``` -### `ascii_box` +### `thick_box` ``` -+-----+-----+-----+-----+-----+ -| # | G | H | R | S | -+-----+-----+-----+-----+-----+ -| 1 | 30 | 40 | 35 | 30 | -+-----+-----+-----+-----+-----+ -| 2 | 30 | 40 | 35 | 30 | -+-----+-----+-----+-----+-----+ -| SUM | 130 | 140 | 135 | 130 | -+-----+-----+-----+-----+-----+ +┏━━━━━┳━━━━━┳━━━━━┳━━━━━┳━━━━━┓ +┃ # ┃ G ┃ H ┃ R ┃ S ┃ +┣━━━━━╋━━━━━╋━━━━━╋━━━━━╋━━━━━┫ +┃ 1 ┃ 30 ┃ 40 ┃ 35 ┃ 30 ┃ +┣━━━━━╋━━━━━╋━━━━━╋━━━━━╋━━━━━┫ +┃ 2 ┃ 30 ┃ 40 ┃ 35 ┃ 30 ┃ +┣━━━━━╋━━━━━╋━━━━━╋━━━━━╋━━━━━┫ +┃ SUM ┃ 130 ┃ 140 ┃ 135 ┃ 130 ┃ +┗━━━━━┻━━━━━┻━━━━━┻━━━━━┻━━━━━┛ -+---+----+----+----+----+ -| 1 | 30 | 40 | 35 | 30 | -+---+----+----+----+----+ -| 2 | 30 | 40 | 35 | 30 | -+---+----+----+----+----+ +┏━━━┳━━━━┳━━━━┳━━━━┳━━━━┓ +┃ 1 ┃ 30 ┃ 40 ┃ 35 ┃ 30 ┃ +┣━━━╋━━━━╋━━━━╋━━━━╋━━━━┫ +┃ 2 ┃ 30 ┃ 40 ┃ 35 ┃ 30 ┃ +┗━━━┻━━━━┻━━━━┻━━━━┻━━━━┛ ``` -### `ascii_compact` +### `thick_compact` ``` -+-----+-----------------------+ -| # | G H R S | -+-----+-----------------------+ -| 1 | 30 40 35 30 | -| 2 | 30 40 35 30 | -+-----+-----------------------+ -| SUM | 130 140 135 130 | -+-----+-----------------------+ +┏━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓ +┃ # ┃ G H R S ┃ +┣━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━┫ +┃ 1 ┃ 30 40 35 30 ┃ +┃ 2 ┃ 30 40 35 30 ┃ +┣━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━┫ +┃ SUM ┃ 130 140 135 130 ┃ +┗━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━┛ -+---+-------------------+ -| 1 | 30 40 35 30 | -| 2 | 30 40 35 30 | -+---+-------------------+ +┏━━━┳━━━━━━━━━━━━━━━━━━━┓ +┃ 1 ┃ 30 40 35 30 ┃ +┃ 2 ┃ 30 40 35 30 ┃ +┗━━━┻━━━━━━━━━━━━━━━━━━━┛ ``` -### `ascii_double` +### `thin` ``` -+-----+-----------------------+ -| # | G H R S | -+=====+=======================+ -| 1 | 30 40 35 30 | -+-----+-----------------------+ -| 2 | 30 40 35 30 | -+=====+=======================+ -| SUM | 130 140 135 130 | -+-----+-----------------------+ +┌─────┬───────────────────────┐ +│ # │ G H R S │ +├─────┼───────────────────────┤ +│ 1 │ 30 40 35 30 │ +├─────┼───────────────────────┤ +│ 2 │ 30 40 35 30 │ +├─────┼───────────────────────┤ +│ SUM │ 130 140 135 130 │ +└─────┴───────────────────────┘ -+---+-------------------+ -| 1 | 30 40 35 30 | -+---+-------------------+ -| 2 | 30 40 35 30 | -+---+-------------------+ +┌───┬───────────────────┐ +│ 1 │ 30 40 35 30 │ +├───┼───────────────────┤ +│ 2 │ 30 40 35 30 │ +└───┴───────────────────┘ ``` -### `ascii_minimalist` +### `thin_box` ``` - ----------------------------- - # | G H R S - ============================= - 1 | 30 40 35 30 - ----------------------------- - 2 | 30 40 35 30 - ============================= - SUM | 130 140 135 130 - ----------------------------- +┌─────┬─────┬─────┬─────┬─────┐ +│ # │ G │ H │ R │ S │ +├─────┼─────┼─────┼─────┼─────┤ +│ 1 │ 30 │ 40 │ 35 │ 30 │ +├─────┼─────┼─────┼─────┼─────┤ +│ 2 │ 30 │ 40 │ 35 │ 30 │ +├─────┼─────┼─────┼─────┼─────┤ +│ SUM │ 130 │ 140 │ 135 │ 130 │ +└─────┴─────┴─────┴─────┴─────┘ - ----------------------- - 1 | 30 40 35 30 - ----------------------- - 2 | 30 40 35 30 - ----------------------- +┌───┬────┬────┬────┬────┐ +│ 1 │ 30 │ 40 │ 35 │ 30 │ +├───┼────┼────┼────┼────┤ +│ 2 │ 30 │ 40 │ 35 │ 30 │ +└───┴────┴────┴────┴────┘ ``` -### `ascii_borderless` +### `thin_compact` ``` - # | G H R S - ----- ----- ----- ----- ----- - 1 | 30 40 35 30 - 2 | 30 40 35 30 - ----- ----- ----- ----- ----- - SUM | 130 140 135 130 +┌─────┬───────────────────────┐ +│ # │ G H R S │ +├─────┼───────────────────────┤ +│ 1 │ 30 40 35 30 │ +│ 2 │ 30 40 35 30 │ +├─────┼───────────────────────┤ +│ SUM │ 130 140 135 130 │ +└─────┴───────────────────────┘ - 1 | 30 40 35 30 - 2 | 30 40 35 30 +┌───┬───────────────────┐ +│ 1 │ 30 40 35 30 │ +│ 2 │ 30 40 35 30 │ +└───┴───────────────────┘ ``` -### `ascii_simple` +### `thin_compact_rounded` ``` - ===== ===== ===== ===== ===== - # | G H R S - ===== ===== ===== ===== ===== - 1 | 30 40 35 30 - 2 | 30 40 35 30 - ===== ===== ===== ===== ===== - SUM | 130 140 135 130 - ===== ===== ===== ===== ===== +╭─────┬───────────────────────╮ +│ # │ G H R S │ +├─────┼───────────────────────┤ +│ 1 │ 30 40 35 30 │ +│ 2 │ 30 40 35 30 │ +├─────┼───────────────────────┤ +│ SUM │ 130 140 135 130 │ +╰─────┴───────────────────────╯ - === ==== ==== ==== ==== - 1 | 30 40 35 30 - 2 | 30 40 35 30 - === ==== ==== ==== ==== +╭───┬───────────────────╮ +│ 1 │ 30 40 35 30 │ +│ 2 │ 30 40 35 30 │ +╰───┴───────────────────╯ ``` -### `markdown` +### `thin_double` ``` -| # | G | H | R | S | -|-----|-----|-----|-----|-----| -| 1 | 30 | 40 | 35 | 30 | -| 2 | 30 | 40 | 35 | 30 | -|-----|-----|-----|-----|-----| -| SUM | 130 | 140 | 135 | 130 | +┌─────┬───────────────────────┐ +│ # │ G H R S │ +╞═════╪═══════════════════════╡ +│ 1 │ 30 40 35 30 │ +├─────┼───────────────────────┤ +│ 2 │ 30 40 35 30 │ +╞═════╪═══════════════════════╡ +│ SUM │ 130 140 135 130 │ +└─────┴───────────────────────┘ -| 1 | 30 | 40 | 35 | 30 | -| 2 | 30 | 40 | 35 | 30 | +┌───┬───────────────────┐ +│ 1 │ 30 40 35 30 │ +├───┼───────────────────┤ +│ 2 │ 30 40 35 30 │ +└───┴───────────────────┘ +``` +### `thin_double_rounded` + +``` +╭─────┬───────────────────────╮ +│ # │ G H R S │ +╞═════╪═══════════════════════╡ +│ 1 │ 30 40 35 30 │ +├─────┼───────────────────────┤ +│ 2 │ 30 40 35 30 │ +╞═════╪═══════════════════════╡ +│ SUM │ 130 140 135 130 │ +╰─────┴───────────────────────╯ + +╭───┬───────────────────╮ +│ 1 │ 30 40 35 30 │ +├───┼───────────────────┤ +│ 2 │ 30 40 35 30 │ +╰───┴───────────────────╯ +``` +### `thin_rounded` + +``` +╭─────┬───────────────────────╮ +│ # │ G H R S │ +├─────┼───────────────────────┤ +│ 1 │ 30 40 35 30 │ +├─────┼───────────────────────┤ +│ 2 │ 30 40 35 30 │ +├─────┼───────────────────────┤ +│ SUM │ 130 140 135 130 │ +╰─────┴───────────────────────╯ + +╭───┬───────────────────╮ +│ 1 │ 30 40 35 30 │ +├───┼───────────────────┤ +│ 2 │ 30 40 35 30 │ +╰───┴───────────────────╯ +``` +### `thin_thick` + +``` +┌─────┬───────────────────────┐ +│ # │ G H R S │ +┝━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━┥ +│ 1 │ 30 40 35 30 │ +├─────┼───────────────────────┤ +│ 2 │ 30 40 35 30 │ +┝━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━┥ +│ SUM │ 130 140 135 130 │ +└─────┴───────────────────────┘ + +┌───┬───────────────────┐ +│ 1 │ 30 40 35 30 │ +├───┼───────────────────┤ +│ 2 │ 30 40 35 30 │ +└───┴───────────────────┘ +``` +### `thin_thick_rounded` + +``` +╭─────┬───────────────────────╮ +│ # │ G H R S │ +┝━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━┥ +│ 1 │ 30 40 35 30 │ +├─────┼───────────────────────┤ +│ 2 │ 30 40 35 30 │ +┝━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━┥ +│ SUM │ 130 140 135 130 │ +╰─────┴───────────────────────╯ + +╭───┬───────────────────╮ +│ 1 │ 30 40 35 30 │ +├───┼───────────────────┤ +│ 2 │ 30 40 35 30 │ +╰───┴───────────────────╯ ``` diff --git a/style_list/generate_style_list.py b/style_list/generate_style_list.py index 8554220..150c32a 100644 --- a/style_list/generate_style_list.py +++ b/style_list/generate_style_list.py @@ -1,39 +1,19 @@ import os -from table2ascii import Styles +from table2ascii import PresetStyle from table2ascii.table_to_ascii import table2ascii # generate README.md containing all themes with previews if __name__ == "__main__": - styles = { - "thin": Styles.thin, - "thin_box": Styles.thin_box, - "thin_rounded": Styles.thin_rounded, - "thin_compact": Styles.thin_compact, - "thin_compact_rounded": Styles.thin_compact_rounded, - "thin_thick": Styles.thin_thick, - "thin_thick_rounded": Styles.thin_thick_rounded, - "thin_double": Styles.thin_double, - "thin_double_rounded": Styles.thin_double_rounded, - "thick": Styles.thick, - "thick_box": Styles.thick_box, - "thick_compact": Styles.thick_compact, - "double": Styles.double, - "double_box": Styles.double_box, - "double_compact": Styles.double_compact, - "double_thin_compact": Styles.double_thin_compact, - "minimalist": Styles.minimalist, - "borderless": Styles.borderless, - "simple": Styles.simple, - "ascii": Styles.ascii, - "ascii_box": Styles.ascii_box, - "ascii_compact": Styles.ascii_compact, - "ascii_double": Styles.ascii_double, - "ascii_minimalist": Styles.ascii_minimalist, - "ascii_borderless": Styles.ascii_borderless, - "ascii_simple": Styles.ascii_simple, - "markdown": Styles.markdown, - } - output = "## Preset styles\n\n" + # get attributes in PresetStyle + attribute_names = [attr for attr in dir(PresetStyle) if not attr.startswith("__")] + attributes = [getattr(PresetStyle, attr) for attr in attribute_names] + # make a dict mapping style names to TableStyles + styles = dict(zip(attribute_names, attributes)) + # README output variables + heading = "## Preset styles" + table_of_contents = "- [Preset styles](#preset-styles)\n" + style_list = "" + # generate tables for each style for style in list(styles.keys()): full = table2ascii( header=["#", "G", "H", "R", "S"], @@ -49,8 +29,12 @@ last_col_heading=False, style=styles[style], ) - output += f"### `{style}`\n\n```\n{full}\n\n{body_only}\n```\n" + table_of_contents += f" - [`{style}`](#{style})\n" + style_list += f"### `{style}`\n\n```\n{full}\n\n{body_only}\n```\n" + # put it all together + output = f"{heading}\n\n{table_of_contents}\n{style_list}" + # overwrite `style_list/README.md` with the changes f = open(os.path.join("style_list", "README.md"), "w") f.write(output) f.close() diff --git a/table2ascii/__init__.py b/table2ascii/__init__.py index a7b945d..fd73c98 100644 --- a/table2ascii/__init__.py +++ b/table2ascii/__init__.py @@ -1,5 +1,5 @@ from .alignment import Alignment -from .styles import Styles +from .preset_style import PresetStyle from .table_style import TableStyle from .table_to_ascii import table2ascii @@ -7,5 +7,5 @@ "table2ascii", "Alignment", "TableStyle", - "Styles", + "PresetStyle", ] diff --git a/table2ascii/options.py b/table2ascii/options.py index 8423e56..9b2b258 100644 --- a/table2ascii/options.py +++ b/table2ascii/options.py @@ -1,7 +1,7 @@ from dataclasses import dataclass from typing import List, Optional -from .styles import Styles +from .preset_style import PresetStyle from .alignment import Alignment from .table_style import TableStyle @@ -17,4 +17,4 @@ class Options: last_col_heading: bool = False column_widths: Optional[List[int]] = None alignments: Optional[List[Alignment]] = None - style: TableStyle = Styles.double_thin_compact + style: TableStyle = PresetStyle.double_thin_compact diff --git a/table2ascii/styles.py b/table2ascii/preset_style.py similarity index 99% rename from table2ascii/styles.py rename to table2ascii/preset_style.py index 181803d..71b518e 100644 --- a/table2ascii/styles.py +++ b/table2ascii/preset_style.py @@ -1,7 +1,7 @@ from .table_style import TableStyle -class Styles: +class PresetStyle: """Importable preset styles for more easily selecting a table style""" thin = TableStyle.from_string("┌─┬─┐││ ├─┼─┤├─┼─┤└┴─┘") diff --git a/tests/test_styles.py b/tests/test_styles.py index 1f645b4..0e8a553 100644 --- a/tests/test_styles.py +++ b/tests/test_styles.py @@ -1,4 +1,4 @@ -from table2ascii import table2ascii as t2a, Styles +from table2ascii import table2ascii as t2a, PresetStyle def test_thin(): @@ -8,7 +8,7 @@ def test_thin(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=Styles.thin, + style=PresetStyle.thin, ) expected = ( "┌─────┬───────────────────────┐\n" @@ -31,7 +31,7 @@ def test_thin_box(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=Styles.thin_box, + style=PresetStyle.thin_box, ) expected = ( "┌─────┬─────┬─────┬─────┬─────┐\n" @@ -54,7 +54,7 @@ def test_thin_rounded(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=Styles.thin_rounded, + style=PresetStyle.thin_rounded, ) expected = ( "╭─────┬───────────────────────╮\n" @@ -77,7 +77,7 @@ def test_thin_compact(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=Styles.thin_compact, + style=PresetStyle.thin_compact, ) expected = ( "┌─────┬───────────────────────┐\n" @@ -99,7 +99,7 @@ def test_thin_compact_rounded(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=Styles.thin_compact_rounded, + style=PresetStyle.thin_compact_rounded, ) expected = ( "╭─────┬───────────────────────╮\n" @@ -121,7 +121,7 @@ def test_thin_thick(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=Styles.thin_thick, + style=PresetStyle.thin_thick, ) expected = ( "┌─────┬───────────────────────┐\n" @@ -144,7 +144,7 @@ def test_thin_thick_rounded(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=Styles.thin_thick_rounded, + style=PresetStyle.thin_thick_rounded, ) expected = ( "╭─────┬───────────────────────╮\n" @@ -167,7 +167,7 @@ def test_thin_double(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=Styles.thin_double, + style=PresetStyle.thin_double, ) expected = ( "┌─────┬───────────────────────┐\n" @@ -190,7 +190,7 @@ def test_thin_double_rounded(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=Styles.thin_double_rounded, + style=PresetStyle.thin_double_rounded, ) expected = ( "╭─────┬───────────────────────╮\n" @@ -213,7 +213,7 @@ def test_thick(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=Styles.thick, + style=PresetStyle.thick, ) expected = ( "┏━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓\n" @@ -236,7 +236,7 @@ def test_thick_box(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=Styles.thick_box, + style=PresetStyle.thick_box, ) expected = ( "┏━━━━━┳━━━━━┳━━━━━┳━━━━━┳━━━━━┓\n" @@ -259,7 +259,7 @@ def test_thick_compact(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=Styles.thick_compact, + style=PresetStyle.thick_compact, ) expected = ( "┏━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓\n" @@ -281,7 +281,7 @@ def test_double(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=Styles.double, + style=PresetStyle.double, ) expected = ( "╔═════╦═══════════════════════╗\n" @@ -304,7 +304,7 @@ def test_double_box(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=Styles.double_box, + style=PresetStyle.double_box, ) expected = ( "╔═════╦═════╦═════╦═════╦═════╗\n" @@ -327,7 +327,7 @@ def test_double_compact(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=Styles.double_compact, + style=PresetStyle.double_compact, ) expected = ( "╔═════╦═══════════════════════╗\n" @@ -349,7 +349,7 @@ def test_double_thin_compact(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=Styles.double_thin_compact, + style=PresetStyle.double_thin_compact, ) expected = ( "╔═════╦═══════════════════════╗\n" @@ -371,7 +371,7 @@ def test_minimalist(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=Styles.minimalist, + style=PresetStyle.minimalist, ) expected = ( " ───────────────────────────── \n" @@ -394,7 +394,7 @@ def test_borderless(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=Styles.borderless, + style=PresetStyle.borderless, ) expected = ( " # ┃ G H R S \n" @@ -414,7 +414,7 @@ def test_simple(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=Styles.simple, + style=PresetStyle.simple, ) expected = ( " ═════ ═════ ═════ ═════ ═════ \n" @@ -436,7 +436,7 @@ def test_ascii(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=Styles.ascii, + style=PresetStyle.ascii, ) expected = ( "+-----+-----------------------+\n" @@ -459,7 +459,7 @@ def test_ascii_box(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=Styles.ascii_box, + style=PresetStyle.ascii_box, ) expected = ( "+-----+-----+-----+-----+-----+\n" @@ -482,7 +482,7 @@ def test_ascii_compact(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=Styles.ascii_compact, + style=PresetStyle.ascii_compact, ) expected = ( "+-----+-----------------------+\n" @@ -504,7 +504,7 @@ def test_ascii_double(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=Styles.ascii_double, + style=PresetStyle.ascii_double, ) expected = ( "+-----+-----------------------+\n" @@ -527,7 +527,7 @@ def test_ascii_minimalist(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=Styles.ascii_minimalist, + style=PresetStyle.ascii_minimalist, ) expected = ( " ----------------------------- \n" @@ -550,7 +550,7 @@ def test_ascii_borderless(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=Styles.ascii_borderless, + style=PresetStyle.ascii_borderless, ) expected = ( " # | G H R S \n" @@ -570,7 +570,7 @@ def test_ascii_simple(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=Styles.ascii_simple, + style=PresetStyle.ascii_simple, ) expected = ( " ===== ===== ===== ===== ===== \n" @@ -592,7 +592,7 @@ def test_markdown(): footer=["SUM", "130", "140", "135", "130"], first_col_heading=True, last_col_heading=False, - style=Styles.markdown, + style=PresetStyle.markdown, ) expected = ( "| # | G | H | R | S |\n" From b3f6a2ee2713a3ce0655827424e04685cade0d97 Mon Sep 17 00:00:00 2001 From: Jonah Lawrence Date: Thu, 29 Apr 2021 09:41:46 +0300 Subject: [PATCH 20/22] Add headings and custom style info --- README.md | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 47f1748..91f0229 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,11 @@ Module for converting 2D Python lists to a fancy ASCII/Unicode tables - [table2ascii](#table2ascii) - [📥 Installation](#-installation) - [🧑‍💻 Usage](#-usage) + - [Convert lists to ASCII tables](#convert-lists-to-ascii-tables) + - [Set first or last column headings](#set-first-or-last-column-headings) + - [Set column widths and alignments](#set-column-widths-and-alignments) + - [Use a preset style](#use-a-preset-style) + - [Define a custom style](#define-a-custom-style) - [🎨 Preset styles](#-preset-styles) - [⚙️ Options](#️-options) - [👨‍🎨 Use cases](#-use-cases) @@ -25,7 +30,7 @@ Module for converting 2D Python lists to a fancy ASCII/Unicode tables ## 🧑‍💻 Usage -Convert Python lists to ASCII tables +### Convert lists to ASCII tables ```py from table2ascii import table2ascii @@ -50,6 +55,8 @@ print(output) """ ``` +### Set first or last column headings + ```py from table2ascii import table2ascii @@ -68,6 +75,8 @@ print(output) """ ``` +### Set column widths and alignments + ```py from table2ascii import table2ascii, Alignment @@ -91,6 +100,8 @@ print(output) """ ``` +### Use a preset style + ```py from table2ascii import table2ascii, PresetStyle @@ -114,6 +125,34 @@ print(output) """ ``` +### Define a custom style + +Check [`TableStyle`](https://github.com/DenverCoder1/table2ascii/blob/main/table2ascii/table_style.py) for more info and [`PresetStyle`](https://github.com/DenverCoder1/table2ascii/blob/main/table2ascii/preset_style.py) for examples. + +```py +from table2ascii import table2ascii, TableStyle + +my_style = TableStyle.from_string("*-..*||:+-+:+ *''*") + +output = table2ascii( + header=["First", "Second", "Third"], + body=[["10", "30", "40"], ["20", "10", "20"], ["30", "20", "30"]], + style=my_style +) + +print(output) + +""" +*-------.--------.-------* +| First : Second : Third | ++-------:--------:-------+ +| 10 : 30 : 40 | +| 20 : 10 : 20 | +| 30 : 20 : 30 | +*-------'--------'-------* +""" +``` + ## 🎨 Preset styles See a list of all preset styles [here](/style_list). From 90bf4266bf8ea9986bc1608aa15b101a99606e88 Mon Sep 17 00:00:00 2001 From: Jonah Lawrence Date: Thu, 29 Apr 2021 09:51:06 +0300 Subject: [PATCH 21/22] Fix duplicate column --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 91f0229..b26821c 100644 --- a/README.md +++ b/README.md @@ -166,7 +166,7 @@ Soon table2ascii will support more options for customization. | Option | Type | Default | Description | | :-----------------: | :---------------: | :----------: | :----------------------------------------------------------------------------------------: | | `header` | `List[str]` | `None` | First row of table seperated by header row seperator | -| `body` | `List[List[str]]` | `None` | `None` | List of rows for the main section of the table | +| `body` | `List[List[str]]` | `None` | List of rows for the main section of the table | | `footer` | `List[str]` | `None` | Last row of table seperated by header row seperator | | `column_widths` | `List[int]` | automatic | List of column widths in characters for each column | | `alignments` | `List[int]` | all centered | Alignments for each column
(ex. `[Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT]`) | From e08b339416a95cd23c35335dbb8a899664b1bb99 Mon Sep 17 00:00:00 2001 From: Jonah Lawrence Date: Thu, 29 Apr 2021 14:57:17 +0300 Subject: [PATCH 22/22] remove header, body, footer from Options class --- table2ascii/options.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/table2ascii/options.py b/table2ascii/options.py index 9b2b258..7635711 100644 --- a/table2ascii/options.py +++ b/table2ascii/options.py @@ -10,9 +10,6 @@ class Options: """Class for storing options that the user sets""" - header: Optional[List] = None - body: Optional[List[List]] = None - footer: Optional[List] = None first_col_heading: bool = False last_col_heading: bool = False column_widths: Optional[List[int]] = None