def test_load_file_object(self): """Tests if D2TXT can load a TXT file from a file object.""" d2txt = D2TXT.load_txt( StringIO( "column 1\tcolumn 2\tcolumn 3\r\n" "value 1\tvalue 2\tvalue 3\r\n" "foo\tbar\tbaz\r\n", newline="", # Required to make csv.reader work correctly )) self.compare_d2txt( d2txt, ["column 1", "column 2", "column 3"], [["value 1", "value 2", "value 3"], ["foo", "bar", "baz"]], )
def test_save_to_file_object(self): """Tests if D2TXT can be saved to a file object.""" d2txt = D2TXT(["column 1", "column 2", "column 3"]) d2txt.extend([["value 1", "value 2", "value 3"], ["foo", "bar", "baz"]]) # newline='' is required to make csv.writer work correctly txtfile = StringIO(newline="") d2txt.to_txt(txtfile) self.assertEqual( txtfile.getvalue(), "column 1\tcolumn 2\tcolumn 3\r\n" "value 1\tvalue 2\tvalue 3\r\n" "foo\tbar\tbaz\r\n", )
def test_column_name_whitespace(self): """Tests if whitespace in columns are preserved when saved to a file.""" d2txt = D2TXT( [" column 1", "column 2 ", " column 3 ", "", " "]) d2txt.extend( [["3 before", "4 after", "2 both", "empty", "spaces only"]]) # newline='' is required to make csv.writer work correctly txtfile = StringIO(newline="") d2txt.to_txt(txtfile) self.assertEqual( txtfile.getvalue(), " column 1\tcolumn 2 \t column 3 \t\t \r\n" "3 before\t4 after\t2 both\tempty\tspaces only\r\n", )
def test_cell_access(self): """Tests if cells can be accessed using row indices and column names.""" d2txt = D2TXT(["column 1", "column 2", "column 3"]) d2txt.append(["foo", "bar", "baz"]) self.assertEqual(d2txt[0]["column 1"], "foo") self.assertEqual(d2txt[0]["column 2"], "bar") self.assertEqual(d2txt[0]["column 3"], "baz") d2txt[0]["column 1"] = "alpha" d2txt[0]["column 2"] = "beta" d2txt[0]["column 3"] = "gamma" self.assertEqual(d2txt[0]["column 1"], "alpha") self.assertEqual(d2txt[0]["column 2"], "beta") self.assertEqual(d2txt[0]["column 3"], "gamma")
def main(argv): """Entrypoint of the command line script.""" arg_parser = argparse.ArgumentParser(__doc__) arg_parser.add_argument("itemtypes_txt", help="Path to ItemTypes.txt") arg_parser.add_argument("weapons_txt", help="Path to Weapons.txt") args = arg_parser.parse_args(argv) item_types_txt = D2TXT.load_txt(args.itemtypes_txt) weapons_txt = D2TXT.load_txt(args.weapons_txt) itype_nodes = parse_itypes(item_types_txt) one_handers, two_handers, mixed_types = classify_itypes_by_hand( itype_nodes, weapons_txt ) print("One-handers: " + ", ".join(one_handers)) print("Two-handers: " + ", ".join(two_handers)) print("Mixed bags : " + ", ".join(mixed_types)) print("-" * 80) for node in itype_nodes.values(): if not node.parents: print_itype_tree(node, one_handers=one_handers, two_handers=two_handers)
def test_assign_list(self): """Tests if D2TXT accepts direct assignment using lists.""" d2txt = D2TXT(["column 1", "column 2", "column 3"]) d2txt.extend([[]] * 3) d2txt[0] = [] d2txt[1] = ["foo", "bar"] d2txt[2] = ["1", "2", "3", "these", "strings", "are", "ignored"] self.assertEqual(len(d2txt), 3) for i, row in enumerate(d2txt): with self.subTest(i=i): self.assertEqual(len(row), 3) self.assertEqual(list(d2txt[0].values()), [None, None, None]) self.assertEqual(list(d2txt[1].values()), ["foo", "bar", None]) self.assertEqual(list(d2txt[2].values()), ["1", "2", "3"])
def test_save_to_path(self): """Tests if D2TXT can be saved to a file path.""" d2txt = D2TXT(["column 1", "column 2", "column 3"]) d2txt.extend([["value 1", "value 2", "value 3"], ["foo", "bar", "baz"]]) d2txt.to_txt(type(self).save_txt_path) # newline='' is required to make csv.writer work correctly with open(type(self).save_txt_path, newline="") as save_txt: saved_contents = save_txt.read() self.assertEqual( saved_contents, "column 1\tcolumn 2\tcolumn 3\r\n" "value 1\tvalue 2\tvalue 3\r\n" "foo\tbar\tbaz\r\n", )
def test_column_name_case_sensitivity(self): """Tests if column names are case-sensitive.""" d2txt = D2TXT(["column name", "Column Name", "COLUMN NAME"]) d2txt.append(["lowercase", "capital letters", "uppercase"]) self.assertEqual( list(d2txt[0].values()), ["lowercase", "capital letters", "uppercase"], ) with self.assertRaises(KeyError): d2txt[0]["column NAME"] # pylint:disable=pointless-statement d2txt[0]["COLUMN NAME"] = "c" d2txt[0]["Column Name"] = "b" d2txt[0]["column name"] = "a" self.assertEqual(list(d2txt[0].values()), ["a", "b", "c"]) with self.assertRaises(KeyError): d2txt[0]["column NAME"] = 1
def test_insert_list(self): """Tests if D2TXT.insert() accepts lists.""" d2txt = D2TXT(["column 1", "column 2", "column 3"]) d2txt.insert(0, []) self.assertEqual(len(d2txt), 1) d2txt.insert(0, ["foo", "bar"]) self.assertEqual(len(d2txt), 2) d2txt.insert(1, ["1", "2", "3", "these", "strings", "are", "ignored"]) self.assertEqual(len(d2txt), 3) for i, row in enumerate(d2txt): with self.subTest(i=i): self.assertEqual(len(row), 3) self.assertEqual(list(d2txt[0].values()), ["foo", "bar", None]) self.assertEqual(list(d2txt[1].values()), ["1", "2", "3"]) self.assertEqual(list(d2txt[2].values()), [None, None, None])
def test_invalid_row_and_cell(self): """Tests if accessing invalid rows and cells raises appropriate exceptions.""" d2txt = D2TXT(["column 1", "column 2", "column 3"]) d2txt.append(["foo", "bar", "baz"]) d2txt.append(["rabbit", "dog", "cow"]) d2txt.append(["one", "two", "six"]) with self.assertRaises(IndexError): d2txt[99] # pylint:disable=pointless-statement with self.assertRaises(IndexError): d2txt[99] = ["mangy", "dog", "cow"] with self.assertRaises(IndexError): d2txt[99]["column 1"] # pylint:disable=pointless-statement with self.assertRaises(IndexError): d2txt[99]["column 1"] = "cat" with self.assertRaises(KeyError): d2txt[0]["column 99"] # pylint:disable=pointless-statement with self.assertRaises(KeyError): d2txt[0]["column 99"] = "bird"
def test_array_group_pack(self): """Tests if columns belonging to an array group are properly packed.""" COLUMN_GROUPS.extend( initialize_column_groups( ("--ArrayGroup", ("column 2", "column 1", "COLUMN 4")))) d2txt = D2TXT(["column 1", "column 2", "column 3", "column 4"]) d2txt.extend([["foo", "bar", 225, 45]]) self.assertEqual( d2txt_to_toml(d2txt), "columns = [\n" " 'column 1',\n 'column 2',\n 'column 3',\n 'column 4',\n" "]\n\n" "[column_groups]\n" "--ArrayGroup = ['column 2', 'column 1', 'column 4']\n\n" "[[rows]]\n" "--ArrayGroup = ['bar', 'foo', '45']\n" "'column 3' = 225\n\n", )
def test_bitfield_decode(self): """Tests if bitfields are correctly decoded when saved to TOML file.""" d2txt = D2TXT(["aurafilter"]) d2txt.extend([["33025"], ["0"], ["65535"], ["4294901760"]]) self.maxDiff = None # pylint: disable=invalid-name self.assertEqual( d2txt_to_toml(d2txt), "columns = [\n 'aurafilter',\n]\n\n" "[[rows]]\naurafilter = [['FindPlayers', 'NotInsideTowns', 'IgnoreAllies']]\n\n" "[[rows]]\naurafilter = [[]]\n\n" "[[rows]]\naurafilter = " "[['FindPlayers', 'FindMonsters', 'FindOnlyUndead', 'FindMissiles', " "'FindObjects', 'FindItems', 'FindAttackable', 'NotInsideTowns', " "'UseLineOfSight', 'FindSelectable', 'FindCorpses', 'NotInsideTowns2', " "'IgnoreBoss', 'IgnoreAllies'], [0x840]]\n\n" "[[rows]]\naurafilter = " "[['IgnoreNPC', 'IgnorePrimeEvil', 'IgnoreJustHitUnits'], [0xFFF20000]]\n\n", )
def test_extend_list(self): """Tests if D2TXT.extend() accepts lists.""" d2txt = D2TXT(["column 1", "column 2", "column 3"]) # Internally uses D2TXT.append(), which uses D2TXT.insert() d2txt.extend([[]]) self.assertEqual(len(d2txt), 1) d2txt.extend([ ["foo", "bar"], ["1", "2", "3", "these", "strings", "are", "ignored"], ]) self.assertEqual(len(d2txt), 3) for i, row in enumerate(d2txt): with self.subTest(i=i): self.assertEqual(len(row), 3) self.assertEqual(list(d2txt[0].values()), [None, None, None]) self.assertEqual(list(d2txt[1].values()), ["foo", "bar", None]) self.assertEqual(list(d2txt[2].values()), ["1", "2", "3"])
def main(argv): """Entrypoint of the command line script.""" args = parse_args(argv) tcex_txt = D2TXT.load_txt(args.tcex_txt) tc_dict = make_tc_dict(tcex_txt) re_flags = 0 if args.ignore_case: re_flags = re.IGNORECASE tc_patterns = [] for pattern_index, pattern_str in enumerate(args.pattern): print(f"Pattern {pattern_index + 1}: {repr(pattern_str)}") tc_patterns.append(re.compile(pattern_str, flags=re_flags)) num_matched_tcs = 0 num_rebalanced_tcs = 0 for tc_entry in tcex_txt: name = tc_entry["Treasure Class"] if not match_in_patterns(name, tc_patterns): continue num_matched_tcs += 1 # Rebalance treasureclasses from top to bottom. Since a treasureclass # can only refer to other TCs above its row, we assume that all previous # TCs have already been rebalanced. for item_col, prob_col in TC_PROB_COLUMNS.items(): item_name = tc_entry[item_col] if not item_name: continue if item_name in tc_dict and match_in_patterns( item_name, tc_patterns): tc_entry[prob_col] = sum_probs(tc_dict[item_name]) num_rebalanced_tcs += 1 tcex_txt.to_txt(args.tcex_txt) print(f"{num_matched_tcs} treasureclass(es) matched, " f"{num_rebalanced_tcs} treasureclass(es) rebalanced.")
def test_falsy_cell(self): """Tests if falsy values in cells are preserved when saved to a file. Tested values include None, integer 0, float 0.0, and False. """ d2txt = D2TXT(["column 1", "column 2", "column 3"]) d2txt.extend([ ["empty", "", ""], ["", "", ""], ["None", None, None], [None, None, None], ["integer 0", 0, 0], [0, 0, 0], ["float 0.0", 0.0, 0.0], [0.0, 0.0, 0.0], ["False", False, False], [False, False, False], ["truncated row"], [], ]) # newline='' is required to make csv.writer work correctly txtfile = StringIO(newline="") d2txt.to_txt(txtfile) self.assertEqual( txtfile.getvalue(), "column 1\tcolumn 2\tcolumn 3\r\n" "empty\t\t\r\n" "\t\t\r\n" "None\t\t\r\n" "\t\t\r\n" "integer 0\t0\t0\r\n" "0\t0\t0\r\n" "float 0.0\t0.0\t0.0\r\n" "0.0\t0.0\t0.0\r\n" "False\tFalse\tFalse\r\n" "False\tFalse\tFalse\r\n" "truncated row\t\t\r\n" "\t\t\r\n", )
def test_load_path(self): """Tests if D2TXT can load a file using a file path, and its contents are preserved.""" file_path = path.join(path.dirname(path.abspath(__file__)), "sample.txt") d2txt = D2TXT.load_txt(file_path) self.compare_d2txt( d2txt, [ "column name", "column 2", "column 3", "", "COLUMN NAME", ], [ [ "lowercase column name", "next cell is empty", "", "empty column name", "UPPERCASE COLUMN NAME", ], [ "next row is empty", " leading spaces", "trailing spaces ", " surrounded by spaces ", '"double quotes"', ], ["", "", "", "", "0"], [ "this row and the next has not enough cells", None, None, None, None ], [None, None, None, None, None], ], )
def test_column_assignment(self): """Tests column name assignment.""" base_column_names = ["column 1", "column 2", "column 3"] d2txt = D2TXT(base_column_names) self.assertEqual(list(d2txt.column_names()), base_column_names)
def test_duplicate_column_names(self): """Tests if duplicate column names cause an error.""" with self.assertRaises(DuplicateColumnNameError): D2TXT(["column name"] * 60)
def main(argv): """Entrypoint of the command line script.""" arg_parser = argparse.ArgumentParser(description=__doc__) arg_parser.add_argument("weapons_txt", help="Path to Weapons.txt") arg_parser.add_argument( "--1h", type=check_item_code, help="If provided, item code to assign to 1-hand weapons", ) arg_parser.add_argument( "--2h", type=check_item_code, help="If provided, item code to assign to 2-hand weapons", ) arg_parser.add_argument( "--both", type=check_item_code, help="If provided, item code to assign to 1-or-2-hand weapons", ) args = vars(arg_parser.parse_args(argv)) weapons_txt = D2TXT.load_txt(args["weapons_txt"]) num_1h = num_2h = num_both = 0 for row_index, weapon in enumerate(weapons_txt): if not (weapon["type"] and weapon["code"]): continue if weapon["type2"]: print(f"Warning: Row {row_index + 1} is skipped -- " f'{weapon["name"]} already has \'type2\' assigned.') continue if weapon["1or2handed"]: item_code = args["both"] num_both += 1 elif weapon["2handed"]: item_code = args["2h"] num_2h += 1 else: item_code = args["1h"] num_1h += 1 if item_code: weapon["type2"] = item_code weapons_txt.to_txt(args["weapons_txt"]) if args["1h"]: print( f'\'{args["1h"]}\' has been assigned to {num_1h} 1-hand weapon(s)') if args["2h"]: print( f'\'{args["2h"]}\' has been assigned to {num_2h} 2-hand weapon(s)') if args["both"]: print( f'\'{args["both"]}\' has been assigned to {num_both} 1-or-2-hand weapon(s)' )