Merged. Still need to update some migrations.

This commit is contained in:
Griatch 2013-07-11 19:11:27 +02:00
commit c676c9965f
29 changed files with 821 additions and 401 deletions

View file

@ -139,14 +139,25 @@ def get_and_merge_cmdsets(caller):
cmdsets = yield [caller_cmdset] + [player_cmdset] + [channel_cmdset] + local_objects_cmdsets
# weed out all non-found sets
cmdsets = yield [cmdset for cmdset in cmdsets if cmdset]
cmdsets = yield [cmdset for cmdset in cmdsets if cmdset and cmdset.key!="Empty"]
# report cmdset errors to user (these should already have been logged)
yield [caller.msg(cmdset.message) for cmdset in cmdsets if cmdset.key == "_CMDSET_ERROR"]
# sort cmdsets after reverse priority (highest prio are merged in last)
yield cmdsets.sort(key=lambda x: x.priority)
#cmdsets = yield sorted(cmdsets, key=lambda x: x.priority)
yield [caller.msg(cmdset.errmessage) for cmdset in cmdsets if cmdset.key == "_CMDSET_ERROR"]
if cmdsets:
# we group and merge all same-prio cmdsets separately (this avoids order-dependent
# clashes in certain cases, such as when duplicates=True)
tempmergers = {}
for cmdset in cmdsets:
prio = cmdset.priority
if prio in tempmergers:
# merge same-prio cmdset together separately
tempmergers[prio] = yield cmdset + tempmergers[prio]
else:
tempmergers[prio] = cmdset
# sort cmdsets after reverse priority (highest prio are merged in last)
cmdsets = yield sorted(tempmergers.values(), key=lambda x: x.priority)
# Merge all command sets into one, beginning with the lowest-prio one
cmdset = cmdsets.pop(0)
for merging_cmdset in cmdsets:

View file

