rewrite (settings): New SettingGroup impl.

Also add `hover_desc` property to interactives.
This commit is contained in:
2022-11-18 08:48:22 +02:00
parent dfa3ef6ec6
commit 860660d152
5 changed files with 94 additions and 12 deletions

View File

@@ -1,4 +1,3 @@
from .data import ModelData from .data import ModelData
from .base import BaseSetting from .base import BaseSetting
from .ui import SettingWidget, InteractiveSetting from .ui import SettingWidget, InteractiveSetting
from .groups import SettingGroup

View File

@@ -66,11 +66,11 @@ class BaseSetting(Generic[ParentID, SettingData, SettingValue]):
return self._default return self._default
@property @property
def value(self) -> Optional[SettingValue]: def value(self) -> SettingValue: # Actually optional *if* _default is None
""" """
Context-aware object or objects associated with the setting. Context-aware object or objects associated with the setting.
""" """
return self._data_to_value(self.parent_id, self.data) return self._data_to_value(self.parent_id, self.data) # type: ignore
@value.setter @value.setter
def value(self, new_value: Optional[SettingValue]): def value(self, new_value: Optional[SettingValue]):

View File

@@ -1,5 +1,79 @@
from discord.ui import View from typing import Generic, Type, TypeVar, Optional
from .ui import InteractiveSetting
from utils.lib import tabulate
class SettingGroup(View): T = TypeVar('T', bound=InteractiveSetting)
...
class SettingDotDict(Generic[T], dict[str, Type[T]]):
"""
Dictionary structure allowing simple dot access to items.
"""
__getattr__ = dict.__getitem__ # type: ignore
__setattr__ = dict.__setitem__ # type: ignore
__delattr__ = dict.__delitem__ # type: ignore
class SettingGroup:
"""
A SettingGroup is a collection of settings under one name.
"""
__initial_settings__: list[Type[InteractiveSetting]] = []
_title: Optional[str] = None
_description: Optional[str] = None
def __init_subclass__(cls, title: Optional[str] = None):
cls._title = title or cls._title
cls._description = cls._description or cls.__doc__
settings: list[Type[InteractiveSetting]] = []
for item in cls.__dict__.values():
if isinstance(item, type) and issubclass(item, InteractiveSetting):
settings.append(item)
cls.__initial_settings__ = settings
def __init_settings__(self):
settings = SettingDotDict()
for setting in self.__initial_settings__:
settings[setting.__name__] = setting
return settings
def __init__(self, title=None, description=None) -> None:
self.title: str = title or self._title or self.__class__.__name__
self.description: str = description or self._description or ""
self.settings: SettingDotDict[InteractiveSetting] = self.__init_settings__()
def attach(self, cls: Type[T], name: Optional[str] = None):
name = name or cls.__name__
self.settings[name] = cls
return cls
def detach(self, cls):
return self.settings.pop(cls.__name__, None)
def update(self, smap):
self.settings.update(smap.settings)
def reduce(self, *keys):
for key in keys:
self.settings.pop(key, None)
return
async def make_setting_table(self, parent_id):
"""
Convenience method for generating a rendered setting table.
"""
rows = []
for setting in self.settings.values():
name = f"{setting.display_name}"
set = await setting.get(parent_id)
value = set.formatted
rows.append((name, value, set.hover_desc))
table_rows = tabulate(
*rows,
row_format="[`{invis}{key:<{pad}}{colon}`](https://lionbot.org \"{field[2]}\")\t{value}"
)
return '\n'.join(table_rows)

View File

@@ -749,7 +749,7 @@ class EnumSetting(InteractiveSetting[ParentID, ET, ET]):
This should almost always include the strings from `_outputs`. This should almost always include the strings from `_outputs`.
""" """
_enum: ET _enum: Type[ET]
_outputs: dict[ET, str] _outputs: dict[ET, str]
_inputs: dict[str, ET] _inputs: dict[str, ET]

View File

@@ -8,7 +8,7 @@ from discord.ui.button import ButtonStyle, Button, button
from discord.ui.modal import Modal from discord.ui.modal import Modal
from discord.ui.text_input import TextInput from discord.ui.text_input import TextInput
from utils.lib import prop_tabulate, recover_context from utils.lib import tabulate, recover_context
from utils.ui import FastModal from utils.ui import FastModal
from meta.config import conf from meta.config import conf
@@ -214,6 +214,15 @@ class InteractiveSetting(BaseSetting[ParentID, SettingData, SettingValue]):
else: else:
return f"Setting Updated! New value: {self.formatted}" return f"Setting Updated! New value: {self.formatted}"
@property
def hover_desc(self):
return '\n'.join((
self.display_name,
'=' * len(self.display_name),
self.long_desc,
f"\nAccepts: {self.accepts}"
))
async def update_response(self, interaction: discord.Interaction, **kwargs): async def update_response(self, interaction: discord.Interaction, **kwargs):
""" """
Respond to an interaction which triggered a setting update. Respond to an interaction which triggered a setting update.
@@ -256,10 +265,10 @@ class InteractiveSetting(BaseSetting[ParentID, SettingData, SettingValue]):
@property @property
def desc_table(self): def desc_table(self):
fields = ("Current value", "Default value") return tabulate(
values = (self.formatted or "Not Set", ("Current Value", self.formatted or "Not Set"),
self._format_data(self.parent_id, self.default) or "None") ("Default Value", self._format_data(self.parent_id, self.default) or "None"),
return prop_tabulate(fields, values) )
@property @property
def input_field(self) -> TextInput: def input_field(self) -> TextInput: