From 3acd966241b2fb46b5d0fcc46b44d16ba00a4e1c Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Tue, 11 Jan 2022 22:01:54 +0100 Subject: [PATCH] Options: add "VerifyKeys" Mixin and showcase it for OoT Logic Tricks --- Options.py | 20 ++++++++++++++++++-- WebHostLib/options.py | 8 ++++++++ worlds/oot/Options.py | 5 ++++- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/Options.py b/Options.py index a5ef5f9c..637f28c6 100644 --- a/Options.py +++ b/Options.py @@ -244,7 +244,21 @@ class OptionNameSet(Option): return cls.from_text(str(data)) -class OptionDict(Option): +class VerifyKeys: + valid_keys = frozenset() + valid_keys_casefold: bool = False + + @classmethod + def verify_keys(cls, data): + if cls.valid_keys: + dataset = set(word.casefold() for word in data) if cls.valid_keys_casefold else set(data) + extra = dataset - cls.valid_keys + if extra: + raise Exception(f"Found unexpected key {', '.join(extra)} in {cls}. " + f"Allowed keys: {cls.valid_keys}.") + + +class OptionDict(Option, VerifyKeys): default = {} supports_weighting = False value: typing.Dict[str, typing.Any] @@ -255,6 +269,7 @@ class OptionDict(Option): @classmethod def from_any(cls, data: typing.Dict[str, typing.Any]) -> OptionDict: if type(data) == dict: + cls.verify_keys(set(data)) return cls(data) else: raise NotImplementedError(f"Cannot Convert from non-dictionary, got {type(data)}") @@ -276,7 +291,7 @@ class ItemDict(OptionDict): super(ItemDict, self).__init__(value) -class OptionList(Option): +class OptionList(Option, VerifyKeys): default = [] supports_weighting = False value: list @@ -292,6 +307,7 @@ class OptionList(Option): @classmethod def from_any(cls, data: typing.Any): if type(data) == list: + cls.verify_keys(set(data)) return cls(data) return cls.from_text(str(data)) diff --git a/WebHostLib/options.py b/WebHostLib/options.py index 8dff42cd..5866b638 100644 --- a/WebHostLib/options.py +++ b/WebHostLib/options.py @@ -1,3 +1,4 @@ +import logging import os from Utils import __version__ from jinja2 import Template @@ -9,6 +10,9 @@ import Options target_folder = os.path.join("WebHostLib", "static", "generated") +handled_in_js = {"start_inventory", "local_items", "non_local_items", "start_hints", "start_location_hints", + "exclude_locations"} + def create(): os.makedirs(os.path.join(target_folder, 'configs'), exist_ok=True) @@ -91,6 +95,10 @@ def create(): "min": option.range_start, "max": option.range_end, } + elif option_name in handled_in_js: + pass + else: + logging.debug(f"{option} not exported to Web Settings.") player_settings["gameOptions"] = game_options diff --git a/worlds/oot/Options.py b/worlds/oot/Options.py index e46927a3..d7383e08 100644 --- a/worlds/oot/Options.py +++ b/worlds/oot/Options.py @@ -1,5 +1,6 @@ import typing -from Options import Option, DefaultOnToggle, Toggle, Choice, Range, OptionList, DeathLink +from Options import Option, DefaultOnToggle, Toggle, Range, OptionList, DeathLink +from .LogicTricks import normalized_name_tricks from .ColorSFXOptions import * @@ -824,6 +825,8 @@ class LogicTricks(OptionList): Format as a comma-separated list of "nice" names: ["Fewer Tunic Requirements", "Hidden Grottos without Stone of Agony"]. A full list of supported tricks can be found at https://github.com/ArchipelagoMW/Archipelago/blob/main/worlds/oot/LogicTricks.py""" displayname = "Logic Tricks" + valid_keys = frozenset(normalized_name_tricks) + valid_keys_casefold = True # All options assembled into a single dict