Skip to content

Commit

Permalink
Fix most pylint warnings, add main()s
Browse files Browse the repository at this point in the history
Move all CLI script code under `if __name__ == "__main__"` to separate
module-level `main()` methods that serve as the entrypoint. This fixes
many invalid-name errors and all redefined-outer-name errors.

Sort imports alphabetically, and group them in the order:
builtins, 3rd-parties, local stuff. This eliminates import-related
warnings.

Other minor warnings are dealt with by fixing the code, or disabling the
warning if it is a false positive.

Notably, refactor warnings (Rxxxx) are not handled. These require
considerably more thought to work out. Since VS code doesn't show them
as errors, we're in no rush.

Unrelated to Pylint warnings: In sample scripts, remove the statements
that directly added the project root to sys.path. This was a hack used
to make d2txt.py importable in sample scripts. Now that we have
`pip install -e .`, there's no need to tamper with sys.path.

Note: As of Pylint 2.4.4, it incorrectly believes that all module-level
variables are constants, and emits invalid-name on them. This check had
to be disabled via comments sprinkled throughout the codebase.
Looks like this will be fixed in Pylint 2.5.0, though. It's already been
integrated into the main branch:
pylint-dev/pylint@3422e4a

Also see relevant issues that motivated the change:
- pylint-dev/pylint#3111
- pylint-dev/pylint#3132

The latest changelog with the fix mentioned under 2.5.0 changes:
https://github.com/PyCQA/pylint/blob/f2f4e6f42416644471ab003d4df7ecf052c3c411/ChangeLog
  • Loading branch information
pastelmind committed Jan 22, 2020
1 parent 4ed39d2 commit 6d918cf
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 60 deletions.
9 changes: 7 additions & 2 deletions d2txt.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import collections.abc
import csv
from itertools import islice
import sys
from typing import Any
from typing import List
from typing import Tuple
Expand Down Expand Up @@ -429,7 +430,8 @@ def toml_to_d2txt(toml_data: str) -> D2TXT:
return d2txt_data


if __name__ == "__main__":
def main(argv: List[str]) -> None:
"""Entrypoint of the command line script."""
arg_parser = ArgumentParser()
arg_subparsers = arg_parser.add_subparsers(dest="command")

Expand All @@ -445,7 +447,7 @@ def toml_to_d2txt(toml_data: str) -> D2TXT:
arg_parser_decompile.add_argument("txtfile", help="TXT file to read from")
arg_parser_decompile.add_argument("tomlfile", help="TOML file to write to")

args = arg_parser.parse_args()
args = arg_parser.parse_args(argv)

if args.command is None:
arg_parser.print_help()
Expand All @@ -460,3 +462,6 @@ def toml_to_d2txt(toml_data: str) -> D2TXT:
else:
raise RuntimeError(f"Unexpected command: {args.command!r}")


if __name__ == "__main__":
main(sys.argv[1:])
15 changes: 7 additions & 8 deletions samples/add_skpoint_restrictions.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,8 @@
Note: This script modifies Skills.txt.
"""


import argparse
import sys
from os import path

sys.path.insert(0, path.abspath(path.join(path.dirname(__file__), "..")))

from d2txt import D2TXT

Expand Down Expand Up @@ -64,9 +61,8 @@ def combine_skpoints_check_formula(formulas):
return f"({formulas}) ? 1 : 999"


if __name__ == "__main__":
import argparse

def main(argv):
"""Entrypoint of the command line script."""
arg_parser = argparse.ArgumentParser(description=__doc__)
arg_parser.add_argument("skills_txt", help="Path to Skills.txt")
arg_parser.add_argument(
Expand All @@ -85,7 +81,7 @@ def combine_skpoints_check_formula(formulas):
help="If provided, specifies minimum blvl of all reqskills as a requirement",
)

args = arg_parser.parse_args()
args = arg_parser.parse_args(argv)

skills_txt = D2TXT.load_txt(args.skills_txt)
num_skills_updated = 0
Expand Down Expand Up @@ -114,3 +110,6 @@ def combine_skpoints_check_formula(formulas):
skills_txt.to_txt(args.skills_txt)
print(f"{num_skills_updated} skill(s) updated in {args.skills_txt}")


if __name__ == "__main__":
main(sys.argv[1:])
18 changes: 9 additions & 9 deletions samples/group_weapons_by_hand.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,8 @@
Note: This script modifies Weapons.txt.
"""