@ -128,9 +128,10 @@ class CmdSet(object):
no_objs = False
no_channels = False
permanent = False
errmessage = ""
# pre-store properties to duplicate straight off
to_duplicate = ("key", "cmdsetobj", "no_exits", "no_objs", "no_channels", "permanent",
"mergetype", "priority", "duplicates")
"mergetype", "priority", "duplicates", "errmessage")
def __init__(self, cmdsetobj=None, key=None):
"""
@ -152,21 +153,21 @@ class CmdSet(object):
# Priority-sensitive merge operations for cmdsets
def _union(self, cmdset_a, cmdset_b, duplicates=False):
def _union(self, cmdset_a, cmdset_b):
"C = A U B. CmdSet A is assumed to have higher priority"
cmdset_c = cmdset_a._duplicate()
# we make copies, not refs by use of [:]
cmdset_c.commands = cmdset_a.commands[:]
if duplicates and cmdset_a.priority == cmdset_b.priority:
if cmdset_a.duplicates and cmdset_a.priority == cmdset_b.priority:
cmdset_c.commands.extend(cmdset_b.commands)
else:
cmdset_c.commands.extend([cmd for cmd in cmdset_b if not cmd in cmdset_a])
return cmdset_c
def _intersect(self, cmdset_a, cmdset_b, duplicates=False):
def _intersect(self, cmdset_a, cmdset_b):
"C = A (intersect) B. A is assumed higher priority"
cmdset_c = cmdset_a._duplicate()
if duplicates and cmdset_a.priority == cmdset_b.priority:
if cmdset_a.duplicates and cmdset_a.priority == cmdset_b.priority:
for cmd in [cmd for cmd in cmdset_a if cmd in cmdset_b]:
cmdset_c.add(cmd)
cmdset_c.add(cmdset_b.get(cmd))
@ -174,13 +175,13 @@ class CmdSet(object):
cmdset_c.commands = [cmd for cmd in cmdset_a if cmd in cmdset_b]
return cmdset_c
def _replace(self, cmdset_a, cmdset_b, cmdset_c):
def _replace(self, cmdset_a, cmdset_b):
"C = A + B where the result is A."
cmdset_c = cmdset_a._duplicate()
cmdset_c.commands = cmdset_a.commands[:]
return cmdset_c
def _remove(self, cmdset_a, cmdset_b, cmdset_c):
def _remove(self, cmdset_a, cmdset_b):
"C = A + B, where B is filtered by A"
cmdset_c = cmdset_a._duplicate()
cmdset_c.commands = [cmd for cmd in cmdset_b if not cmd in cmdset_a]
@ -267,13 +268,13 @@ class CmdSet(object):
mergetype = self.key_mergetypes.get(cmdset_b.key, self.mergetype)
if mergetype == "Intersect":
cmdset_c = self._intersect(self, cmdset_b, cmdset_b.duplicates)
cmdset_c = self._intersect(self, cmdset_b)
elif mergetype == "Replace":
cmdset_c = self._replace(self, cmdset_b, cmdset_b.duplicates)
cmdset_c = self._replace(self, cmdset_b)
elif mergetype == "Remove":
cmdset_c = self._remove(self, cmdset_b, cmdset_b.duplicates)
cmdset_c = self._remove(self, cmdset_b)
else: # Union
cmdset_c = self._union(self, cmdset_b, cmdset_b.duplicates)
cmdset_c = self._union(self, cmdset_b)
cmdset_c.no_channels = self.no_channels
cmdset_c.no_exits = self.no_exits
cmdset_c.no_objs = self.no_objs
@ -286,13 +287,13 @@ class CmdSet(object):
mergetype = cmdset_b.key_mergetypes.get(self.key, cmdset_b.mergetype)
if mergetype == "Intersect":
cmdset_c = self._intersect(cmdset_b, self, self.duplicates)
cmdset_c = self._intersect(cmdset_b, self)
elif mergetype == "Replace":
cmdset_c = self._replace(cmdset_b, self, self.duplicates)
cmdset_c = self._replace(cmdset_b, self)
elif mergetype == "Remove":
cmdset_c = self._remove(self, cmdset_b, self.duplicates)
cmdset_c = self._remove(self, cmdset_b)
else: # Union
cmdset_c = self._union(cmdset_b, self, self.duplicates)
cmdset_c = self._union(cmdset_b, self)
cmdset_c.no_channels = cmdset_b.no_channels
cmdset_c.no_exits = cmdset_b.no_exits
cmdset_c.no_objs = cmdset_b.no_objs

View file

@ -76,7 +76,7 @@ _CACHED_CMDSETS = {}
class _ErrorCmdSet(CmdSet):
"This is a special cmdset used to report errors"
key = "_CMDSET_ERROR"
message = "Error when loading cmdset."
errmessage = "Error when loading cmdset."
def import_cmdset(python_path, cmdsetobj, emit_to_obj=None, no_logging=False):
"""
@ -130,7 +130,7 @@ def import_cmdset(python_path, cmdsetobj, emit_to_obj=None, no_logging=False):
if emit_to_obj and not ServerConfig.objects.conf("server_starting_mode"):
object.__getattribute__(emit_to_obj, "msg")(errstring)
err_cmdset = _ErrorCmdSet()
err_cmdset.message = errstring
err_cmdset.errmessage = errstring
return err_cmdset
# classes
@ -283,7 +283,7 @@ class CmdSetHandler(object):
elif isinstance(cmdset, basestring):
# this is (maybe) a python path. Try to import from cache.
cmdset = self._import_cmdset(cmdset)
if cmdset:
if cmdset and cmdset.key != '_CMDSET_ERROR':
if permanent and cmdset.key != '_CMDSET_ERROR':
# store the path permanently
cmdset.permanent = True
@ -315,7 +315,7 @@ class CmdSetHandler(object):
elif isinstance(cmdset, basestring):
# this is (maybe) a python path. Try to import from cache.
cmdset = self._import_cmdset(cmdset)
if cmdset:
if cmdset and cmdset.key != '_CMDSET_ERROR':
if self.cmdset_stack:
self.cmdset_stack[0] = cmdset
self.mergetype_stack[0] = cmdset.mergetype

View file

