From 50d355a949490dbc641720c3032fe21e756db48c Mon Sep 17 00:00:00 2001 From: Aaron Wagener Date: Fri, 15 Dec 2023 15:01:48 -0600 Subject: [PATCH] PEP8 current option_groups progress (#2604) * Make the python more PEP8 and remove unneeded imports * remove LocationSet from `Item & Location Options` group --- Options.py | 19 +++--- WebHostLib/misc.py | 15 ++--- WebHostLib/options.py | 145 ++++++++++++++++++------------------------ docs/options api.md | 4 +- 4 files changed, 79 insertions(+), 104 deletions(-) diff --git a/Options.py b/Options.py index 727501db3727..f43049bc5197 100644 --- a/Options.py +++ b/Options.py @@ -1,9 +1,7 @@ from __future__ import annotations import abc -import collections import logging -from copy import deepcopy from dataclasses import dataclass import functools import math @@ -110,6 +108,9 @@ class Option(typing.Generic[T], metaclass=AssembleOptions): name_lookup: typing.Dict[T, str] options: typing.Dict[str, int] + group_name: typing.ClassVar[str] = "Game Options" + """Name of the group to categorize this option in for display on the WebHost and in generated YAMLS.""" + def __repr__(self) -> str: return f"{self.__class__.__name__}({self.current_option_name})" @@ -805,7 +806,6 @@ def verify(self, world: typing.Type[World], player_name: str, plando_options: "P class OptionDict(Option[typing.Dict[str, typing.Any]], VerifyKeys, typing.Mapping[str, typing.Any]): default: typing.Dict[str, typing.Any] = {} supports_weighting = False - group_name = "Item & Location Options" def __init__(self, value: typing.Dict[str, typing.Any]): self.value = deepcopy(value) @@ -847,7 +847,6 @@ class OptionList(Option[typing.List[typing.Any]], VerifyKeys): default: typing.List[typing.Any] = [] supports_weighting = False - group_name = "Item & Location Options" def __init__(self, value: typing.List[typing.Any]): self.value = deepcopy(value) @@ -874,7 +873,6 @@ def __contains__(self, item): class OptionSet(Option[typing.Set[str]], VerifyKeys): default: typing.Union[typing.Set[str], typing.FrozenSet[str]] = frozenset() supports_weighting = False - group_name = "Item & Location Options" def __init__(self, value: typing.Iterable[str]): self.value = set(deepcopy(value)) @@ -1000,6 +998,7 @@ class StartInventory(ItemDict): """Start with these items.""" verify_item_name = True display_name = "Start Inventory" + group_name = "Item & Location Options" class StartInventoryPool(StartInventory): @@ -1007,6 +1006,7 @@ class StartInventoryPool(StartInventory): The game decides what the replacement items will be.""" verify_item_name = True display_name = "Start Inventory from Pool" + group_name = "Item & Location Options" class StartHints(ItemSet): @@ -1023,16 +1023,19 @@ class LocationSet(OptionSet): class StartLocationHints(LocationSet): """Start with these locations and their item prefilled into the !hint command""" display_name = "Start Location Hints" + group_name = "Item & Location Options" class ExcludeLocations(LocationSet): """Prevent these locations from having an important item""" display_name = "Excluded Locations" + group_name = "Item & Location Options" class PriorityLocations(LocationSet): """Prevent these locations from having an unimportant item""" display_name = "Priority Locations" + group_name = "Item & Location Options" class DeathLink(Toggle): @@ -1156,11 +1159,11 @@ def dictify_range(option: Range): for game_name, world in AutoWorldRegister.world_types.items(): if not world.hidden or generate_hidden: - all_options: typing.Dict[str, AssembleOptions] = world.options_dataclass.type_hints + all_options = world.options_dataclass.type_hints - grouped_options = collections.defaultdict(dict) + grouped_options = {} for option_name, option in all_options.items(): - grouped_options[getattr(option, "group_name", "Game Options")][option_name] = option + grouped_options.setdefault(option.group_name, {})[option_name] = option with open(local_path("data", "options.yaml")) as f: file_data = f.read() diff --git a/WebHostLib/misc.py b/WebHostLib/misc.py index 71a44d827c0d..6ec73ddcff1b 100644 --- a/WebHostLib/misc.py +++ b/WebHostLib/misc.py @@ -1,7 +1,6 @@ import datetime import os from typing import List, Dict, Union -import collections import jinja2.exceptions from flask import request, redirect, url_for, render_template, Response, session, abort, send_from_directory @@ -63,24 +62,18 @@ def player_settings(game: str): def player_options(game: str): world = AutoWorldRegister.world_types[game] all_options: Dict[str, Options.AssembleOptions] = world.options_dataclass.type_hints - grouped_options = collections.defaultdict(dict) + grouped_options = {} for option_name, option in all_options.items(): - if issubclass(option, Options.ItemDict) and not option.verify_item_name: - continue - - if issubclass(option, Options.OptionList) and not hasattr(option, "valid_keys"): + if issubclass(option, (Options.ItemDict, Options.ItemSet)) and not option.verify_item_name: continue if issubclass(option, Options.LocationSet) and not option.verify_location_name: continue - if issubclass(option, Options.ItemSet) and not option.verify_item_name: - continue - - if issubclass(option, Options.OptionSet) and not hasattr(option, "valid_keys"): + if issubclass(option, (Options.OptionList, Options.OptionSet)) and not hasattr(option, "valid_keys"): continue - grouped_options[getattr(option, "group_name", "Game Options")][option_name] = option + grouped_options.setdefault(getattr(option, "group_name", "Game Options"), {})[option_name] = option return render_template( "playerOptions/playerOptions.html", diff --git a/WebHostLib/options.py b/WebHostLib/options.py index 2963e43fce4f..78f2f3f5a64a 100644 --- a/WebHostLib/options.py +++ b/WebHostLib/options.py @@ -2,7 +2,6 @@ import logging import os import typing -import collections import Options from Utils import local_path @@ -34,11 +33,6 @@ def get_html_doc(option_type: type(Options.Option)) -> str: for game_name, world in AutoWorldRegister.world_types.items(): - all_options: typing.Dict[str, Options.AssembleOptions] = world.options_dataclass.type_hints - grouped_options = collections.defaultdict(dict) - for option_name, option in all_options.items(): - grouped_options[getattr(option, "group_name", "Game Options")][option_name] = option - # Generate JSON files for player-options pages player_options = { "baseOptions": { @@ -48,87 +42,72 @@ def get_html_doc(option_type: type(Options.Option)) -> str: }, } + all_options = world.options_dataclass.type_hints game_option_groups = {} - for group_name, group_options in grouped_options.items(): - if not hasattr(game_option_groups, group_name): - game_option_groups[group_name] = {} - - for option_name, option in group_options.items(): - if option_name in handled_in_js: - pass - - elif issubclass(option, Options.Choice) or issubclass(option, Options.Toggle): - game_option_groups[group_name][option_name] = this_option = { - "type": "select", - "groupName": option.group_name if hasattr(option, "group_name") else None, - "displayName": option.display_name if hasattr(option, "display_name") else option_name, - "description": get_html_doc(option), - "defaultValue": None, - "options": [] - } - - for sub_option_id, sub_option_name in option.name_lookup.items(): - if sub_option_name != "random": - this_option["options"].append({ - "name": option.get_option_name(sub_option_id), - "value": sub_option_name, - }) - if sub_option_id == option.default: - this_option["defaultValue"] = sub_option_name - - if not this_option["defaultValue"]: - this_option["defaultValue"] = "random" - - elif issubclass(option, Options.Range): - game_option_groups[group_name][option_name] = { - "type": "range", - "groupName": option.group_name if hasattr(option, "group_name") else None, - "displayName": option.display_name if hasattr(option, "display_name") else option_name, - "description": get_html_doc(option), - "defaultValue": option.default if hasattr( - option, "default") and option.default != "random" else option.range_start, - "min": option.range_start, - "max": option.range_end, - } - - if issubclass(option, Options.NamedRange): - game_option_groups[group_name][option_name]["type"] = 'named_range' - game_option_groups[group_name][option_name]["value_names"] = {} - for key, val in option.special_range_names.items(): - game_option_groups[group_name][option_name]["value_names"][key] = val - - elif issubclass(option, Options.ItemSet): - game_option_groups[group_name][option_name] = { - "type": "items-list", - "groupName": option.group_name if hasattr(option, "group_name") else None, - "displayName": option.display_name if hasattr(option, "display_name") else option_name, - "description": get_html_doc(option), - "defaultValue": list(option.default) - } - - elif issubclass(option, Options.LocationSet): - game_option_groups[group_name][option_name] = { - "type": "locations-list", - "groupName": option.group_name if hasattr(option, "group_name") else None, - "displayName": option.display_name if hasattr(option, "display_name") else option_name, + for option_name, option in all_options.items(): + if option_name in handled_in_js: + continue + + this_option = game_option_groups.setdefault(option.group_name, {}).setdefault(option_name, {}) + if issubclass(option, Options.Choice) or issubclass(option, Options.Toggle): + this_option.update({ + "type": "select", + "groupName": option.group_name, + "displayName": getattr(option, "display_name", option_name), + "description": get_html_doc(option), + "defaultValue": None, + "options": [], + }) + + for sub_option_id, sub_option_name in option.name_lookup.items(): + if sub_option_name != "random": + this_option["options"].append({ + "name": option.get_option_name(sub_option_id), + "value": sub_option_name, + }) + this_option["defaultValue"] = option.default + + elif issubclass(option, Options.Range): + this_option.update({ + "type": "range", + "groupName": option.group_name, + "displayName": getattr(option, "display_name", option_name), + "description": get_html_doc(option), + "defaultValue": getattr(option, "default", option.range_start), + "min": option.range_start, + "max": option.range_end, + }) + + if issubclass(option, Options.NamedRange): + this_option["type"] = 'named_range' + this_option["value_names"] = option.special_range_names.copy() + + elif issubclass(option, (Options.ItemSet, Options.LocationSet)): + this_option.update({ + "type": "items-list", + "groupName": option.group_name, + "displayName": getattr(option, "display_name", option_name), + "description": get_html_doc(option), + "defaultValue": list(option.default), + }) + + elif issubclass(option, Options.VerifyKeys) and not issubclass(option, Options.OptionDict): + if option.valid_keys: + this_option.update({ + "type": "custom-list", + "groupName": getattr(option, "group_name", "Game Options"), + "displayName": getattr(option, "display_name", option_name), "description": get_html_doc(option), - "defaultValue": list(option.default) - } - - elif issubclass(option, Options.VerifyKeys) and not issubclass(option, Options.OptionDict): - if option.valid_keys: - game_option_groups[group_name][option_name] = { - "type": "custom-list", - "groupName": option.group_name if hasattr(option, "group_name") else None, - "displayName": option.display_name if hasattr(option, "display_name") else option_name, - "description": get_html_doc(option), - "options": list(option.valid_keys), - "defaultValue": list(option.default) if hasattr(option, "default") else [] - } - + "options": list(option.valid_keys), + "defaultValue": list(getattr(option, "default", [])), + }) else: - logging.debug(f"{option} not exported to Web Options.") + del game_option_groups[option.group_name][option_name] + + else: + del game_option_groups[option.group_name][option_name] + logging.debug(f"{option} not exported to Web Options.") player_options["gameOptionGroups"] = game_option_groups diff --git a/docs/options api.md b/docs/options api.md index 77d7a2976ff8..f0fb852763ca 100644 --- a/docs/options api.md +++ b/docs/options api.md @@ -73,8 +73,8 @@ from Options import Toggle class StartingSword(Toggle): """Adds a sword to your starting inventory""" - display_name: 'Start With Sword' - group_name: 'Inventory Options' + display_name = 'Start With Sword' + group_name = 'Inventory Options' ``` ### Option Checking