Unit testing/debugging olc menu
This commit is contained in:
parent
9360dc71f1
commit
194eb8e42f
4 changed files with 171 additions and 31 deletions
|
|
@ -29,7 +29,7 @@ _MENU_ATTR_LITERAL_EVAL_ERROR = (
|
||||||
|
|
||||||
|
|
||||||
def _get_menu_prototype(caller):
|
def _get_menu_prototype(caller):
|
||||||
|
"""Return currently active menu prototype."""
|
||||||
prototype = None
|
prototype = None
|
||||||
if hasattr(caller.ndb._menutree, "olc_prototype"):
|
if hasattr(caller.ndb._menutree, "olc_prototype"):
|
||||||
prototype = caller.ndb._menutree.olc_prototype
|
prototype = caller.ndb._menutree.olc_prototype
|
||||||
|
|
@ -40,11 +40,23 @@ def _get_menu_prototype(caller):
|
||||||
|
|
||||||
|
|
||||||
def _is_new_prototype(caller):
|
def _is_new_prototype(caller):
|
||||||
|
"""Check if prototype is marked as new or was loaded from a saved one."""
|
||||||
return hasattr(caller.ndb._menutree, "olc_new")
|
return hasattr(caller.ndb._menutree, "olc_new")
|
||||||
|
|
||||||
|
|
||||||
def _format_property(prop, required=False, prototype=None, cropper=None):
|
def _format_option_value(prop, required=False, prototype=None, cropper=None):
|
||||||
|
"""
|
||||||
|
Format wizard option values.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
prop (str): Name or value to format.
|
||||||
|
required (bool, optional): The option is required.
|
||||||
|
prototype (dict, optional): If given, `prop` will be considered a key in this prototype.
|
||||||
|
cropper (callable, optional): A function to crop the value to a certain width.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
value (str): The formatted value.
|
||||||
|
"""
|
||||||
if prototype is not None:
|
if prototype is not None:
|
||||||
prop = prototype.get(prop, '')
|
prop = prototype.get(prop, '')
|
||||||
|
|
||||||
|
|
@ -61,7 +73,8 @@ def _format_property(prop, required=False, prototype=None, cropper=None):
|
||||||
return " ({}|n)".format(cropper(out) if cropper else utils.crop(out, _MENU_CROP_WIDTH))
|
return " ({}|n)".format(cropper(out) if cropper else utils.crop(out, _MENU_CROP_WIDTH))
|
||||||
|
|
||||||
|
|
||||||
def _set_prototype_value(caller, field, value):
|
def _set_prototype_value(caller, field, value, parse=True):
|
||||||
|
"""Set prototype's field in a safe way."""
|
||||||
prototype = _get_menu_prototype(caller)
|
prototype = _get_menu_prototype(caller)
|
||||||
prototype[field] = value
|
prototype[field] = value
|
||||||
caller.ndb._menutree.olc_prototype = prototype
|
caller.ndb._menutree.olc_prototype = prototype
|
||||||
|
|
@ -70,15 +83,21 @@ def _set_prototype_value(caller, field, value):
|
||||||
|
|
||||||
def _set_property(caller, raw_string, **kwargs):
|
def _set_property(caller, raw_string, **kwargs):
|
||||||
"""
|
"""
|
||||||
Update a property. To be called by the 'goto' option variable.
|
Add or update a property. To be called by the 'goto' option variable.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
caller (Object, Account): The user of the wizard.
|
caller (Object, Account): The user of the wizard.
|
||||||
raw_string (str): Input from user on given node - the new value to set.
|
raw_string (str): Input from user on given node - the new value to set.
|
||||||
|
|
||||||
Kwargs:
|
Kwargs:
|
||||||
|
test_parse (bool): If set (default True), parse raw_string for protfuncs and obj-refs and
|
||||||
|
try to run result through literal_eval. The parser will be run in 'testing' mode and any
|
||||||
|
parsing errors will shown to the user. Note that this is just for testing, the original
|
||||||
|
given string will be what is inserted.
|
||||||
prop (str): Property name to edit with `raw_string`.
|
prop (str): Property name to edit with `raw_string`.
|
||||||
processor (callable): Converts `raw_string` to a form suitable for saving.
|
processor (callable): Converts `raw_string` to a form suitable for saving.
|
||||||
next_node (str): Where to redirect to after this has run.
|
next_node (str): Where to redirect to after this has run.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
next_node (str): Next node to go to.
|
next_node (str): Next node to go to.
|
||||||
|
|
||||||
|
|
@ -103,7 +122,7 @@ def _set_property(caller, raw_string, **kwargs):
|
||||||
if not value:
|
if not value:
|
||||||
return next_node
|
return next_node
|
||||||
|
|
||||||
prototype = _set_prototype_value(caller, "prototype_key", value)
|
prototype = _set_prototype_value(caller, prop, value)
|
||||||
|
|
||||||
# typeclass and prototype_parent can't co-exist
|
# typeclass and prototype_parent can't co-exist
|
||||||
if propname_low == "typeclass":
|
if propname_low == "typeclass":
|
||||||
|
|
@ -113,16 +132,26 @@ def _set_property(caller, raw_string, **kwargs):
|
||||||
|
|
||||||
caller.ndb._menutree.olc_prototype = prototype
|
caller.ndb._menutree.olc_prototype = prototype
|
||||||
|
|
||||||
caller.msg("Set {prop} to '{value}'.".format(prop=prop, value=str(value)))
|
out = [" Set {prop} to {value} ({typ}).".format(prop=prop, value=value, typ=type(value))]
|
||||||
|
|
||||||
|
if kwargs.get("test_parse", True):
|
||||||
|
out.append(" Simulating parsing ...")
|
||||||
|
err, parsed_value = protlib.protfunc_parser(value, testing=True)
|
||||||
|
if err:
|
||||||
|
out.append(" |yPython `literal_eval` warning: {}|n".format(err))
|
||||||
|
if parsed_value != value:
|
||||||
|
out.append(" |g(Example-)value when parsed ({}):|n {}".format(
|
||||||
|
type(parsed_value), parsed_value))
|
||||||
|
else:
|
||||||
|
out.append(" |gNo change.")
|
||||||
|
|
||||||
|
caller.msg("\n".join(out))
|
||||||
|
|
||||||
return next_node
|
return next_node
|
||||||
|
|
||||||
|
|
||||||
def _wizard_options(curr_node, prev_node, next_node, color="|W"):
|
def _wizard_options(curr_node, prev_node, next_node, color="|W"):
|
||||||
"""
|
"""Creates default navigation options available in the wizard."""
|
||||||
Creates default navigation options available in the wizard.
|
|
||||||
|
|
||||||
"""
|
|
||||||
options = []
|
options = []
|
||||||
if prev_node:
|
if prev_node:
|
||||||
options.append({"key": ("|wb|Wack", "b"),
|
options.append({"key": ("|wb|Wack", "b"),
|
||||||
|
|
@ -166,7 +195,7 @@ def node_index(caller):
|
||||||
|
|
||||||
options = []
|
options = []
|
||||||
options.append(
|
options.append(
|
||||||
{"desc": "|WPrototype-Key|n|n{}".format(_format_property("Key", True, prototype, None)),
|
{"desc": "|WPrototype-Key|n|n{}".format(_format_option_value("Key", True, prototype, None)),
|
||||||
"goto": "node_prototype_key"})
|
"goto": "node_prototype_key"})
|
||||||
for key in ('Prototype', 'Typeclass', 'Key', 'Aliases', 'Attrs', 'Tags', 'Locks',
|
for key in ('Prototype', 'Typeclass', 'Key', 'Aliases', 'Attrs', 'Tags', 'Locks',
|
||||||
'Permissions', 'Location', 'Home', 'Destination'):
|
'Permissions', 'Location', 'Home', 'Destination'):
|
||||||
|
|
@ -178,13 +207,13 @@ def node_index(caller):
|
||||||
cropper = _path_cropper
|
cropper = _path_cropper
|
||||||
options.append(
|
options.append(
|
||||||
{"desc": "|w{}|n{}".format(
|
{"desc": "|w{}|n{}".format(
|
||||||
key, _format_property(key, required, prototype, cropper=cropper)),
|
key, _format_option_value(key, required, prototype, cropper=cropper)),
|
||||||
"goto": "node_{}".format(key.lower())})
|
"goto": "node_{}".format(key.lower())})
|
||||||
required = False
|
required = False
|
||||||
for key in ('Desc', 'Tags', 'Locks'):
|
for key in ('Desc', 'Tags', 'Locks'):
|
||||||
options.append(
|
options.append(
|
||||||
{"desc": "|WPrototype-{}|n|n{}".format(
|
{"desc": "|WPrototype-{}|n|n{}".format(
|
||||||
key, _format_property(key, required, prototype, None)),
|
key, _format_option_value(key, required, prototype, None)),
|
||||||
"goto": "node_prototype_{}".format(key.lower())})
|
"goto": "node_prototype_{}".format(key.lower())})
|
||||||
|
|
||||||
return text, options
|
return text, options
|
||||||
|
|
@ -215,6 +244,7 @@ def _check_prototype_key(caller, key):
|
||||||
olc_new = _is_new_prototype(caller)
|
olc_new = _is_new_prototype(caller)
|
||||||
key = key.strip().lower()
|
key = key.strip().lower()
|
||||||
if old_prototype:
|
if old_prototype:
|
||||||
|
old_prototype = old_prototype[0]
|
||||||
# we are starting a new prototype that matches an existing
|
# we are starting a new prototype that matches an existing
|
||||||
if not caller.locks.check_lockstring(
|
if not caller.locks.check_lockstring(
|
||||||
caller, old_prototype['prototype_locks'], access_type='edit'):
|
caller, old_prototype['prototype_locks'], access_type='edit'):
|
||||||
|
|
@ -229,7 +259,7 @@ def _check_prototype_key(caller, key):
|
||||||
caller.msg("Prototype already exists. Reloading.")
|
caller.msg("Prototype already exists. Reloading.")
|
||||||
return "node_index"
|
return "node_index"
|
||||||
|
|
||||||
return _set_property(caller, key, prop='prototype_key', next_node="node_prototype")
|
return _set_property(caller, key, prop='prototype_key', next_node="node_prototype_parent")
|
||||||
|
|
||||||
|
|
||||||
def node_prototype_key(caller):
|
def node_prototype_key(caller):
|
||||||
|
|
@ -250,27 +280,32 @@ def node_prototype_key(caller):
|
||||||
return text, options
|
return text, options
|
||||||
|
|
||||||
|
|
||||||
def _all_prototypes(caller):
|
def _all_prototype_parents(caller):
|
||||||
|
"""Return prototype_key of all available prototypes for listing in menu"""
|
||||||
return [prototype["prototype_key"]
|
return [prototype["prototype_key"]
|
||||||
for prototype in protlib.search_prototype() if "prototype_key" in prototype]
|
for prototype in protlib.search_prototype() if "prototype_key" in prototype]
|
||||||
|
|
||||||
|
|
||||||
def _prototype_examine(caller, prototype_name):
|
def _prototype_parent_examine(caller, prototype_name):
|
||||||
|
"""Convert prototype to a string representation for closer inspection"""
|
||||||
prototypes = protlib.search_prototype(key=prototype_name)
|
prototypes = protlib.search_prototype(key=prototype_name)
|
||||||
if prototypes:
|
if prototypes:
|
||||||
caller.msg(protlib.prototype_to_str(prototypes[0]))
|
ret = protlib.prototype_to_str(prototypes[0])
|
||||||
caller.msg("Prototype not registered.")
|
caller.msg(ret)
|
||||||
return None
|
return ret
|
||||||
|
else:
|
||||||
|
caller.msg("Prototype not registered.")
|
||||||
|
|
||||||
|
|
||||||
def _prototype_select(caller, prototype):
|
def _prototype_parent_select(caller, prototype):
|
||||||
ret = _set_property(caller, prototype, prop="prototype", processor=str, next_node="node_key")
|
ret = _set_property(caller, prototype['prototype_key'],
|
||||||
|
prop="prototype_parent", processor=str, next_node="node_key")
|
||||||
caller.msg("Selected prototype |y{}|n. Removed any set typeclass parent.".format(prototype))
|
caller.msg("Selected prototype |y{}|n. Removed any set typeclass parent.".format(prototype))
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
@list_node(_all_prototypes, _prototype_select)
|
@list_node(_all_prototype_parents, _prototype_parent_select)
|
||||||
def node_prototype(caller):
|
def node_prototype_parent(caller):
|
||||||
prototype = _get_menu_prototype(caller)
|
prototype = _get_menu_prototype(caller)
|
||||||
|
|
||||||
prot_parent_key = prototype.get('prototype')
|
prot_parent_key = prototype.get('prototype')
|
||||||
|
|
@ -289,18 +324,20 @@ def node_prototype(caller):
|
||||||
text = "\n\n".join(text)
|
text = "\n\n".join(text)
|
||||||
options = _wizard_options("prototype", "prototype_key", "typeclass", color="|W")
|
options = _wizard_options("prototype", "prototype_key", "typeclass", color="|W")
|
||||||
options.append({"key": "_default",
|
options.append({"key": "_default",
|
||||||
"goto": _prototype_examine})
|
"goto": _prototype_parent_examine})
|
||||||
|
|
||||||
return text, options
|
return text, options
|
||||||
|
|
||||||
|
|
||||||
def _all_typeclasses(caller):
|
def _all_typeclasses(caller):
|
||||||
|
"""Get name of available typeclasses."""
|
||||||
return list(name for name in
|
return list(name for name in
|
||||||
sorted(utils.get_all_typeclasses("evennia.objects.models.ObjectDB").keys())
|
sorted(utils.get_all_typeclasses("evennia.objects.models.ObjectDB").keys())
|
||||||
if name != "evennia.objects.models.ObjectDB")
|
if name != "evennia.objects.models.ObjectDB")
|
||||||
|
|
||||||
|
|
||||||
def _typeclass_examine(caller, typeclass_path):
|
def _typeclass_examine(caller, typeclass_path):
|
||||||
|
"""Show info (docstring) about given typeclass."""
|
||||||
if typeclass_path is None:
|
if typeclass_path is None:
|
||||||
# this means we are exiting the listing
|
# this means we are exiting the listing
|
||||||
return "node_key"
|
return "node_key"
|
||||||
|
|
@ -319,10 +356,11 @@ def _typeclass_examine(caller, typeclass_path):
|
||||||
else:
|
else:
|
||||||
txt = "This is typeclass |y{}|n.".format(typeclass)
|
txt = "This is typeclass |y{}|n.".format(typeclass)
|
||||||
caller.msg(txt)
|
caller.msg(txt)
|
||||||
return None
|
return txt
|
||||||
|
|
||||||
|
|
||||||
def _typeclass_select(caller, typeclass):
|
def _typeclass_select(caller, typeclass):
|
||||||
|
"""Select typeclass from list and add it to prototype. Return next node to go to."""
|
||||||
ret = _set_property(caller, typeclass, prop='typeclass', processor=str, next_node="node_key")
|
ret = _set_property(caller, typeclass, prop='typeclass', processor=str, next_node="node_key")
|
||||||
caller.msg("Selected typeclass |y{}|n. Removed any set prototype parent.".format(typeclass))
|
caller.msg("Selected typeclass |y{}|n. Removed any set prototype parent.".format(typeclass))
|
||||||
return ret
|
return ret
|
||||||
|
|
@ -350,7 +388,7 @@ def node_key(caller):
|
||||||
prototype = _get_menu_prototype(caller)
|
prototype = _get_menu_prototype(caller)
|
||||||
key = prototype.get("key")
|
key = prototype.get("key")
|
||||||
|
|
||||||
text = ["Set the prototype's |yKey|n. This will retain case sensitivity."]
|
text = ["Set the prototype's name (|yKey|n.) This will retain case sensitivity."]
|
||||||
if key:
|
if key:
|
||||||
text.append("Current key value is '|y{key}|n'.".format(key=key))
|
text.append("Current key value is '|y{key}|n'.".format(key=key))
|
||||||
else:
|
else:
|
||||||
|
|
@ -370,7 +408,7 @@ def node_aliases(caller):
|
||||||
aliases = prototype.get("aliases")
|
aliases = prototype.get("aliases")
|
||||||
|
|
||||||
text = ["Set the prototype's |yAliases|n. Separate multiple aliases with commas. "
|
text = ["Set the prototype's |yAliases|n. Separate multiple aliases with commas. "
|
||||||
"ill retain case sensitivity."]
|
"they'll retain case sensitivity."]
|
||||||
if aliases:
|
if aliases:
|
||||||
text.append("Current aliases are '|y{aliases}|n'.".format(aliases=aliases))
|
text.append("Current aliases are '|y{aliases}|n'.".format(aliases=aliases))
|
||||||
else:
|
else:
|
||||||
|
|
@ -714,7 +752,7 @@ def start_olc(caller, session=None, prototype=None):
|
||||||
menudata = {"node_index": node_index,
|
menudata = {"node_index": node_index,
|
||||||
"node_validate_prototype": node_validate_prototype,
|
"node_validate_prototype": node_validate_prototype,
|
||||||
"node_prototype_key": node_prototype_key,
|
"node_prototype_key": node_prototype_key,
|
||||||
"node_prototype": node_prototype,
|
"node_prototype_parent": node_prototype_parent,
|
||||||
"node_typeclass": node_typeclass,
|
"node_typeclass": node_typeclass,
|
||||||
"node_key": node_key,
|
"node_key": node_key,
|
||||||
"node_aliases": node_aliases,
|
"node_aliases": node_aliases,
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,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)
|
get_all_typeclasses, to_str)
|
||||||
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
|
from evennia.utils import inlinefuncs
|
||||||
|
|
@ -64,6 +64,7 @@ def protfunc_parser(value, available_functions=None, testing=False, stacktrace=F
|
||||||
value (any): The value to test for a parseable protfunc. Only strings will be parsed for
|
value (any): The value to test for a parseable protfunc. Only strings will be parsed for
|
||||||
protfuncs, all other types are returned as-is.
|
protfuncs, all other types are returned as-is.
|
||||||
available_functions (dict, optional): Mapping of name:protfunction to use for this parsing.
|
available_functions (dict, optional): Mapping of name:protfunction to use for this parsing.
|
||||||
|
If not set, use default sources.
|
||||||
testing (bool, optional): Passed to protfunc. If in a testing mode, some protfuncs may
|
testing (bool, optional): Passed to protfunc. If in a testing mode, some protfuncs may
|
||||||
behave differently.
|
behave differently.
|
||||||
stacktrace (bool, optional): If set, print the stack parsing process of the protfunc-parser.
|
stacktrace (bool, optional): If set, print the stack parsing process of the protfunc-parser.
|
||||||
|
|
@ -86,7 +87,8 @@ def protfunc_parser(value, available_functions=None, testing=False, stacktrace=F
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if not isinstance(value, basestring):
|
if not isinstance(value, basestring):
|
||||||
return value
|
value = to_str(value, force_string=True)
|
||||||
|
|
||||||
available_functions = _PROT_FUNCS if available_functions is None else available_functions
|
available_functions = _PROT_FUNCS if available_functions is None else available_functions
|
||||||
|
|
||||||
# insert $obj(#dbref) for #dbref
|
# insert $obj(#dbref) for #dbref
|
||||||
|
|
|
||||||
|
|
@ -308,6 +308,91 @@ class TestPrototypeStorage(EvenniaTest):
|
||||||
self.assertTrue(str(unicode(protlib.list_prototypes(self.char1))))
|
self.assertTrue(str(unicode(protlib.list_prototypes(self.char1))))
|
||||||
|
|
||||||
|
|
||||||
|
class _MockMenu(object):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class TestMenuModule(EvenniaTest):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestMenuModule, self).setUp()
|
||||||
|
|
||||||
|
# set up fake store
|
||||||
|
self.caller = self.char1
|
||||||
|
menutree = _MockMenu()
|
||||||
|
self.caller.ndb._menutree = menutree
|
||||||
|
|
||||||
|
self.test_prot = {"prototype_key": "test_prot",
|
||||||
|
"prototype_locks": "edit:all();spawn:all()"}
|
||||||
|
|
||||||
|
def test_helpers(self):
|
||||||
|
|
||||||
|
caller = self.caller
|
||||||
|
|
||||||
|
# general helpers
|
||||||
|
|
||||||
|
self.assertEqual(olc_menus._get_menu_prototype(caller), {})
|
||||||
|
self.assertEqual(olc_menus._is_new_prototype(caller), True)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
olc_menus._set_prototype_value(caller, "key", "TestKey"), {"key": "TestKey"})
|
||||||
|
self.assertEqual(olc_menus._get_menu_prototype(caller), {"key": "TestKey"})
|
||||||
|
|
||||||
|
self.assertEqual(olc_menus._format_option_value(
|
||||||
|
"key", required=True, prototype=olc_menus._get_menu_prototype(caller)), " (TestKey|n)")
|
||||||
|
self.assertEqual(olc_menus._format_option_value(
|
||||||
|
[1, 2, 3, "foo"], required=True), ' (1, 2, 3, foo|n)')
|
||||||
|
|
||||||
|
self.assertEqual(olc_menus._set_property(
|
||||||
|
caller, "ChangedKey", prop="key", processor=str, next_node="foo"), "foo")
|
||||||
|
self.assertEqual(olc_menus._get_menu_prototype(caller), {"key": "ChangedKey"})
|
||||||
|
|
||||||
|
self.assertEqual(olc_menus._wizard_options(
|
||||||
|
"ThisNode", "PrevNode", "NextNode"),
|
||||||
|
[{'goto': 'node_PrevNode', 'key': ('|wb|Wack', 'b'), 'desc': '|W(PrevNode)|n'},
|
||||||
|
{'goto': 'node_NextNode', 'key': ('|wf|Worward', 'f'), 'desc': '|W(NextNode)|n'},
|
||||||
|
{'goto': 'node_index', 'key': ('|wi|Wndex', 'i')},
|
||||||
|
{'goto': ('node_validate_prototype', {'back': 'ThisNode'}),
|
||||||
|
'key': ('|wv|Walidate prototype', 'v')}])
|
||||||
|
|
||||||
|
def test_node_helpers(self):
|
||||||
|
|
||||||
|
caller = self.caller
|
||||||
|
|
||||||
|
with mock.patch("evennia.prototypes.menus.protlib.search_prototype",
|
||||||
|
new=mock.MagicMock(return_value=[self.test_prot])):
|
||||||
|
self.assertEqual(olc_menus._check_prototype_key(caller, "test_prot"),
|
||||||
|
"node_prototype_parent")
|
||||||
|
caller.ndb._menutree.olc_new = True
|
||||||
|
self.assertEqual(olc_menus._check_prototype_key(caller, "test_prot"),
|
||||||
|
"node_index")
|
||||||
|
|
||||||
|
self.assertEqual(olc_menus._all_prototype_parents(caller), ['test_prot'])
|
||||||
|
self.assertEqual(olc_menus._prototype_parent_examine(
|
||||||
|
caller, 'test_prot'),
|
||||||
|
'|cprototype key:|n test_prot, |ctags:|n None, |clocks:|n edit:all();spawn:all() '
|
||||||
|
'\n|cdesc:|n None \n|cprototype:|n {\n \n}')
|
||||||
|
self.assertEqual(olc_menus._prototype_parent_select(caller, self.test_prot), "node_key")
|
||||||
|
self.assertEqual(olc_menus._get_menu_prototype(caller),
|
||||||
|
{'prototype_key': 'test_prot',
|
||||||
|
'prototype_locks': 'edit:all();spawn:all()',
|
||||||
|
'prototype_parent': "test_prot"})
|
||||||
|
|
||||||
|
with mock.patch("evennia.utils.utils.get_all_typeclasses",
|
||||||
|
new=mock.MagicMock(return_value={"foo": None, "bar": None})):
|
||||||
|
self.assertEqual(olc_menus._all_typeclasses(caller), ["bar", "foo"])
|
||||||
|
self.assertTrue(olc_menus._typeclass_examine(
|
||||||
|
caller, "evennia.objects.objects.DefaultObject").startswith("Typeclass |y"))
|
||||||
|
|
||||||
|
self.assertEqual(olc_menus._typeclass_select(
|
||||||
|
caller, "evennia.objects.objects.DefaultObject"), "node_key")
|
||||||
|
# prototype_parent should be popped off here
|
||||||
|
self.assertEqual(olc_menus._get_menu_prototype(caller),
|
||||||
|
{'prototype_key': 'test_prot',
|
||||||
|
'prototype_locks': 'edit:all();spawn:all()',
|
||||||
|
'typeclass': 'evennia.objects.objects.DefaultObject'})
|
||||||
|
|
||||||
|
|
||||||
@mock.patch("evennia.prototypes.menus.protlib.search_prototype", new=mock.MagicMock(
|
@mock.patch("evennia.prototypes.menus.protlib.search_prototype", new=mock.MagicMock(
|
||||||
return_value=[{"prototype_key": "TestPrototype",
|
return_value=[{"prototype_key": "TestPrototype",
|
||||||
"typeclass": "TypeClassTest", "key": "TestObj"}]))
|
"typeclass": "TypeClassTest", "key": "TestObj"}]))
|
||||||
|
|
@ -320,6 +405,7 @@ class TestOLCMenu(TestEvMenu):
|
||||||
startnode = "node_index"
|
startnode = "node_index"
|
||||||
|
|
||||||
debug_output = True
|
debug_output = True
|
||||||
|
expect_all_nodes = True
|
||||||
|
|
||||||
expected_node_texts = {
|
expected_node_texts = {
|
||||||
"node_index": "|c --- Prototype wizard --- |n"
|
"node_index": "|c --- Prototype wizard --- |n"
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,20 @@ def clr(*args, **kwargs):
|
||||||
def null(*args, **kwargs):
|
def null(*args, **kwargs):
|
||||||
return args[0] if args else ''
|
return args[0] if args else ''
|
||||||
|
|
||||||
|
|
||||||
|
def nomatch(name, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Default implementation of nomatch returns the function as-is as a string.
|
||||||
|
|
||||||
|
"""
|
||||||
|
kwargs.pop("inlinefunc_stack_depth", None)
|
||||||
|
kwargs.pop("session")
|
||||||
|
|
||||||
|
return "${name}({args}{kwargs})".format(
|
||||||
|
name=name,
|
||||||
|
args=",".join(args),
|
||||||
|
kwargs=",".join("{}={}".format(key, val) for key, val in kwargs.items()))
|
||||||
|
|
||||||
_INLINE_FUNCS = {}
|
_INLINE_FUNCS = {}
|
||||||
|
|
||||||
# we specify a default nomatch function to use if no matching func was
|
# we specify a default nomatch function to use if no matching func was
|
||||||
|
|
@ -284,7 +298,6 @@ def parse_inlinefunc(string, strip=False, available_funcs=None, stacktrace=False
|
||||||
|
|
||||||
"""
|
"""
|
||||||
global _PARSING_CACHE
|
global _PARSING_CACHE
|
||||||
|
|
||||||
usecache = False
|
usecache = False
|
||||||
if not available_funcs:
|
if not available_funcs:
|
||||||
available_funcs = _INLINE_FUNCS
|
available_funcs = _INLINE_FUNCS
|
||||||
|
|
@ -357,6 +370,7 @@ def parse_inlinefunc(string, strip=False, available_funcs=None, stacktrace=False
|
||||||
except KeyError:
|
except KeyError:
|
||||||
stack.append(available_funcs["nomatch"])
|
stack.append(available_funcs["nomatch"])
|
||||||
stack.append(funcname)
|
stack.append(funcname)
|
||||||
|
stack.append(None)
|
||||||
ncallable += 1
|
ncallable += 1
|
||||||
elif gdict["escaped"]:
|
elif gdict["escaped"]:
|
||||||
# escaped tokens
|
# escaped tokens
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue