Make options accept default kwarg, add new raise_exception. Fix datetime validatorfunc accoring to spec. Resolves #1967.
This commit is contained in:
parent
6e561d95a1
commit
bfe533441e
5 changed files with 38 additions and 14 deletions
|
|
@ -42,6 +42,8 @@ without arguments starts a full interactive Python console.
|
||||||
- Improve performance of `find` and `objects` commands on large data sets (strikaco)
|
- Improve performance of `find` and `objects` commands on large data sets (strikaco)
|
||||||
- New `CHANNEL_HANDLER_CLASS` setting allows for replacing the ChannelHandler entirely.
|
- New `CHANNEL_HANDLER_CLASS` setting allows for replacing the ChannelHandler entirely.
|
||||||
- Made `py` interactive mode support regular quit() and more verbose.
|
- Made `py` interactive mode support regular quit() and more verbose.
|
||||||
|
- Made `Account.options.get` accept `default=None` kwarg to mimic other uses of get. Set
|
||||||
|
the new `raise_exception` boolean if ranting to raise KeyError on a missing key.
|
||||||
|
|
||||||
|
|
||||||
## Evennia 0.9 (2018-2019)
|
## Evennia 0.9 (2018-2019)
|
||||||
|
|
|
||||||
|
|
@ -105,9 +105,9 @@ class AccountDB(TypedObject, AbstractUser):
|
||||||
objects = AccountDBManager()
|
objects = AccountDBManager()
|
||||||
|
|
||||||
# defaults
|
# defaults
|
||||||
__settingsclasspath__ = settings.BASE_SCRIPT_TYPECLASS
|
|
||||||
__defaultclasspath__ = "evennia.accounts.accounts.DefaultAccount"
|
__defaultclasspath__ = "evennia.accounts.accounts.DefaultAccount"
|
||||||
__applabel__ = "accounts"
|
__applabel__ = "accounts"
|
||||||
|
__settingsclasspath__ = settings.BASE_SCRIPT_TYPECLASS
|
||||||
|
|
||||||
class Meta(object):
|
class Meta(object):
|
||||||
verbose_name = "Account"
|
verbose_name = "Account"
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,7 @@ class InMemorySaveHandler(object):
|
||||||
|
|
||||||
class OptionHandler(object):
|
class OptionHandler(object):
|
||||||
"""
|
"""
|
||||||
This is a generic Option handler. It is commonly used
|
This is a generic Option handler. Retrieve options either as properties on
|
||||||
implements AttributeHandler. Retrieve options eithers as properties on
|
|
||||||
this handler or by using the .get method.
|
this handler or by using the .get method.
|
||||||
|
|
||||||
This is used for Account.options but it could be used by Scripts or Objects
|
This is used for Account.options but it could be used by Scripts or Objects
|
||||||
|
|
@ -116,14 +115,16 @@ class OptionHandler(object):
|
||||||
self.options[key] = loaded_option
|
self.options[key] = loaded_option
|
||||||
return loaded_option
|
return loaded_option
|
||||||
|
|
||||||
def get(self, key, return_obj=False):
|
def get(self, key, default=None, return_obj=False, raise_error=False):
|
||||||
"""
|
"""
|
||||||
Retrieves an Option stored in the handler. Will load it if it doesn't exist.
|
Retrieves an Option stored in the handler. Will load it if it doesn't exist.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key (str): The option key to retrieve.
|
key (str): The option key to retrieve.
|
||||||
|
default (any): What to return if the option is defined.
|
||||||
return_obj (bool, optional): If True, returns the actual option
|
return_obj (bool, optional): If True, returns the actual option
|
||||||
object instead of its value.
|
object instead of its value.
|
||||||
|
raise_error (bool, optional): Raise Exception if key is not found in options.
|
||||||
Returns:
|
Returns:
|
||||||
option_value (any or Option): An option value the Option itself.
|
option_value (any or Option): An option value the Option itself.
|
||||||
Raises:
|
Raises:
|
||||||
|
|
@ -131,7 +132,10 @@ class OptionHandler(object):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if key not in self.options_dict:
|
if key not in self.options_dict:
|
||||||
raise KeyError("Option not found!")
|
if raise_error:
|
||||||
|
raise KeyError("Option not found!")
|
||||||
|
return default
|
||||||
|
# get the options or load/recache it
|
||||||
op_found = self.options.get(key) or self._load_option(key)
|
op_found = self.options.get(key) or self._load_option(key)
|
||||||
return op_found if return_obj else op_found.value
|
return op_found if return_obj else op_found.value
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,11 @@ class TestValidatorFuncs(TestCase):
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
isinstance(validatorfuncs.datetime(dt, from_tz=pytz.UTC), datetime.datetime)
|
isinstance(validatorfuncs.datetime(dt, from_tz=pytz.UTC), datetime.datetime)
|
||||||
)
|
)
|
||||||
|
account = mock.MagicMock()
|
||||||
|
account.options.get = mock.MagicMock(return_value="America/Chicago")
|
||||||
|
expected = datetime.datetime(1492, 10, 12, 6, 51, tzinfo=pytz.UTC)
|
||||||
|
self.assertEqual(expected, validatorfuncs.datetime("Oct 12 1:00 1492", account=account))
|
||||||
|
account.options.get.assert_called_with("timezone", "UTC")
|
||||||
|
|
||||||
def test_datetime_raises_ValueError(self):
|
def test_datetime_raises_ValueError(self):
|
||||||
for dt in ["", "January 1, 2019", "1/1/2019", "Jan 1 2019"]:
|
for dt in ["", "January 1, 2019", "1/1/2019", "Jan 1 2019"]:
|
||||||
|
|
@ -121,6 +126,7 @@ class TestValidatorFuncs(TestCase):
|
||||||
validatorfuncs.boolean(b)
|
validatorfuncs.boolean(b)
|
||||||
|
|
||||||
def test_timezone_ok(self):
|
def test_timezone_ok(self):
|
||||||
|
|
||||||
for tz in ["America/Chicago", "GMT", "UTC"]:
|
for tz in ["America/Chicago", "GMT", "UTC"]:
|
||||||
self.assertEqual(tz, validatorfuncs.timezone(tz).zone)
|
self.assertEqual(tz, validatorfuncs.timezone(tz).zone)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,24 +40,36 @@ def color(entry, option_key="Color", **kwargs):
|
||||||
|
|
||||||
def datetime(entry, option_key="Datetime", account=None, from_tz=None, **kwargs):
|
def datetime(entry, option_key="Datetime", account=None, from_tz=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
Process a datetime string in standard forms while accounting for the inputter's timezone.
|
Process a datetime string in standard forms while accounting for the inputer's timezone. Always
|
||||||
|
returns a result in UTC.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
entry (str): A date string from a user.
|
entry (str): A date string from a user.
|
||||||
option_key (str): Name to display this datetime as.
|
option_key (str): Name to display this datetime as.
|
||||||
account (AccountDB): The Account performing this lookup. Unless from_tz is provided,
|
account (AccountDB): The Account performing this lookup. Unless `from_tz` is provided,
|
||||||
account's timezone will be used (if found) for local time and convert the results
|
the account's timezone option will be used.
|
||||||
to UTC.
|
from_tz (pytz.timezone): An instance of a pytz timezone object from the
|
||||||
from_tz (pytz): An instance of pytz from the user. If not provided, defaults to whatever
|
user. If not provided, tries to use the timezone option of the `account'.
|
||||||
the Account uses. If neither one is provided, defaults to UTC.
|
If neither one is provided, defaults to UTC.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
datetime in utc.
|
datetime in UTC.
|
||||||
|
Raises:
|
||||||
|
ValueError: If encountering a malformed timezone, date string or other format error.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if not entry:
|
if not entry:
|
||||||
raise ValueError(f"No {option_key} entered!")
|
raise ValueError(f"No {option_key} entered!")
|
||||||
if not from_tz:
|
if not from_tz:
|
||||||
from_tz = _pytz.UTC
|
from_tz = _pytz.UTC
|
||||||
|
if account:
|
||||||
|
acct_tz = account.options.get("timezone", "UTC")
|
||||||
|
try:
|
||||||
|
from_tz = _pytz.timezone(acct_tz)
|
||||||
|
except Exception as err:
|
||||||
|
raise ValueError(f"Timezone string '{acct_tz}' is not a valid timezone ({err})")
|
||||||
|
else:
|
||||||
|
from_tz = _pytz.UTC
|
||||||
|
|
||||||
utc = _pytz.UTC
|
utc = _pytz.UTC
|
||||||
now = _dt.datetime.utcnow().replace(tzinfo=utc)
|
now = _dt.datetime.utcnow().replace(tzinfo=utc)
|
||||||
cur_year = now.strftime("%Y")
|
cur_year = now.strftime("%Y")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue