Add more work on OLC field structures.
This commit is contained in:
parent
e8a1daa526
commit
69d7362203
1 changed files with 127 additions and 14 deletions
|
|
@ -6,6 +6,9 @@ know what data to read and how to display it.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from collections import deque
|
from collections import deque
|
||||||
|
from evennia.utils.utils import to_str, to_unicode
|
||||||
|
from evennia.utils.olc import olc_utils
|
||||||
|
|
||||||
# from django.conf import settings
|
# from django.conf import settings
|
||||||
|
|
||||||
_OLC_VALIDATION_ERROR = """
|
_OLC_VALIDATION_ERROR = """
|
||||||
|
|
@ -18,6 +21,22 @@ The reported error was
|
||||||
_LEN_HISTORY = 10 # settings.OLC_HISTORY_LENGTH
|
_LEN_HISTORY = 10 # settings.OLC_HISTORY_LENGTH
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidActionError(RuntimeError):
|
||||||
|
"""
|
||||||
|
Raised when trying to perform a field action the field
|
||||||
|
does not support.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ValidationError(RuntimeError):
|
||||||
|
"""
|
||||||
|
Raised when failing to validate new data being entered
|
||||||
|
into the field (from any source)
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class OLCField(object):
|
class OLCField(object):
|
||||||
"""
|
"""
|
||||||
This is the parent for all OLC fields. This docstring acts
|
This is the parent for all OLC fields. This docstring acts
|
||||||
|
|
@ -31,10 +50,10 @@ class OLCField(object):
|
||||||
# used for displaying extra info in the OLC
|
# used for displaying extra info in the OLC
|
||||||
label = "Empty field"
|
label = "Empty field"
|
||||||
# initial value of field if not given
|
# initial value of field if not given
|
||||||
initial = None
|
default = None
|
||||||
# actions available on this field. Available actions
|
# actions available on this field. Available actions
|
||||||
# are replace, edit, append, remove, clear, help
|
# are replace, edit, append, remove, clear, help
|
||||||
actions = ['replace', 'edit', 'remove', 'clear', 'help']
|
actions = ['replace', 'edit', 'clear', 'help']
|
||||||
|
|
||||||
def __init__(self, olcsession):
|
def __init__(self, olcsession):
|
||||||
self.olcsession = olcsession
|
self.olcsession = olcsession
|
||||||
|
|
@ -43,7 +62,74 @@ class OLCField(object):
|
||||||
self._has_changed = False
|
self._has_changed = False
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return self.display()
|
return to_str(self.display())
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return to_unicode(self.display())
|
||||||
|
|
||||||
|
# perform actions
|
||||||
|
# TODO - include editor in check!
|
||||||
|
def do_replace(self, newval):
|
||||||
|
"""
|
||||||
|
Replace field value.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
newval (any): New value to replace existing one.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
InvalidActionError: If replacing is not allowed.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if 'replace' in self.actions:
|
||||||
|
self.value = newval
|
||||||
|
else:
|
||||||
|
raise InvalidActionError('Replace {value}->{newval}'.format(value=self.value, newval))
|
||||||
|
|
||||||
|
def can_edit(self):
|
||||||
|
"""
|
||||||
|
Check if we may edit.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
can_edit (bool): If we can edit or not.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if 'edit' in self.actions:
|
||||||
|
return self.value
|
||||||
|
return False
|
||||||
|
|
||||||
|
def do_clear(self):
|
||||||
|
"""
|
||||||
|
Clear field back to default.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
default (any): The field'd default value, now set.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
InvalidActionError: If clearing is not allowed.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if 'clear' in self.actions:
|
||||||
|
# don't validate this
|
||||||
|
object.__setattr__(self, 'value', self.default)
|
||||||
|
return self.value
|
||||||
|
else:
|
||||||
|
raise InvalidActionError('Clear')
|
||||||
|
|
||||||
|
def get_help(self):
|
||||||
|
"""
|
||||||
|
Get the help text for the field.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
help (str): Field help text.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
InvalidActionError: If help is not given for this field,
|
||||||
|
either becuase it's disallowed or unset.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if 'help' not in self.actions or not self.__doc__:
|
||||||
|
raise InvalidActioNError('Help')
|
||||||
|
return self.__doc__
|
||||||
|
|
||||||
# storing data to the field in a history-aware way
|
# storing data to the field in a history-aware way
|
||||||
@property
|
@property
|
||||||
|
|
@ -60,8 +146,7 @@ class OLCField(object):
|
||||||
value = self.validate(value)
|
value = self.validate(value)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
errtext = _OLC_VALIDATION_ERROR.format(fieldname=self.key, value=original_value, error=err)
|
errtext = _OLC_VALIDATION_ERROR.format(fieldname=self.key, value=original_value, error=err)
|
||||||
self.olcsession.caller.msg(errtext)
|
raise ValidationError(errtxt)
|
||||||
return
|
|
||||||
if (self._value_history and isinstance(value, (basestring, bool, int, float)) and
|
if (self._value_history and isinstance(value, (basestring, bool, int, float)) and
|
||||||
self._value_history[0] == value):
|
self._value_history[0] == value):
|
||||||
# don't change/update history if re-adding the same thing
|
# don't change/update history if re-adding the same thing
|
||||||
|
|
@ -104,7 +189,9 @@ class OLCField(object):
|
||||||
|
|
||||||
def from_entity(self, entity, **kwargs):
|
def from_entity(self, entity, **kwargs):
|
||||||
"""
|
"""
|
||||||
Populate this field from an entity.
|
Populate this field by retrieving data from an entity.
|
||||||
|
All fields on a page will have this called, so must
|
||||||
|
be able to handle also incompatible entities.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
entity (any): An object to use for
|
entity (any): An object to use for
|
||||||
|
|
@ -124,7 +211,7 @@ class OLCField(object):
|
||||||
|
|
||||||
def validate(self, value, **kwargs):
|
def validate(self, value, **kwargs):
|
||||||
"""
|
"""
|
||||||
Validate/preprocess data to store in this field.
|
Validate/preprocess incoming data to store in this field.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
value (any): An input value to
|
value (any): An input value to
|
||||||
|
|
@ -187,7 +274,7 @@ class OLCLocationField(OLCField):
|
||||||
label = "The object's current location"
|
label = "The object's current location"
|
||||||
|
|
||||||
def validate(self, value):
|
def validate(self, value):
|
||||||
return self.olcsession.search_by_string(value)
|
return olc_utils.search_by_string(self.olcsession, value)
|
||||||
|
|
||||||
def from_entity(self, entity, **kwargs):
|
def from_entity(self, entity, **kwargs):
|
||||||
self.value = entity.db_location
|
self.value = entity.db_location
|
||||||
|
|
@ -208,7 +295,7 @@ class OLCHomeField(OLCField):
|
||||||
label = "The object's home location"
|
label = "The object's home location"
|
||||||
|
|
||||||
def validate(self, value):
|
def validate(self, value):
|
||||||
return self.olcsession.search_by_string(value)
|
return olc_utils.search_by_string(self.olcsession, value)
|
||||||
|
|
||||||
def from_entity(self, entity, **kwargs):
|
def from_entity(self, entity, **kwargs):
|
||||||
self.value = entity.db_home
|
self.value = entity.db_home
|
||||||
|
|
@ -216,6 +303,7 @@ class OLCHomeField(OLCField):
|
||||||
def to_prototype(self, prototype):
|
def to_prototype(self, prototype):
|
||||||
prototype['home'] = self.value
|
prototype['home'] = self.value
|
||||||
|
|
||||||
|
|
||||||
class OLCDestinationField(OLCField):
|
class OLCDestinationField(OLCField):
|
||||||
"""
|
"""
|
||||||
An object's destination is usually not set unless the object
|
An object's destination is usually not set unless the object
|
||||||
|
|
@ -229,7 +317,7 @@ class OLCDestinationField(OLCField):
|
||||||
label = "The object's (usually exit's) destination"
|
label = "The object's (usually exit's) destination"
|
||||||
|
|
||||||
def validate(self, value):
|
def validate(self, value):
|
||||||
return self.olcsession.search_by_string(value)
|
return olc_utils.search_by_string(self.olcsession, value)
|
||||||
|
|
||||||
def from_entity(self, entity, **kwargs):
|
def from_entity(self, entity, **kwargs):
|
||||||
self.value = entity.db_destination
|
self.value = entity.db_destination
|
||||||
|
|
@ -238,6 +326,7 @@ class OLCDestinationField(OLCField):
|
||||||
prototype['destination'] = self.value
|
prototype['destination'] = self.value
|
||||||
|
|
||||||
|
|
||||||
|
# batch-setting aliases
|
||||||
class OLCAliasField(OLCField):
|
class OLCAliasField(OLCField):
|
||||||
"""
|
"""
|
||||||
Specify as a comma-separated list. Use quotes around the
|
Specify as a comma-separated list. Use quotes around the
|
||||||
|
|
@ -255,7 +344,7 @@ class OLCAliasField(OLCField):
|
||||||
actions = OLCField.actions + ['append']
|
actions = OLCField.actions + ['append']
|
||||||
|
|
||||||
def validate(self, value):
|
def validate(self, value):
|
||||||
return split_by_comma(value)
|
return olc_utils.split_by_comma(value)
|
||||||
|
|
||||||
def from_entity(self, entity, **kwargs):
|
def from_entity(self, entity, **kwargs):
|
||||||
self.value = list(entity.db_aliases.all())
|
self.value = list(entity.db_aliases.all())
|
||||||
|
|
@ -264,6 +353,7 @@ class OLCAliasField(OLCField):
|
||||||
prototype['aliases'] = self.value
|
prototype['aliases'] = self.value
|
||||||
|
|
||||||
|
|
||||||
|
# batch-setting tags
|
||||||
class OLCTagField(OLCField):
|
class OLCTagField(OLCField):
|
||||||
"""
|
"""
|
||||||
Specify as a comma-separated list of tagname or tagname:category.
|
Specify as a comma-separated list of tagname or tagname:category.
|
||||||
|
|
@ -276,12 +366,12 @@ class OLCTagField(OLCField):
|
||||||
"""
|
"""
|
||||||
key = 'Aliases'
|
key = 'Aliases'
|
||||||
required = False
|
required = False
|
||||||
label = "The object's (usually exit's) destination"
|
label = "Alternative ways to refer to this object."
|
||||||
actions = OLCField.actions + ['append']
|
actions = OLCField.actions + ['append']
|
||||||
|
|
||||||
def validate(self, value):
|
def validate(self, value):
|
||||||
return [tagstr.split(':', 1) if ':' in tagstr else (tagstr, None)
|
return [tuple(tagstr.split(':', 1)) if ':' in tagstr else (tagstr, None)
|
||||||
for tagstr in split_by_comma(value)]
|
for tagstr in olc_utils.split_by_comma(value)]
|
||||||
|
|
||||||
def from_entity(self, entity, **kwargs):
|
def from_entity(self, entity, **kwargs):
|
||||||
self.value = entity.tags.all(return_key_and_category=True)
|
self.value = entity.tags.all(return_key_and_category=True)
|
||||||
|
|
@ -289,3 +379,26 @@ class OLCTagField(OLCField):
|
||||||
def to_prototype(self, prototype):
|
def to_prototype(self, prototype):
|
||||||
prototype['tags'] = self.value
|
prototype['tags'] = self.value
|
||||||
|
|
||||||
|
|
||||||
|
# batch-setting attributes
|
||||||
|
class OLCAttributeField(OLCField):
|
||||||
|
"""
|
||||||
|
Specify as a comma-separated list of attrname=value or attrname:category=value.
|
||||||
|
|
||||||
|
Attributes are arbitrary pieces of data attached to an object. They can
|
||||||
|
contain references to other objects as well as simple Python structures such
|
||||||
|
as lists and dicts.
|
||||||
|
|
||||||
|
"""
|
||||||
|
key = 'Attributes'
|
||||||
|
required = False
|
||||||
|
label = "Additional data attached to this object."
|
||||||
|
actions = OLCField.actions + ['append']
|
||||||
|
|
||||||
|
def validate(self, value):
|
||||||
|
return [tuple(lhs.split(':', 1) + [rhs]) if ':' in lhs else (lhs, None) + (rhs, )
|
||||||
|
for lhs, rhs in (attrstr.split('=', 1) if ':' in attrstr else ((attrstr, None),))
|
||||||
|
for attrstr in olc_utils.split_by_comma(value)]
|
||||||
|
|
||||||
|
def from_entity(self, entity, **kwargs):
|
||||||
|
self.value = entity.attributes.all
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue