diff options
| author | Kevin Van Brunt <kmvanbrunt@gmail.com> | 2021-10-26 13:59:56 -0400 |
|---|---|---|
| committer | Kevin Van Brunt <kmvanbrunt@gmail.com> | 2021-10-26 13:59:56 -0400 |
| commit | 0d60017ba650ce2c8eedf2de7317477292e80056 (patch) | |
| tree | e6ac33b6f4f6c07a6ca02b2dbff4333d511d7117 | |
| parent | fcf3410b343c074806343e289cff5d385b7eb16b (diff) | |
| download | cmd2-git-0d60017ba650ce2c8eedf2de7317477292e80056.tar.gz | |
Updated table example.
Renamed Column settings:
override_header_style -> style_header_text
override_data_style -> style_data_text
| -rw-r--r-- | cmd2/table_creator.py | 34 | ||||
| -rwxr-xr-x | examples/table_creation.py | 107 | ||||
| -rw-r--r-- | tests/test_table_creator.py | 30 |
3 files changed, 92 insertions, 79 deletions
diff --git a/cmd2/table_creator.py b/cmd2/table_creator.py index de2c41c7..68d46a01 100644 --- a/cmd2/table_creator.py +++ b/cmd2/table_creator.py @@ -64,10 +64,10 @@ class Column: width: Optional[int] = None, header_horiz_align: HorizontalAlignment = HorizontalAlignment.LEFT, header_vert_align: VerticalAlignment = VerticalAlignment.BOTTOM, - override_header_style: bool = True, + style_header_text: bool = True, data_horiz_align: HorizontalAlignment = HorizontalAlignment.LEFT, data_vert_align: VerticalAlignment = VerticalAlignment.TOP, - override_data_style: bool = True, + style_data_text: bool = True, max_data_lines: Union[int, float] = constants.INFINITY, ) -> None: """ @@ -79,16 +79,16 @@ class Column: this width using word-based wrapping (defaults to actual width of header or 1 if header is blank) :param header_horiz_align: horizontal alignment of header cells (defaults to left) :param header_vert_align: vertical alignment of header cells (defaults to bottom) - :param override_header_style: if True, then the table is allowed to apply text styles to the header, which may - conflict with any styles the header already has. If False, the header is printed as is. - Table classes which apply style to headers must account for the value of this flag. - (defaults to True) + :param style_header_text: if True, then the table is allowed to apply styles to the header text, which may + conflict with any styles the header already has. If False, the header is printed as is. + Table classes which apply style to headers must account for the value of this flag. + (defaults to True) :param data_horiz_align: horizontal alignment of data cells (defaults to left) :param data_vert_align: vertical alignment of data cells (defaults to top) - :param override_data_style: if True, then the table is allowed to apply text styles to the data, which may - conflict with any styles the data already has. If False, the data is printed as is. - Table classes which apply style to data must account for the value of this flag. - (defaults to True) + :param style_data_text: if True, then the table is allowed to apply styles to the data text, which may + conflict with any styles the data already has. If False, the data is printed as is. + Table classes which apply style to data must account for the value of this flag. + (defaults to True) :param max_data_lines: maximum lines allowed in a data cell. If line count exceeds this, then the final line displayed will be truncated with an ellipsis. (defaults to INFINITY) :raises: ValueError if width is less than 1 @@ -103,11 +103,11 @@ class Column: self.header_horiz_align = header_horiz_align self.header_vert_align = header_vert_align - self.override_header_style = override_header_style + self.style_header_text = style_header_text self.data_horiz_align = data_horiz_align self.data_vert_align = data_vert_align - self.override_data_style = override_data_style + self.style_data_text = style_data_text if max_data_lines < 1: raise ValueError("Max data lines cannot be less than 1") @@ -655,7 +655,7 @@ class SimpleTable(TableCreator): # Apply background color to header text in Columns which allow it to_display: List[Any] = [] for index, col in enumerate(self.cols): - if col.override_header_style: + if col.style_header_text: to_display.append(self.apply_header_bg(col.header)) else: to_display.append(col.header) @@ -691,7 +691,7 @@ class SimpleTable(TableCreator): # Apply background color to data text in Columns which allow it to_display: List[Any] = [] for index, col in enumerate(self.cols): - if col.override_data_style: + if col.style_data_text: to_display.append(self.apply_data_bg(row_data[index])) else: to_display.append(row_data[index]) @@ -940,7 +940,7 @@ class BorderedTable(TableCreator): # Apply background color to header text in Columns which allow it to_display: List[Any] = [] for index, col in enumerate(self.cols): - if col.override_header_style: + if col.style_header_text: to_display.append(self.apply_header_bg(col.header)) else: to_display.append(col.header) @@ -981,7 +981,7 @@ class BorderedTable(TableCreator): # Apply background color to data text in Columns which allow it to_display: List[Any] = [] for index, col in enumerate(self.cols): - if col.override_data_style: + if col.style_data_text: to_display.append(self.apply_data_bg(row_data[index])) else: to_display.append(row_data[index]) @@ -1028,7 +1028,7 @@ class AlternatingTable(BorderedTable): Implementation of BorderedTable which uses background colors to distinguish between rows instead of row border lines. This class can be used to create the whole table at once or one row at a time. - To nest an AlternatingTable within another AlternatingTable, set override_data_style to False on the Column + To nest an AlternatingTable within another AlternatingTable, set style_data_text to False on the Column which contains the nested table. That will prevent the current row's background color from affecting the colors of the nested table. """ diff --git a/examples/table_creation.py b/examples/table_creation.py index 0c637aad..4fc7f2e6 100755 --- a/examples/table_creation.py +++ b/examples/table_creation.py @@ -42,18 +42,18 @@ class DollarFormatter: class Book: """Class used for example data""" - def __init__(self, title: str, due_date: str) -> None: + def __init__(self, title: str, year_published: str) -> None: self.title = title - self.due_date = due_date + self.year_published = year_published -class Person: +class Author: """Class used for example data""" - def __init__(self, name: str, birthday: str, department: str) -> None: + def __init__(self, name: str, birthday: str, place_of_birth: str) -> None: self.name = name self.birthday = birthday - self.department = department + self.place_of_birth = place_of_birth self.books: List[Book] = [] @@ -108,48 +108,61 @@ def basic_tables(): def nested_tables(): """ - Demonstrates how to nest tables using the override_data_style keyword to handle tables with conflicting styles. + Demonstrates how to nest tables using the style_data_text keyword to handle tables with conflicting styles. In these cases, the inner tables reset the background color applied by the outer AlternatingTable. It also demonstrates coloring various aspects of tables. """ # Create data for this example - person_data: List[Person] = [] - person_1 = Person("Bill Anderson", "01/22/1955", "Accounting") - person_1.books.append(Book("Great Expectations", "11/01/2025")) - person_1.books.append(Book("Strange Case of Dr Jekyll and Mr Hyde", "07/16/2026")) - person_1.books.append(Book("Dune", "01/24/2027")) - - person_2 = Person("Arthur Smith", "06/11/1974", "Automotive") - person_2.books.append(Book("Nineteen Eighty-Four", "08/07/2025")) - person_2.books.append(Book("Pride and Prejudice", "04/13/2026")) - person_2.books.append(Book("Fahrenheit 451", "07/29/2026")) - person_2.books.append(Book("The Count of Monte Cristo", "10/15/2027")) - - person_data.append(person_1) - person_data.append(person_2) - - # Define table which presents Person data fields vertically with no header. + author_data: List[Author] = [] + author_1 = Author("Frank Herbert", "10/08/1920", "Tacoma, Washington") + author_1.books.append(Book("Dune", "1965")) + author_1.books.append(Book("Dune Messiah", "1969")) + author_1.books.append(Book("Children of Dune", "1976")) + author_1.books.append(Book("God Emperor of Dune", "1981")) + author_1.books.append(Book("Heretics of Dune", "1984")) + author_1.books.append(Book("Chapterhouse: Dune", "1985")) + + author_2 = Author("Jane Austen", "12/16/1775", "Steventon, Hampshire, England") + author_2.books.append(Book("Sense and Sensibility", "1811")) + author_2.books.append(Book("Pride and Prejudice", "1813")) + author_2.books.append(Book("Mansfield Park ", "1814")) + author_2.books.append(Book("Emma", "1815")) + author_2.books.append(Book("Northanger Abbey", "1818")) + author_2.books.append(Book("Persuasion", "1818")) + author_2.books.append(Book("Lady Susan", "1871")) + + author_data.append(author_1) + author_data.append(author_2) + + # Define table which presents Author data fields vertically with no header. # This will be nested in the parent table. - person_columns: List[Column] = list() - person_columns.append(Column("", width=10)) - person_columns.append(Column("", width=20)) + author_columns: List[Column] = list() + author_columns.append(Column("", width=14)) + author_columns.append(Column("", width=20)) # The text labels in this table will be bold text. They will also be aligned by the table code. # When styled text is aligned, a TextStyle.RESET_ALL sequence is inserted between the aligned text - # and the fill characters. Therefore, the Person table will contain TextStyle.RESET_ALL sequences, + # and the fill characters. Therefore, the Author table will contain TextStyle.RESET_ALL sequences, # which would interfere with the background color applied by the parent table. To account for this, - # we will color the Person tables to match the background colors of the parent AlternatingTable's rows - # and set override_data_style to False in the Person column. See below for that. - odd_person_tbl = SimpleTable(person_columns, data_bg=EightBitBg.GRAY_0) - even_person_tbl = SimpleTable(person_columns, data_bg=EightBitBg.GRAY_15) + # we will color the Author tables to match the background colors of the parent AlternatingTable's rows + # and set style_data_text to False in the Author column. See below for that. + odd_author_tbl = SimpleTable(author_columns, data_bg=EightBitBg.GRAY_0) + even_author_tbl = SimpleTable(author_columns, data_bg=EightBitBg.GRAY_15) # Define AlternatingTable table for books checked out by people in the first table. # This will also be nested in the parent table. books_columns: List[Column] = list() - books_columns.append(Column("Title", width=28)) - books_columns.append(Column("Due Date", width=10)) + books_columns.append(Column("Title", width=25)) + books_columns.append( + Column( + "Published", + width=9, + header_horiz_align=HorizontalAlignment.RIGHT, + data_horiz_align=HorizontalAlignment.RIGHT, + ) + ) books_tbl = AlternatingTable( books_columns, @@ -160,13 +173,13 @@ def nested_tables(): even_bg=EightBitBg.GRAY_15, ) - # Define parent AlternatingTable which contains Person and Book tables + # Define parent AlternatingTable which contains Author and Book tables parent_tbl_columns: List[Column] = list() - # Both the Person and Books tables already have background colors. Set override_data_style + # Both the Author and Books tables already have background colors. Set style_data_text # to False so the parent AlternatingTable does not apply background color to them. - parent_tbl_columns.append(Column("Person", width=odd_person_tbl.total_width(), override_data_style=False)) - parent_tbl_columns.append(Column("Books", width=books_tbl.total_width(), override_data_style=False)) + parent_tbl_columns.append(Column("Author", width=odd_author_tbl.total_width(), style_data_text=False)) + parent_tbl_columns.append(Column("Books", width=books_tbl.total_width(), style_data_text=False)) parent_tbl = AlternatingTable( parent_tbl_columns, @@ -178,26 +191,26 @@ def nested_tables(): # Construct the tables parent_table_data: List[List[Any]] = [] - for row, person in enumerate(person_data, start=1): - # First build the person table and color it based on row number - person_tbl = even_person_tbl if row % 2 == 0 else odd_person_tbl + for row, author in enumerate(author_data, start=1): + # First build the author table and color it based on row number + author_tbl = even_author_tbl if row % 2 == 0 else odd_author_tbl # This table has three rows and two columns table_data = [ - [ansi.style("Name", bold=True), person.name], - [ansi.style("Birthday", bold=True), person.birthday], - [ansi.style("Department", bold=True), person.department], + [ansi.style("Name", bold=True), author.name], + [ansi.style("Birthday", bold=True), author.birthday], + [ansi.style("Place of Birth", bold=True), author.place_of_birth], ] - # Build the person table string - person_tbl_str = person_tbl.generate_table(table_data, include_header=False, row_spacing=0) + # Build the author table string + author_tbl_str = author_tbl.generate_table(table_data, include_header=False, row_spacing=0) - # Now build this person's book table - table_data = [[book.title, book.due_date] for book in person.books] + # Now build this author's book table + table_data = [[book.title, book.year_published] for book in author.books] book_tbl_str = books_tbl.generate_table(table_data) # Add these tables to the parent table's data - parent_table_data.append(['\n' + person_tbl_str, '\n' + book_tbl_str + '\n\n']) + parent_table_data.append(['\n' + author_tbl_str, '\n' + book_tbl_str + '\n\n']) # Build the parent table top_table_str = parent_tbl.generate_table(parent_table_data) diff --git a/tests/test_table_creator.py b/tests/test_table_creator.py index 12c3e36b..275a1103 100644 --- a/tests/test_table_creator.py +++ b/tests/test_table_creator.py @@ -71,18 +71,18 @@ def test_column_creation(): tc = TableCreator([c]) assert tc.cols[0].width == ansi.style_aware_wcswidth("line with tabs") - # Add basic tests for override_header_style and override_data_style to make sure these members don't get removed. + # Add basic tests for style_header_text and style_data_text to make sure these members don't get removed. c = Column("Column 1") - assert c.override_header_style is True - assert c.override_data_style is True + assert c.style_header_text is True + assert c.style_data_text is True - c = Column("Column 1", override_header_style=False) - assert c.override_header_style is False - assert c.override_data_style is True + c = Column("Column 1", style_header_text=False) + assert c.style_header_text is False + assert c.style_data_text is True - c = Column("Column 1", override_data_style=False) - assert c.override_header_style is True - assert c.override_data_style is False + c = Column("Column 1", style_data_text=False) + assert c.style_header_text is True + assert c.style_data_text is False def test_column_alignment(): @@ -465,9 +465,9 @@ def test_simple_table_creation(): '\x1b[0m\x1b[104mCol 1 Row 2\x1b[49m\x1b[0m\x1b[104m \x1b[49m\x1b[0m\x1b[104m \x1b[49m\x1b[0m\x1b[104mCol 2 Row 2\x1b[49m\x1b[0m\x1b[104m \x1b[49m\x1b[0m' ) - # Make sure SimpleTable respects override_header_style override_data_style flags. + # Make sure SimpleTable respects style_header_text and style_data_text flags. # Don't apply parent table's background colors to header or data text in second column. - st = SimpleTable([column_1, Column("Col 2", width=16, override_header_style=False, override_data_style=False)], + st = SimpleTable([column_1, Column("Col 2", width=16, style_header_text=False, style_data_text=False)], divider_char=None, header_bg=Bg.GREEN, data_bg=Bg.LIGHT_BLUE) table = st.generate_table(row_data) assert table == ( @@ -576,9 +576,9 @@ def test_bordered_table_creation(): '\x1b[93m╚═\x1b[39m\x1b[0m\x1b[0m\x1b[93m═══════════════\x1b[39m\x1b[0m\x1b[93m═╧═\x1b[39m\x1b[0m\x1b[0m\x1b[93m═══════════════\x1b[39m\x1b[0m\x1b[93m═╝\x1b[39m' ) - # Make sure BorderedTable respects override_header_style override_data_style flags. + # Make sure BorderedTable respects style_header_text and style_data_text flags. # Don't apply parent table's background colors to header or data text in second column. - bt = BorderedTable([column_1, Column("Col 2", width=15, override_header_style=False, override_data_style=False)], + bt = BorderedTable([column_1, Column("Col 2", width=15, style_header_text=False, style_data_text=False)], header_bg=Bg.GREEN, data_bg=Bg.LIGHT_BLUE) table = bt.generate_table(row_data) assert table == ( @@ -702,9 +702,9 @@ def test_alternating_table_creation(): '\x1b[93m╚═\x1b[39m\x1b[0m\x1b[0m\x1b[93m═══════════════\x1b[39m\x1b[0m\x1b[93m═╧═\x1b[39m\x1b[0m\x1b[0m\x1b[93m═══════════════\x1b[39m\x1b[0m\x1b[93m═╝\x1b[39m' ) - # Make sure AlternatingTable respects override_header_style override_data_style flags. + # Make sure AlternatingTable respects style_header_text and style_data_text flags. # Don't apply parent table's background colors to header or data text in second column. - at = AlternatingTable([column_1, Column("Col 2", width=15, override_header_style=False, override_data_style=False)], + at = AlternatingTable([column_1, Column("Col 2", width=15, style_header_text=False, style_data_text=False)], header_bg=Bg.GREEN, odd_bg=Bg.LIGHT_BLUE, even_bg=Bg.LIGHT_RED) table = at.generate_table(row_data) assert table == ( |
