def test_namedtuple_rows(): expected = ''' ╔══════════════════════╤════════╤═════╤═══════╤════════════╗ ║ │ │ Num │ │ ║ ║ First │ Second │ 1 │ Num 2 │ Multiplied ║ ╠══════════════════════╪════════╪═════╪═══════╪════════════╣ ║ RLonger text that │ RA2 │ R5 │ R56 │ R280 ║ ║ Rwill trigger the │ │ │ │ ║ ║ Rcolumn wrapping │ │ │ │ ║ ║ GB1 │ GB2 │ G23 │ G8 │ G184 ║ ║ │ GB2 │ │ │ ║ ║ │ GB2 │ │ │ ║ ║ C1 │ C2 │ 4 │ 9 │ 36 ║ ║ D1 │ D2 │ 7 │ 5 │ 35 ║ ╚══════════════════════╧════════╧═════╧═══════╧════════════╝ '''.lstrip('\n') rows = [ tf.Row(NamedTupleRow( 'Longer text that will trigger the column wrapping', 'A2', 5, 56), text_color='R'), tf.Row(NamedTupleRow('B1', 'B2\nB2\nB2', 23, 8), text_color='G'), NamedTupleRow('C1', 'C2', 4, 9), NamedTupleRow('D1', 'D2', 7, 5) ] columns = (tf.Column('First', width=20, attrib='field1'), tf.Column('Second', attrib='field2'), tf.Column('Num 1', width=3, attrib='field3'), tf.Column('Num 2', attrib='field4'), tf.Column('Multiplied', obj_formatter=multiply_named_tuple)) table = tf.generate_table(rows, columns) assert table == expected
def test_tuple_rows(): expected = ''' ╔══════════════════════╤════════╤═══════╤═══════════╤════════════╗ ║ First │ Second │ Num 1 │ Num 2 │ Multiplied ║ ╠══════════════════════╪════════╪═══════╪═══════════╪════════════╣ ║ RLonger text that wil │ RA2 │ R5 │ RFifty-six │ R280 ║ ║ GB1 │ GB2 │ G23 │ GEight │ G184 ║ ║ │ GB2 │ │ │ ║ ║ │ GB2 │ │ │ ║ ║ C1 │ C2 │ 4 │ Nine │ 36 ║ ║ D1 │ D2 │ 7 │ Five │ 35 ║ ╚══════════════════════╧════════╧═══════╧═══════════╧════════════╝ '''.lstrip('\n') rows = [ tf.Row('Longer text that will trigger the column wrapping', 'A2', 5, 56, None, text_color='R'), tf.Row('B1', 'B2\nB2\nB2', 23, 8, None, text_color='G'), ('C1', 'C2', 4, 9, None), ('D1', 'D2', 7, 5, None) ] columns = (tf.Column('First', width=20, wrap_mode=tf.WrapMode.TRUNCATE_HARD), tf.Column('Second'), tf.Column('Num 1'), tf.Column('Num 2', formatter=int2word), tf.Column('Multiplied', obj_formatter=multiply_tuple)) table = tf.generate_table(rows, columns) assert table == expected
def test_fmt_tuple_rows(): expected = ''' ╔═══════════╤═══════════════════╤═══════╤═══════════╤════════════╗ ║ First │ Second │ Num 1 │ Num 2 │ Multiplied ║ ╠═══════════╪═══════════════════╪═══════╪═══════════╪════════════╣ ║ │ │ 17 │ Four │ 68 ║ ║ 123.00 B │ 123 │ 5 │ Fifty-six │ 280 ║ ║ 123.00 B │ 123 │ 5 │ Fifty-six │ 280 ║ ║ 12.06 KB │ 12,345 │ 23 │ Eight │ 184 ║ ║ 11.77 MB │ 12,345,678 │ 4 │ Nine │ 36 ║ ║ 1.15 GB │ 1,234,567,890 │ 7 │ Five │ 35 ║ ║ 1.12 TB │ 1,234,567,890,123 │ 7 │ Five │ 35 ║ ╚═══════════╧═══════════════════╧═══════╧═══════════╧════════════╝ '''.lstrip('\n') rows = [(None, None, 17, 4, None), ('123', '123', 5, 56, None), (123, 123, 5, 56, None), (12345, 12345, 23, 8, None), (12345678, 12345678, 4, 9, None), (1234567890, 1234567890, 7, 5, None), (1234567890123, 1234567890123, 7, 5, None)] columns = (tf.Column('First', width=20, formatter=tf.FormatBytes(), cell_halign=tf.ColumnAlignment.AlignRight), tf.Column('Second', formatter=tf.FormatCommas(), cell_halign=tf.ColumnAlignment.AlignRight), tf.Column('Num 1'), tf.Column('Num 2', formatter=int2word), tf.Column('Multiplied', obj_formatter=multiply_tuple)) table = tf.generate_table(rows, columns) assert table == expected
def test_iterable_of_non_iterable_objects(): rows = [MyRowObject(1, 2, 3, 4), MyRowObject(5, 6, 7, 8)] columns = (tf.Column('col1', attrib='field1'), tf.Column('col2', attrib='field2'), tf.Column('col3', attrib='get_field3'), tf.Column('col4', attrib='field4')) table = tf.generate_table(rows, columns) assert table == EXPECTED_WITH_HEADERS
def column(option: TaskDisplayOptions) -> tf.Column: return tf.Column( option.name, attrib=mapping[option], width=width[option], cell_padding=0, wrap_mode=tf.WrapMode.WRAP, )
def test_object_table_columns_rearranged(obj_rows): cols2 = (tf.Column('Col1', attrib='field3'), tf.Column('Col2', attrib='field2'), tf.Column('Col3', attrib='field1'), tf.Column('Col4', attrib='field4')) expected = ''' ╔══════╤══════╤══════╤══════╗ ║ Col1 │ Col2 │ Col3 │ Col4 ║ ╠══════╪══════╪══════╪══════╣ ║ │ A2 │ A1 │ A4 ║ ║ │ B2 │ B1 │ B4 ║ ║ │ B2 │ │ ║ ║ │ B2 │ │ ║ ║ │ C2 │ C1 │ C4 ║ ║ │ D2 │ D1 │ D4 ║ ╚══════╧══════╧══════╧══════╝ '''.lstrip('\n') table = tf.generate_table(obj_rows, cols2) assert table == expected
def test_truncate_front_custom_padding_cell_align_right(obj_rows): columns = (tf.Column('First', width=20, attrib='field1', wrap_mode=tf.WrapMode.TRUNCATE_FRONT), tf.Column('Second', attrib='field2', cell_padding=5, cell_halign=tf.ColumnAlignment.AlignRight), tf.Column('Num 1', attrib='get_field3'), tf.Column('Num 2', attrib='field4'), tf.Column('Multiplied', attrib=None, obj_formatter=multiply)) table = tf.generate_table(obj_rows, columns) expected = ''' ╔══════════════════════╤════════════════╤═══════╤═══════╤════════════╗ ║ First │ Second │ Num 1 │ Num 2 │ Multiplied ║ ╠══════════════════════╪════════════════╪═══════╪═══════╪════════════╣ ║ …the column wrapping │ A2 │ 5 │ 56 │ 280 ║ ║ B1 │ B2 │ 23 │ 8 │ 184 ║ ║ │ B2 │ │ │ ║ ║ │ B2 │ │ │ ║ ║ C1 │ C2 │ 4 │ 9 │ 36 ║ ║ D1 │ D2 │ 7 │ 5 │ 35 ║ ╚══════════════════════╧════════════════╧═══════╧═══════╧════════════╝ '''.lstrip('\n') assert table == expected
def test_truncate_hard_field_formatter(obj_rows): columns = (tf.Column('First', width=20, attrib='field1', wrap_mode=tf.WrapMode.TRUNCATE_HARD), tf.Column('Second', attrib='field2'), tf.Column('Num 1', attrib='get_field3'), tf.Column('Num 2', attrib='field4', formatter=int2word), tf.Column('Multiplied', attrib=None, obj_formatter=multiply)) table = tf.generate_table(obj_rows, columns) expected = ''' ╔══════════════════════╤════════╤═══════╤═══════════╤════════════╗ ║ First │ Second │ Num 1 │ Num 2 │ Multiplied ║ ╠══════════════════════╪════════╪═══════╪═══════════╪════════════╣ ║ Longer text that wil │ A2 │ 5 │ Fifty-six │ 280 ║ ║ B1 │ B2 │ 23 │ Eight │ 184 ║ ║ │ B2 │ │ │ ║ ║ │ B2 │ │ │ ║ ║ C1 │ C2 │ 4 │ Nine │ 36 ║ ║ D1 │ D2 │ 7 │ Five │ 35 ║ ╚══════════════════════╧════════╧═══════╧═══════════╧════════════╝ '''.lstrip('\n') assert table == expected
def test_truncate_middle_cell_align_bottom(obj_rows): columns = (tf.Column('First', width=20, attrib='field1', wrap_mode=tf.WrapMode.TRUNCATE_MIDDLE), tf.Column('Second', attrib='field2'), tf.Column('Num 1', attrib='get_field3'), tf.Column('Num 2', attrib='field4', cell_valign=tf.ColumnAlignment.AlignBottom), tf.Column('Multiplied', attrib=None, obj_formatter=multiply)) table = tf.generate_table(obj_rows, columns) expected = ''' ╔══════════════════════╤════════╤═══════╤═══════╤════════════╗ ║ First │ Second │ Num 1 │ Num 2 │ Multiplied ║ ╠══════════════════════╪════════╪═══════╪═══════╪════════════╣ ║ Longer t … wrapping │ A2 │ 5 │ 56 │ 280 ║ ║ B1 │ B2 │ 23 │ │ 184 ║ ║ │ B2 │ │ │ ║ ║ │ B2 │ │ 8 │ ║ ║ C1 │ C2 │ 4 │ 9 │ 36 ║ ║ D1 │ D2 │ 7 │ 5 │ 35 ║ ╚══════════════════════╧════════╧═══════╧═══════╧════════════╝ '''.lstrip('\n') assert table == expected
def test_truncate_end_custom_padding(obj_rows): columns = (tf.Column('First', width=20, attrib='field1', wrap_mode=tf.WrapMode.TRUNCATE_END), tf.Column('Second', attrib='field2', cell_padding=3), tf.Column('Num 1', width=3, attrib='get_field3'), tf.Column('Num 2', attrib='field4'), tf.Column('Multiplied', attrib=None, obj_formatter=multiply)) table = tf.generate_table(obj_rows, columns) expected = ''' ╔══════════════════════╤════════════╤═════╤═══════╤════════════╗ ║ │ │ Num │ │ ║ ║ First │ Second │ 1 │ Num 2 │ Multiplied ║ ╠══════════════════════╪════════════╪═════╪═══════╪════════════╣ ║ Longer text that wi… │ A2 │ 5 │ 56 │ 280 ║ ║ B1 │ B2 │ 23 │ 8 │ 184 ║ ║ │ B2 │ │ │ ║ ║ │ B2 │ │ │ ║ ║ C1 │ C2 │ 4 │ 9 │ 36 ║ ║ D1 │ D2 │ 7 │ 5 │ 35 ║ ╚══════════════════════╧════════════╧═════╧═══════╧════════════╝ '''.lstrip('\n') assert table == expected
def test_fmt_obj_rows(): expected = ''' ╔═══════════╤═══════════════════╤═════╤═══════╤════════════╗ ║ │ │ Num │ │ ║ ║ First │ Second │ 1 │ Num 2 │ Multiplied ║ ╠═══════════╪═══════════════════╪═════╪═══════╪════════════╣ ║ │ │ 17 │ 4 │ 68 ║ ║ 123.00 B │ 123 │ 5 │ 56 │ 280 ║ ║ 123.00 B │ 123 │ 5 │ 56 │ 280 ║ ║ 12.06 KB │ 12,345 │ 23 │ 8 │ 184 ║ ║ 11.77 MB │ 12,345,678 │ 4 │ 9 │ 36 ║ ║ 1.15 GB │ 1,234,567,890 │ 7 │ 5 │ 35 ║ ║ 1.12 TB │ 1,234,567,890,123 │ 7 │ 5 │ 35 ║ ╚═══════════╧═══════════════════╧═════╧═══════╧════════════╝ '''.lstrip('\n') rows = [ MyRowObject(None, None, 17, 4), MyRowObject('123', '123', 5, 56), MyRowObject(123, 123, 5, 56), MyRowObject(12345, 12345, 23, 8), MyRowObject(12345678, 12345678, 4, 9), MyRowObject(1234567890, 1234567890, 7, 5), MyRowObject(1234567890123, 1234567890123, 7, 5) ] columns = (tf.Column('First', width=20, attrib='field1', formatter=tf.FormatBytes(), cell_halign=tf.ColumnAlignment.AlignRight), tf.Column('Second', attrib='field2', formatter=tf.FormatCommas(), cell_halign=tf.ColumnAlignment.AlignRight), tf.Column('Num 1', width=3, attrib='get_field3'), tf.Column('Num 2', attrib='field4'), tf.Column('Multiplied', obj_formatter=multiply)) table = tf.generate_table(rows, columns) assert table == expected
def test_wrapped_object_formatter(obj_rows): columns = (tf.Column('First', width=20, attrib='field1'), tf.Column('Second', attrib='field2'), tf.Column('Num 1', width=3, attrib='get_field3'), tf.Column('Num 2', attrib='field4'), tf.Column('Multiplied', obj_formatter=multiply)) table = tf.generate_table(obj_rows, columns) expected = ''' ╔══════════════════════╤════════╤═════╤═══════╤════════════╗ ║ │ │ Num │ │ ║ ║ First │ Second │ 1 │ Num 2 │ Multiplied ║ ╠══════════════════════╪════════╪═════╪═══════╪════════════╣ ║ Longer text that │ A2 │ 5 │ 56 │ 280 ║ ║ will trigger the │ │ │ │ ║ ║ column wrapping │ │ │ │ ║ ║ B1 │ B2 │ 23 │ 8 │ 184 ║ ║ │ B2 │ │ │ ║ ║ │ B2 │ │ │ ║ ║ C1 │ C2 │ 4 │ 9 │ 36 ║ ║ D1 │ D2 │ 7 │ 5 │ 35 ║ ╚══════════════════════╧════════╧═════╧═══════╧════════════╝ '''.lstrip('\n') assert table == expected
def test_wrapped_indent_center_header(obj_rows): columns = (tf.Column('First', width=20, attrib='field1', wrap_mode=tf.WrapMode.WRAP_WITH_INDENT), tf.Column('Second', attrib='field2'), tf.Column('Num 1', width=3, attrib='get_field3', header_halign=tf.ColumnAlignment.AlignCenter), tf.Column('Num 2', attrib='field4'), tf.Column('Multiplied', attrib=None, obj_formatter=multiply)) table = tf.generate_table(obj_rows, columns) expected = ''' ╔══════════════════════╤════════╤═════╤═══════╤════════════╗ ║ │ │ Num │ │ ║ ║ First │ Second │ 1 │ Num 2 │ Multiplied ║ ╠══════════════════════╪════════╪═════╪═══════╪════════════╣ ║ Longer text that │ A2 │ 5 │ 56 │ 280 ║ ║ » will trigger the │ │ │ │ ║ ║ » column wrapping │ │ │ │ ║ ║ B1 │ B2 │ 23 │ 8 │ 184 ║ ║ │ B2 │ │ │ ║ ║ │ B2 │ │ │ ║ ║ C1 │ C2 │ 4 │ 9 │ 36 ║ ║ D1 │ D2 │ 7 │ 5 │ 35 ║ ╚══════════════════════╧════════╧═════╧═══════╧════════════╝ '''.lstrip('\n') assert table == expected
['Shenzen (深圳市)', 'Guangdong', 'China', 'Asia', 13723000, 1493.32], ['Guangzho (广州市)', 'Guangdong', 'China', 'Asia', 13081000, 1347.81], ['Mumbai (मुंबई)', 'Maharashtra', 'India', 'Asia', 12442373, 465.78], [ 'Istanbul (İstanbuld)', 'Istanbul', 'Turkey', 'Eurasia', 12661000, 620.29 ], ] # Calculate population density for row in EXAMPLE_ITERABLE_DATA: row.append(row[-2] / row[-1]) # Column headers plus optional formatting info for each column COLUMNS = [ tf.Column('City', width=11, header_halign=tf.ColumnAlignment.AlignCenter), tf.Column('Province', header_halign=tf.ColumnAlignment.AlignCenter), 'Country', # NOTE: If you don't need any special effects, you can just pass a string tf.Column('Continent', cell_halign=tf.ColumnAlignment.AlignCenter), tf.Column('Population', cell_halign=tf.ColumnAlignment.AlignRight, formatter=tf.FormatCommas()), tf.Column('Area (km²)', width=7, header_halign=tf.ColumnAlignment.AlignCenter, cell_halign=tf.ColumnAlignment.AlignRight, formatter=two_dec), tf.Column('Pop. Density (/km²)', width=12, header_halign=tf.ColumnAlignment.AlignCenter, cell_halign=tf.ColumnAlignment.AlignRight,
def obj_cols(): columns = (tf.Column('Col1', attrib='field1'), tf.Column('Col2', attrib='field2'), tf.Column('Col3', attrib='get_field3'), tf.Column('Col4', attrib='field4')) return columns
return opts rows = [ MyRowObject(None, None, 17, 4), MyRowObject('123', '123', 5, 56), MyRowObject(123, 123, 5, 56), MyRowObject(12345, 12345, 23, 8), MyRowObject(12345678, 12345678, 4, 9), MyRowObject(1234567890, 1234567890, 7, 5), MyRowObject(1234567890123, 1234567890123, 7, 5) ] columns = (tf.Column('First', width=20, attrib='field1', formatter=tf.FormatBytes(), cell_halign=tf.ColumnAlignment.AlignRight), tf.Column('Second', attrib='field2', formatter=tf.FormatCommas(), cell_halign=tf.ColumnAlignment.AlignRight), tf.Column('Num 1', width=3, attrib='get_field3'), tf.Column('Num 2', attrib='field4'), tf.Column('Multiplied', obj_formatter=multiply)) print("Formatters on object-based row entries") print(tf.generate_table(rows, columns, row_tagger=tag_row_obj)) def tag_row_tuples(row_tuple: Tuple) -> dict:
else: print("num out of range") rows = [ tf.Row(MyRowObject('Longer text that will trigger the column wrapping', 'A2', 5, 56), text_color=tf.TableColors.TEXT_COLOR_RED), tf.Row(MyRowObject('B1', 'B2\nB2\nB2', 23, 8), text_color=tf.TableColors.TEXT_COLOR_GREEN), MyRowObject('C1', 'C2', 4, 9), MyRowObject('D1', 'D2', 7, 5) ] columns = (tf.Column('First', width=20, attrib='field1'), tf.Column('Second', attrib='field2'), tf.Column('Num 1', width=3, attrib='get_field3'), tf.Column('Num 2', attrib='field4'), tf.Column('Multiplied', obj_formatter=multiply)) print("Per-row customizations with object-based row entries") print(tf.generate_table(rows, columns)) rows = [ tf.Row('Longer text that will trigger the column wrapping', 'A2', 5, 56, None, text_color=tf.TableColors.TEXT_COLOR_RED), tf.Row('B1', 'B2\nB2\nB2',
else: words = ones_and_teens[ hundreds] + separator + "hundred" + separator + ones_and_teens[below_ten].lower() return words else: print("num out of range") rows = [MyRowObject('Longer text that will trigger the column wrapping', 'A2', 5, 56), MyRowObject('B1', 'B2\nB2\nB2', 23, 8), MyRowObject('C1', 'C2', 4, 9), MyRowObject('D1', 'D2', 7, 5)] columns = (tf.Column('First', width=20, attrib='field1'), tf.Column('Second', attrib='field2'), tf.Column('Num 1', width=3, attrib='get_field3'), tf.Column('Num 2', attrib='field4'), tf.Column('Multiplied', obj_formatter=multiply)) print("First: Wrapped\nMultiplied: object formatter") print(tf.generate_table(rows, columns)) columns = (tf.Column('First', width=20, attrib='field1', wrap_mode=tf.WrapMode.WRAP_WITH_INDENT), tf.Column('Second', attrib='field2'), tf.Column('Num 1', width=3, attrib='get_field3', header_halign=tf.ColumnAlignment.AlignCenter), tf.Column('Num 2', attrib='field4'), tf.Column('Multiplied', attrib=None, obj_formatter=multiply)) print("First: Wrapped with indent\nNum 1: header align center") print(tf.generate_table(rows, columns))
dict_of_iterables = od print( "Data type: dict of iterables (dict keys iterated through as rows where each key must be a hashable iterable)" ) print(dict_of_iterables) print(tf.generate_table(dict_of_iterables)) class MyRowObject(object): """Simple object to demonstrate using a list of non-iterable objects with TableFormatter""" def __init__(self, field1: int, field2: int, field3: int, field4: int): self.field1 = field1 self.field2 = field2 self._field3 = field3 self.field4 = field4 def get_field3(self): """Demonstrates accessing object functions""" return self._field3 rows = [MyRowObject(1, 2, 3, 4), MyRowObject(5, 6, 7, 8)] columns = (tf.Column('Col1', attrib='field1'), tf.Column('Col2', attrib='field2'), tf.Column('Col3', attrib='get_field3'), tf.Column('Col4', attrib='field4')) print("Data type: iterable of arbitrary non-iterable objects") print(rows) print(tf.generate_table(rows, columns))
"\" \"" + f.name + "\" | sqlite3") student_result = runcommand("cat \"" + database_script_path + "\" \"" + f.name + "\" | sqlite3") # Run proposed solutions against the databases proposed_result_sample = runcommand("cat \"" + database_script_path_sample + "\" \"" + proposed_answer_location + "\" | sqlite3") proposed_result = runcommand("cat \"" + database_script_path + "\" \"" + proposed_answer_location + "\" | sqlite3") rows = [("SQL", student_answer, proposed_answer, ""), ("Example DB", student_result_sample, proposed_result_sample, student_result_sample == proposed_result_sample), ("Complete DB", student_result, proposed_result, student_result == proposed_result)] columns = (tf.Column(''), tf.Column("Student: " + firstname + " " + surname + " " + email, width=80, wrap_mode=tf.WrapMode.WRAP), tf.Column("Professor", width=80, wrap_mode=tf.WrapMode.WRAP), tf.Column("Match")) print(tf.generate_table(rows, columns, grid_style=tf.FancyGrid())) currentRow = currentRow + 1 print("Results for " + question_name + " done.")