From 1678db243598134f95f2829aeec692385a72f46f Mon Sep 17 00:00:00 2001 From: Andrew Bastien Date: Wed, 10 Apr 2019 21:05:04 -0400 Subject: [PATCH] More draft efforts in new Options handler. @style works! --- evennia/__init__.py | 1 + evennia/accounts/accounts.py | 6 +-- evennia/commands/default/account.py | 18 ++++++-- evennia/commands/default/muxcommand.py | 12 ++--- evennia/settings_default.py | 5 ++- evennia/utils/option.py | 62 ++++++++++++++++++++++++++ evennia/utils/validfuncs.py | 2 +- 7 files changed, 90 insertions(+), 16 deletions(-) create mode 100644 evennia/utils/option.py diff --git a/evennia/__init__.py b/evennia/__init__.py index 81d99e8764..68dc41c386 100644 --- a/evennia/__init__.py +++ b/evennia/__init__.py @@ -112,6 +112,7 @@ CHANNEL_HANDLER = None VALID_HANDLER = None + def _create_version(): """ Helper function for building the version string diff --git a/evennia/accounts/accounts.py b/evennia/accounts/accounts.py index d5eaebc022..68c39b22c7 100644 --- a/evennia/accounts/accounts.py +++ b/evennia/accounts/accounts.py @@ -20,7 +20,7 @@ from django.utils.module_loading import import_string from evennia.typeclasses.models import TypeclassBase from evennia.accounts.manager import AccountManager from evennia.accounts.models import AccountDB -from evennia.accounts.styles import StyleHandler +from evennia.utils.option import OptionHandler from evennia.objects.models import ObjectDB from evennia.comms.models import ChannelDB from evennia.commands import cmdhandler @@ -1385,8 +1385,8 @@ class DefaultAccount(with_metaclass(TypeclassBase, AccountDB)): return look_string @lazy_property - def style(self): - return StyleHandler(self) + def option(self): + return OptionHandler(self, options_dict=settings.ACCOUNT_OPTIONS, save_category='option') class DefaultGuest(DefaultAccount): diff --git a/evennia/commands/default/account.py b/evennia/commands/default/account.py index 01d0cb3410..d552d05fc9 100644 --- a/evennia/commands/default/account.py +++ b/evennia/commands/default/account.py @@ -880,9 +880,19 @@ class CmdStyle(COMMAND_DEFAULT_CLASS): if not self.args: self.list_styles() return + self.set() def list_styles(self): - styles_table = self.style_table('Option', 'Description', 'Value') - for k, v in settings.DEFAULT_STYLES.items(): - styles_table.add_row(k, v[0], v[2]) - self.msg(str(styles_table)) \ No newline at end of file + styles_table = self.style_table('Option', 'Description', 'Type', 'Value') + for k, v in self.account.option.options_dict.items(): + styles_table.add_row(k, v[0], v[1], v[2]) + self.msg(str(styles_table)) + + def set(self): + try: + result = self.account.option.set(self.lhs, self.rhs) + except ValueError as e: + self.msg(str(e)) + return + self.msg('Success! The new value is: %s' % result) + diff --git a/evennia/commands/default/muxcommand.py b/evennia/commands/default/muxcommand.py index f2de5aa2f0..e83e7f1033 100644 --- a/evennia/commands/default/muxcommand.py +++ b/evennia/commands/default/muxcommand.py @@ -236,8 +236,8 @@ class MuxCommand(Command): return self.session.protocol_flags['SCREENWIDTH'][0] def style_table(self, *args, **kwargs): - border_color = self.account.style.get('border_color') - column_color = self.account.style.get('column_names_color') + border_color = self.account.option.get('border_color') + column_color = self.account.option.get('column_names_color') colornames = ['|%s%s|n' % (column_color, col) for col in args] @@ -267,9 +267,9 @@ class MuxCommand(Command): def render_header(self, header_text=None, fill_character=None, edge_character=None, mode='header', color_header=True): colors = dict() - colors['border'] = self.account.style.get('border_color') - colors['headertext'] = self.account.style.get('%s_text_color' % mode) - colors['headerstar'] = self.account.style.get('%s_star_color' % mode) + colors['border'] = self.account.option.get('border_color') + colors['headertext'] = self.account.option.get('%s_text_color' % mode) + colors['headerstar'] = self.account.option.get('%s_star_color' % mode) width = self.width() if edge_character: @@ -288,7 +288,7 @@ class MuxCommand(Command): else: center_string = '' - fill_character = self.account.style.get('%s_fill' % mode) + fill_character = self.account.option.get('%s_fill' % mode) remain_fill = width - len(center_string) if remain_fill % 2 == 0: diff --git a/evennia/settings_default.py b/evennia/settings_default.py index 06b36e46f4..a43529b825 100644 --- a/evennia/settings_default.py +++ b/evennia/settings_default.py @@ -490,14 +490,14 @@ START_LOCATION = "#2" TYPECLASS_AGGRESSIVE_CACHE = True ###################################################################### -# Styles +# Options ###################################################################### # Replace entries in this dictionary to change the default stylings # Evennia uses for commands. Or add more entries! Accounts can have # per-user settings that override these. -DEFAULT_STYLES = { +ACCOUNT_OPTIONS = { 'border_color': ('Headers, footers, table borders, etc.', 'color', 'M'), 'header_star_color': ('* inside Header lines.', 'color', 'm'), 'header_text_color': ('Text inside Header lines.', 'color', 'w'), @@ -508,6 +508,7 @@ DEFAULT_STYLES = { 'footer_fill': ('Fill for Footer Lines.', 'word', '='), 'help_category_color': ('Help category names.', 'color', 'g'), 'help_entry_color': ('Help entry names.', 'color', 'c'), + } ###################################################################### diff --git a/evennia/utils/option.py b/evennia/utils/option.py new file mode 100644 index 0000000000..4977f49bcb --- /dev/null +++ b/evennia/utils/option.py @@ -0,0 +1,62 @@ +from evennia.utils.utils import string_partial_matching + + +class OptionHandler(object): + """ + This is a generic Option handler meant for Typed Objects - anything that implements AttributeHandler. + + It uses a dictionary to store-and-cache frequently used settings such as colors for borders or an + account's timezone. + """ + + def __init__(self, obj, options_dict=None, save_category=None): + if not options_dict: + options_dict = dict() + self.options_dict = options_dict + self.save_category = save_category + self.obj = obj + self.options = dict() + + def __getitem__(self, item): + if item not in self.options_dict: + raise KeyError("Option not found!") + if item in self.options: + return self.options[item] + import evennia + option_def = self.options_dict[item] + save_data = self.obj.attributes.get(item, category=self.save_category) + if not save_data: + return evennia.VALID_HANDLER[option_def[1]](option_def[2]) + self.options[item] = save_data + return save_data + + def get(self, item): + return self[item] + + def set(self, option, value): + """ + Change an individual option. + + Args: + option (str): The key of an option that can be changed. Allows partial matching. + value (str): The value that should be checked, coerced, and stored. + + Returns: + New value + """ + import evennia + if not option: + raise ValueError("Option field blank!") + found = string_partial_matching(list(self.options_dict.keys()), option, ret_index=False) + if not found: + raise ValueError("Option not found!") + if len(found) > 1: + raise ValueError(f"That matched: {', '.join(found)}. Please be more specific.") + found = found[0] + option_def = self.options_dict[found] + if not value: + raise ValueError("Value field blank!") + new_value = evennia.VALID_HANDLER[option_def[1]](value, thing_name=found) + self.obj.attributes.add(found, category=self.save_category, value=new_value) + self.options[found] = new_value + return new_value diff --git a/evennia/utils/validfuncs.py b/evennia/utils/validfuncs.py index 4265b94347..a403dd3bb5 100644 --- a/evennia/utils/validfuncs.py +++ b/evennia/utils/validfuncs.py @@ -158,7 +158,7 @@ def email(entry, thing_name="Email Address"): return entry -def lockstring(entry, thing_name='lockstring', options=None): +def lock(entry, thing_name='lockstring', options=None): entry = entry.strip() if not entry: raise ValueError(f"No {thing_name} entered to set!")