import argparse
import sys
from os import path

sys.path.insert(0, path.abspath(path.join(path.dirname(__file__), "..")))

from d2txt import D2TXT

Expand All @@ -35,9 +32,8 @@ def check_item_code(item_code):
return item_code


if __name__ == "__main__":
import argparse

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")
Expand All @@ -57,7 +53,7 @@ def check_item_code(item_code):
help="If provided, item code to assign to 1-or-2-hand weapons",
)

args = vars(arg_parser.parse_args())
args = vars(arg_parser.parse_args(argv))

weapons_txt = D2TXT.load_txt(args["weapons_txt"])

Expand All @@ -69,7 +65,8 @@ def check_item_code(item_code):

if weapon["type2"]:
print(
f'Warning: Row {row_index + 1} is skipped -- {weapon["name"]} already has \'type2\' assigned.'
f"Warning: Row {row_index + 1} is skipped -- "
f'{weapon["name"]} already has \'type2\' assigned.'
)
continue

Expand Down Expand Up @@ -97,3 +94,6 @@ def check_item_code(item_code):
f'\'{args["both"]}\' has been assigned to {num_both} 1-or-2-hand weapon(s)'
)


if __name__ == "__main__":
main(sys.argv[1:])
19 changes: 10 additions & 9 deletions samples/itype_analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,16 @@

"""Reads ItemTypes.txt, Weapons.txt and prints graphs of the item type hierarchy."""


import colorama
import argparse
import sys
from os import path

sys.path.insert(0, path.abspath(path.join(path.dirname(__file__), "..")))
import colorama
from colorama import Fore

from d2txt import D2TXT


colorama.init()
Fore = colorama.Fore


class ITypeNode:
Expand Down Expand Up @@ -129,14 +127,13 @@ def print_itype_tree(node, one_handers=None, two_handers=None, current_depth=0):
print_itype_tree(child, one_handers, two_handers, current_depth + 1)


if __name__ == "__main__":
import argparse

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()
args = arg_parser.parse_args(argv)

item_types_txt = D2TXT.load_txt(args.itemtypes_txt)
weapons_txt = D2TXT.load_txt(args.weapons_txt)
Expand All @@ -154,3 +151,7 @@ def print_itype_tree(node, one_handers=None, two_handers=None, current_depth=0):
for node in itype_nodes.values():
if not node.parents:
print_itype_tree(node, one_handers=one_handers, two_handers=two_handers)