@ -9,58 +9,72 @@ import re
from src.locks.lockhandler import LockHandler
from src.utils.utils import is_iter, fill
def _init_command(mcs, **kwargs):
"""
Helper command.
Makes sure all data are stored as lowercase and
do checking on all properties that should be in list form.
Sets up locks to be more forgiving. This is used both by the metaclass
and (optionally) at instantiation time.
If kwargs are given, these are set as instance-specific properties on the command.
"""
for i in range(len(kwargs)):
# used for dynamic creation of commands
key, value = kwargs.popitem()
setattr(mcs, key, value)
mcs.key = mcs.key.lower()
if mcs.aliases and not is_iter(mcs.aliases):
try:
mcs.aliases = [str(alias).strip().lower() for alias in mcs.aliases.split(',')]
except Exception:
mcs.aliases = []
mcs.aliases = list(set(alias for alias in mcs.aliases if alias != mcs.key))
# optimization - a set is much faster to match against than a list
mcs._matchset = set([mcs.key] + mcs.aliases)
# optimization for looping over keys+aliases
mcs._keyaliases = tuple(mcs._matchset)
# by default we don't save the command between runs
if not hasattr(mcs, "save_for_next"):
mcs.save_for_next = False
# pre-process locks as defined in class definition
temp = []
if hasattr(mcs, 'permissions'):
mcs.locks = mcs.permissions
if not hasattr(mcs, 'locks'):
# default if one forgets to define completely
mcs.locks = "cmd:all()"
if not "cmd:" in mcs.locks:
mcs.locks = "cmd:all();" + mcs.locks
for lockstring in mcs.locks.split(';'):
if lockstring and not ':' in lockstring:
lockstring = "cmd:%s" % lockstring
temp.append(lockstring)
mcs.lock_storage = ";".join(temp)
if hasattr(mcs, 'arg_regex') and isinstance(mcs.arg_regex, basestring):
mcs.arg_regex = re.compile(r"%s" % mcs.arg_regex, re.I)
else:
mcs.arg_regex = None
if not hasattr(mcs, "auto_help"):
mcs.auto_help = True
if not hasattr(mcs, 'is_exit'):
mcs.is_exit = False
if not hasattr(mcs, "help_category"):
mcs.help_category = "general"
mcs.help_category = mcs.help_category.lower()
class CommandMeta(type):
"""
This metaclass makes some minor on-the-fly convenience fixes to the command
class in case the admin forgets to put things in lowercase etc.
The metaclass cleans up all properties on the class
"""
def __init__(mcs, *args, **kwargs):
"""
Simply make sure all data are stored as lowercase and
do checking on all properties that should be in list form.
Sets up locks to be more forgiving.
"""
mcs.key = mcs.key.lower()
if mcs.aliases and not is_iter(mcs.aliases):
try:
mcs.aliases = [str(alias).strip().lower() for alias in mcs.aliases.split(',')]
except Exception:
mcs.aliases = []
mcs.aliases = list(set(alias for alias in mcs.aliases if alias != mcs.key))
# optimization - a set is much faster to match against than a list
mcs._matchset = set([mcs.key] + mcs.aliases)
# optimization for looping over keys+aliases
mcs._keyaliases = tuple(mcs._matchset)
# by default we don't save the command between runs
if not hasattr(mcs, "save_for_next"):
mcs.save_for_next = False
# pre-process locks as defined in class definition
temp = []
if hasattr(mcs, 'permissions'):
mcs.locks = mcs.permissions
if not hasattr(mcs, 'locks'):
# default if one forgets to define completely
mcs.locks = "cmd:all()"
for lockstring in mcs.locks.split(';'):
if lockstring and not ':' in lockstring:
lockstring = "cmd:%s" % lockstring
temp.append(lockstring)
mcs.lock_storage = ";".join(temp)
if hasattr(mcs, 'arg_regex') and isinstance(mcs.arg_regex, basestring):
mcs.arg_regex = re.compile(r"%s" % mcs.arg_regex, re.I)
else:
mcs.arg_regex = None
if not hasattr(mcs, "auto_help"):
mcs.auto_help = True
if not hasattr(mcs, 'is_exit'):
mcs.is_exit = False
if not hasattr(mcs, "help_category"):
mcs.help_category = "general"
mcs.help_category = mcs.help_category.lower()
_init_command(mcs, **kwargs)
super(CommandMeta, mcs).__init__(*args, **kwargs)
# The Command class is the basic unit of an Evennia command; when
@ -125,8 +139,12 @@ class Command(object):
# sessid - which session-id (if any) is responsible for triggering this command
#
def __init__(self):
"the lockhandler works the same as for objects."
def __init__(self, **kwargs):
"""the lockhandler works the same as for objects.
optional kwargs will be set as properties on the Command at runtime,
overloading evential same-named class properties."""
if kwargs:
_init_command(self, **kwargs)
self.lockhandler = LockHandler(self)
def __str__(self):

View file

@ -606,9 +606,6 @@ class CmdQuell(MuxPlayerCommand):
Hierarchical permission quelling only work downwards, thus a Player cannot
use a higher-permission Character to escalate their permission level.
Use the unquell command to revert back to normal operation.
Note that the superuser character cannot be quelled. Use a separate
admin account for testing.
"""
key = "@quell"

View file

@ -4,7 +4,6 @@ Commands that are available from the connect screen.
import re
import traceback
from django.conf import settings
from django.contrib.auth.models import User
from src.players.models import PlayerDB
from src.objects.models import ObjectDB
from src.server.models import ServerConfig
@ -68,7 +67,7 @@ class CmdUnconnectedConnect(MuxCommand):
player = PlayerDB.objects.get_player_from_name(playername)
pswd = None
if player:
pswd = player.user.check_password(password)
pswd = player.check_password(password)
if not (player and pswd):
# No playername or password match
@ -142,7 +141,7 @@ class CmdUnconnectedCreate(MuxCommand):
return
# strip excessive spaces in playername
playername = re.sub(r"\s+", " ", playername).strip()
if PlayerDB.objects.filter(user__username__iexact=playername) or User.objects.filter(username__iexact=playername):
if PlayerDB.objects.filter(username__iexact=playername):
# player already exists (we also ignore capitalization here)
session.msg("Sorry, there is already a player with the name '%s'." % playername)
return