Merge pull request #1716 from Henddher/bug_1704

#1704: traceback when prototype key contains `#Number` [READY FOR REVIEW/MERGE]
This commit is contained in:
Griatch 2018-12-02 14:53:12 +01:00 committed by GitHub
commit 8ba00beef1
3 changed files with 92 additions and 11 deletions

View file

@ -37,12 +37,15 @@ prototype key (this value must be possible to serialize in an Attribute).
from ast import literal_eval
from random import randint as base_randint, random as base_random, choice as base_choice
import re
from evennia.utils import search
from evennia.utils.utils import justify as base_justify, is_iter, to_str
_PROTLIB = None
_RE_DBREF = re.compile(r"\#[0-9]+")
# default protfuncs
@ -325,3 +328,14 @@ def objlist(*args, **kwargs):
"""
return ["#{}".format(obj.id) for obj in _obj_search(return_list=True, *args, **kwargs)]
def dbref(*args, **kwargs):
"""
Usage $dbref(<#dbref>)
Returns one Object searched globally by #dbref. Error if #dbref is invalid.
"""
if not args or len(args) < 1 or _RE_DBREF.match(args[0]) is None:
raise ValueError('$dbref requires a valid #dbref argument.')
return obj(args[0])

View file

@ -5,7 +5,6 @@ Handling storage of prototypes, both database-based ones (DBPrototypes) and thos
"""
import re
import hashlib
import time
from ast import literal_eval
@ -33,8 +32,6 @@ _PROTOTYPE_TAG_CATEGORY = "from_prototype"
_PROTOTYPE_TAG_META_CATEGORY = "db_prototype"
PROT_FUNCS = {}
_RE_DBREF = re.compile(r"(?<!\$obj\()(#[0-9]+)")
class PermissionError(RuntimeError):
pass
@ -576,9 +573,6 @@ def protfunc_parser(value, available_functions=None, testing=False, stacktrace=F
available_functions = PROT_FUNCS if available_functions is None else available_functions
# insert $obj(#dbref) for #dbref
value = _RE_DBREF.sub("$obj(\\1)", value)
result = inlinefuncs.parse_inlinefunc(
value, available_funcs=available_functions,
stacktrace=stacktrace, testing=testing, **kwargs)

View file

@ -11,6 +11,7 @@ from evennia.utils.test_resources import EvenniaTest
from evennia.utils.tests.test_evmenu import TestEvMenu
from evennia.prototypes import spawner, prototypes as protlib
from evennia.prototypes import menus as olc_menus
from evennia.prototypes import protfuncs as protofuncs
from evennia.prototypes.prototypes import _PROTOTYPE_TAG_META_CATEGORY
@ -312,11 +313,83 @@ class TestProtFuncs(EvenniaTest):
self.assertEqual(protlib.protfunc_parser(
"$eval({'test': '1', 2:3, 3: $toint(3.5)})"), {'test': '1', 2: 3, 3: 3})
self.assertEqual(protlib.protfunc_parser("$obj(#1)", session=self.session), '#1')
self.assertEqual(protlib.protfunc_parser("#1", session=self.session), '#1')
self.assertEqual(protlib.protfunc_parser("$obj(Char)", session=self.session), '#6')
self.assertEqual(protlib.protfunc_parser("$obj(Char)", session=self.session), '#6')
self.assertEqual(protlib.protfunc_parser("$objlist(#1)", session=self.session), ['#1'])
# no object search
with mock.patch("evennia.prototypes.protfuncs._obj_search", wraps=protofuncs._obj_search) as mocked__obj_search:
self.assertEqual(protlib.protfunc_parser("obj(#1)", session=self.session), 'obj(#1)')
mocked__obj_search.assert_not_called()
with mock.patch("evennia.prototypes.protfuncs._obj_search", wraps=protofuncs._obj_search) as mocked__obj_search:
self.assertEqual(protlib.protfunc_parser("dbref(#1)", session=self.session), 'dbref(#1)')
mocked__obj_search.assert_not_called()
with mock.patch("evennia.prototypes.protfuncs._obj_search", wraps=protofuncs._obj_search) as mocked__obj_search:
self.assertEqual(protlib.protfunc_parser("stone(#12345)", session=self.session), 'stone(#12345)')
mocked__obj_search.assert_not_called()
with mock.patch("evennia.prototypes.protfuncs._obj_search", wraps=protofuncs._obj_search) as mocked__obj_search:
self.assertEqual(protlib.protfunc_parser("#1", session=self.session), '#1')
mocked__obj_search.assert_not_called()
with mock.patch("evennia.prototypes.protfuncs._obj_search", wraps=protofuncs._obj_search) as mocked__obj_search:
self.assertEqual(protlib.protfunc_parser("#12345", session=self.session), '#12345')
mocked__obj_search.assert_not_called()
with mock.patch("evennia.prototypes.protfuncs._obj_search", wraps=protofuncs._obj_search) as mocked__obj_search:
self.assertEqual(protlib.protfunc_parser("nothing(#1)", session=self.session), 'nothing(#1)')
mocked__obj_search.assert_not_called()
with mock.patch("evennia.prototypes.protfuncs._obj_search", wraps=protofuncs._obj_search) as mocked__obj_search:
self.assertEqual(protlib.protfunc_parser("(#12345)", session=self.session), '(#12345)')
mocked__obj_search.assert_not_called()
with mock.patch("evennia.prototypes.protfuncs._obj_search", wraps=protofuncs._obj_search) as mocked__obj_search:
self.assertEqual(protlib.protfunc_parser("obj(Char)", session=self.session), 'obj(Char)')
mocked__obj_search.assert_not_called()
with mock.patch("evennia.prototypes.protfuncs._obj_search", wraps=protofuncs._obj_search) as mocked__obj_search:
self.assertEqual(protlib.protfunc_parser("objlist(#1)", session=self.session), 'objlist(#1)')
mocked__obj_search.assert_not_called()
with mock.patch("evennia.prototypes.protfuncs._obj_search", wraps=protofuncs._obj_search) as mocked__obj_search:
self.assertEqual(protlib.protfunc_parser("dbref(Char)", session=self.session), 'dbref(Char)')
mocked__obj_search.assert_not_called()
# obj search happens
with mock.patch("evennia.prototypes.protfuncs._obj_search", wraps=protofuncs._obj_search) as mocked__obj_search:
self.assertEqual(protlib.protfunc_parser("$objlist(#1)", session=self.session), ['#1'])
mocked__obj_search.assert_called_once()
assert ('#1',) == mocked__obj_search.call_args[0]
with mock.patch("evennia.prototypes.protfuncs._obj_search", wraps=protofuncs._obj_search) as mocked__obj_search:
self.assertEqual(protlib.protfunc_parser("$obj(#1)", session=self.session), '#1')
mocked__obj_search.assert_called_once()
assert ('#1',) == mocked__obj_search.call_args[0]
with mock.patch("evennia.prototypes.protfuncs._obj_search", wraps=protofuncs._obj_search) as mocked__obj_search:
self.assertEqual(protlib.protfunc_parser("$dbref(#1)", session=self.session), '#1')
mocked__obj_search.assert_called_once()
assert ('#1',) == mocked__obj_search.call_args[0]
with mock.patch("evennia.prototypes.protfuncs._obj_search", wraps=protofuncs._obj_search) as mocked__obj_search:
self.assertEqual(protlib.protfunc_parser("$obj(Char)", session=self.session), '#6')
mocked__obj_search.assert_called_once()
assert ('Char',) == mocked__obj_search.call_args[0]
# bad invocation
with mock.patch("evennia.prototypes.protfuncs._obj_search", wraps=protofuncs._obj_search) as mocked__obj_search:
self.assertEqual(protlib.protfunc_parser("$badfunc(#1)", session=self.session), '<UNKNOWN>')
mocked__obj_search.assert_not_called()
with mock.patch("evennia.prototypes.protfuncs._obj_search", wraps=protofuncs._obj_search) as mocked__obj_search:
self.assertRaises(ValueError, protlib.protfunc_parser, "$dbref(Char)")
mocked__obj_search.assert_not_called()
self.assertEqual(protlib.value_to_obj(
protlib.protfunc_parser("#6", session=self.session)), self.char1)