mirror of
https://github.com/evennia/evennia.git
synced 2026-03-21 23:36:30 +01:00
After lots of discussions, default commands where moved from game/gamesrc/commands/default to src/commands/default in order to make it clearer which parts are updated as part of evennia and which can be tweaked at heart's content. New templates where left in gamesrc/commands that should hopefully make it clearer how to extend the command system. Also game/web was moved to src/web - we'll likely extend this from game/gamesrc/web in the future. If you already did extensions you should just have to edit your import paths and make use of the new cmdset template supplied.
The unit testing was for commands was split out from src/objects/tests.py into the new src/commands/default/test.py in order to keep the testing modules thematically grouped with the things they are testing.
This commit is contained in:
parent
a3917073ff
commit
72d40285b8
61 changed files with 381 additions and 184 deletions
|
|
@ -1,17 +1,106 @@
|
|||
|
||||
"""
|
||||
This is the parent class for all Commands in Evennia. Inherit from this and
|
||||
|
||||
|
||||
Inherit from this and
|
||||
overload the member functions to define your own commands.
|
||||
See commands/default/muxcommand.py for an example.
|
||||
See src/commands/default/muxcommand.py for an example.
|
||||
|
||||
"""
|
||||
|
||||
from src.commands.command import Command as BaseCommand
|
||||
from src.commands.default.muxcommand import MuxCommand as BaseMuxCommand
|
||||
from src.permissions import permissions
|
||||
from src.utils import utils
|
||||
|
||||
class MuxCommand(BaseMuxCommand):
|
||||
"""
|
||||
This sets up the basis for a Evennia's 'MUX-like' command
|
||||
style. The idea is that most other Mux-related commands should
|
||||
just inherit from this and don't have to implement much parsing of
|
||||
their own unless they do something particularly advanced.
|
||||
|
||||
Note that the class's __doc__ string (this text) is used by
|
||||
Evennia to create the automatic help entry for the command, so
|
||||
make sure to document consistently here.
|
||||
|
||||
Most of the time your child classes should not need to implement
|
||||
parse() at all, but only the main func() method for doing useful
|
||||
things. See examples in src/commands/default.
|
||||
|
||||
"""
|
||||
|
||||
def parse(self):
|
||||
"""
|
||||
This method is called by the cmdhandler once the command name
|
||||
has been identified. It creates a new set of member variables
|
||||
that can be later accessed from self.func() (see below)
|
||||
|
||||
The following variables are available for our use when entering this
|
||||
method (from the command definition, and assigned on the fly by the
|
||||
cmdhandler):
|
||||
self.key - the name of this command ('look')
|
||||
self.aliases - the aliases of this cmd ('l')
|
||||
self.permissions - permission string for this command
|
||||
self.help_category - overall category of command
|
||||
|
||||
self.caller - the object calling this command
|
||||
self.cmdstring - the actual command name used to call this
|
||||
(this allows you to know which alias was used,
|
||||
for example)
|
||||
self.args - the raw input; everything following self.cmdstring.
|
||||
self.cmdset - the cmdset from which this command was picked. Not
|
||||
often used (useful for commands like 'help' or to
|
||||
list all available commands etc)
|
||||
self.obj - the object on which this command was defined. It is often
|
||||
the same as self.caller.
|
||||
|
||||
A MUX command has the following possible syntax:
|
||||
|
||||
name[ with several words][/switch[/switch..]] arg1[,arg2,...] [[=|,] arg[,..]]
|
||||
|
||||
The 'name[ with several words]' part is already dealt with by the
|
||||
cmdhandler at this point, and stored in self.cmdname (we don't use
|
||||
it here). The rest of the command is stored in self.args, which can start
|
||||
with the switch indicator /.
|
||||
|
||||
This parser breaks self.args into its constituents and stores them in the
|
||||
following variables:
|
||||
self.switches = [list of /switches (without the /)]
|
||||
self.raw = This is the raw argument input, including switches
|
||||
self.args = This is re-defined to be everything *except* the switches
|
||||
self.lhs = Everything to the left of = (lhs:'left-hand side'). If
|
||||
no = is found, this is identical to self.args.
|
||||
self.rhs: Everything to the right of = (rhs:'right-hand side').
|
||||
If no '=' is found, this is None.
|
||||
self.lhslist - [self.lhs split into a list by comma]
|
||||
self.rhslist - [list of self.rhs split into a list by comma]
|
||||
self.arglist = [list of space-separated args (stripped, including '=' if it exists)]
|
||||
|
||||
All args and list members are stripped of excess whitespace around the
|
||||
strings, but case is preserved.
|
||||
"""
|
||||
# parse all that makes it a MUX command (don't remove this)
|
||||
super(MuxCommand, self).parse()
|
||||
|
||||
def func(self):
|
||||
"""
|
||||
This is the hook function that actually does all the work. It is called
|
||||
by the cmdhandler right after self.parser() finishes, and so has access
|
||||
to all the variables defined therein.
|
||||
"""
|
||||
# this can be removed in your child class, it's just
|
||||
# printing the ingoing variables as a demo
|
||||
super(MuxCommand, self).func()
|
||||
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
"""
|
||||
This is the basic command class (MuxCommand is a child of
|
||||
this). Inherit from this if you want to create your own
|
||||
command styles.
|
||||
|
||||
Note that the class's __doc__ string (this text) is
|
||||
used by Evennia to create the automatic help entry for
|
||||
the command, so make sure to document consistently here.
|
||||
|
|
@ -22,7 +111,7 @@ class Command(BaseCommand):
|
|||
if srcobj is allowed to execute this command. This
|
||||
also determines if the command appears in help etc.
|
||||
|
||||
By default, We use checks of the 'c' type of lock to determine
|
||||
By default, We use checks of the 'cmd' type of lock to determine
|
||||
if the command should be run.
|
||||
"""
|
||||
return permissions.has_perm(srcobj, self, 'cmd')
|
||||
|
|
@ -61,18 +150,9 @@ class Command(BaseCommand):
|
|||
by the cmdhandler right after self.parser() finishes, and so has access
|
||||
to all the variables defined therein.
|
||||
"""
|
||||
# a simple test command to show the available properties
|
||||
string = "-" * 50
|
||||
string += "\n{w%s{n - Command variables from evennia:\n" % self.key
|
||||
string += "-" * 50
|
||||
string += "\nname of cmd (self.key): {w%s{n\n" % self.key
|
||||
string += "cmd aliases (self.aliases): {w%s{n\n" % self.aliases
|
||||
string += "cmd perms (self.permissions): {w%s{n\n" % self.permissions
|
||||
string += "help category (self.help_category): {w%s{n\n" % self.help_category
|
||||
string += "object calling (self.caller): {w%s{n\n" % self.caller
|
||||
string += "object storing cmdset (self.obj): {w%s{n\n" % self.obj
|
||||
string += "command string given (self.cmdstring): {w%s{n\n" % self.cmdstring
|
||||
# show cmdset.key instead of cmdset to shorten output
|
||||
string += utils.fill("current cmdset (self.cmdset): {w%s{n\n" % self.cmdset)
|
||||
|
||||
self.caller.msg(string)
|
||||
|
||||
# this can be removed in your child class, it's just
|
||||
# printing the ingoing variables as a demo
|
||||
super(MuxCommand, self).func()
|
||||
|
||||
|
||||
|
|
|
|||
65
game/gamesrc/commands/empty_cmdset.py
Normal file
65
game/gamesrc/commands/empty_cmdset.py
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
"""
|
||||
This is the second component of using a Command in your game - a
|
||||
command set. A cmdset groups any number of commands together. CmdSets
|
||||
are stored on character and objects and all available cmdsets are
|
||||
searched when Evennia tries to determine if a command is
|
||||
available. Sets can be merged and combined in many different ways (see
|
||||
the docs).
|
||||
|
||||
You can use the classes below as templates for extending the game with
|
||||
new command sets; you can also import the default Evennia cmdset and
|
||||
extend/overload that.
|
||||
|
||||
To change default cmdset (the one all character start the game with),
|
||||
Create your custom commands in other modules
|
||||
(inheriting from game.gamesrc.commands.basecommand), add them to a
|
||||
cmdset class, then set your settings.CMDSET_DEFAULT to point to this
|
||||
new cmdset class.
|
||||
|
||||
"""
|
||||
|
||||
from src.commands.cmdset import CmdSet
|
||||
from src.commands.default import cmdset_default
|
||||
|
||||
from game.gamesrc.commands.basecommands import Command
|
||||
|
||||
class ExampleCmdSet(CmdSet):
|
||||
"""
|
||||
Implements an example cmdset.
|
||||
"""
|
||||
|
||||
key = "ExampleSet"
|
||||
|
||||
def at_cmdset_creation(self):
|
||||
"""
|
||||
This is the only method defined in a cmdset, called during
|
||||
its creation. It should populate the set with command instances.
|
||||
|
||||
Here we just add the base Command object.
|
||||
"""
|
||||
self.add(Command())
|
||||
|
||||
|
||||
class ExtendedDefaultSet(cmdset_default.DefaultCmdSet):
|
||||
"""
|
||||
This is an example of how to overload the default command
|
||||
set defined in src/commands/default/cmdset_default.py.
|
||||
|
||||
Here we copy everything by calling the parent, but you can
|
||||
copy&paste any combination of the default command to customize
|
||||
your default set. Next you change settings.CMDSET_DEFAULT to point
|
||||
to this class.
|
||||
"""
|
||||
key = "DefaultMUX"
|
||||
|
||||
def at_cmdset_creation(self):
|
||||
"""
|
||||
Populates the cmdset
|
||||
"""
|
||||
super(ExtendedDefaultSet, self).at_cmdset_creation()
|
||||
|
||||
#
|
||||
# any commands you add below will overload the default ones.
|
||||
#
|
||||
|
||||
|
||||
|
|
@ -204,13 +204,22 @@ class CmdSet(object):
|
|||
"""
|
||||
Add a command to this cmdset.
|
||||
|
||||
Note that if cmd already has
|
||||
Note that if cmd already exists in set,
|
||||
it will replace the old one (no priority checking etc
|
||||
at this point; this is often used to overload
|
||||
default commands).
|
||||
"""
|
||||
cmd = instantiate(cmd)
|
||||
|
||||
if cmd:
|
||||
if not hasattr(cmd, 'obj'):
|
||||
cmd.obj = self.cmdsetobj
|
||||
self.commands.append(cmd)
|
||||
try:
|
||||
ic = self.commands.index(cmd)
|
||||
self.commands[ic] = cmd # replace
|
||||
except ValueError:
|
||||
self.commands.append(cmd)
|
||||
# extra run to make sure to avoid doublets
|
||||
self.commands = list(set(self.commands))
|
||||
|
||||
def remove(self, cmd):
|
||||
|
|
|
|||
|
|
@ -145,5 +145,18 @@ class Command(object):
|
|||
of this module for which object properties are available
|
||||
(beyond those set in self.parse())
|
||||
"""
|
||||
string = "Command '%s' was executed with arg string '%s'."
|
||||
self.caller.msg(string % (self.key, self.args))
|
||||
# a simple test command to show the available properties
|
||||
string = "-" * 50
|
||||
string += "\n{w%s{n - Command variables from evennia:\n" % self.key
|
||||
string += "-" * 50
|
||||
string += "\nname of cmd (self.key): {w%s{n\n" % self.key
|
||||
string += "cmd aliases (self.aliases): {w%s{n\n" % self.aliases
|
||||
string += "cmd perms (self.permissions): {w%s{n\n" % self.permissions
|
||||
string += "help category (self.help_category): {w%s{n\n" % self.help_category
|
||||
string += "object calling (self.caller): {w%s{n\n" % self.caller
|
||||
string += "object storing cmdset (self.obj): {w%s{n\n" % self.obj
|
||||
string += "command string given (self.cmdstring): {w%s{n\n" % self.cmdstring
|
||||
# show cmdset.key instead of cmdset to shorten output
|
||||
string += utils.fill("current cmdset (self.cmdset): {w%s{n\n" % self.cmdset)
|
||||
|
||||
self.caller.msg(string)
|
||||
|
|
|
|||
|
|
@ -7,12 +7,11 @@ Admin commands
|
|||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from src.players.models import PlayerDB
|
||||
from game.gamesrc.commands.default.muxcommand import MuxCommand
|
||||
from src.server import sessionhandler
|
||||
from src.permissions.permissions import has_perm, has_perm_string
|
||||
from src.permissions.models import PermissionGroup
|
||||
from src.utils import utils
|
||||
|
||||
from src.commands.default.muxcommand import MuxCommand
|
||||
|
||||
class CmdBoot(MuxCommand):
|
||||
"""
|
||||
|
|
@ -24,9 +24,8 @@ Example batch-code file: game/gamesrc/commands/examples/example_batch_code.py
|
|||
from traceback import format_exc
|
||||
from django.conf import settings
|
||||
from src.utils.batchprocessors import BATCHCMD, BATCHCODE
|
||||
from game.gamesrc.commands.default.muxcommand import MuxCommand
|
||||
from src.commands.cmdset import CmdSet
|
||||
|
||||
from src.commands.default.muxcommand import MuxCommand
|
||||
|
||||
HEADER_WIDTH = 70
|
||||
UTF8_ERROR = \
|
||||
|
|
@ -7,8 +7,8 @@ Building and world design commands
|
|||
from django.conf import settings
|
||||
from src.permissions.permissions import has_perm, has_perm_string
|
||||
from src.objects.models import ObjectDB, ObjAttribute
|
||||
from game.gamesrc.commands.default.muxcommand import MuxCommand
|
||||
from src.utils import create, utils, debug
|
||||
from src.commands.default.muxcommand import MuxCommand
|
||||
|
||||
class ObjManipCommand(MuxCommand):
|
||||
"""
|
||||
|
|
@ -2,9 +2,9 @@
|
|||
This module ties together all the commands of the default command set.
|
||||
"""
|
||||
from src.commands.cmdset import CmdSet
|
||||
from game.gamesrc.commands.default import general, help, admin, system
|
||||
from game.gamesrc.commands.default import tests, comms, building
|
||||
from game.gamesrc.commands.default import batchprocess
|
||||
from src.commands.default import general, help, admin, system
|
||||
from src.commands.default import utils, comms, building
|
||||
from src.commands.default import batchprocess
|
||||
|
||||
class DefaultCmdSet(CmdSet):
|
||||
"""
|
||||
|
|
@ -92,7 +92,7 @@ class DefaultCmdSet(CmdSet):
|
|||
self.add(batchprocess.CmdBatchCommands())
|
||||
self.add(batchprocess.CmdBatchCode())
|
||||
|
||||
# Testing commands
|
||||
self.add(tests.CmdTest())
|
||||
self.add(tests.CmdTestPerms())
|
||||
self.add(tests.TestCom())
|
||||
# Testing/Utility commands
|
||||
self.add(utils.CmdTest())
|
||||
self.add(utils.CmdTestPerms())
|
||||
self.add(utils.TestCom())
|
||||
|
|
@ -4,7 +4,7 @@ The setting STATE_UNLOGGED should be set to the python path
|
|||
of the state instance in this module.
|
||||
"""
|
||||
from src.commands.cmdset import CmdSet
|
||||
from game.gamesrc.commands.default import unloggedin
|
||||
from src.commands.default import unloggedin
|
||||
|
||||
class UnloggedinCmdSet(CmdSet):
|
||||
"""
|
||||
|
|
@ -3,10 +3,9 @@ Comsys command module.
|
|||
"""
|
||||
|
||||
from src.comms.models import Channel, Msg, ChannelConnection
|
||||
from game.gamesrc.commands.default.muxcommand import MuxCommand
|
||||
from src.utils import create, utils
|
||||
from src.permissions.permissions import has_perm
|
||||
|
||||
from src.commands.default.muxcommand import MuxCommand
|
||||
|
||||
def find_channel(caller, channelname):
|
||||
"""
|
||||
|
|
@ -9,8 +9,7 @@ from src.permissions.models import PermissionGroup
|
|||
from src.permissions.permissions import has_perm, has_perm_string
|
||||
from src.objects.models import HANDLE_SEARCH_ERRORS
|
||||
from src.utils import utils
|
||||
|
||||
from game.gamesrc.commands.default.muxcommand import MuxCommand
|
||||
from src.commands.default.muxcommand import MuxCommand
|
||||
|
||||
class CmdHome(MuxCommand):
|
||||
"""
|
||||
|
|
@ -11,7 +11,7 @@ from src.commands.command import Command
|
|||
from src.help.models import HelpEntry
|
||||
from src.permissions.permissions import has_perm
|
||||
from src.utils import create
|
||||
from game.gamesrc.commands.default.muxcommand import MuxCommand
|
||||
from src.commands.default.muxcommand import MuxCommand
|
||||
|
||||
LIST_ARGS = ["list", "all"]
|
||||
|
||||
|
|
@ -3,7 +3,7 @@ The command template for the default MUX-style command set
|
|||
"""
|
||||
|
||||
from src.utils import utils
|
||||
from game.gamesrc.commands.basecommand import Command
|
||||
from src.commands.command import Command
|
||||
|
||||
class MuxCommand(Command):
|
||||
"""
|
||||
|
|
@ -17,7 +17,7 @@ to implement a line-editor where you don't have to start each
|
|||
line with a command (if there is no match to a known command,
|
||||
the line is just added to the editor buffer).
|
||||
"""
|
||||
from game.gamesrc.commands.default.muxcommand import MuxCommand
|
||||
|
||||
from src.comms.models import Channel
|
||||
from src.utils import create
|
||||
from src.permissions.permissions import has_perm
|
||||
|
|
@ -31,6 +31,7 @@ from src.commands.cmdhandler import CMD_NOPERM
|
|||
from src.commands.cmdhandler import CMD_CHANNEL
|
||||
from src.commands.cmdhandler import CMD_EXIT
|
||||
|
||||
from src.commands.default.muxcommand import MuxCommand
|
||||
|
||||
# Command called when there is no input at line
|
||||
# (i.e. an lone return key)
|
||||
|
|
@ -14,7 +14,7 @@ from src.scripts.models import ScriptDB
|
|||
from src.objects.models import ObjectDB
|
||||
from src.config.models import ConfigValue
|
||||
from src.utils import reloads, create, logger, utils, gametime
|
||||
from game.gamesrc.commands.default.muxcommand import MuxCommand
|
||||
from src.commands.default.muxcommand import MuxCommand
|
||||
|
||||
class CmdReload(MuxCommand):
|
||||
"""
|
||||
126
src/commands/default/tests.py
Normal file
126
src/commands/default/tests.py
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
** OBS - this is not a normal command module! **
|
||||
** You cannot import anythin in this module as a command! **
|
||||
|
||||
This is part of the Evennia unittest framework, for testing the
|
||||
stability and integrity of the codebase during updates. This module
|
||||
test the default command set. It is instantiated by the
|
||||
src/objects/tests.py module, which in turn is run by as part of the
|
||||
main test suite started with
|
||||
> python game/manage.py test.
|
||||
|
||||
"""
|
||||
|
||||
import re, time
|
||||
try:
|
||||
# this is a special optimized Django version, only available in current Django devel
|
||||
from django.utils.unittest import TestCase
|
||||
except ImportError:
|
||||
from django.test import TestCase
|
||||
from django.conf import settings
|
||||
from src.utils import create
|
||||
from src.server import session, sessionhandler
|
||||
|
||||
#------------------------------------------------------------
|
||||
# Command testing
|
||||
# ------------------------------------------------------------
|
||||
|
||||
# print all feedback from test commands (can become very verbose!)
|
||||
VERBOSE = False
|
||||
|
||||
class FakeSession(session.SessionProtocol):
|
||||
"""
|
||||
A fake session that
|
||||
implements dummy versions of the real thing; this is needed to
|
||||
mimic a logged-in player.
|
||||
"""
|
||||
def connectionMade(self):
|
||||
self.prep_session()
|
||||
sessionhandler.add_session(self)
|
||||
def prep_session(self):
|
||||
self.server, self.address = None, "0.0.0.0"
|
||||
self.name, self.uid = None, None
|
||||
self.logged_in = False
|
||||
self.encoding = "utf-8"
|
||||
self.cmd_last, self.cmd_last_visible, self.cmd_conn_time = time.time(), time.time(), time.time()
|
||||
self.cmd_total = 0
|
||||
def disconnectClient(self):
|
||||
pass
|
||||
def lineReceived(self, raw_string):
|
||||
pass
|
||||
def msg(self, message, markup=True):
|
||||
if VERBOSE:
|
||||
print message
|
||||
|
||||
class CommandTest(TestCase):
|
||||
"""
|
||||
Sets up the basics of testing the default commands and the generic things
|
||||
that should always be present in a command.
|
||||
|
||||
Inherit new tests from this.
|
||||
"""
|
||||
def setUp(self):
|
||||
"sets up the testing environment"
|
||||
self.room1 = create.create_object(settings.BASE_ROOM_TYPECLASS, key="room1")
|
||||
self.room2 = create.create_object(settings.BASE_ROOM_TYPECLASS, key="room2")
|
||||
|
||||
# create a faux player/character for testing.
|
||||
self.char1 = create.create_player("TestingPlayer", "testplayer@test.com", "testpassword", location=self.room1)
|
||||
self.char1.player.user.is_superuser = True
|
||||
sess = FakeSession()
|
||||
sess.connectionMade()
|
||||
sess.login(self.char1.player)
|
||||
|
||||
self.char2 = create.create_object(settings.BASE_CHARACTER_TYPECLASS, key="char2", location=self.room1)
|
||||
self.obj1 = create.create_object(settings.BASE_OBJECT_TYPECLASS, key="obj1", location=self.room1)
|
||||
self.obj2 = create.create_object(settings.BASE_OBJECT_TYPECLASS, key="obj2", location=self.room1)
|
||||
self.exit1 = create.create_object(settings.BASE_EXIT_TYPECLASS, key="exit1", location=self.room1)
|
||||
self.exit2 = create.create_object(settings.BASE_EXIT_TYPECLASS, key="exit2", location=self.room2)
|
||||
|
||||
def get_cmd(self, cmd_class, argument_string=""):
|
||||
"""
|
||||
Obtain a cmd instance from a class and an input string
|
||||
Note: This does not make use of the cmdhandler functionality.
|
||||
"""
|
||||
cmd = cmd_class()
|
||||
cmd.caller = self.char1
|
||||
cmd.cmdstring = cmd_class.key
|
||||
cmd.args = argument_string
|
||||
cmd.cmdset = None
|
||||
cmd.obj = self.char1
|
||||
return cmd
|
||||
|
||||
def execute_cmd(self, raw_string):
|
||||
"""
|
||||
Creates the command through faking a normal command call;
|
||||
This also mangles the input in various ways to test if the command
|
||||
will be fooled.
|
||||
"""
|
||||
test1 = re.sub(r'\s', '', raw_string) # remove all whitespace inside it
|
||||
test2 = "%s/åäö öäö;-:$£@*~^' 'test" % raw_string # inserting weird characters in call
|
||||
test3 = "%s %s" % (raw_string, raw_string) # multiple calls
|
||||
self.char1.execute_cmd(test1)
|
||||
self.char1.execute_cmd(test2)
|
||||
self.char1.execute_cmd(test3)
|
||||
self.char1.execute_cmd(raw_string)
|
||||
|
||||
#------------------------------------------------------------
|
||||
# Default set Command testing
|
||||
#------------------------------------------------------------
|
||||
|
||||
class TestHome(CommandTest):
|
||||
def test_call(self):
|
||||
self.char1.home = self.room2
|
||||
self.execute_cmd("home")
|
||||
self.assertEqual(self.char1.location, self.room2)
|
||||
class TestLook(CommandTest):
|
||||
def test_call(self):
|
||||
self.execute_cmd("look here")
|
||||
class TestPassword(CommandTest):
|
||||
def test_call(self):
|
||||
self.execute_cmd("@password testpassword = newpassword")
|
||||
class TestNick(CommandTest):
|
||||
def test_call(self):
|
||||
self.execute_cmd("nickname testalias = testaliasedstring")
|
||||
self.assertEquals("testaliasedstring", self.char1.nicks.get("testalias", None))
|
||||
|
|
@ -10,7 +10,7 @@ from src.objects.models import ObjectDB
|
|||
from src.config.models import ConfigValue
|
||||
from src.comms.models import Channel
|
||||
from src.utils import create, logger, utils
|
||||
from game.gamesrc.commands.default.muxcommand import MuxCommand
|
||||
from src.commands.default.muxcommand import MuxCommand
|
||||
|
||||
class CmdConnect(MuxCommand):
|
||||
"""
|
||||
|
|
@ -8,7 +8,7 @@ from django.db import IntegrityError
|
|||
from src.comms.models import Msg
|
||||
from src.permissions import permissions
|
||||
from src.utils import create, debug, utils
|
||||
from game.gamesrc.commands.default.muxcommand import MuxCommand
|
||||
from src.commands.default.muxcommand import MuxCommand
|
||||
|
||||
from src.commands import cmdsethandler
|
||||
|
||||
|
|
@ -225,5 +225,3 @@ class TestCom(MuxCommand):
|
|||
caller.msg(string)
|
||||
return
|
||||
caller.msg("Usage: @testcom/create channel")
|
||||
|
||||
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
"""
|
||||
Unit testing of the 'objects' Evennia component.
|
||||
|
||||
Runs as part of the Evennia's test suite with 'manage.py test-evennia'.
|
||||
Runs as part of the Evennia's test suite with 'manage.py test"
|
||||
|
||||
Please add new tests to this module as needed.
|
||||
|
||||
|
|
@ -14,20 +14,20 @@ Guidelines:
|
|||
Inside the test methods, special member methods assert*() are used to test the behaviour.
|
||||
"""
|
||||
|
||||
import re, time
|
||||
import sys
|
||||
try:
|
||||
# this is a special optimized Django version, only available in current Django devel
|
||||
from django.utils.unittest import TestCase
|
||||
except ImportError:
|
||||
# if our Django is older we use the normal version
|
||||
# TODO: Switch this to django.test.TestCase when the but has been plugged that gives
|
||||
# traceback when using that module over TransactionTestCase.
|
||||
from django.test import TestCase
|
||||
#from django.test import TransactionTestCase as TestCase
|
||||
try:
|
||||
from django.utils import unittest
|
||||
except ImportError:
|
||||
import unittest
|
||||
|
||||
from django.conf import settings
|
||||
from src.objects import models, objects
|
||||
from src.utils import create
|
||||
from src.server import session, sessionhandler
|
||||
from src.commands.default import tests as commandtests
|
||||
|
||||
class TestObjAttrs(TestCase):
|
||||
"""
|
||||
|
|
@ -38,8 +38,6 @@ class TestObjAttrs(TestCase):
|
|||
self.attr = models.ObjAttribute()
|
||||
self.obj1 = create.create_object(objects.Object, key="testobj1", location=None)
|
||||
self.obj2 = create.create_object(objects.Object, key="testobj2", location=self.obj1)
|
||||
|
||||
# tests
|
||||
def test_store_str(self):
|
||||
hstring = "sdfv00=97sfjs842 ivfjlQKFos9GF^8dddsöäå-?%"
|
||||
self.obj1.db.testattr = hstring
|
||||
|
|
@ -48,106 +46,13 @@ class TestObjAttrs(TestCase):
|
|||
self.obj1.db.testattr = self.obj2
|
||||
self.assertEqual(self.obj2 ,self.obj1.db.testattr)
|
||||
self.assertEqual(self.obj2.location, self.obj1.db.testattr.location)
|
||||
|
||||
|
||||
#------------------------------------------------------------
|
||||
# Command testing
|
||||
#------------------------------------------------------------
|
||||
|
||||
# print all feedback from test commands (can become very verbose!)
|
||||
VERBOSE = False
|
||||
|
||||
class FakeSession(session.SessionProtocol):
|
||||
"""
|
||||
A fake session that implements dummy versions of the real thing; this is needed to mimic
|
||||
a logged-in player.
|
||||
"""
|
||||
def connectionMade(self):
|
||||
self.prep_session()
|
||||
sessionhandler.add_session(self)
|
||||
def prep_session(self):
|
||||
self.server, self.address = None, "0.0.0.0"
|
||||
self.name, self.uid = None, None
|
||||
self.logged_in = False
|
||||
self.encoding = "utf-8"
|
||||
self.cmd_last, self.cmd_last_visible, self.cmd_conn_time = time.time(), time.time(), time.time()
|
||||
self.cmd_total = 0
|
||||
def disconnectClient(self):
|
||||
pass
|
||||
def lineReceived(self, raw_string):
|
||||
pass
|
||||
def msg(self, message, markup=True):
|
||||
if VERBOSE:
|
||||
print message
|
||||
|
||||
class TestCommand(TestCase):
|
||||
"""
|
||||
Sets up the basics of testing the default commands and the generic things
|
||||
that should always be present in a command.
|
||||
|
||||
Inherit new tests from this.
|
||||
"""
|
||||
def setUp(self):
|
||||
"sets up the testing environment"
|
||||
self.room1 = create.create_object(settings.BASE_ROOM_TYPECLASS, key="room1")
|
||||
self.room2 = create.create_object(settings.BASE_ROOM_TYPECLASS, key="room2")
|
||||
|
||||
# create a faux player/character for testing.
|
||||
self.char1 = create.create_player("TestingPlayer", "testplayer@test.com", "testpassword", location=self.room1)
|
||||
self.char1.player.user.is_superuser = True
|
||||
sess = FakeSession()
|
||||
sess.connectionMade()
|
||||
sess.login(self.char1.player)
|
||||
|
||||
self.char2 = create.create_object(settings.BASE_CHARACTER_TYPECLASS, key="char2", location=self.room1)
|
||||
self.obj1 = create.create_object(settings.BASE_OBJECT_TYPECLASS, key="obj1", location=self.room1)
|
||||
self.obj2 = create.create_object(settings.BASE_OBJECT_TYPECLASS, key="obj2", location=self.room1)
|
||||
self.exit1 = create.create_object(settings.BASE_EXIT_TYPECLASS, key="exit1", location=self.room1)
|
||||
self.exit2 = create.create_object(settings.BASE_EXIT_TYPECLASS, key="exit2", location=self.room2)
|
||||
|
||||
def get_cmd(self, cmd_class, argument_string=""):
|
||||
"""
|
||||
Obtain a cmd instance from a class and an input string
|
||||
Note: This does not make use of the cmdhandler functionality.
|
||||
"""
|
||||
cmd = cmd_class()
|
||||
cmd.caller = self.char1
|
||||
cmd.cmdstring = cmd_class.key
|
||||
cmd.args = argument_string
|
||||
cmd.cmdset = None
|
||||
cmd.obj = self.char1
|
||||
return cmd
|
||||
|
||||
def execute_cmd(self, raw_string):
|
||||
"""
|
||||
Creates the command through faking a normal command call;
|
||||
This also mangles the input in various ways to test if the command
|
||||
will be fooled.
|
||||
"""
|
||||
test1 = re.sub(r'\s', '', raw_string) # remove all whitespace inside it
|
||||
test2 = "%s/åäö öäö;-:$£@*~^' 'test" % raw_string # inserting weird characters in call
|
||||
test3 = "%s %s" % (raw_string, raw_string) # multiple calls
|
||||
self.char1.execute_cmd(test1)
|
||||
self.char1.execute_cmd(test2)
|
||||
self.char1.execute_cmd(test3)
|
||||
self.char1.execute_cmd(raw_string)
|
||||
|
||||
#------------------------------------------------------------
|
||||
# Default set Command testing
|
||||
#------------------------------------------------------------
|
||||
|
||||
class TestHome(TestCommand):
|
||||
def test_call(self):
|
||||
self.char1.home = self.room2
|
||||
self.execute_cmd("home")
|
||||
self.assertEqual(self.char1.location, self.room2)
|
||||
class TestLook(TestCommand):
|
||||
def test_call(self):
|
||||
self.execute_cmd("look here")
|
||||
class TestPassword(TestCommand):
|
||||
def test_call(self):
|
||||
self.execute_cmd("@password testpassword = newpassword")
|
||||
class TestNick(TestCommand):
|
||||
def test_call(self):
|
||||
self.execute_cmd("nickname testalias = testaliasedstring")
|
||||
self.assertEquals("testaliasedstring", self.char1.nicks.get("testalias", None))
|
||||
def suite():
|
||||
"""
|
||||
This function is called automatically by the django test runner.
|
||||
This also runs the command tests defined in src/commands/default/tests.py.
|
||||
"""
|
||||
tsuite = unittest.TestSuite()
|
||||
tsuite.addTest(unittest.defaultTestLoader.loadTestsFromModule(sys.modules[__name__]))
|
||||
tsuite.addTest(unittest.defaultTestLoader.loadTestsFromModule(commandtests))
|
||||
return tsuite
|
||||
|
|
|
|||
|
|
@ -47,10 +47,10 @@ ALLOW_MULTISESSION = True
|
|||
SECRET_KEY = 'changeme!(*#&*($&*(#*(&SDFKJJKLS*(@#KJAS'
|
||||
# The path that contains this settings.py file (no trailing slash).
|
||||
BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
# Path to the game directory (containing the database file if using sqlite).
|
||||
GAME_DIR = os.path.join(BASE_PATH, 'game')
|
||||
# Path to the src directory containing the bulk of the codebase's code.
|
||||
SRC_DIR = os.path.join(BASE_PATH, 'src')
|
||||
# Path to the game directory (containing the database file if using sqlite).
|
||||
GAME_DIR = os.path.join(BASE_PATH, 'game')
|
||||
# Place to put log files
|
||||
LOG_DIR = os.path.join(GAME_DIR, 'logs')
|
||||
DEFAULT_LOG_FILE = os.path.join(LOG_DIR, 'evennia.log')
|
||||
|
|
@ -136,9 +136,9 @@ ALTERNATE_OBJECT_SEARCH_MULTIMATCH_PARSER = ""
|
|||
###################################################
|
||||
|
||||
# Command set used before player has logged in
|
||||
CMDSET_UNLOGGEDIN = "game.gamesrc.commands.default.cmdset_unloggedin.UnloggedinCmdSet"
|
||||
CMDSET_UNLOGGEDIN = "src.commands.default.cmdset_unloggedin.UnloggedinCmdSet"
|
||||
# Default set for logged in players (fallback)
|
||||
CMDSET_DEFAULT = "game.gamesrc.commands.default.cmdset_default.DefaultCmdSet"
|
||||
CMDSET_DEFAULT = "src.commands.default.cmdset_default.DefaultCmdSet"
|
||||
|
||||
|
||||
###################################################
|
||||
|
|
@ -326,7 +326,7 @@ ADMINS = () #'Your Name', 'your_email@domain.com'),)
|
|||
MANAGERS = ADMINS
|
||||
# Absolute path to the directory that holds media (no trailing slash).
|
||||
# Example: "/home/media/media.lawrence.com"
|
||||
MEDIA_ROOT = os.path.join(GAME_DIR, 'web', 'media')
|
||||
MEDIA_ROOT = os.path.join(SRC_DIR, 'web', 'media')
|
||||
# It's safe to dis-regard this, as it's a Django feature we only half use as a
|
||||
# dependency, not actually what it's primarily meant for.
|
||||
SITE_ID = 1
|
||||
|
|
@ -354,7 +354,7 @@ SERVE_MEDIA = True
|
|||
|
||||
# The master urlconf file that contains all of the sub-branches to the
|
||||
# applications.
|
||||
ROOT_URLCONF = 'game.web.urls'
|
||||
ROOT_URLCONF = 'src.web.urls'
|
||||
# Where users are redirected after logging in via contrib.auth.login.
|
||||
LOGIN_REDIRECT_URL = '/'
|
||||
# Where to redirect users when using the @login_required decorator.
|
||||
|
|
@ -373,8 +373,8 @@ ADMIN_MEDIA_PREFIX = '/media/amedia/'
|
|||
ACTIVE_TEMPLATE = 'prosimii'
|
||||
# We setup the location of the website template as well as the admin site.
|
||||
TEMPLATE_DIRS = (
|
||||
os.path.join(GAME_DIR, "web", "templates", ACTIVE_TEMPLATE),
|
||||
os.path.join(GAME_DIR, "web", "templates"),)
|
||||
os.path.join(SRC_DIR, "web", "templates", ACTIVE_TEMPLATE),
|
||||
os.path.join(SRC_DIR, "web", "templates"),)
|
||||
# List of callables that know how to import templates from various sources.
|
||||
TEMPLATE_LOADERS = (
|
||||
'django.template.loaders.filesystem.load_template_source',
|
||||
|
|
@ -397,12 +397,10 @@ TEMPLATE_CONTEXT_PROCESSORS = (
|
|||
'django.core.context_processors.auth',
|
||||
'django.core.context_processors.media',
|
||||
'django.core.context_processors.debug',
|
||||
'game.web.utils.general_context.general_context',)
|
||||
# Use a custom test runner that just tests Evennia-specific apps.
|
||||
TEST_RUNNER = 'src.utils.test_utils.EvenniaTestSuiteRunner'
|
||||
'src.web.utils.general_context.general_context',)
|
||||
|
||||
###################################################
|
||||
# Evennia components (django apps)
|
||||
# Evennia components
|
||||
###################################################
|
||||
|
||||
# Global and Evennia-specific apps. This ties everything together so we can
|
||||
|
|
@ -424,12 +422,13 @@ INSTALLED_APPS = (
|
|||
'src.help',
|
||||
'src.scripts',
|
||||
'src.permissions',
|
||||
'game.web.news',
|
||||
'game.web.website',)
|
||||
|
||||
'src.web.news',
|
||||
'src.web.website',)
|
||||
# The user profile extends the User object with more functionality;
|
||||
# This should usually not be changed.
|
||||
AUTH_PROFILE_MODULE = "players.PlayerDB"
|
||||
# Use a custom test runner that just tests Evennia-specific apps.
|
||||
TEST_RUNNER = 'src.utils.test_utils.EvenniaTestSuiteRunner'
|
||||
|
||||
###################################################
|
||||
# Django extensions
|
||||
|
|
@ -443,7 +442,7 @@ try:
|
|||
except ImportError:
|
||||
pass
|
||||
# South handles automatic database scheme migrations when evennia updates
|
||||
try:
|
||||
try:
|
||||
import south
|
||||
INSTALLED_APPS = INSTALLED_APPS + ('south',)
|
||||
except ImportError:
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
"""
|
||||
Test runner for Evennia test suite. Run with "game/manage.py test".
|
||||
|
||||
"""
|
||||
|
||||
from django.conf import settings
|
||||
from django.test.simple import DjangoTestSuiteRunner
|
||||
|
||||
|
|
@ -14,4 +19,4 @@ class EvenniaTestSuiteRunner(DjangoTestSuiteRunner):
|
|||
if not test_labels:
|
||||
test_labels = [applabel.rsplit('.', 1)[1] for applabel in settings.INSTALLED_APPS
|
||||
if (applabel.startswith('src.') or applabel.startswith('game.'))]
|
||||
return super(EvenniaTestSuiteRunner, self).build_suite(test_labels, extra_tests=extra_tests, **kwargs)
|
||||
return super(EvenniaTestSuiteRunner, self).build_suite(test_labels, extra_tests=extra_tests, **kwargs)
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 672 KiB After Width: | Height: | Size: 672 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
|
@ -4,7 +4,7 @@
|
|||
#
|
||||
|
||||
from django.contrib import admin
|
||||
from game.web.news.models import NewsTopic, NewsEntry
|
||||
from src.web.news.models import NewsTopic, NewsEntry
|
||||
|
||||
class NewsTopicAdmin(admin.ModelAdmin):
|
||||
list_display = ('name', 'icon')
|
||||
|
|
@ -5,7 +5,7 @@ It is imported from the root handler, game.web.urls.py.
|
|||
|
||||
from django.conf.urls.defaults import *
|
||||
|
||||
urlpatterns = patterns('game.web.news.views',
|
||||
urlpatterns = patterns('src.web.news.views',
|
||||
(r'^show/(?P<entry_id>\d+)/$', 'show_news'),
|
||||
(r'^archive/$', 'news_archive'),
|
||||
(r'^search/$', 'search_form'),
|
||||
|
|
@ -14,7 +14,7 @@ from django.contrib.auth.models import User
|
|||
from django import forms
|
||||
from django.db.models import Q
|
||||
|
||||
from game.web.news.models import NewsTopic, NewsEntry
|
||||
from src.web.news.models import NewsTopic, NewsEntry
|
||||
|
||||
# The sidebar text to be included as a variable on each page. There's got to
|
||||
# be a better, cleaner way to include this on every page.
|
||||
|
|
@ -23,12 +23,12 @@ urlpatterns = patterns('',
|
|||
url(r'^accounts/logout', 'django.contrib.auth.views.logout'),
|
||||
|
||||
# Front page
|
||||
url(r'^', include('game.web.website.urls')),
|
||||
url(r'^', include('src.web.website.urls')),
|
||||
# News stuff
|
||||
url(r'^news/', include('game.web.news.urls')),
|
||||
url(r'^news/', include('src.web.news.urls')),
|
||||
|
||||
# Page place-holder for things that aren't implemented yet.
|
||||
url(r'^tbi/', 'game.web.website.views.to_be_implemented'),
|
||||
url(r'^tbi/', 'src.web.website.views.to_be_implemented'),
|
||||
|
||||
# Admin interface
|
||||
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
|
||||
|
|
@ -5,6 +5,6 @@ webpage 'application'.
|
|||
|
||||
from django.conf.urls.defaults import *
|
||||
|
||||
urlpatterns = patterns('game.web.website.views',
|
||||
urlpatterns = patterns('src.web.website.views',
|
||||
(r'^$', 'page_index'),
|
||||
)
|
||||
|
|
@ -7,7 +7,7 @@ from src.config.models import ConfigValue
|
|||
from src.objects.models import ObjectDB
|
||||
from src.typeclasses.models import TypedObject
|
||||
from src.players.models import PlayerDB
|
||||
from game.web.news.models import NewsEntry
|
||||
from src.web.news.models import NewsEntry
|
||||
|
||||
"""
|
||||
This file contains the generic, assorted views that don't fall under one of
|
||||
Loading…
Add table
Add a link
Reference in a new issue