Merge branch 'master' of https://github.com/evennia/evennia into puzzles
This commit is contained in:
commit
a0f113ad52
4 changed files with 50 additions and 14 deletions
|
|
@ -2889,7 +2889,8 @@ class CmdSpawn(COMMAND_DEFAULT_CLASS):
|
||||||
"use the 'exec' prototype key.")
|
"use the 'exec' prototype key.")
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
protlib.validate_prototype(prototype)
|
# we homogenize first, to be more lenient
|
||||||
|
protlib.validate_prototype(protlib.homogenize_prototype(prototype))
|
||||||
except RuntimeError as err:
|
except RuntimeError as err:
|
||||||
self.caller.msg(str(err))
|
self.caller.msg(str(err))
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ Handling storage of prototypes, both database-based ones (DBPrototypes) and thos
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
import hashlib
|
||||||
|
import time
|
||||||
from ast import literal_eval
|
from ast import literal_eval
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from evennia.scripts.scripts import DefaultScript
|
from evennia.scripts.scripts import DefaultScript
|
||||||
|
|
@ -13,7 +15,7 @@ from evennia.objects.models import ObjectDB
|
||||||
from evennia.utils.create import create_script
|
from evennia.utils.create import create_script
|
||||||
from evennia.utils.utils import (
|
from evennia.utils.utils import (
|
||||||
all_from_module, make_iter, is_iter, dbid_to_obj, callables_from_module,
|
all_from_module, make_iter, is_iter, dbid_to_obj, callables_from_module,
|
||||||
get_all_typeclasses, to_str, dbref, justify)
|
get_all_typeclasses, to_str, dbref, justify, class_from_module)
|
||||||
from evennia.locks.lockhandler import validate_lockstring, check_lockstring
|
from evennia.locks.lockhandler import validate_lockstring, check_lockstring
|
||||||
from evennia.utils import logger
|
from evennia.utils import logger
|
||||||
from evennia.utils import inlinefuncs, dbserialize
|
from evennia.utils import inlinefuncs, dbserialize
|
||||||
|
|
@ -47,8 +49,8 @@ class ValidationError(RuntimeError):
|
||||||
|
|
||||||
def homogenize_prototype(prototype, custom_keys=None):
|
def homogenize_prototype(prototype, custom_keys=None):
|
||||||
"""
|
"""
|
||||||
Homogenize the more free-form prototype (where undefined keys are non-category attributes)
|
Homogenize the more free-form prototype supported pre Evennia 0.7 into the stricter form.
|
||||||
into the stricter form using `attrs` required by the system.
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
prototype (dict): Prototype.
|
prototype (dict): Prototype.
|
||||||
|
|
@ -56,18 +58,45 @@ def homogenize_prototype(prototype, custom_keys=None):
|
||||||
the default reserved keys.
|
the default reserved keys.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
homogenized (dict): Prototype where all non-identified keys grouped as attributes.
|
homogenized (dict): Prototype where all non-identified keys grouped as attributes and other
|
||||||
|
homogenizations like adding missing prototype_keys and setting a default typeclass.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
reserved = _PROTOTYPE_RESERVED_KEYS + (custom_keys or ())
|
reserved = _PROTOTYPE_RESERVED_KEYS + (custom_keys or ())
|
||||||
|
|
||||||
attrs = list(prototype.get('attrs', [])) # break reference
|
attrs = list(prototype.get('attrs', [])) # break reference
|
||||||
|
tags = make_iter(prototype.get('tags', []))
|
||||||
|
homogenized_tags = []
|
||||||
|
|
||||||
homogenized = {}
|
homogenized = {}
|
||||||
for key, val in prototype.items():
|
for key, val in prototype.items():
|
||||||
if key in reserved:
|
if key in reserved:
|
||||||
homogenized[key] = val
|
if key == 'tags':
|
||||||
|
for tag in tags:
|
||||||
|
if not is_iter(tag):
|
||||||
|
homogenized_tags.append((tag, None, None))
|
||||||
|
else:
|
||||||
|
homogenized_tags.append(tag)
|
||||||
|
else:
|
||||||
|
homogenized[key] = val
|
||||||
else:
|
else:
|
||||||
|
# unassigned keys -> attrs
|
||||||
attrs.append((key, val, None, ''))
|
attrs.append((key, val, None, ''))
|
||||||
if attrs:
|
if attrs:
|
||||||
homogenized['attrs'] = attrs
|
homogenized['attrs'] = attrs
|
||||||
|
if homogenized_tags:
|
||||||
|
homogenized['tags'] = homogenized_tags
|
||||||
|
|
||||||
|
# add required missing parts that had defaults before
|
||||||
|
|
||||||
|
if "prototype_key" not in prototype:
|
||||||
|
# assign a random hash as key
|
||||||
|
homogenized["prototype_key"] = "prototype-{}".format(
|
||||||
|
hashlib.md5(str(time.time())).hexdigest()[:7])
|
||||||
|
|
||||||
|
if "typeclass" not in prototype and "prototype_parent" not in prototype:
|
||||||
|
homogenized["typeclass"] = settings.BASE_OBJECT_TYPECLASS
|
||||||
|
|
||||||
return homogenized
|
return homogenized
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -432,11 +461,13 @@ def validate_prototype(prototype, protkey=None, protparents=None,
|
||||||
_flags['warnings'].append("Prototype {} can only be used as a mixin since it lacks "
|
_flags['warnings'].append("Prototype {} can only be used as a mixin since it lacks "
|
||||||
"a typeclass or a prototype_parent.".format(protkey))
|
"a typeclass or a prototype_parent.".format(protkey))
|
||||||
|
|
||||||
if (strict and typeclass and typeclass not
|
if strict and typeclass:
|
||||||
in get_all_typeclasses("evennia.objects.models.ObjectDB")):
|
try:
|
||||||
_flags['errors'].append(
|
class_from_module(typeclass)
|
||||||
"Prototype {} is based on typeclass {}, which could not be imported!".format(
|
except ImportError as err:
|
||||||
protkey, typeclass))
|
_flags['errors'].append(
|
||||||
|
"{}: Prototype {} is based on typeclass {}, which could not be imported!".format(
|
||||||
|
err, protkey, typeclass))
|
||||||
|
|
||||||
# recursively traverese prototype_parent chain
|
# recursively traverese prototype_parent chain
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -659,6 +659,9 @@ def spawn(*prototypes, **kwargs):
|
||||||
# get available protparents
|
# get available protparents
|
||||||
protparents = {prot['prototype_key'].lower(): prot for prot in protlib.search_prototype()}
|
protparents = {prot['prototype_key'].lower(): prot for prot in protlib.search_prototype()}
|
||||||
|
|
||||||
|
if not kwargs.get("only_validate"):
|
||||||
|
prototypes = [protlib.homogenize_prototype(prot) for prot in prototypes]
|
||||||
|
|
||||||
# overload module's protparents with specifically given protparents
|
# overload module's protparents with specifically given protparents
|
||||||
# we allow prototype_key to be the key of the protparent dict, to allow for module-level
|
# we allow prototype_key to be the key of the protparent dict, to allow for module-level
|
||||||
# prototype imports. We need to insert prototype_key in this case
|
# prototype imports. We need to insert prototype_key in this case
|
||||||
|
|
@ -730,7 +733,7 @@ def spawn(*prototypes, **kwargs):
|
||||||
val = make_iter(prot.pop("attrs", []))
|
val = make_iter(prot.pop("attrs", []))
|
||||||
attributes = []
|
attributes = []
|
||||||
for (attrname, value, category, locks) in val:
|
for (attrname, value, category, locks) in val:
|
||||||
attributes.append((attrname, init_spawn_value(val), category, locks))
|
attributes.append((attrname, init_spawn_value(value), category, locks))
|
||||||
|
|
||||||
simple_attributes = []
|
simple_attributes = []
|
||||||
for key, value in ((key, value) for key, value in prot.items()
|
for key, value in ((key, value) for key, value in prot.items()
|
||||||
|
|
|
||||||
|
|
@ -384,8 +384,9 @@ class TestPrototypeStorage(EvenniaTest):
|
||||||
prot3 = protlib.create_prototype(**self.prot3)
|
prot3 = protlib.create_prototype(**self.prot3)
|
||||||
|
|
||||||
# partial match
|
# partial match
|
||||||
self.assertEqual(list(protlib.search_prototype("prot")), [prot1b, prot2, prot3])
|
with mock.patch("evennia.prototypes.prototypes._MODULE_PROTOTYPES", {}):
|
||||||
self.assertEqual(list(protlib.search_prototype(tags="foo1")), [prot1b, prot2, prot3])
|
self.assertEqual(list(protlib.search_prototype("prot")), [prot1b, prot2, prot3])
|
||||||
|
self.assertEqual(list(protlib.search_prototype(tags="foo1")), [prot1b, prot2, prot3])
|
||||||
|
|
||||||
self.assertTrue(str(unicode(protlib.list_prototypes(self.char1))))
|
self.assertTrue(str(unicode(protlib.list_prototypes(self.char1))))
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue