Merge branch 'master' into develop

This commit is contained in:
Griatch 2018-12-02 16:28:45 +01:00
commit 9b2ae6caed
6 changed files with 119 additions and 20 deletions

View file

@ -105,7 +105,7 @@ def _create_version():
print(err)
try:
version = "%s (rev %s)" % (version, check_output("git rev-parse --short HEAD", shell=True, cwd=root, stderr=STDOUT).strip())
except (IOError, CalledProcessError):
except (IOError, CalledProcessError, WindowsError):
# ignore if we cannot get to git
pass
return version

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)

View file

@ -98,7 +98,10 @@ TWISTED_MIN = '18.0.0'
DJANGO_MIN = '1.11'
DJANGO_REC = '1.11'
sys.path[1] = EVENNIA_ROOT
try:
sys.path[1] = EVENNIA_ROOT
except IndexError:
sys.path.append(EVENNIA_ROOT)
# ------------------------------------------------------------
#
@ -274,7 +277,7 @@ INFO_WINDOWS_BATFILE = \
twistd.bat to point to the actual location of the Twisted
executable (usually called twistd.py) on your machine.
This procedure is only done once. Run evennia.py again when you
This procedure is only done once. Run `evennia` again when you
are ready to start the server.
"""
@ -1214,7 +1217,7 @@ def evennia_version():
"git rev-parse --short HEAD",
shell=True, cwd=EVENNIA_ROOT, stderr=STDOUT).strip()
version = "%s (rev %s)" % (version, rev)
except (IOError, CalledProcessError):
except (IOError, CalledProcessError, WindowsError):
# move on if git is not answering
pass
return version
@ -1641,7 +1644,7 @@ def error_check_python_modules():
#
# ------------------------------------------------------------
def init_game_directory(path, check_db=True):
def init_game_directory(path, check_db=True, need_gamedir=True):
"""
Try to analyze the given path to find settings.py - this defines
the game directory and also sets PYTHONPATH as well as the django
@ -1650,15 +1653,17 @@ def init_game_directory(path, check_db=True):
Args:
path (str): Path to new game directory, including its name.
check_db (bool, optional): Check if the databae exists.
need_gamedir (bool, optional): set to False if Evennia doesn't require to be run in a valid game directory.
"""
# set the GAMEDIR path
set_gamedir(path)
if need_gamedir:
set_gamedir(path)
# Add gamedir to python path
sys.path.insert(0, GAMEDIR)
if TEST_MODE:
if TEST_MODE or not need_gamedir:
if ENFORCED_SETTING:
print(NOTE_TEST_CUSTOM.format(settings_dotpath=SETTINGS_DOTPATH))
os.environ['DJANGO_SETTINGS_MODULE'] = SETTINGS_DOTPATH
@ -1685,6 +1690,10 @@ def init_game_directory(path, check_db=True):
if check_db:
check_database()
# if we don't have to check the game directory, return right away
if not need_gamedir:
return
# set up the Evennia executables and log file locations
global AMP_PORT, AMP_HOST, AMP_INTERFACE
global SERVER_PY_FILE, PORTAL_PY_FILE
@ -2088,6 +2097,10 @@ def main():
elif option != "noop":
# pass-through to django manager
check_db = False
need_gamedir = True
# some commands don't require the presence of a game directory to work
if option in ('makemessages', 'compilemessages'):
need_gamedir = False
# handle special django commands
if option in ('runserver', 'testserver'):
@ -2100,7 +2113,7 @@ def main():
global TEST_MODE
TEST_MODE = True
init_game_directory(CURRENT_DIR, check_db=check_db)
init_game_directory(CURRENT_DIR, check_db=check_db, need_gamedir=need_gamedir)
# pass on to the manager
args = [option]
@ -2116,6 +2129,11 @@ def main():
kwargs[arg.lstrip("--")] = value
else:
args.append(arg)
# makemessages needs a special syntax to not conflict with the -l option
if len(args) > 1 and args[0] == "makemessages":
args.insert(1, "-l")
try:
django.core.management.call_command(*args, **kwargs)
except django.core.management.base.CommandError as exc:

View file

@ -117,7 +117,7 @@ AMP_INTERFACE = '127.0.0.1'
EVENNIA_DIR = os.path.dirname(os.path.abspath(__file__))
# Path to the game directory (containing the server/conf/settings.py file)
# This is dynamically created- there is generally no need to change this!
if sys.argv[1] == 'test' if len(sys.argv) > 1 else False:
if EVENNIA_DIR.lower() == os.getcwd().lower() or (sys.argv[1] == 'test' if len(sys.argv) > 1 else False):
# unittesting mode
GAME_DIR = os.getcwd()
else: