Resolve merge conflicts
This commit is contained in:
commit
74f22791d8
10 changed files with 241 additions and 150 deletions
|
|
@ -15,6 +15,107 @@ _MULTIMATCH_REGEX = re.compile(settings.SEARCH_MULTIMATCH_REGEX, re.I + re.U)
|
||||||
_CMD_IGNORE_PREFIXES = settings.CMD_IGNORE_PREFIXES
|
_CMD_IGNORE_PREFIXES = settings.CMD_IGNORE_PREFIXES
|
||||||
|
|
||||||
|
|
||||||
|
def create_match(cmdname, string, cmdobj, raw_cmdname):
|
||||||
|
"""
|
||||||
|
Builds a command match by splitting the incoming string and
|
||||||
|
evaluating the quality of the match.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
cmdname (str): Name of command to check for.
|
||||||
|
string (str): The string to match against.
|
||||||
|
cmdobj (str): The full Command instance.
|
||||||
|
raw_cmdname (str, optional): If CMD_IGNORE_PREFIX is set and the cmdname starts with
|
||||||
|
one of the prefixes to ignore, this contains the raw, unstripped cmdname,
|
||||||
|
otherwise it is None.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
match (tuple): This is on the form (cmdname, args, cmdobj, cmdlen, mratio, raw_cmdname),
|
||||||
|
where `cmdname` is the command's name and `args` is the rest of the incoming
|
||||||
|
string, without said command name. `cmdobj` is
|
||||||
|
the Command instance, the cmdlen is the same as len(cmdname) and mratio
|
||||||
|
is a measure of how big a part of the full input string the cmdname
|
||||||
|
takes up - an exact match would be 1.0. Finally, the `raw_cmdname` is
|
||||||
|
the cmdname unmodified by eventual prefix-stripping.
|
||||||
|
|
||||||
|
"""
|
||||||
|
cmdlen, strlen = len(str(cmdname)), len(str(string))
|
||||||
|
mratio = 1 - (strlen - cmdlen) / (1.0 * strlen)
|
||||||
|
args = string[cmdlen:]
|
||||||
|
return (cmdname, args, cmdobj, cmdlen, mratio, raw_cmdname)
|
||||||
|
|
||||||
|
|
||||||
|
def build_matches(raw_string, cmdset, include_prefixes=False):
|
||||||
|
"""
|
||||||
|
Build match tuples by matching raw_string against available commands.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
raw_string (str): Input string that can look in any way; the only assumption is
|
||||||
|
that the sought command's name/alias must be *first* in the string.
|
||||||
|
cmdset (CmdSet): The current cmdset to pick Commands from.
|
||||||
|
include_prefixes (bool): If set, include prefixes like @, ! etc (specified in settings)
|
||||||
|
in the match, otherwise strip them before matching.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
matches (list) A list of match tuples created by `cmdparser.create_match`.
|
||||||
|
|
||||||
|
"""
|
||||||
|
l_raw_string = raw_string.lower()
|
||||||
|
matches = []
|
||||||
|
try:
|
||||||
|
if include_prefixes:
|
||||||
|
# use the cmdname as-is
|
||||||
|
for cmd in cmdset:
|
||||||
|
matches.extend([create_match(cmdname, raw_string, cmd, cmdname)
|
||||||
|
for cmdname in [cmd.key] + cmd.aliases
|
||||||
|
if cmdname and l_raw_string.startswith(cmdname.lower()) and
|
||||||
|
(not cmd.arg_regex or
|
||||||
|
cmd.arg_regex.match(l_raw_string[len(cmdname):]))])
|
||||||
|
else:
|
||||||
|
# strip prefixes set in settings
|
||||||
|
for cmd in cmdset:
|
||||||
|
for raw_cmdname in [cmd.key] + cmd.aliases:
|
||||||
|
cmdname = raw_cmdname.lstrip(_CMD_IGNORE_PREFIXES) if len(raw_cmdname) > 1 else raw_cmdname
|
||||||
|
if cmdname and l_raw_string.startswith(cmdname.lower()) and \
|
||||||
|
(not cmd.arg_regex or cmd.arg_regex.match(l_raw_string[len(cmdname):])):
|
||||||
|
matches.append(create_match(cmdname, raw_string, cmd, raw_cmdname))
|
||||||
|
except Exception:
|
||||||
|
log_trace("cmdhandler error. raw_input:%s" % raw_string)
|
||||||
|
return matches
|
||||||
|
|
||||||
|
|
||||||
|
def try_num_prefixes(raw_string):
|
||||||
|
"""
|
||||||
|
Test if user tried to separate multi-matches with a number separator
|
||||||
|
(default 1-name, 2-name etc). This is usually called last, if no other
|
||||||
|
match was found.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
raw_string (str): The user input to parse.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
mindex, new_raw_string (tuple): If a multimatch-separator was detected,
|
||||||
|
this is stripped out as an integer to separate between the matches. The
|
||||||
|
new_raw_string is the result of stripping out that identifier. If no
|
||||||
|
such form was found, returns (None, None).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
In the default configuration, entering 2-ball (e.g. in a room will more
|
||||||
|
than one 'ball' object), will lead to a multimatch and this function
|
||||||
|
will parse `"2-ball"` and return `(2, "ball")`.
|
||||||
|
|
||||||
|
"""
|
||||||
|
# no matches found
|
||||||
|
num_ref_match = _MULTIMATCH_REGEX.match(raw_string)
|
||||||
|
if num_ref_match:
|
||||||
|
# the user might be trying to identify the command
|
||||||
|
# with a #num-command style syntax. We expect the regex to
|
||||||
|
# contain the groups "number" and "name".
|
||||||
|
mindex, new_raw_string = num_ref_match.group("number"), num_ref_match.group("name")
|
||||||
|
return mindex, new_raw_string
|
||||||
|
else:
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
|
||||||
def cmdparser(raw_string, cmdset, caller, match_index=None):
|
def cmdparser(raw_string, cmdset, caller, match_index=None):
|
||||||
"""
|
"""
|
||||||
This function is called by the cmdhandler once it has
|
This function is called by the cmdhandler once it has
|
||||||
|
|
@ -30,6 +131,10 @@ def cmdparser(raw_string, cmdset, caller, match_index=None):
|
||||||
the first run resulted in a multimatch, and the index is given
|
the first run resulted in a multimatch, and the index is given
|
||||||
to select between the results for the second run.
|
to select between the results for the second run.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
matches (list): This is a list of match-tuples as returned by `create_match`.
|
||||||
|
If no matches were found, this is an empty list.
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
The cmdparser understand the following command combinations (where
|
The cmdparser understand the following command combinations (where
|
||||||
[] marks optional parts.
|
[] marks optional parts.
|
||||||
|
|
@ -47,75 +152,11 @@ def cmdparser(raw_string, cmdset, caller, match_index=None):
|
||||||
the remaining arguments, and the matched cmdobject from the cmdset.
|
the remaining arguments, and the matched cmdobject from the cmdset.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def create_match(cmdname, string, cmdobj, raw_cmdname):
|
|
||||||
"""
|
|
||||||
Builds a command match by splitting the incoming string and
|
|
||||||
evaluating the quality of the match.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
cmdname (str): Name of command to check for.
|
|
||||||
string (str): The string to match against.
|
|
||||||
cmdobj (str): The full Command instance.
|
|
||||||
raw_cmdname (str, optional): If CMD_IGNORE_PREFIX is set and the cmdname starts with
|
|
||||||
one of the prefixes to ignore, this contains the raw, unstripped cmdname,
|
|
||||||
otherwise it is None.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
match (tuple): This is on the form (cmdname, args, cmdobj, cmdlen, mratio, raw_cmdname), where
|
|
||||||
`cmdname` is the command's name and `args` the rest of the incoming string,
|
|
||||||
without said command name. `cmdobj` is the Command instance, the cmdlen is
|
|
||||||
the same as len(cmdname) and mratio is a measure of how big a part of the
|
|
||||||
full input string the cmdname takes up - an exact match would be 1.0. Finally,
|
|
||||||
the `raw_cmdname` is the cmdname unmodified by eventual prefix-stripping.
|
|
||||||
|
|
||||||
"""
|
|
||||||
cmdlen, strlen = len(str(cmdname)), len(str(string))
|
|
||||||
mratio = 1 - (strlen - cmdlen) / (1.0 * strlen)
|
|
||||||
args = string[cmdlen:]
|
|
||||||
return (cmdname, args, cmdobj, cmdlen, mratio, raw_cmdname)
|
|
||||||
|
|
||||||
def build_matches(raw_string, include_prefixes=False):
|
|
||||||
l_raw_string = raw_string.lower()
|
|
||||||
matches = []
|
|
||||||
try:
|
|
||||||
if include_prefixes:
|
|
||||||
# use the cmdname as-is
|
|
||||||
for cmd in cmdset:
|
|
||||||
matches.extend([create_match(cmdname, raw_string, cmd, cmdname)
|
|
||||||
for cmdname in [cmd.key] + cmd.aliases
|
|
||||||
if cmdname and l_raw_string.startswith(cmdname.lower()) and
|
|
||||||
(not cmd.arg_regex or
|
|
||||||
cmd.arg_regex.match(l_raw_string[len(cmdname):]))])
|
|
||||||
else:
|
|
||||||
# strip prefixes set in settings
|
|
||||||
for cmd in cmdset:
|
|
||||||
for raw_cmdname in [cmd.key] + cmd.aliases:
|
|
||||||
cmdname = raw_cmdname.lstrip(_CMD_IGNORE_PREFIXES) if len(raw_cmdname) > 1 else raw_cmdname
|
|
||||||
if cmdname and l_raw_string.startswith(cmdname.lower()) and \
|
|
||||||
(not cmd.arg_regex or cmd.arg_regex.match(l_raw_string[len(cmdname):])):
|
|
||||||
matches.append(create_match(cmdname, raw_string, cmd, raw_cmdname))
|
|
||||||
except Exception:
|
|
||||||
log_trace("cmdhandler error. raw_input:%s" % raw_string)
|
|
||||||
return matches
|
|
||||||
|
|
||||||
def try_num_prefixes(raw_string):
|
|
||||||
if not matches:
|
|
||||||
# no matches found
|
|
||||||
num_ref_match = _MULTIMATCH_REGEX.match(raw_string)
|
|
||||||
if num_ref_match:
|
|
||||||
# the user might be trying to identify the command
|
|
||||||
# with a #num-command style syntax. We expect the regex to
|
|
||||||
# contain the groups "number" and "name".
|
|
||||||
mindex, new_raw_string = num_ref_match.group("number"), num_ref_match.group("name")
|
|
||||||
return mindex, new_raw_string
|
|
||||||
return None, None
|
|
||||||
|
|
||||||
if not raw_string:
|
if not raw_string:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
# find mathces, first using the full name
|
# find mathces, first using the full name
|
||||||
matches = build_matches(raw_string, include_prefixes=True)
|
matches = build_matches(raw_string, cmdset, include_prefixes=True)
|
||||||
if not matches:
|
if not matches:
|
||||||
# try to match a number 1-cmdname, 2-cmdname etc
|
# try to match a number 1-cmdname, 2-cmdname etc
|
||||||
mindex, new_raw_string = try_num_prefixes(raw_string)
|
mindex, new_raw_string = try_num_prefixes(raw_string)
|
||||||
|
|
@ -124,7 +165,7 @@ def cmdparser(raw_string, cmdset, caller, match_index=None):
|
||||||
if _CMD_IGNORE_PREFIXES:
|
if _CMD_IGNORE_PREFIXES:
|
||||||
# still no match. Try to strip prefixes
|
# still no match. Try to strip prefixes
|
||||||
raw_string = raw_string.lstrip(_CMD_IGNORE_PREFIXES) if len(raw_string) > 1 else raw_string
|
raw_string = raw_string.lstrip(_CMD_IGNORE_PREFIXES) if len(raw_string) > 1 else raw_string
|
||||||
matches = build_matches(raw_string, include_prefixes=False)
|
matches = build_matches(raw_string, cmdset, include_prefixes=False)
|
||||||
|
|
||||||
# only select command matches we are actually allowed to call.
|
# only select command matches we are actually allowed to call.
|
||||||
matches = [match for match in matches if match[2].access(caller, 'cmd')]
|
matches = [match for match in matches if match[2].access(caller, 'cmd')]
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ the line is just added to the editor buffer).
|
||||||
|
|
||||||
from evennia.comms.models import ChannelDB
|
from evennia.comms.models import ChannelDB
|
||||||
from evennia.utils import create
|
from evennia.utils import create
|
||||||
|
from evennia.utils.utils import at_search_result
|
||||||
|
|
||||||
# The command keys the engine is calling
|
# The command keys the engine is calling
|
||||||
# (the actual names all start with __)
|
# (the actual names all start with __)
|
||||||
|
|
@ -76,57 +77,30 @@ class SystemMultimatch(COMMAND_DEFAULT_CLASS):
|
||||||
The cmdhandler adds a special attribute 'matches' to this
|
The cmdhandler adds a special attribute 'matches' to this
|
||||||
system command.
|
system command.
|
||||||
|
|
||||||
matches = [(candidate, cmd) , (candidate, cmd), ...],
|
matches = [(cmdname, args, cmdobj, cmdlen, mratio, raw_cmdname) , (cmdname, ...), ...]
|
||||||
|
|
||||||
|
Here, `cmdname` is the command's name and `args` the rest of the incoming string,
|
||||||
|
without said command name. `cmdobj` is the Command instance, the cmdlen is
|
||||||
|
the same as len(cmdname) and mratio is a measure of how big a part of the
|
||||||
|
full input string the cmdname takes up - an exact match would be 1.0. Finally,
|
||||||
|
the `raw_cmdname` is the cmdname unmodified by eventual prefix-stripping.
|
||||||
|
|
||||||
where candidate is an instance of evennia.commands.cmdparser.CommandCandidate
|
|
||||||
and cmd is an an instantiated Command object matching the candidate.
|
|
||||||
"""
|
"""
|
||||||
key = CMD_MULTIMATCH
|
key = CMD_MULTIMATCH
|
||||||
locks = "cmd:all()"
|
locks = "cmd:all()"
|
||||||
|
|
||||||
def format_multimatches(self, caller, matches):
|
|
||||||
"""
|
|
||||||
Format multiple command matches to a useful error.
|
|
||||||
|
|
||||||
This is copied directly from the default method in
|
|
||||||
evennia.commands.cmdhandler.
|
|
||||||
|
|
||||||
"""
|
|
||||||
string = "There were multiple matches:"
|
|
||||||
for num, match in enumerate(matches):
|
|
||||||
# each match is a tuple (candidate, cmd)
|
|
||||||
candidate, cmd = match
|
|
||||||
|
|
||||||
is_channel = hasattr(cmd, "is_channel") and cmd.is_channel
|
|
||||||
if is_channel:
|
|
||||||
is_channel = " (channel)"
|
|
||||||
else:
|
|
||||||
is_channel = ""
|
|
||||||
is_exit = hasattr(cmd, "is_exit") and cmd.is_exit
|
|
||||||
if is_exit and cmd.destination:
|
|
||||||
is_exit = " (exit to %s)" % cmd.destination
|
|
||||||
else:
|
|
||||||
is_exit = ""
|
|
||||||
|
|
||||||
id1 = ""
|
|
||||||
id2 = ""
|
|
||||||
if not (is_channel or is_exit) and (hasattr(cmd, 'obj') and cmd.obj != caller):
|
|
||||||
# the command is defined on some other object
|
|
||||||
id1 = "%s-" % cmd.obj.name
|
|
||||||
id2 = " (%s-%s)" % (num + 1, candidate.cmdname)
|
|
||||||
else:
|
|
||||||
id1 = "%s-" % (num + 1)
|
|
||||||
id2 = ""
|
|
||||||
string += "\n %s%s%s%s%s" % (id1, candidate.cmdname, id2, is_channel, is_exit)
|
|
||||||
return string
|
|
||||||
|
|
||||||
def func(self):
|
def func(self):
|
||||||
"""
|
"""
|
||||||
argument to cmd is a comma-separated string of
|
Handle multiple-matches by using the at_search_result default handler.
|
||||||
all the clashing matches.
|
|
||||||
"""
|
"""
|
||||||
string = self.format_multimatches(self.caller, self.matches)
|
# this was set by the cmdparser and is a tuple
|
||||||
self.msg(string)
|
# (cmdname, args, cmdobj, cmdlen, mratio, raw_cmdname). See
|
||||||
|
# evennia.commands.cmdparse.create_match for more details.
|
||||||
|
matches = self.matches
|
||||||
|
# at_search_result will itself msg the multimatch options to the caller.
|
||||||
|
at_search_result(
|
||||||
|
[match[2] for match in matches], self.caller, query=matches[0][0])
|
||||||
|
|
||||||
|
|
||||||
# Command called when the command given at the command line
|
# Command called when the command given at the command line
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,12 @@ from mock import Mock, mock
|
||||||
|
|
||||||
from evennia.commands.default.cmdset_character import CharacterCmdSet
|
from evennia.commands.default.cmdset_character import CharacterCmdSet
|
||||||
from evennia.utils.test_resources import EvenniaTest
|
from evennia.utils.test_resources import EvenniaTest
|
||||||
from evennia.commands.default import help, general, system, admin, account, building, batchprocess, comms, unloggedin
|
from evennia.commands.default import help, general, system, admin, account, building, batchprocess, comms, unloggedin, syscommands
|
||||||
|
from evennia.commands.cmdparser import build_matches
|
||||||
from evennia.commands.default.muxcommand import MuxCommand
|
from evennia.commands.default.muxcommand import MuxCommand
|
||||||
from evennia.commands.command import Command, InterruptCommand
|
from evennia.commands.command import Command, InterruptCommand
|
||||||
|
from evennia.commands import cmdparser
|
||||||
|
from evennia.commands.cmdset import CmdSet
|
||||||
from evennia.utils import ansi, utils, gametime
|
from evennia.utils import ansi, utils, gametime
|
||||||
from evennia.server.sessionhandler import SESSIONS
|
from evennia.server.sessionhandler import SESSIONS
|
||||||
from evennia import search_object
|
from evennia import search_object
|
||||||
|
|
@ -660,3 +663,33 @@ class TestUnconnectedCommand(CommandTest):
|
||||||
SESSIONS.account_count(), utils.get_evennia_version())
|
SESSIONS.account_count(), utils.get_evennia_version())
|
||||||
self.call(unloggedin.CmdUnconnectedInfo(), "", expected)
|
self.call(unloggedin.CmdUnconnectedInfo(), "", expected)
|
||||||
del gametime.SERVER_START_TIME
|
del gametime.SERVER_START_TIME
|
||||||
|
|
||||||
|
|
||||||
|
# Test syscommands
|
||||||
|
|
||||||
|
class TestSystemCommands(CommandTest):
|
||||||
|
|
||||||
|
def test_simple_defaults(self):
|
||||||
|
self.call(syscommands.SystemNoInput(), "")
|
||||||
|
self.call(syscommands.SystemNoMatch(), "Huh?")
|
||||||
|
|
||||||
|
def test_multimatch(self):
|
||||||
|
# set up fake matches and store on command instance
|
||||||
|
cmdset = CmdSet()
|
||||||
|
cmdset.add(general.CmdLook())
|
||||||
|
cmdset.add(general.CmdLook())
|
||||||
|
matches = cmdparser.build_matches("look", cmdset)
|
||||||
|
|
||||||
|
multimatch = syscommands.SystemMultimatch()
|
||||||
|
multimatch.matches = matches
|
||||||
|
|
||||||
|
self.call(multimatch, "look", "")
|
||||||
|
|
||||||
|
@mock.patch("evennia.commands.default.syscommands.ChannelDB")
|
||||||
|
def test_channelcommand(self, mock_channeldb):
|
||||||
|
channel = mock.MagicMock()
|
||||||
|
channel.msg = mock.MagicMock()
|
||||||
|
mock_channeldb.objects.get_channel = mock.MagicMock(return_value=channel)
|
||||||
|
|
||||||
|
self.call(syscommands.SystemSendToChannel(), "public:Hello")
|
||||||
|
channel.msg.assert_called()
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,23 @@ def _get_prototype(inprot, protparents, uninherited=None, _workprot=None):
|
||||||
uninherited (dict): Parts of prototype to not inherit.
|
uninherited (dict): Parts of prototype to not inherit.
|
||||||
_workprot (dict, optional): Work dict for the recursive algorithm.
|
_workprot (dict, optional): Work dict for the recursive algorithm.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
merged (dict): A prototype where parent's have been merged as needed (the
|
||||||
|
`prototype_parent` key is removed).
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
def _inherit_tags(old_tags, new_tags):
|
||||||
|
old = {(tup[0], tup[1]): tup for tup in old_tags}
|
||||||
|
new = {(tup[0], tup[1]): tup for tup in new_tags}
|
||||||
|
old.update(new)
|
||||||
|
return list(old.values())
|
||||||
|
|
||||||
|
def _inherit_attrs(old_attrs, new_attrs):
|
||||||
|
old = {(tup[0], tup[2]): tup for tup in old_attrs}
|
||||||
|
new = {(tup[0], tup[2]): tup for tup in new_attrs}
|
||||||
|
old.update(new)
|
||||||
|
return list(old.values())
|
||||||
|
|
||||||
_workprot = {} if _workprot is None else _workprot
|
_workprot = {} if _workprot is None else _workprot
|
||||||
if "prototype_parent" in inprot:
|
if "prototype_parent" in inprot:
|
||||||
# move backwards through the inheritance
|
# move backwards through the inheritance
|
||||||
|
|
@ -173,8 +189,20 @@ def _get_prototype(inprot, protparents, uninherited=None, _workprot=None):
|
||||||
# Build the prot dictionary in reverse order, overloading
|
# Build the prot dictionary in reverse order, overloading
|
||||||
new_prot = _get_prototype(protparents.get(prototype.lower(), {}),
|
new_prot = _get_prototype(protparents.get(prototype.lower(), {}),
|
||||||
protparents, _workprot=_workprot)
|
protparents, _workprot=_workprot)
|
||||||
|
|
||||||
|
# attrs, tags have internal structure that should be inherited separately
|
||||||
|
new_prot['attrs'] = _inherit_attrs(
|
||||||
|
_workprot.get("attrs", {}), new_prot.get("attrs", {}))
|
||||||
|
new_prot['tags'] = _inherit_tags(
|
||||||
|
_workprot.get("tags", {}), new_prot.get("tags", {}))
|
||||||
|
|
||||||
_workprot.update(new_prot)
|
_workprot.update(new_prot)
|
||||||
# the inprot represents a higher level (a child prot), which should override parents
|
# the inprot represents a higher level (a child prot), which should override parents
|
||||||
|
|
||||||
|
inprot['attrs'] = _inherit_attrs(
|
||||||
|
_workprot.get("attrs", {}), inprot.get("attrs", {}))
|
||||||
|
inprot['tags'] = _inherit_tags(
|
||||||
|
_workprot.get("tags", {}), inprot.get("tags", {}))
|
||||||
_workprot.update(inprot)
|
_workprot.update(inprot)
|
||||||
if uninherited:
|
if uninherited:
|
||||||
# put back the parts that should not be inherited
|
# put back the parts that should not be inherited
|
||||||
|
|
|
||||||
0
evennia/server/tests/__init__.py
Normal file
0
evennia/server/tests/__init__.py
Normal file
19
evennia/server/tests/test_initial_setup.py
Normal file
19
evennia/server/tests/test_initial_setup.py
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
"""
|
||||||
|
Test initial startup procedure
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from mock import MagicMock, patch
|
||||||
|
from django.conf import settings
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
from evennia.server import initial_setup
|
||||||
|
|
||||||
|
|
||||||
|
class TestInitialSetup(TestCase):
|
||||||
|
|
||||||
|
@patch("evennia.server.initial_setup.AccountDB")
|
||||||
|
def test_get_god_account(self, mocked_accountdb):
|
||||||
|
mocked_accountdb.objects.get = MagicMock(return_value=1)
|
||||||
|
self.assertEqual(initial_setup.get_god_account(), 1)
|
||||||
|
mocked_accountdb.objects.get.assert_called_with(id=1)
|
||||||
|
|
@ -1,28 +1,11 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Unit testing of the 'objects' Evennia component.
|
Testing various individual functionalities in the server package.
|
||||||
|
|
||||||
Runs as part of the Evennia's test suite with 'manage.py test"
|
|
||||||
|
|
||||||
Please add new tests to this module as needed.
|
|
||||||
|
|
||||||
Guidelines:
|
|
||||||
A 'test case' is testing a specific component and is defined as a class
|
|
||||||
inheriting from unittest.TestCase. The test case class can have a method
|
|
||||||
setUp() that creates and sets up the testing environment.
|
|
||||||
All methods inside the test case class whose names start with 'test' are
|
|
||||||
used as test methods by the runner. Inside the test methods, special member
|
|
||||||
methods assert*() are used to test the behaviour.
|
|
||||||
"""
|
"""
|
||||||
try:
|
import unittest
|
||||||
from django.utils.unittest import TestCase
|
from django.test import TestCase
|
||||||
except ImportError:
|
|
||||||
from django.test import TestCase
|
|
||||||
try:
|
|
||||||
from django.utils import unittest
|
|
||||||
except ImportError:
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
from evennia.server.validators import EvenniaPasswordValidator
|
from evennia.server.validators import EvenniaPasswordValidator
|
||||||
from evennia.utils.test_resources import EvenniaTest
|
from evennia.utils.test_resources import EvenniaTest
|
||||||
|
|
@ -31,23 +14,7 @@ from django.test.runner import DiscoverRunner
|
||||||
|
|
||||||
from evennia.server.throttle import Throttle
|
from evennia.server.throttle import Throttle
|
||||||
|
|
||||||
from .deprecations import check_errors
|
from ..deprecations import check_errors
|
||||||
|
|
||||||
|
|
||||||
class EvenniaTestSuiteRunner(DiscoverRunner):
|
|
||||||
"""
|
|
||||||
This test runner only runs tests on the apps specified in evennia/
|
|
||||||
avoid running the large number of tests defined by Django
|
|
||||||
"""
|
|
||||||
|
|
||||||
def build_suite(self, test_labels, extra_tests=None, **kwargs):
|
|
||||||
"""
|
|
||||||
Build a test suite for Evennia. test_labels is a list of apps to test.
|
|
||||||
If not given, a subset of settings.INSTALLED_APPS will be used.
|
|
||||||
"""
|
|
||||||
import evennia
|
|
||||||
evennia._init()
|
|
||||||
return super().build_suite(test_labels, extra_tests=extra_tests, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class MockSettings(object):
|
class MockSettings(object):
|
||||||
27
evennia/server/tests/testrunner.py
Normal file
27
evennia/server/tests/testrunner.py
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
"""
|
||||||
|
Main test-suite runner of Evennia. The runner collates tests from
|
||||||
|
all over the code base and runs them.
|
||||||
|
|
||||||
|
Runs as part of the Evennia's test suite with 'evennia test evennia"
|
||||||
|
|
||||||
|
"""
|
||||||
|
from django.test.runner import DiscoverRunner
|
||||||
|
|
||||||
|
|
||||||
|
class EvenniaTestSuiteRunner(DiscoverRunner):
|
||||||
|
"""
|
||||||
|
Pointed to by the TEST_RUNNER setting.
|
||||||
|
This test runner only runs tests on the apps specified in evennia/
|
||||||
|
avoid running the large number of tests defined by Django
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def build_suite(self, test_labels, extra_tests=None, **kwargs):
|
||||||
|
"""
|
||||||
|
Build a test suite for Evennia. test_labels is a list of apps to test.
|
||||||
|
If not given, a subset of settings.INSTALLED_APPS will be used.
|
||||||
|
"""
|
||||||
|
import evennia
|
||||||
|
evennia._init()
|
||||||
|
return super(EvenniaTestSuiteRunner, self).build_suite(
|
||||||
|
test_labels, extra_tests=extra_tests, **kwargs)
|
||||||
|
|
@ -831,9 +831,9 @@ AUTH_USERNAME_VALIDATORS = [
|
||||||
{'NAME': 'evennia.server.validators.EvenniaUsernameAvailabilityValidator'}]
|
{'NAME': 'evennia.server.validators.EvenniaUsernameAvailabilityValidator'}]
|
||||||
|
|
||||||
# Use a custom test runner that just tests Evennia-specific apps.
|
# Use a custom test runner that just tests Evennia-specific apps.
|
||||||
TEST_RUNNER = 'evennia.server.tests.EvenniaTestSuiteRunner'
|
TEST_RUNNER = 'evennia.server.tests.testrunner.EvenniaTestSuiteRunner'
|
||||||
|
|
||||||
# Messages and Bootstrap don't classify events the same way; this setting maps
|
# Messages and Bootstrap don't classify events the same way; this setting maps
|
||||||
# messages.error() to Bootstrap 'danger' classes.
|
# messages.error() to Bootstrap 'danger' classes.
|
||||||
MESSAGE_TAGS = {
|
MESSAGE_TAGS = {
|
||||||
messages.ERROR: 'danger',
|
messages.ERROR: 'danger',
|
||||||
|
|
|
||||||
|
|
@ -1853,7 +1853,9 @@ def at_search_result(matches, caller, query="", quiet=False, **kwargs):
|
||||||
Returns:
|
Returns:
|
||||||
processed_result (Object or None): This is always a single result
|
processed_result (Object or None): This is always a single result
|
||||||
or `None`. If `None`, any error reporting/handling should
|
or `None`. If `None`, any error reporting/handling should
|
||||||
already have happened.
|
already have happened. The returned object is of the type we are
|
||||||
|
checking multimatches for (e.g. Objects or Commands)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
error = ""
|
error = ""
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue