Cleanup of options methods, callables

This commit is contained in:
Griatch 2019-04-14 17:01:32 +02:00
parent 6ddc98a947
commit f2d9391827
3 changed files with 90 additions and 58 deletions

View file

@ -35,32 +35,34 @@ class Container(object):
"""
self.loaded_data = None
def _load_data(self):
def load_data(self):
"""
Delayed import to avoid eventual circular imports from inside
the storage modules.
"""
if self.loaded_data is None:
self.loaded_data = {}
for module in self.storage_modules:
self.loaded_data.update(callables_from_module(module))
def __getattr__(self, key):
self._load_data()
return self.loaded_data.get(key)
return self.get(key)
def get(self, key):
def get(self, key, default=None):
"""
Retrive data by key (in case of not knowing it beforehand).
Args:
key (str): The name of the script.
default (any, optional): Value to return if key is not found.
Returns:
any (any): The data loaded on this container.
"""
return self.__getattr__(key)
self.load_data()
return self.loaded_data.get(key, default)
def all(self):
"""
@ -70,7 +72,7 @@ class Container(object):
scripts (list): All global script objects stored on the container.
"""
self._load_data()
self.load_data()
return list(self.loaded_data.values())
@ -121,12 +123,7 @@ class GlobalScriptContainer(Container):
self.script_storage = {}
self.typeclass_storage = None
def __getattr__(self, key):
if key not in self.loaded_data:
return None
return self.script_storage.get(key) or self._load_script(key)
def _load_data(self):
def load_data(self):
"""
This delayed import avoids trying to load Scripts before they are
initialized.
@ -144,7 +141,7 @@ class GlobalScriptContainer(Container):
def _load_script(self, key):
self._load_data()
self.load_data()
typeclass = self.typeclass_storage[key]
found = typeclass.objects.filter(db_key=key).first()
@ -175,6 +172,23 @@ class GlobalScriptContainer(Container):
self.script_storage[key] = found
return found
def get(self, key, default=None):
"""
Retrive data by key (in case of not knowing it beforehand).
Args:
key (str): The name of the script.
default (any, optional): Value to return if key is not found
at all on this container (i.e it cannot be loaded at all).
Returns:
any (any): The data loaded on this container.
"""
if key not in self.loaded_data:
return default
return self.script_storage.get(key) or self._load_script(key)
def all(self):
"""
Get all scripts.

View file

@ -3,6 +3,7 @@ from evennia import logger as _log
from evennia.utils.ansi import ANSIString as _ANSI
from evennia.utils.validatorfuncs import _TZ_DICT
from evennia.utils.containers import VALIDATOR_FUNCS
from evennia.utils.utils import crop
class BaseOption(object):
@ -22,7 +23,11 @@ class BaseOption(object):
validator_key = ''
def __str__(self):
return self.key
return "<Option {key}: {value}>".format(
key=self.key, value=crop(str(self.value), width=10))
def __repr__(self):
return str(self)
def __init__(self, handler, key, description, default, save_data=None):
"""
@ -163,6 +168,10 @@ class BaseOption(object):
"""
Renders the Option's value as something pretty to look at.
Kwargs:
any (any): These are options passed by the caller to potentially
customize display dynamically.
Returns:
str: How the stored value should be projected to users (e.g. a raw
timedelta is pretty ugly).
@ -171,6 +180,7 @@ class BaseOption(object):
return self.value
# Option classes
class Text(BaseOption):

View file

@ -4,13 +4,12 @@ from evennia.utils.containers import OPTION_CLASSES
class OptionHandler(object):
"""
This is a generic Option handler meant for Typed Objects - anything that implements AttributeHandler.
This is a generic Option handler meant for Typed Objects - anything that
implements AttributeHandler. Retrieve options eithers as properties on
this handler or by using the .get method.
It uses a dictionary to store-and-cache frequently used settings such as colors for borders or an
account's timezone.
This is used for Account.options but it could be used by Scripts or Objects just as easily. All
it needs to be provided is an options_dict.
This is used for Account.options but it could be used by Scripts or Objects
just as easily. All it needs to be provided is an options_dict.
"""
def __init__(self, obj, options_dict=None, save_category=None):
@ -18,60 +17,70 @@ class OptionHandler(object):
Initialize an OptionHandler.
Args:
obj (TypedObject): The Typed Object this sits on. Obj MUST implement the Evennia AttributeHandler
or this will barf.
options_dict (dict): A dictionary of option keys, where the values are options. The format of those
tuples is: ('key', "Description to show", 'option_type', <default value>)
save_category (str): The Options data will be stored to this Attribute category on obj.
obj (TypedObject): The Typed Object this sits on. Obj MUST
implement the Evennia AttributeHandler or this will barf.
options_dict (dict): A dictionary of option keys, where the values
are options. The format of those tuples is: ('key', "Description to
show", 'option_type', <default value>)
save_category (str): The Options data will be stored to this
Attribute category on obj.
"""
if not options_dict:
options_dict = dict()
options_dict = {}
self.options_dict = options_dict
self.save_category = save_category
self.obj = obj
# This dictionary stores the in-memory Options by their key. Values are the Option objects.
self.options = dict()
self.options = {}
# We use lazy-loading of each Option when it's called for, but it's good to have the save data
# on hand.
self.save_data = {s.key: s.value for s in obj.attributes.get(category=save_category,
return_list=True, return_obj=True) if s}
# We use lazy-loading of each Option when it's called for, but it's
# good to have the save data on hand.
self.save_data = {s.key: s.value for s in obj.attributes.get(
category=save_category, return_list=True, return_obj=True) if s}
def __getitem__(self, item):
"""
Shortcut to self.get(item) used as a different syntax. This entire object is
essentially a dictionary of option_key -> value.
def __getattr__(self, key):
return self.get(key).value
Args:
item (str): The Key of the item to get.
Returns:
The Option's value.
"""
return self.get(item).value
def get(self, item, return_obj=False):
def get(self, key, return_obj=False):
"""
Retrieves an Option stored in the handler. Will load it if it doesn't exist.
Args:
item (str): The key to retrieve.
return_obj (bool): If True, returns the actual option object instead of its value.
key (str): The option key to retrieve.
return_obj (bool, optional): If True, returns the actual option
object instead of its value.
Returns:
An option value (varies) or the Option itself.
option_value (any or Option): An option value the Option itself.
Raises:
KeyError: If option is not defined.
"""
if item not in self.options_dict:
if key not in self.options_dict:
raise KeyError("Option not found!")
if item in self.options:
op_found = self.options[item]
if key in self.options:
op_found = self.options[key]
else:
op_found = self._load_option(item)
op_found = self._load_option(key)
if return_obj:
return op_found
return op_found.value
def all(self, return_objs=False):
"""
Get all options defined on this handler.
Args:
return_objs (bool, optional): Return the actual Option objects rather
than their values.
Returns:
all_options (dict): All options on this handler, either `{key: value}`
or `{key: <Option>}` if `return_objs` is `True`.
"""
return [self.get(key, return_obj=return_objs) for key in self.options_dict]
def _load_option(self, key):
"""
Loads option on-demand if it has not been loaded yet.
@ -82,10 +91,10 @@ class OptionHandler(object):
Returns:
"""
option_def = self.options_dict[key]
desc, clsname, default_val = self.options_dict[key]
save_data = self.save_data.get(key, None)
self.obj.msg(save_data)
loaded_option = OPTION_CONTAINER[option_def[1]](self, key, option_def[0], option_def[2], save_data)
loaded_option = OPTION_CLASSES.get(clsname)(self, key, desc, default_val, save_data)
self.options[key] = loaded_option
return loaded_option
@ -96,6 +105,8 @@ class OptionHandler(object):
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.
kwargs (any, optional): These are passed into the Option's validation function,
save function and display function and allows to customize either.
Returns:
New value
@ -110,7 +121,4 @@ class OptionHandler(object):
found = found[0]
op = self.get(found, return_obj=True)
op.set(value, **kwargs)
return op.display()
return op.display(**kwargs)