def test_wrap_long_word_max_data_lines(): column_1 = Column("Col 1", width=10, max_data_lines=2) column_2 = Column("Col 2", width=10, max_data_lines=2) column_3 = Column("Col 3", width=10, max_data_lines=2) column_4 = Column("Col 4", width=10, max_data_lines=1) columns = [column_1, column_2, column_3, column_4] tc = TableCreator(columns) row_data = list() # This long word will exactly fit the last line and it's the final word in the text. No ellipsis should appear. row_data.append("LongerThan10FitsLast") # This long word will exactly fit the last line but it's not the final word in the text. # Make sure ellipsis word's final character. row_data.append("LongerThan10FitsLast\nMore lines") # This long word will run over the last line. Make sure it is truncated. row_data.append("LongerThan10RunsOverLast") # This long word will start on the final line after another word. Therefore it won't wrap but will instead be truncated. row_data.append("A LongerThan10RunsOverLast") row = tc.generate_row(row_data=row_data) assert row == ('LongerThan LongerThan LongerThan A LongerT…\n' '10FitsLast 10FitsLas… 10RunsOve… ')
def show_current_sample(target, samples, heading1=None, sample_index=None): columns: List[Column] = list() data_list: List[List[Any]] = list() if sample_index is None: sample_index = target.active_attack.sample_index if heading1 is None: heading1 = "Sample Index" # future support for multiple indices if not hasattr(sample_index, "__iter__"): sample_index = [sample_index] columns.append( Column( heading1, width=20, header_horiz_align=HorizontalAlignment.CENTER, data_horiz_align=HorizontalAlignment.RIGHT, )) columns.append( Column( "Value", width=80, header_horiz_align=HorizontalAlignment.CENTER, data_horiz_align=HorizontalAlignment.LEFT, )) for index, value in zip(sample_index, samples): data_list.append([index, value]) st = SimpleTable(columns) output = "\n" + st.generate_table(data_list, row_spacing=0) + "\n" return output
def test_alternating_table_creation(): column_1 = Column("Col 1", width=15) column_2 = Column("Col 2", width=15) row_data = list() row_data.append(["Col 1 Row 1", "Col 2 Row 1"]) row_data.append(["Col 1 Row 2", "Col 2 Row 2"]) # Default options at = AlternatingTable([column_1, column_2]) table = at.generate_table(row_data) assert table == ('╔═════════════════╤═════════════════╗\n' '║ Col 1 │ Col 2 ║\n' '╠═════════════════╪═════════════════╣\n' '║ Col 1 Row 1 │ Col 2 Row 1 ║\n' '\x1b[100m║ \x1b[49m\x1b[0m\x1b[100mCol 1 Row 2\x1b[49m\x1b[0m\x1b[100m \x1b[49m\x1b[100m \x1b[49m\x1b[100m \x1b[49m\x1b[100m \x1b[49m\x1b[0m\x1b[100m │ \x1b[49m\x1b[0m\x1b[100mCol 2 Row 2\x1b[49m\x1b[0m\x1b[100m \x1b[49m\x1b[100m \x1b[49m\x1b[100m \x1b[49m\x1b[100m \x1b[49m\x1b[0m\x1b[100m ║\x1b[49m\n' '╚═════════════════╧═════════════════╝') # Other bg colors at = AlternatingTable([column_1, column_2], bg_odd=ansi.bg.bright_blue, bg_even=ansi.bg.green) table = at.generate_table(row_data) assert table == ('╔═════════════════╤═════════════════╗\n' '║ Col 1 │ Col 2 ║\n' '╠═════════════════╪═════════════════╣\n' '\x1b[104m║ \x1b[49m\x1b[0m\x1b[104mCol 1 Row 1\x1b[49m\x1b[0m\x1b[104m \x1b[49m\x1b[104m \x1b[49m\x1b[104m \x1b[49m\x1b[104m \x1b[49m\x1b[0m\x1b[104m │ \x1b[49m\x1b[0m\x1b[104mCol 2 Row 1\x1b[49m\x1b[0m\x1b[104m \x1b[49m\x1b[104m \x1b[49m\x1b[104m \x1b[49m\x1b[104m \x1b[49m\x1b[0m\x1b[104m ║\x1b[49m\n' '\x1b[42m║ \x1b[49m\x1b[0m\x1b[42mCol 1 Row 2\x1b[49m\x1b[0m\x1b[42m \x1b[49m\x1b[42m \x1b[49m\x1b[42m \x1b[49m\x1b[42m \x1b[49m\x1b[0m\x1b[42m │ \x1b[49m\x1b[0m\x1b[42mCol 2 Row 2\x1b[49m\x1b[0m\x1b[42m \x1b[49m\x1b[42m \x1b[49m\x1b[42m \x1b[49m\x1b[42m \x1b[49m\x1b[0m\x1b[42m ║\x1b[49m\n' '╚═════════════════╧═════════════════╝') # No column borders at = AlternatingTable([column_1, column_2], column_borders=False) table = at.generate_table(row_data) assert table == ('╔══════════════════════════════════╗\n' '║ Col 1 Col 2 ║\n' '╠══════════════════════════════════╣\n' '║ Col 1 Row 1 Col 2 Row 1 ║\n' '\x1b[100m║ \x1b[49m\x1b[0m\x1b[100mCol 1 Row 2\x1b[49m\x1b[0m\x1b[100m \x1b[49m\x1b[100m \x1b[49m\x1b[100m \x1b[49m\x1b[100m \x1b[49m\x1b[0m\x1b[100m \x1b[49m\x1b[0m\x1b[100mCol 2 Row 2\x1b[49m\x1b[0m\x1b[100m \x1b[49m\x1b[100m \x1b[49m\x1b[100m \x1b[49m\x1b[100m \x1b[49m\x1b[0m\x1b[100m ║\x1b[49m\n' '╚══════════════════════════════════╝') # No header at = AlternatingTable([column_1, column_2]) table = at.generate_table(row_data, include_header=False) assert table == ('╔═════════════════╤═════════════════╗\n' '║ Col 1 Row 1 │ Col 2 Row 1 ║\n' '\x1b[100m║ \x1b[49m\x1b[0m\x1b[100mCol 1 Row 2\x1b[49m\x1b[0m\x1b[100m \x1b[49m\x1b[100m \x1b[49m\x1b[100m \x1b[49m\x1b[100m \x1b[49m\x1b[0m\x1b[100m │ \x1b[49m\x1b[0m\x1b[100mCol 2 Row 2\x1b[49m\x1b[0m\x1b[100m \x1b[49m\x1b[100m \x1b[49m\x1b[100m \x1b[49m\x1b[100m \x1b[49m\x1b[0m\x1b[100m ║\x1b[49m\n' '╚═════════════════╧═════════════════╝') # Non-default padding at = AlternatingTable([column_1, column_2], padding=2) table = at.generate_table(row_data) assert table == ('╔═══════════════════╤═══════════════════╗\n' '║ Col 1 │ Col 2 ║\n' '╠═══════════════════╪═══════════════════╣\n' '║ Col 1 Row 1 │ Col 2 Row 1 ║\n' '\x1b[100m║ \x1b[49m\x1b[0m\x1b[100mCol 1 Row 2\x1b[49m\x1b[0m\x1b[100m \x1b[49m\x1b[100m \x1b[49m\x1b[100m \x1b[49m\x1b[100m \x1b[49m\x1b[0m\x1b[100m │ \x1b[49m\x1b[0m\x1b[100mCol 2 Row 2\x1b[49m\x1b[0m\x1b[100m \x1b[49m\x1b[100m \x1b[49m\x1b[100m \x1b[49m\x1b[100m \x1b[49m\x1b[0m\x1b[100m ║\x1b[49m\n' '╚═══════════════════╧═══════════════════╝') # Invalid padding with pytest.raises(ValueError) as excinfo: AlternatingTable([column_1, column_2], padding=-1) assert "Padding cannot be less than 0" in str(excinfo.value)
def test_column_alignment(): column_1 = Column("Col 1", width=10, header_horiz_align=HorizontalAlignment.LEFT, header_vert_align=VerticalAlignment.TOP, data_horiz_align=HorizontalAlignment.LEFT, data_vert_align=VerticalAlignment.TOP) column_2 = Column("Col 2", width=10, header_horiz_align=HorizontalAlignment.CENTER, header_vert_align=VerticalAlignment.MIDDLE, data_horiz_align=HorizontalAlignment.CENTER, data_vert_align=VerticalAlignment.MIDDLE) column_3 = Column("Col 3", width=10, header_horiz_align=HorizontalAlignment.RIGHT, header_vert_align=VerticalAlignment.BOTTOM, data_horiz_align=HorizontalAlignment.RIGHT, data_vert_align=VerticalAlignment.BOTTOM) column_4 = Column("Three\nline\nheader", width=10) columns = [column_1, column_2, column_3, column_4] tc = TableCreator(columns) # Check defaults assert column_4.header_horiz_align == HorizontalAlignment.LEFT assert column_4.header_vert_align == VerticalAlignment.BOTTOM assert column_4.data_horiz_align == HorizontalAlignment.LEFT assert column_4.data_vert_align == VerticalAlignment.TOP # Create a header row header = tc.generate_row() assert header == ('Col 1 Three \n' ' Col 2 line \n' ' Col 3 header ') # Create a data row row_data = ["Val 1", "Val 2", "Val 3", "Three\nline\ndata"] row = tc.generate_row(row_data=row_data) assert row == ('Val 1 Three \n' ' Val 2 line \n' ' Val 3 data ')
def show_target_info(target): columns: List[Column] = list() data_list: List[List[Any]] = list() columns.append( Column("", width=25, header_horiz_align=HorizontalAlignment.CENTER, data_horiz_align=HorizontalAlignment.RIGHT)) columns.append( Column("", width=80, header_horiz_align=HorizontalAlignment.CENTER, data_horiz_align=HorizontalAlignment.LEFT)) st = SimpleTable(columns) output = "\nTarget Information" data_list.append(["model name", target.model_name]) data_list.append(["model data type", target.model_data_type]) data_list.append(["model endpoint", target.model_endpoint]) data_list.append(["model input shape", target.model_input_shape]) data_list.append([ f"model output classes ({len(target.model_output_classes)})", target.model_output_classes ]) if target.__doc__: data_list.append(["model docs", target.__doc__]) output += st.generate_table(data_list, row_spacing=0) + "\n" if target.active_attack: output += show_attack_info(target.active_attack) return output
def test_wrap_long_word(): # Make sure words wider than column start on own line and wrap column_1 = Column("LongColumnName", width=10) column_2 = Column("Col 2", width=10) columns = [column_1, column_2] tc = TableCreator(columns) # Test header row header = tc.generate_row() assert header == ('LongColumn \n' 'Name Col 2 ') # Test data row row_data = list() # Long word should start on the first line (style should not affect width) row_data.append(ansi.style("LongerThan10", fg=ansi.fg.green)) # Long word should start on the second line row_data.append("Word LongerThan10") row = tc.generate_row(row_data=row_data) expected = (ansi.RESET_ALL + ansi.fg.green + "LongerThan" + ansi.RESET_ALL + " Word \n" + ansi.RESET_ALL + ansi.fg.green + "10" + ansi.fg.reset + ansi.RESET_ALL + ' ' + ansi.RESET_ALL + ' LongerThan\n' ' 10 ') assert row == expected
def test_tabs(): column_1 = Column("Col\t1", width=20) column_2 = Column("Col 2") tc = TableCreator([column_1, column_2], tab_width=2) row = tc.generate_row(fill_char='\t', pre_line='\t', inter_cell='\t', post_line='\t') assert row == ' Col 1 Col 2 '
def test_simple_table(): column_1 = Column("Col 1", width=15) column_2 = Column("Col 2", width=15) row_data = list() row_data.append(["Col 1 Row 1", "Col 2 Row 1"]) row_data.append(["Col 1 Row 2", "Col 2 Row 2"]) # Default options st = SimpleTable([column_1, column_2]) table = st.generate_table(row_data) assert table == ('Col 1 Col 2 \n' '--------------------------------\n' 'Col 1 Row 1 Col 2 Row 1 \n' '\n' 'Col 1 Row 2 Col 2 Row 2 \n') # Custom divider st = SimpleTable([column_1, column_2], divider_char='─') table = st.generate_table(row_data) assert table == ('Col 1 Col 2 \n' '────────────────────────────────\n' 'Col 1 Row 1 Col 2 Row 1 \n' '\n' 'Col 1 Row 2 Col 2 Row 2 \n') # No divider st = SimpleTable([column_1, column_2], divider_char=None) table = st.generate_table(row_data) assert table == ('Col 1 Col 2 \n' 'Col 1 Row 1 Col 2 Row 1 \n' '\n' 'Col 1 Row 2 Col 2 Row 2 \n') # No row spacing st = SimpleTable([column_1, column_2]) table = st.generate_table(row_data, row_spacing=0) assert table == ('Col 1 Col 2 \n' '--------------------------------\n' 'Col 1 Row 1 Col 2 Row 1 \n' 'Col 1 Row 2 Col 2 Row 2 \n') # No header st = SimpleTable([column_1, column_2]) table = st.generate_table(row_data, include_header=False) assert table == ('Col 1 Row 1 Col 2 Row 1 \n' '\n' 'Col 1 Row 2 Col 2 Row 2 \n') # Invalid row spacing st = SimpleTable([column_1, column_2]) with pytest.raises(ValueError) as excinfo: st.generate_table(row_data, row_spacing=-1) assert "Row spacing cannot be less than 0" in str(excinfo.value)
def show_attack_options(attack): columns: List[Column] = list() data_list: List[List[Any]] = list() # create structure to ensure all params are present params_struct = namedtuple( "params", [i for i in attack.default.keys()] + ["sample_index", "target_class"], defaults=list(attack.default.values()) + [0, 0], ) # get default parameters default_params = params_struct() if hasattr(attack, 'parameters'): # get current parameters current_params = {k: v for k, v in attack.parameters.items()} current_params["sample_index"] = attack.sample_index current_params["target_class"] = attack.target_class # ensure everything exists and is ordered correctly current_params = params_struct(**current_params)._asdict() columns.append( Column( "Attack Parameter (type)", width=25, header_horiz_align=HorizontalAlignment.LEFT, data_horiz_align=HorizontalAlignment.RIGHT, )) columns.append( Column( "Default", width=12, header_horiz_align=HorizontalAlignment.CENTER, data_horiz_align=HorizontalAlignment.LEFT, )) if hasattr(attack, 'parameters'): columns.append( Column( "Current", width=12, header_horiz_align=HorizontalAlignment.CENTER, data_horiz_align=HorizontalAlignment.LEFT, )) st = SimpleTable(columns) for k, v in zip(default_params._fields, default_params): param = f"{k} ({str(type(v).__name__)})" default_value = v if hasattr(attack, 'parameters'): # active attack with current parameters? current_value = current_params.get(k, "") data_list.append([param, default_value, current_value]) else: data_list.append([param, default_value]) return st.generate_table(data_list, row_spacing=0) + "\n"
def test_bordered_table_creation(): column_1 = Column("Col 1", width=15) column_2 = Column("Col 2", width=15) row_data = list() row_data.append(["Col 1 Row 1", "Col 2 Row 1"]) row_data.append(["Col 1 Row 2", "Col 2 Row 2"]) # Default options bt = BorderedTable([column_1, column_2]) table = bt.generate_table(row_data) assert table == ('╔═════════════════╤═════════════════╗\n' '║ Col 1 │ Col 2 ║\n' '╠═════════════════╪═════════════════╣\n' '║ Col 1 Row 1 │ Col 2 Row 1 ║\n' '╟─────────────────┼─────────────────╢\n' '║ Col 1 Row 2 │ Col 2 Row 2 ║\n' '╚═════════════════╧═════════════════╝') # No column borders bt = BorderedTable([column_1, column_2], column_borders=False) table = bt.generate_table(row_data) assert table == ('╔══════════════════════════════════╗\n' '║ Col 1 Col 2 ║\n' '╠══════════════════════════════════╣\n' '║ Col 1 Row 1 Col 2 Row 1 ║\n' '╟──────────────────────────────────╢\n' '║ Col 1 Row 2 Col 2 Row 2 ║\n' '╚══════════════════════════════════╝') # No header bt = BorderedTable([column_1, column_2]) table = bt.generate_table(row_data, include_header=False) assert table == ('╔═════════════════╤═════════════════╗\n' '║ Col 1 Row 1 │ Col 2 Row 1 ║\n' '╟─────────────────┼─────────────────╢\n' '║ Col 1 Row 2 │ Col 2 Row 2 ║\n' '╚═════════════════╧═════════════════╝') # Non-default padding bt = BorderedTable([column_1, column_2], padding=2) table = bt.generate_table(row_data) assert table == ('╔═══════════════════╤═══════════════════╗\n' '║ Col 1 │ Col 2 ║\n' '╠═══════════════════╪═══════════════════╣\n' '║ Col 1 Row 1 │ Col 2 Row 1 ║\n' '╟───────────────────┼───────────────────╢\n' '║ Col 1 Row 2 │ Col 2 Row 2 ║\n' '╚═══════════════════╧═══════════════════╝') # Invalid padding with pytest.raises(ValueError) as excinfo: BorderedTable([column_1, column_2], padding=-1) assert "Padding cannot be less than 0" in str(excinfo.value)
def list_frameworks(): columns: List[Column] = list() data_list: List[List[Any]] = list() columns.append(Column("Framework", width=20)) columns.append(Column("# of Attacks", width=30)) for framework, list_of_attacks in CFState.get_instance( ).loaded_frameworks.items(): data_list.append([framework, len(list_of_attacks)]) st = SimpleTable(columns) print() print(st.generate_table(data_list, row_spacing=0)) print()
def test_tabs(): column_1 = Column("Col\t1", width=20) column_2 = Column("Col 2") tc = TableCreator([column_1, column_2], tab_width=2) row = tc.generate_row(fill_char='\t', pre_line='\t', inter_cell='\t', post_line='\t') assert row == ' Col 1 Col 2 ' with pytest.raises(ValueError) as excinfo: TableCreator([column_1, column_2], tab_width=0) assert "Tab width cannot be less than 1" in str(excinfo.value)
def test_wrap_text_max_lines(): column_1 = Column("Col 1", width=10, max_data_lines=2) tc = TableCreator([column_1]) # Test not needing to truncate the final line row_data = ['First line last line'] row = tc.generate_row(row_data=row_data) assert row == ('First line\n' 'last line ') # Test having to truncate the last word because it's too long for the final line row_data = ['First line last lineextratext'] row = tc.generate_row(row_data=row_data) assert row == ('First line\n' 'last line…') # Test having to truncate the last word because it fits the final line but there is more text not being included row_data = ['First line thistxtfit extra'] row = tc.generate_row(row_data=row_data) assert row == ('First line\n' 'thistxtfi…') # Test having to truncate the last word because it fits the final line but there are more lines not being included row_data = ['First line thistxtfit\nextra'] row = tc.generate_row(row_data=row_data) assert row == ('First line\n' 'thistxtfi…') # Test having space left on the final line and adding an ellipsis because there are more lines not being included row_data = ['First line last line\nextra line'] row = tc.generate_row(row_data=row_data) assert row == ('First line\n' 'last line…')
def list_attacks(): columns: List[Column] = list() data_list: List[List[Any]] = list() columns.append(Column("Name", width=25)) columns.append(Column("Type", width=15)) columns.append(Column("Category", width=15)) columns.append(Column("Tags", width=15)) columns.append(Column("Framework", width=10)) for _, attack_obj in CFState.get_instance().loaded_attacks.items(): tags = ", ".join(attack_obj.tags) data_list.append([ attack_obj.attack_name, attack_obj.attack_type, attack_obj.category, tags, attack_obj.framework ]) st = SimpleTable(columns) print() print(st.generate_table(data_list, row_spacing=0)) print()
def test_wrap_long_char_wider_than_max_width(): """ This tests case where a character is wider than max_width. This can happen if max_width is 1 and the text contains wide characters (e.g. East Asian). Replace it with an ellipsis. """ column_1 = Column("Col 1", width=1) tc = TableCreator([column_1]) row = tc.generate_row(row_data=['深']) assert row == '…'
def test_simple_table_width(): # Base width for num_cols in range(1, 10): assert SimpleTable.base_width(num_cols) == (num_cols - 1) * 2 # Invalid num_cols value with pytest.raises(ValueError) as excinfo: SimpleTable.base_width(0) assert "Column count cannot be less than 1" in str(excinfo.value) # Total width column_1 = Column("Col 1", width=16) column_2 = Column("Col 2", width=16) row_data = list() row_data.append(["Col 1 Row 1", "Col 2 Row 1"]) row_data.append(["Col 1 Row 2", "Col 2 Row 2"]) st = SimpleTable([column_1, column_2]) assert st.total_width() == 34
def list_targets(): columns: List[Column] = list() data_list: List[List[Any]] = list() columns.append(Column("Name", width=15)) columns.append(Column("Type", width=15)) columns.append(Column("Input Shape", width=15)) columns.append(Column("Location", width=85)) for _, target_obj in CFState.get_instance().loaded_targets.items(): shp = str(target_obj.model_input_shape) data_list.append([ target_obj.model_name, target_obj.model_data_type, shp, target_obj.model_endpoint ]) st = SimpleTable(columns) print() print(st.generate_table( data_list, row_spacing=0, )) print()
def test_column_creation(): # No width specified, blank label c = Column("") assert c.width == 1 # No width specified, label isn't blank but has no width c = Column(ansi.style('', fg=ansi.fg.green)) assert c.width == 1 # No width specified, label has width c = Column("short\nreally long") assert c.width == ansi.style_aware_wcswidth("really long") # Width less than 1 with pytest.raises(ValueError) as excinfo: Column("Column 1", width=0) assert "Column width cannot be less than 1" in str(excinfo.value) # Width specified c = Column("header", width=20) assert c.width == 20 # max_data_lines less than 1 with pytest.raises(ValueError) as excinfo: Column("Column 1", max_data_lines=0) assert "Max data lines cannot be less than 1" in str(excinfo.value)
def print_generic_table(self, data): columns: List[Column] = list() data_list: List[List[Any]] = list() max_len0 = 0 max_len1 = 0 for row in data: col_len = len(row[0]) if col_len > max_len0: max_len0 = col_len col_len = len(row[1]) if col_len > max_len1: max_len1 = col_len data_list.append(row) columns.append(Column("", width=max_len0)) columns.append(Column("", width=max_len1)) bt = BorderedTable(columns) table = bt.generate_table(data_list, include_header=False) ansi.style_aware_write(sys.stdout, table + '\n\n')
def show_attack_info(attack): columns: List[Column] = list() data_list: List[List[Any]] = list() columns.append( Column( "", width=25, header_horiz_align=HorizontalAlignment.CENTER, data_horiz_align=HorizontalAlignment.RIGHT, )) columns.append( Column("", width=80, header_horiz_align=HorizontalAlignment.CENTER, data_horiz_align=HorizontalAlignment.LEFT)) st = SimpleTable(columns) data_list.append(["attack name", attack.attack_name]) data_list.append(["attack type", attack.attack_type]) data_list.append(["attack category", attack.category]) data_list.append(["attack tags", attack.tags]) data_list.append(["attack framework", attack.framework]) if attack.attack_cls.__doc__: data_list.append([ "attack docs", attack.attack_cls.__doc__.replace('\n', ' ').replace('\t', '').replace( ' ', ' ') ]) output = '\nAttack Information' + st.generate_table(data_list, row_spacing=0) + "\n" output += "\n" + show_attack_options(attack) return output
def test_bordered_table_width(): # Default behavior (column_borders=True, padding=1) assert BorderedTable.base_width(1) == 4 assert BorderedTable.base_width(2) == 7 assert BorderedTable.base_width(3) == 10 # No column borders assert BorderedTable.base_width(1, column_borders=False) == 4 assert BorderedTable.base_width(2, column_borders=False) == 6 assert BorderedTable.base_width(3, column_borders=False) == 8 # No padding assert BorderedTable.base_width(1, padding=0) == 2 assert BorderedTable.base_width(2, padding=0) == 3 assert BorderedTable.base_width(3, padding=0) == 4 # Extra padding assert BorderedTable.base_width(1, padding=3) == 8 assert BorderedTable.base_width(2, padding=3) == 15 assert BorderedTable.base_width(3, padding=3) == 22 # Invalid num_cols value with pytest.raises(ValueError) as excinfo: BorderedTable.base_width(0) assert "Column count cannot be less than 1" in str(excinfo.value) # Total width column_1 = Column("Col 1", width=15) column_2 = Column("Col 2", width=15) row_data = list() row_data.append(["Col 1 Row 1", "Col 2 Row 1"]) row_data.append(["Col 1 Row 2", "Col 2 Row 2"]) bt = BorderedTable([column_1, column_2]) assert bt.total_width() == 37
def test_column_creation(): # Width less than 1 with pytest.raises(ValueError) as excinfo: Column("Column 1", width=0) assert "Column width cannot be less than 1" in str(excinfo.value) # Width specified c = Column("header", width=20) assert c.width == 20 # max_data_lines less than 1 with pytest.raises(ValueError) as excinfo: Column("Column 1", max_data_lines=0) assert "Max data lines cannot be less than 1" in str(excinfo.value) # No width specified, blank label c = Column("") assert c.width is None tc = TableCreator([c]) assert tc.cols[0].width == 1 # No width specified, label isn't blank but has no width c = Column(ansi.style('', fg=ansi.fg.green)) assert c.width is None tc = TableCreator([c]) assert tc.cols[0].width == 1 # No width specified, label has width c = Column("a line") assert c.width is None tc = TableCreator([c]) assert tc.cols[0].width == ansi.style_aware_wcswidth("a line") # No width specified, label has width and multiple lines c = Column("short\nreally long") assert c.width is None tc = TableCreator([c]) assert tc.cols[0].width == ansi.style_aware_wcswidth("really long") # No width specified, label has tabs c = Column("line\twith\ttabs") assert c.width is None tc = TableCreator([c]) assert tc.cols[0].width == ansi.style_aware_wcswidth( "line with tabs")
def test_blank_last_line(): """This tests that an empty line is inserted when the last data line is blank""" column_1 = Column("Col 1", width=10) tc = TableCreator([column_1]) row_data = ['my line\n\n'] row = tc.generate_row(row_data=row_data) assert row == ('my line \n' ' ') row_data = ['\n'] row = tc.generate_row(row_data=row_data) assert row == ' ' row_data = [''] row = tc.generate_row(row_data=row_data) assert row == ' '
def test_wrap_text(): column_1 = Column("Col 1", width=10) tc = TableCreator([column_1]) # Test normal wrapping row_data = ['Some text to wrap\nA new line that will wrap\nNot wrap\n 1 2 3'] row = tc.generate_row(row_data=row_data) assert row == ('Some text \n' 'to wrap \n' 'A new line\n' 'that will \n' 'wrap \n' 'Not wrap \n' ' 1 2 3 ') # Test preserving a multiple space sequence across a line break row_data = ['First last one'] row = tc.generate_row(row_data=row_data) assert row == ('First \n' ' last one ')
def test_generate_row_exceptions(): column_1 = Column("Col 1") tc = TableCreator([column_1]) row_data = ['fake'] # fill_char too long with pytest.raises(TypeError) as excinfo: tc.generate_row(row_data=row_data, fill_char='too long') assert "Fill character must be exactly one character long" in str(excinfo.value) # Unprintable characters for arg in ['fill_char', 'pre_line', 'inter_cell', 'post_line']: kwargs = {arg: '\n'} with pytest.raises(ValueError) as excinfo: tc.generate_row(row_data=row_data, **kwargs) assert "{} contains an unprintable character".format(arg) in str(excinfo.value) # data with too many columns row_data = ['Data 1', 'Extra Column'] with pytest.raises(ValueError) as excinfo: tc.generate_row(row_data=row_data) assert "Length of row_data must match length of cols" in str(excinfo.value)
def print_pivot_table(self): bold = functools.partial(ansi.style, bold=True) columns: List[Column] = list() columns.append(Column(bold("ID"), width=5)) columns.append(Column(bold("Alive"), width=6)) columns.append(Column(bold("Socks Port"), width=12)) columns.append(Column(bold("PID"), width=10)) columns.append(Column(bold("User"), width=25)) columns.append(Column(bold("Computer"), width=25)) columns.append(Column(bold("Last"), width=12)) data_list: List[List[Any]] = list() for pivot in ProxyPivots.instances.values(): data_list.append(pivot.get_list()) bt = BorderedTable(columns, column_borders=False) table = bt.generate_table(data_list) ansi.style_aware_write(sys.stdout, table + '\n\n')
def __init__(self, val: float) -> None: self.val = val def __str__(self) -> str: """Returns the value in dollar currency form (e.g. $100.22)""" return "${:,.2f}".format(self.val) # Text styles used in the data bold_yellow = functools.partial(ansi.style, fg=ansi.fg.bright_yellow, bold=True) blue = functools.partial(ansi.style, fg=ansi.fg.bright_blue) green = functools.partial(ansi.style, fg=ansi.fg.green) # Table Columns (width does not account for any borders or padding which may be added) columns: List[Column] = list() columns.append(Column("Name", width=20)) columns.append(Column("Address", width=38)) columns.append(Column("Income", width=14, header_horiz_align=HorizontalAlignment.RIGHT, data_horiz_align=HorizontalAlignment.RIGHT)) # Table data which demonstrates handling of wrapping and text styles data_list: List[List[Any]] = list() data_list.append(["Billy Smith", "123 Sesame St.\n" "Fake Town, USA 33445", DollarFormatter(100333.03)]) data_list.append(["William Longfellow Marmaduke III", "984 Really Long Street Name Which Will Wrap Nicely\n" "Apt 22G\n" "Pensacola, FL 32501", DollarFormatter(55135.22)]) data_list.append(["James " + blue("Bluestone"),
def do_predict(self, args): """Predict a single sample for the active target""" if CFState.get_instance().active_target is None: self.pwarning("\n [!] must first `interact` with a target.\n") return else: target = CFState.get_instance().active_target if sum([args.random, args.sample_index is not None, args.result]) > 1: self.pwarning("\n [!] must specify only one of {random, sample_index, result}.\n") return heading1 = "Sample Index" if args.random: sample_index = random.randint(0, len(target.X) - 1) samples = set_attack_samples(target, sample_index) elif args.sample_index: # default behavior sample_index = args.sample_index samples = set_attack_samples(target, sample_index) elif args.result: try: samples = target.active_attack.results['final']['input'] sample_index = [target.active_attack.attack_id] * len(samples) heading1 = "Attack ID" except (KeyError, AttributeError): self.pwarning("\n [!] No results found. First 'run' an attack.\n") return elif target.active_attack is not None and target.active_attack.sample_index is not None: sample_index = target.active_attack.sample_index samples = set_attack_samples(target, sample_index) else: self.pwarning("\n [!] No index sample, setting random index.\n") sample_index = random.randint(0, len(target.X) - 1) samples = set_attack_samples(target, sample_index) result = target._submit(samples) columns: List[Column] = list() columns.append( Column( heading1, width=8, header_horiz_align=HorizontalAlignment.LEFT, data_horiz_align=HorizontalAlignment.RIGHT, ) ) columns.append( Column( "Sample", width=60, header_horiz_align=HorizontalAlignment.CENTER, data_horiz_align=HorizontalAlignment.RIGHT, ) ) columns.append( Column( "Output Scores\n" + str(target.model_output_classes).replace(',', ''), width=30, header_horiz_align=HorizontalAlignment.CENTER, data_horiz_align=HorizontalAlignment.RIGHT, ) ) if not hasattr(sample_index, "__iter__"): sample_index = [sample_index] samples_str = get_printable_batch(target, samples) results_str = printable_numpy(result) data_list: List[List[Any]] = list() for idx, samp, res in zip(sample_index, samples_str, results_str): data_list.append([idx, samp, res]) st = SimpleTable(columns) self.poutput("\n" + st.generate_table(data_list, row_spacing=0) + "\n")
def get_printable_scan_summary(summaries_by_attack, summaries_by_label=None): output = "\n =============== \n SCAN SUMMARY \n ===============\n\n" terminal_cols = os.get_terminal_size().columns results_width = terminal_cols - 128 # default Windows is 120x30 if results_width <= 0: output += bold_yellow( """\nIncrease terminal width to show parameters.\n\n""") columns: List[Column] = list() columns.append( Column( "Attack Name", width=15, header_horiz_align=HorizontalAlignment.LEFT, data_horiz_align=HorizontalAlignment.RIGHT, )) columns.append( Column( "Total Runs", width=10, header_horiz_align=HorizontalAlignment.LEFT, data_horiz_align=HorizontalAlignment.RIGHT, )) columns.append( Column( "Successes (%)", width=13, header_horiz_align=HorizontalAlignment.LEFT, data_horiz_align=HorizontalAlignment.RIGHT, )) columns.append( Column( "Time[sec] (min/avg/max)", width=15, header_horiz_align=HorizontalAlignment.LEFT, data_horiz_align=HorizontalAlignment.RIGHT, )) columns.append( Column( "Queries (min/avg/max)", width=18, header_horiz_align=HorizontalAlignment.LEFT, data_horiz_align=HorizontalAlignment.RIGHT, )) columns.append( Column( "Best Score (attack_id)", width=15, header_horiz_align=HorizontalAlignment.LEFT, data_horiz_align=HorizontalAlignment.RIGHT, )) if results_width > 0: columns.append( Column( "Best Parameters", width=25, header_horiz_align=HorizontalAlignment.RIGHT, data_horiz_align=HorizontalAlignment.RIGHT, )) data_list: List[List[Any]] = list() for name, summary in summaries_by_attack.items(): frac = summary["total_successes"] / summary["total_runs"] successes = f"{summary['total_successes']} ({frac:>.1%})" times = f"{summary['min_time']:>4.1f}/{summary['avg_time']:>4.1f}/{summary['max_time']:>4.1f}" queries = f"{summary['min_queries']:>5d}/{summary['avg_queries']:>5d}/{summary['max_queries']:>5d}" best = ( f"{summary['best_attack_score']:0.1f} ({summary['best_attack_id']})" if summary["best_attack_score"] else "N/A") if results_width > 0: if summary["best_params"] is not None: trunc_params = shallow_dict_to_fixed_width( (summary["best_params"])) param_str = json.dumps(trunc_params, indent=1, separators=("", "="))[2:-1].replace( '"', "") else: param_str = "N/A" data_list.append([ name, summary["total_runs"], successes, times, queries, best, param_str ]) else: data_list.append( [name, summary["total_runs"], successes, times, queries, best]) st = SimpleTable(columns) output += '\n' + st.generate_table(data_list, row_spacing=0) + '\n' if summaries_by_label is not None: output += "\n" # table by sample_index columns: List[Column] = list() columns.append( Column( "Class Label", width=15, header_horiz_align=HorizontalAlignment.LEFT, data_horiz_align=HorizontalAlignment.RIGHT, )) columns.append( Column( "Total Runs", width=10, header_horiz_align=HorizontalAlignment.LEFT, data_horiz_align=HorizontalAlignment.RIGHT, )) columns.append( Column( "Successes (%)", width=13, header_horiz_align=HorizontalAlignment.LEFT, data_horiz_align=HorizontalAlignment.RIGHT, )) columns.append( Column( "Time[sec] (min/avg/max)", width=15, header_horiz_align=HorizontalAlignment.LEFT, data_horiz_align=HorizontalAlignment.RIGHT, )) columns.append( Column( "Queries (min/avg/max)", width=18, header_horiz_align=HorizontalAlignment.LEFT, data_horiz_align=HorizontalAlignment.RIGHT, )) columns.append( Column( "Best Score (Attack)", width=15, header_horiz_align=HorizontalAlignment.LEFT, data_horiz_align=HorizontalAlignment.RIGHT, )) data_list: List[List[Any]] = list() for name, summary in sorted(summaries_by_label.items()): frac = summary["total_successes"] / summary["total_runs"] successes = f"{summary['total_successes']} ({frac:>.1%})" times = f"{summary['min_time']:>4.1f}/{summary['avg_time']:>4.1f}/{summary['max_time']:>4.1f}" queries = f"{summary['min_queries']:>5d}/{summary['avg_queries']:>5d}/{summary['max_queries']:>5d}" best = ( f"{summary['best_attack_score']:0.1f} ({summary['best_attack_name']})" if summary["best_attack_score"] else "N/A") data_list.append( [name, summary["total_runs"], successes, times, queries, best]) st = SimpleTable(columns) output += '\n' + st.generate_table(data_list, row_spacing=0) + '\n' return output
def test_simple_table_creation(): column_1 = Column("Col 1", width=16) column_2 = Column("Col 2", width=16) row_data = list() row_data.append(["Col 1 Row 1", "Col 2 Row 1"]) row_data.append(["Col 1 Row 2", "Col 2 Row 2"]) # Default options st = SimpleTable([column_1, column_2]) table = st.generate_table(row_data) assert table == ('Col 1 Col 2 \n' '----------------------------------\n' 'Col 1 Row 1 Col 2 Row 1 \n' '\n' 'Col 1 Row 2 Col 2 Row 2 ') # Custom divider st = SimpleTable([column_1, column_2], divider_char='─') table = st.generate_table(row_data) assert table == ('Col 1 Col 2 \n' '──────────────────────────────────\n' 'Col 1 Row 1 Col 2 Row 1 \n' '\n' 'Col 1 Row 2 Col 2 Row 2 ') # No divider st = SimpleTable([column_1, column_2], divider_char=None) table = st.generate_table(row_data) assert table == ('Col 1 Col 2 \n' 'Col 1 Row 1 Col 2 Row 1 \n' '\n' 'Col 1 Row 2 Col 2 Row 2 ') # No row spacing st = SimpleTable([column_1, column_2]) table = st.generate_table(row_data, row_spacing=0) assert table == ('Col 1 Col 2 \n' '----------------------------------\n' 'Col 1 Row 1 Col 2 Row 1 \n' 'Col 1 Row 2 Col 2 Row 2 ') # No header st = SimpleTable([column_1, column_2]) table = st.generate_table(row_data, include_header=False) assert table == ('Col 1 Row 1 Col 2 Row 1 \n' '\n' 'Col 1 Row 2 Col 2 Row 2 ') # Wide custom divider (divider needs no padding) st = SimpleTable([column_1, column_2], divider_char='深') table = st.generate_table(row_data) assert table == ('Col 1 Col 2 \n' '深深深深深深深深深深深深深深深深深\n' 'Col 1 Row 1 Col 2 Row 1 \n' '\n' 'Col 1 Row 2 Col 2 Row 2 ') # Wide custom divider (divider needs padding) column_2 = Column("Col 2", width=17) st = SimpleTable([column_1, column_2], divider_char='深') table = st.generate_table(row_data) assert table == ('Col 1 Col 2 \n' '深深深深深深深深深深深深深深深深深 \n' 'Col 1 Row 1 Col 2 Row 1 \n' '\n' 'Col 1 Row 2 Col 2 Row 2 ') # Invalid divider character with pytest.raises(TypeError) as excinfo: SimpleTable([column_1, column_2], divider_char='too long') assert "Divider character must be exactly one character long" in str(excinfo.value) with pytest.raises(ValueError) as excinfo: SimpleTable([column_1, column_2], divider_char='\n') assert "Divider character is an unprintable character" in str(excinfo.value) # Invalid row spacing st = SimpleTable([column_1, column_2]) with pytest.raises(ValueError) as excinfo: st.generate_table(row_data, row_spacing=-1) assert "Row spacing cannot be less than 0" in str(excinfo.value)