if __name__ == "__main__":
main(sys.argv[1:])
Original file line number Diff line number Diff line change
Expand Up @@ -11,41 +11,38 @@
Note: This script modifies TreasureClassEx.txt.
"""


import argparse
import re
import sys
from os import path

sys.path.insert(0, path.abspath(path.join(path.dirname(__file__), "..")))

from d2txt import D2TXT
import re


class DuplicateKeyError(Exception):
pass
"Error raised when a duplicate key is found."


def make_tc_dict(tcex_txt):
"""Returns a dictionary of rows in TreasureClassEx.txt keyed by name."""
tc_dict = {}
for tc in tcex_txt:
name = tc["Treasure Class"]
for tc_entry in tcex_txt:
name = tc_entry["Treasure Class"]
if name in tc_dict:
raise DuplicateKeyError(name)
tc_dict[name] = tc
tc_dict[name] = tc_entry
return tc_dict


TC_PROB_COLUMNS = {f"Item{i}": f"Prob{i}" for i in range(1, 11)}


def sum_probs(tc):
def sum_probs(tc_entry):
"""Returns the sum of all `ProbN` fields in the given treasureclass row."""
total_probs = 0
for item_col, prob_col in TC_PROB_COLUMNS.items():
if not tc[item_col]:
if not tc_entry[item_col]:
continue
total_probs += int(tc[prob_col])
total_probs += int(tc_entry[prob_col])
return total_probs


Expand All @@ -54,9 +51,8 @@ def match_in_patterns(text, patterns):
return any(pattern.search(text) for pattern in patterns)


if __name__ == "__main__":
import argparse

def main(argv):
"""Entrypoint of the command line script."""
arg_parser = argparse.ArgumentParser(description=__doc__)
arg_parser.add_argument("tcex_txt", help="Path to TreasureClassEx.txt")
arg_parser.add_argument(
Expand All @@ -66,7 +62,7 @@ def match_in_patterns(text, patterns):
"-i", "--ignore-case", action="store_true", help="Use case-insensitive matching"
)

args = arg_parser.parse_args()
args = arg_parser.parse_args(argv)

tcex_txt = D2TXT.load_txt(args.tcex_txt)
tc_dict = make_tc_dict(tcex_txt)
Expand All @@ -82,8 +78,8 @@ def match_in_patterns(text, patterns):

num_matched_tcs = 0
num_rebalanced_tcs = 0
for tc in tcex_txt:
name = tc["Treasure Class"]
for tc_entry in tcex_txt:
name = tc_entry["Treasure Class"]
if not match_in_patterns(name, tc_patterns):
continue

Expand All @@ -93,15 +89,19 @@ def match_in_patterns(text, patterns):
# 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[item_col]
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[prob_col] = sum_probs(tc_dict[item_name])
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, {num_rebalanced_tcs} treasureclass(es) rebalanced."
f"{num_matched_tcs} treasureclass(es) matched, "
f"{num_rebalanced_tcs} treasureclass(es) rebalanced."
)


if __name__ == "__main__":
main(sys.argv[1:])
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


with open("README.md", "r") as readme_md:
readme = readme_md.read()
readme = readme_md.read() # pylint: disable=invalid-name

setuptools.setup(
name="d2txt",
Expand Down
11 changes: 5 additions & 6 deletions tests/test_d2txt.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def test_empty_txt(self):
d2txt = D2TXT([])
self.assertEqual(len(d2txt), 0)
with self.assertRaises(IndexError):
d2txt[0]
d2txt[0] # pylint:disable=pointless-statement
with self.assertRaises(IndexError):
d2txt[0] = []

Expand Down Expand Up @@ -93,15 +93,15 @@ def test_invalid_row_and_cell(self):
d2txt.append(["one", "two", "six"])

with self.assertRaises(IndexError):
d2txt[99]
d2txt[99] # pylint:disable=pointless-statement
with self.assertRaises(IndexError):
d2txt[99] = ["mangy", "dog", "cow"]
with self.assertRaises(IndexError):
d2txt[99]["column 1"]
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"]
d2txt[0]["column 99"] # pylint:disable=pointless-statement
with self.assertRaises(KeyError):
d2txt[0]["column 99"] = "bird"

Expand All @@ -114,7 +114,7 @@ def test_column_name_case_sensitivity(self):
list(d2txt[0].values()), ["lowercase", "capital letters", "uppercase"],
)
with self.assertRaises(KeyError):
d2txt[0]["column NAME"]
d2txt[0]["column NAME"] # pylint:disable=pointless-statement

d2txt[0]["COLUMN NAME"] = "c"
d2txt[0]["Column Name"] = "b"
Expand Down Expand Up @@ -589,4 +589,3 @@ def test_surrounding_quotes(self):
"'single quotes'\t\"double quotes\"\t`backticks`\r\n"
"'single quotes'\t\"double quotes\"\t`backticks`\r\n",
)

12 changes: 8 additions & 4 deletions tests/test_toml.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"""Unit test for conversion to and from TOML."""

import os
from os import path
from tempfile import NamedTemporaryFile
import unittest

Expand Down Expand Up @@ -92,12 +91,17 @@ def test_bitfield_decode(self):
d2txt = D2TXT(["aurafilter"])
d2txt.extend([["33025"], ["0"], ["65535"], ["4294901760"]])

self.maxDiff = None
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",
"[[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",
)

0 comments on commit 6d918cf

Please sign in to comment.