Add only-type-any and only-type-all options (#241)
* Added only-type options * added ci test for only-type options
This commit is contained in:
parent
a796dc59bd
commit
088c3b633d
134
domdiv/main.py
134
domdiv/main.py
@ -27,12 +27,6 @@ LINE_CHOICES = ["line", "dot", "cropmarks", "dot-cropmarks"]
|
|||||||
|
|
||||||
EDITION_CHOICES = ["1", "2", "latest", "all"]
|
EDITION_CHOICES = ["1", "2", "latest", "all"]
|
||||||
|
|
||||||
EXPANSION_CHOICES = ["adventures", "alchemy", "base", "cornucopia", "dark ages",
|
|
||||||
"dominion1stEdition", "dominion2ndEdition", "dominion2ndEditionUpgrade",
|
|
||||||
"empires", "guilds", "hinterlands",
|
|
||||||
"intrigue1stEdition", "intrigue2ndEdition", "intrigue2ndEditionUpgrade",
|
|
||||||
"promo", "prosperity", "renaissance", "seaside", "nocturne"]
|
|
||||||
FAN_CHOICES = ["animals"]
|
|
||||||
ORDER_CHOICES = ["expansion", "global", "colour", "cost"]
|
ORDER_CHOICES = ["expansion", "global", "colour", "cost"]
|
||||||
|
|
||||||
LANGUAGE_DEFAULT = 'en_us' # the primary language used if a language's parts are missing
|
LANGUAGE_DEFAULT = 'en_us' # the primary language used if a language's parts are missing
|
||||||
@ -63,6 +57,46 @@ def get_resource_stream(path):
|
|||||||
return codecs.EncodedFile(pkg_resources.resource_stream('domdiv', path), "utf-8")
|
return codecs.EncodedFile(pkg_resources.resource_stream('domdiv', path), "utf-8")
|
||||||
|
|
||||||
|
|
||||||
|
def get_expansions():
|
||||||
|
set_db_filepath = os.path.join("card_db", "sets_db.json")
|
||||||
|
with get_resource_stream(set_db_filepath) as setfile:
|
||||||
|
set_file = json.loads(setfile.read().decode('utf-8'))
|
||||||
|
assert set_file, "Could not load any sets from database"
|
||||||
|
|
||||||
|
fan = []
|
||||||
|
official = []
|
||||||
|
for s in set_file:
|
||||||
|
if 'extras' not in s:
|
||||||
|
# Make sure this are set either True or False
|
||||||
|
set_file[s]['fan'] = set_file[s].get('fan', False)
|
||||||
|
if set_file[s]['fan']:
|
||||||
|
fan.append(s)
|
||||||
|
else:
|
||||||
|
official.append(s)
|
||||||
|
fan.sort()
|
||||||
|
official.sort()
|
||||||
|
return official, fan
|
||||||
|
|
||||||
|
|
||||||
|
EXPANSION_CHOICES, FAN_CHOICES = get_expansions()
|
||||||
|
|
||||||
|
|
||||||
|
def get_types(language='en_us'):
|
||||||
|
# get a list of valid types
|
||||||
|
language = language.lower()
|
||||||
|
type_text_filepath = os.path.join("card_db", language, "types_{}.json".format(language))
|
||||||
|
with get_resource_stream(type_text_filepath) as type_text_file:
|
||||||
|
type_text = json.loads(type_text_file.read().decode('utf-8'))
|
||||||
|
assert type_text, "Could not load type file for %r" % language
|
||||||
|
|
||||||
|
types = [x.lower() for x in type_text]
|
||||||
|
types.sort()
|
||||||
|
return types
|
||||||
|
|
||||||
|
|
||||||
|
TYPE_CHOICES = get_types(LANGUAGE_DEFAULT)
|
||||||
|
|
||||||
|
|
||||||
# Load Label information
|
# Load Label information
|
||||||
LABEL_INFO = None
|
LABEL_INFO = None
|
||||||
LABEL_CHOICES = []
|
LABEL_CHOICES = []
|
||||||
@ -301,8 +335,7 @@ def parse_opts(cmdline_args=None):
|
|||||||
"'*' any number of characters, '?' matches any single character, "
|
"'*' any number of characters, '?' matches any single character, "
|
||||||
"'[seq]' matches any character in seq, and '[!seq]' matches any character not in seq. "
|
"'[seq]' matches any character in seq, and '[!seq]' matches any character not in seq. "
|
||||||
"For example, 'dominion*' will match all expansions that start with 'dominion'. "
|
"For example, 'dominion*' will match all expansions that start with 'dominion'. "
|
||||||
"Choices available in all languages include: %s" %
|
"Choices available in all languages include: {}".format(", ".join("%s" % x for x in EXPANSION_CHOICES)))
|
||||||
", ".join("%s" % x for x in EXPANSION_CHOICES))
|
|
||||||
group_select.add_argument(
|
group_select.add_argument(
|
||||||
"--fan",
|
"--fan",
|
||||||
nargs="*",
|
nargs="*",
|
||||||
@ -316,8 +349,7 @@ def parse_opts(cmdline_args=None):
|
|||||||
"Values are not case sensitive. Wildcards may be used: "
|
"Values are not case sensitive. Wildcards may be used: "
|
||||||
"'*' any number of characters, '?' matches any single character, "
|
"'*' any number of characters, '?' matches any single character, "
|
||||||
"'[seq]' matches any character in seq, and '[!seq]' matches any character not in seq. "
|
"'[seq]' matches any character in seq, and '[!seq]' matches any character not in seq. "
|
||||||
"Choices available in all languages include: %s" %
|
"Choices available in all languages include: {}".format(", ".join("%s" % x for x in FAN_CHOICES)))
|
||||||
", ".join("%s" % x for x in FAN_CHOICES))
|
|
||||||
group_select.add_argument(
|
group_select.add_argument(
|
||||||
"--edition",
|
"--edition",
|
||||||
choices=EDITION_CHOICES,
|
choices=EDITION_CHOICES,
|
||||||
@ -373,6 +405,27 @@ def parse_opts(cmdline_args=None):
|
|||||||
"--exclude-landmarks",
|
"--exclude-landmarks",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="Group all 'Landmark' cards across all expansions into one divider.")
|
help="Group all 'Landmark' cards across all expansions into one divider.")
|
||||||
|
group_select.add_argument(
|
||||||
|
"--only-type-any", "--only-type", "--type-any",
|
||||||
|
nargs="*",
|
||||||
|
action="append",
|
||||||
|
dest="only_type_any",
|
||||||
|
help="Limit dividers to only those with the specified types. "
|
||||||
|
"A divider is kept if ANY of the provided types are associated with the divider. "
|
||||||
|
"Default is all types are included. "
|
||||||
|
"Any type with a space in the name must be enclosed in double quotes. "
|
||||||
|
"Values are not case sensitive. "
|
||||||
|
"Choices available in all languages include: {}".format(", ".join("%s" % x for x in TYPE_CHOICES)))
|
||||||
|
group_select.add_argument(
|
||||||
|
"--only-type-all", "--type-all",
|
||||||
|
nargs="*",
|
||||||
|
action="append",
|
||||||
|
dest="only_type_all",
|
||||||
|
help="Limit dividers to only those with the specified types. "
|
||||||
|
"A divider is kept if ALL of the provided types are associated with the divider. "
|
||||||
|
"Any type with a space in the name must be enclosed in double quotes. "
|
||||||
|
"Values are not case sensitive. "
|
||||||
|
"Choices available in all languages include: {}".format(", ".join("%s" % x for x in TYPE_CHOICES)))
|
||||||
|
|
||||||
# Divider Sleeves/Wrappers
|
# Divider Sleeves/Wrappers
|
||||||
group_wrapper = parser.add_argument_group(
|
group_wrapper = parser.add_argument_group(
|
||||||
@ -633,6 +686,20 @@ def clean_opts(options):
|
|||||||
# keyword to indicate no options. Same as --fan without any expansions given
|
# keyword to indicate no options. Same as --fan without any expansions given
|
||||||
options.fan = []
|
options.fan = []
|
||||||
|
|
||||||
|
if options.only_type_any is None:
|
||||||
|
# No instance given, so default to empty list
|
||||||
|
options.only_type_any = []
|
||||||
|
else:
|
||||||
|
# options.only_type_any is a list of lists. Reduce to single lowercase list
|
||||||
|
options.only_type_any = list(set([item.lower() for sublist in options.only_type_any for item in sublist]))
|
||||||
|
|
||||||
|
if options.only_type_all is None:
|
||||||
|
# No instance given, so default to empty list
|
||||||
|
options.only_type_all = []
|
||||||
|
else:
|
||||||
|
# options.only_type_any is a list of lists. Reduce to single lowercase list
|
||||||
|
options.only_type_all = list(set([item.lower() for sublist in options.only_type_all for item in sublist]))
|
||||||
|
|
||||||
if options.tabs_only and options.label_name is None:
|
if options.tabs_only and options.label_name is None:
|
||||||
# default is Avery 8867
|
# default is Avery 8867
|
||||||
options.label_name = "8867"
|
options.label_name = "8867"
|
||||||
@ -1359,6 +1426,53 @@ def filter_sort_cards(cards, options):
|
|||||||
card_tag=set_tag)
|
card_tag=set_tag)
|
||||||
cards.append(c)
|
cards.append(c)
|
||||||
|
|
||||||
|
# Take care of any --only-type-xxx requirements
|
||||||
|
if options.only_type_any or options.only_type_all:
|
||||||
|
# First make a dictionary for easier lookup of Type name used by the program
|
||||||
|
# The index in each case is lower case for easier matching
|
||||||
|
# The value in each case is the type index as used in types_en_us.json
|
||||||
|
types_lookup = defaultdict(dict)
|
||||||
|
for x in Card.type_names:
|
||||||
|
types_lookup[x.lower()] = x
|
||||||
|
types_lookup[Card.type_names[x].lower()] = x
|
||||||
|
|
||||||
|
# Start the valid lists
|
||||||
|
type_unknown = []
|
||||||
|
type_known_any = []
|
||||||
|
type_known_all = []
|
||||||
|
|
||||||
|
# Assemble a list of valid "any" types. Options are already lowercase.
|
||||||
|
for x in options.only_type_any:
|
||||||
|
if x in types_lookup:
|
||||||
|
type_known_any.append(types_lookup[x])
|
||||||
|
else:
|
||||||
|
type_unknown.append(x)
|
||||||
|
|
||||||
|
# Assemble a list of valid "all" types. Options are already lowercase.
|
||||||
|
for x in options.only_type_all:
|
||||||
|
if x in types_lookup:
|
||||||
|
type_known_all.append(types_lookup[x])
|
||||||
|
else:
|
||||||
|
type_unknown.append(x)
|
||||||
|
|
||||||
|
# Indicate if unknown types are given
|
||||||
|
assert not type_unknown, "Error - unknown type(s): {}".format(", ".join(type_unknown))
|
||||||
|
|
||||||
|
# If there are any valid Types left, go through the cards and keep cards that match
|
||||||
|
if type_known_any or type_known_all:
|
||||||
|
keep_cards = []
|
||||||
|
for c in cards:
|
||||||
|
if type_known_any and any(x in c.types for x in type_known_any):
|
||||||
|
keep_it = True
|
||||||
|
elif type_known_all and all(x in c.types for x in type_known_all):
|
||||||
|
keep_it = True
|
||||||
|
else:
|
||||||
|
keep_it = False
|
||||||
|
|
||||||
|
if keep_it:
|
||||||
|
keep_cards.append(c)
|
||||||
|
cards = keep_cards
|
||||||
|
|
||||||
# Now sort what is left
|
# Now sort what is left
|
||||||
cards.sort(key=cardSorter)
|
cards.sort(key=cardSorter)
|
||||||
|
|
||||||
|
|||||||
@ -111,3 +111,19 @@ def test_languagetool_run(pytestconfig):
|
|||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
assert e.output == ''
|
assert e.output == ''
|
||||||
assert out.decode('utf-8') == ''
|
assert out.decode('utf-8') == ''
|
||||||
|
|
||||||
|
|
||||||
|
def test_only_type():
|
||||||
|
options = main.parse_opts(['--expansions', 'base', 'alchemy',
|
||||||
|
'--include-blanks', '5',
|
||||||
|
'--only-type-any', 'blank', 'curse',
|
||||||
|
'--only-type-all', 'attack', 'action'])
|
||||||
|
options = main.clean_opts(options)
|
||||||
|
options.data_path = '.'
|
||||||
|
cards = main.read_card_data(options)
|
||||||
|
cards = main.filter_sort_cards(cards, options)
|
||||||
|
# Total 8 from
|
||||||
|
# Blank: +5 added in options
|
||||||
|
# Curse: +1 from base
|
||||||
|
# Action Attack: +2 from Alchemy
|
||||||
|
assert len(cards) == 8
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user