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

@ -561,6 +561,7 @@ class CrumblingWall(TutorialObject, Exit):
self.aliases = ["secret passage", "passage", "crack", "opening", "secret door"] self.aliases = ["secret passage", "passage", "crack", "opening", "secret door"]
# this is assigned first when pushing button, so assign this at creation time! # this is assigned first when pushing button, so assign this at creation time!
self.db.destination = 2 self.db.destination = 2
# locks on the object directly transfer to the exit "command" # locks on the object directly transfer to the exit "command"
self.locks.add("cmd:not locattr(is_dark)") self.locks.add("cmd:not locattr(is_dark)")

View file

@ -139,14 +139,25 @@ def get_and_merge_cmdsets(caller):
cmdsets = yield [caller_cmdset] + [player_cmdset] + [channel_cmdset] + local_objects_cmdsets cmdsets = yield [caller_cmdset] + [player_cmdset] + [channel_cmdset] + local_objects_cmdsets
# weed out all non-found sets # 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) # 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"] yield [caller.msg(cmdset.errmessage) 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)
if cmdsets: 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 # Merge all command sets into one, beginning with the lowest-prio one
cmdset = cmdsets.pop(0) cmdset = cmdsets.pop(0)
for merging_cmdset in cmdsets: for merging_cmdset in cmdsets:

View file

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

View file

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

View file

@ -9,17 +9,21 @@ import re
from src.locks.lockhandler import LockHandler from src.locks.lockhandler import LockHandler
from src.utils.utils import is_iter, fill from src.utils.utils import is_iter, fill
class CommandMeta(type): def _init_command(mcs, **kwargs):
""" """
This metaclass makes some minor on-the-fly convenience fixes to the command Helper command.
class in case the admin forgets to put things in lowercase etc. Makes sure all data are stored as lowercase and
"""
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. do checking on all properties that should be in list form.
Sets up locks to be more forgiving. 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() mcs.key = mcs.key.lower()
if mcs.aliases and not is_iter(mcs.aliases): if mcs.aliases and not is_iter(mcs.aliases):
try: try:
@ -44,6 +48,8 @@ class CommandMeta(type):
if not hasattr(mcs, 'locks'): if not hasattr(mcs, 'locks'):
# default if one forgets to define completely # default if one forgets to define completely
mcs.locks = "cmd:all()" mcs.locks = "cmd:all()"
if not "cmd:" in mcs.locks:
mcs.locks = "cmd:all();" + mcs.locks
for lockstring in mcs.locks.split(';'): for lockstring in mcs.locks.split(';'):
if lockstring and not ':' in lockstring: if lockstring and not ':' in lockstring:
lockstring = "cmd:%s" % lockstring lockstring = "cmd:%s" % lockstring
@ -61,6 +67,14 @@ class CommandMeta(type):
if not hasattr(mcs, "help_category"): if not hasattr(mcs, "help_category"):
mcs.help_category = "general" mcs.help_category = "general"
mcs.help_category = mcs.help_category.lower() mcs.help_category = mcs.help_category.lower()
class CommandMeta(type):
"""
The metaclass cleans up all properties on the class
"""
def __init__(mcs, *args, **kwargs):
_init_command(mcs, **kwargs)
super(CommandMeta, mcs).__init__(*args, **kwargs) super(CommandMeta, mcs).__init__(*args, **kwargs)
# The Command class is the basic unit of an Evennia command; when # 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 # sessid - which session-id (if any) is responsible for triggering this command
# #
def __init__(self): def __init__(self, **kwargs):
"the lockhandler works the same as for objects." """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) self.lockhandler = LockHandler(self)
def __str__(self): def __str__(self):

View file

@ -606,9 +606,6 @@ class CmdQuell(MuxPlayerCommand):
Hierarchical permission quelling only work downwards, thus a Player cannot Hierarchical permission quelling only work downwards, thus a Player cannot
use a higher-permission Character to escalate their permission level. use a higher-permission Character to escalate their permission level.
Use the unquell command to revert back to normal operation. 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" key = "@quell"

View file

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

View file

@ -90,7 +90,7 @@ class ChannelCommand(command.Command):
msgobj.senders = sender msgobj.senders = sender
msgobj.channels = channel msgobj.channels = channel
# send new message object to channel # send new message object to channel
channel.msg(msgobj, senders=sender) channel.msg(msgobj, senders=sender, online=True)
class ChannelHandler(object): class ChannelHandler(object):
""" """
@ -136,14 +136,11 @@ class ChannelHandler(object):
and run self.update on the handler. and run self.update on the handler.
""" """
# map the channel to a searchable command # map the channel to a searchable command
cmd = ChannelCommand() cmd = ChannelCommand(key=channel.key.strip().lower(),
cmd.key = channel.key.strip().lower() aliases=channel.aliases if channel.aliases else [],
cmd.obj = channel locks="cmd:all();%s" % channel.locks,
obj=channel)
cmd.__doc__= self._format_help(channel) cmd.__doc__= self._format_help(channel)
if channel.aliases:
cmd.aliases = channel.aliases
cmd.lock_storage = "cmd:all();%s" % channel.locks
cmd.lockhandler.reset()
self.cached_channel_cmds.append(cmd) self.cached_channel_cmds.append(cmd)
self.cached_cmdsets = {} self.cached_cmdsets = {}

View file

@ -11,6 +11,7 @@ _GA = object.__getattribute__
_PlayerDB = None _PlayerDB = None
_ObjectDB = None _ObjectDB = None
_Channel = None _Channel = None
_SESSIONS = None
_ExternalConnection = None _ExternalConnection = None
_User = None _User = None
@ -198,7 +199,7 @@ class MsgManager(models.Manager):
NOTE: This can potentially be slow, so make sure to supply NOTE: This can potentially be slow, so make sure to supply
one of the other arguments to limit the search. one of the other arguments to limit the search.
dbref - (int) the exact database id of the message. This will override dbref - (int) the exact database id of the message. This will override
all other search crieteria since it's unique and all other search criteria since it's unique and
always gives a list with only one match. always gives a list with only one match.
""" """
# unique msg id # unique msg id
@ -299,19 +300,33 @@ class ChannelManager(models.Manager):
CHANNELHANDLER.update() CHANNELHANDLER.update()
return None return None
def get_all_connections(self, channel): def get_all_connections(self, channel, online=False):
""" """
Return the connections of all players listening Return the connections of all players listening
to this channel to this channel. If Online is true, it only returns
connected players.
""" """
# import here to avoid circular imports global _SESSIONS
#from src.comms.models import PlayerChannelConnection if not _SESSIONS:
from src.server.sessionhandler import SESSIONS as _SESSIONS
PlayerChannelConnection = ContentType.objects.get(app_label="comms", PlayerChannelConnection = ContentType.objects.get(app_label="comms",
model="playerchannelconnection").model_class() model="playerchannelconnection").model_class()
ExternalChannelConnection = ContentType.objects.get(app_label="comms", ExternalChannelConnection = ContentType.objects.get(app_label="comms",
model="externalchannelconnection").model_class() model="externalchannelconnection").model_class()
return itertools.chain(PlayerChannelConnection.objects.get_all_connections(channel), players = []
ExternalChannelConnection.objects.get_all_connections(channel)) if online:
session_list = _SESSIONS.get_sessions()
unique_online_users = set(sess.uid for sess in session_list if sess.logged_in)
online_players = (sess.get_player() for sess in session_list if sess.uid in unique_online_users)
for player in online_players:
players.extend(PlayerChannelConnection.objects.filter(db_player=player, db_channel=channel))
else:
players.extend(PlayerChannelConnection.objects.get_all_connections(channel))
external_connections = ExternalChannelConnection.objects.get_all_connections(channel)
return itertools.chain(players, external_connections)
def channel_search(self, ostring): def channel_search(self, ostring):
""" """

View file

@ -553,7 +553,7 @@ class Channel(SharedMemoryModel):
# do the check # do the check
return PlayerChannelConnection.objects.has_player_connection(player, self) return PlayerChannelConnection.objects.has_player_connection(player, self)
def msg(self, msgobj, header=None, senders=None, persistent=True): def msg(self, msgobj, header=None, senders=None, persistent=True, online=False):
""" """
Send the given message to all players connected to channel. Note that Send the given message to all players connected to channel. Note that
no permission-checking is done here; it is assumed to have been no permission-checking is done here; it is assumed to have been
@ -566,7 +566,8 @@ class Channel(SharedMemoryModel):
persistent=False. persistent=False.
persistent (bool) - ignored if msgobj is a Msg or TempMsg. If True, a Msg will be created, using persistent (bool) - ignored if msgobj is a Msg or TempMsg. If True, a Msg will be created, using
header and senders keywords. If False, other keywords will be ignored. header and senders keywords. If False, other keywords will be ignored.
online (bool) - If this is set true, only messages people who are online. Otherwise, messages all players
connected. This can make things faster, but may not trigger listeners on players that are offline.
""" """
if isinstance(msgobj, basestring): if isinstance(msgobj, basestring):
@ -588,7 +589,7 @@ class Channel(SharedMemoryModel):
msg = msgobj.message msg = msgobj.message
# get all players connected to this channel and send to them # get all players connected to this channel and send to them
for conn in Channel.objects.get_all_connections(self): for conn in Channel.objects.get_all_connections(self, online=online):
try: try:
conn.player.msg(msg, senders) conn.player.msg(msg, senders)
except AttributeError: except AttributeError:

View file

@ -34,7 +34,6 @@ class ObjectManager(TypedObjectManager):
get_dbref_range get_dbref_range
object_totals object_totals
typeclass_search typeclass_search
get_object_with_user
get_object_with_player get_object_with_player
get_objs_with_key_and_typeclass get_objs_with_key_and_typeclass
get_objs_with_attr get_objs_with_attr
@ -52,29 +51,8 @@ class ObjectManager(TypedObjectManager):
# ObjectManager Get methods # ObjectManager Get methods
# #
# user/player related # player related
@returns_typeclass
def get_object_with_user(self, user):
"""
Matches objects with obj.player.user matching the argument.
A player<->user is a one-to-relationship, so this always
returns just one result or None.
user - may be a user object or user id.
"""
dbref = self.dbref(user)
if dbref:
try:
return self.get(db_player__user__id=dbref)
except self.model.DoesNotExist:
pass
try:
return self.get(db_player__user=user)
except self.model.DoesNotExist:
return None
# This returns typeclass since get_object_with_user and get_dbref does.
@returns_typeclass @returns_typeclass
def get_object_with_player(self, ostring, exact=True, candidates=None): def get_object_with_player(self, ostring, exact=True, candidates=None):
""" """
@ -92,9 +70,9 @@ class ObjectManager(TypedObjectManager):
# not a dbref. Search by name. # not a dbref. Search by name.
cand_restriction = candidates and Q(pk__in=[_GA(obj, "id") for obj in make_iter(candidates) if obj]) or Q() cand_restriction = candidates and Q(pk__in=[_GA(obj, "id") for obj in make_iter(candidates) if obj]) or Q()
if exact: if exact:
return self.filter(cand_restriction & Q(db_player__user__username__iexact=ostring)) return self.filter(cand_restriction & Q(db_player__username__iexact=ostring))
else: # fuzzy matching else: # fuzzy matching
ply_cands = self.filter(cand_restriction & Q(playerdb__user__username__istartswith=ostring)).values_list("db_key", flat=True) ply_cands = self.filter(cand_restriction & Q(playerdb__username__istartswith=ostring)).values_list("db_key", flat=True)
if candidates: if candidates:
index_matches = string_partial_matching(ply_cands, ostring, ret_index=True) index_matches = string_partial_matching(ply_cands, ostring, ret_index=True)
return [obj for ind, obj in enumerate(make_iter(candidates)) if ind in index_matches] return [obj for ind, obj in enumerate(make_iter(candidates)) if ind in index_matches]
@ -175,7 +153,8 @@ class ObjectManager(TypedObjectManager):
if isinstance(property_value, basestring): if isinstance(property_value, basestring):
property_value = to_unicode(property_value) property_value = to_unicode(property_value)
if isinstance(property_name, basestring): if isinstance(property_name, basestring):
property_name = "db_%s" % property_name.lstrip('db_') if not property_name.startswith('db_'):
property_name = "db_%s" % property_name
querykwargs = {property_name:property_value} querykwargs = {property_name:property_value}
cand_restriction = candidates and Q(pk__in=[_GA(obj, "id") for obj in make_iter(candidates) if obj]) or Q() cand_restriction = candidates and Q(pk__in=[_GA(obj, "id") for obj in make_iter(candidates) if obj]) or Q()
type_restriction = typeclasses and Q(db_typeclass_path__in=make_iter(typeclasses)) or Q() type_restriction = typeclasses and Q(db_typeclass_path__in=make_iter(typeclasses)) or Q()
@ -183,6 +162,10 @@ class ObjectManager(TypedObjectManager):
return list(self.filter(cand_restriction & type_restriction & Q(**querykwargs))) return list(self.filter(cand_restriction & type_restriction & Q(**querykwargs)))
except exceptions.FieldError: except exceptions.FieldError:
return [] return []
except ValueError:
from src.utils import logger
logger.log_errmsg("The property '%s' does not support search criteria of the type %s." % (property_name, type(property_value)))
return []
@returns_typeclass_list @returns_typeclass_list
def get_contents(self, location, excludeobj=None): def get_contents(self, location, excludeobj=None):
@ -253,7 +236,8 @@ class ObjectManager(TypedObjectManager):
By default (if not attribute_name is set), this will search object.key and object.aliases in order. Can also By default (if not attribute_name is set), this will search object.key and object.aliases in order. Can also
be on the form #dbref, which will, if exact=True be matched against primary key. be on the form #dbref, which will, if exact=True be matched against primary key.
attribute_name: (str): Use this named ObjectAttribute to match searchdata against, instead attribute_name: (str): Use this named ObjectAttribute to match searchdata against, instead
of the defaults. of the defaults. If this is the name of a database field (with or without the db_ prefix), that
will be matched too.
typeclass (str or TypeClass): restrict matches to objects having this typeclass. This will help typeclass (str or TypeClass): restrict matches to objects having this typeclass. This will help
speed up global searches. speed up global searches.
candidates (list obj ObjectDBs): If supplied, search will only be performed among the candidates candidates (list obj ObjectDBs): If supplied, search will only be performed among the candidates

View file

@ -640,7 +640,7 @@ class ObjectDB(TypedObject):
if searchdata == _HERE: if searchdata == _HERE:
return self.location return self.location
if searchdata in (_ME, _SELF): if searchdata in (_ME, _SELF):
return self return self.typeclass
if use_nicks: if use_nicks:
nick = None nick = None

View file

@ -37,14 +37,14 @@ class Object(TypeClass):
# __init__ is only defined here in order to present docstring to API. # __init__ is only defined here in order to present docstring to API.
def __init__(self, dbobj): def __init__(self, dbobj):
""" """
This is the root typeclass object representing all entities This is the root typeclass object, representing all entities
that has and actual presence in-game. Objects generally has a that have an actual presence in-game. Objects generally have a
location, can be manipulated and looked at. Most game entities location. They can also be manipulated and looked at. Most
you define should inherit from Object at some distance. game entities you define should inherit from Object at some distance.
Important subclasses of Object are that Evennia defines by Evennia defines some important subclasses of Object by default, namely
default for you are Characters, Exits and Rooms. Characters, Exits and Rooms (see the bottom of this module).
Note that all Objects and its subclasses *must* always be Note that all new Objects and their subclasses *must* always be
created using the ev.create_object() function. This is so the created using the ev.create_object() function. This is so the
typeclass system can be correctly initiated behind the scenes. typeclass system can be correctly initiated behind the scenes.
@ -54,7 +54,7 @@ class Object(TypeClass):
* Available properties (only available on *initiated* typeclass objects) * Available properties (only available on *initiated* typeclass objects)
key (string) - name of object key (string) - name of object
name (string)- same as key name (string) - same as key
aliases (list of strings) - aliases to the object. Will be saved to database as AliasDB entries but returned as strings. aliases (list of strings) - aliases to the object. Will be saved to database as AliasDB entries but returned as strings.
dbref (int, read-only) - unique #id-number. Also "id" can be used. dbref (int, read-only) - unique #id-number. Also "id" can be used.
dbobj (Object, read-only) - link to database model. dbobj.typeclass points back to this class dbobj (Object, read-only) - link to database model. dbobj.typeclass points back to this class
@ -465,12 +465,13 @@ class Object(TypeClass):
""" """
pass pass
def at_pre_puppet(self, player): def at_pre_puppet(self, player, sessid=None):
""" """
Called just before a Player connects to this object Called just before a Player connects to this object
to puppet it. to puppet it.
player - connecting player object player - connecting player object
sessid - session id controlling the connection
""" """
pass pass
@ -488,13 +489,14 @@ class Object(TypeClass):
""" """
pass pass
def at_post_unpuppet(self, player): def at_post_unpuppet(self, player, sessid=None):
""" """
Called just after the Player successfully disconnected Called just after the Player successfully disconnected
from this object, severing all connections. from this object, severing all connections.
player - the player object that just disconnected from player - the player object that just disconnected from
this object. this object.
sessid - session id controlling the connection
""" """
pass pass
@ -755,7 +757,7 @@ class Object(TypeClass):
return message return message
# #
# Base Player object # Base Character object
# #
class Character(Object): class Character(Object):
@ -793,7 +795,7 @@ class Character(Object):
"Default is to look around after a move." "Default is to look around after a move."
self.execute_cmd('look') self.execute_cmd('look')
def at_pre_puppet(self, player): def at_pre_puppet(self, player, sessid=None):
""" """
This recovers the character again after having been "stoved away" at the unpuppet This recovers the character again after having been "stoved away" at the unpuppet
""" """
@ -809,7 +811,7 @@ class Character(Object):
self.location.msg_contents("%s has entered the game." % self.name, exclude=[self]) self.location.msg_contents("%s has entered the game." % self.name, exclude=[self])
self.location.at_object_receive(self, self.location) self.location.at_object_receive(self, self.location)
else: else:
player.msg("{r%s has no location and no home is set.{n" % self) player.msg("{r%s has no location and no home is set.{n" % self, sessid=sessid)
def at_post_puppet(self): def at_post_puppet(self):
""" """
@ -820,7 +822,7 @@ class Character(Object):
if self.location: if self.location:
self.location.msg_contents("%s has entered the game." % self.name, exclude=[self]) self.location.msg_contents("%s has entered the game." % self.name, exclude=[self])
def at_post_unpuppet(self, player): def at_post_unpuppet(self, player, sessid=None):
""" """
We stove away the character when the player goes ooc/logs off, otherwise the character object will We stove away the character when the player goes ooc/logs off, otherwise the character object will
remain in the room also after the player logged off ("headless", so to say). remain in the room also after the player logged off ("headless", so to say).
@ -836,14 +838,13 @@ class Character(Object):
class Room(Object): class Room(Object):
""" """
This is the base room object. It's basically This is the base room object. It's just like any Object except its
like any Object except its location is None. location is None.
""" """
def basetype_setup(self): def basetype_setup(self):
""" """
Simple setup, shown as an example Simple setup, shown as an example
(since default is None anyway) (since default is None anyway)
""" """
super(Room, self).basetype_setup() super(Room, self).basetype_setup()
@ -852,19 +853,18 @@ class Room(Object):
self.location = None self.location = None
# #
# Exits # Base Exit object
# #
class Exit(Object): class Exit(Object):
""" """
This is the base exit object - it connects a location to This is the base exit object - it connects a location to another.
another. This is done by the exit assigning a "command" on itself This is done by the exit assigning a "command" on itself with the
with the same name as the exit object (to do this we need to same name as the exit object (to do this we need to remember to
remember to re-create the command when the object is cached since it must be re-create the command when the object is cached since it must be
created dynamically depending on what the exit is called). This created dynamically depending on what the exit is called). This
command (which has a high priority) will thus allow us to traverse exits command (which has a high priority) will thus allow us to traverse
simply by giving the exit-object's name on its own. exits simply by giving the exit-object's name on its own.
""" """
# Helper classes and methods to implement the Exit. These need not # Helper classes and methods to implement the Exit. These need not
@ -909,13 +909,12 @@ class Exit(Object):
self.obj.at_failed_traverse(self.caller) self.obj.at_failed_traverse(self.caller)
# create an exit command. # create an exit command.
cmd = ExitCommand() cmd = ExitCommand(key=exidbobj.db_key.strip().lower(),
cmd.key = exidbobj.db_key.strip().lower() aliases=exidbobj.aliases,
cmd.obj = exidbobj locks=str(exidbobj.locks),
cmd.aliases = exidbobj.aliases auto_help=False,
cmd.locks = str(exidbobj.locks) destination=exidbobj.db_destination,
cmd.destination = exidbobj.db_destination obj=exidbobj)
cmd.auto_help = False
# create a cmdset # create a cmdset
exit_cmdset = cmdset.CmdSet(None) exit_cmdset = cmdset.CmdSet(None)
exit_cmdset.key = '_exitset' exit_cmdset.key = '_exitset'

View file

@ -142,6 +142,7 @@ class UserAdmin(BaseUserAdmin):
{'fields': ('username', 'password1', 'password2', 'email'), {'fields': ('username', 'password1', 'password2', 'email'),
'description':"<i>These account details are shared by the admin system and the game.</i>"},),) 'description':"<i>These account details are shared by the admin system and the game.</i>"},),)
# TODO! Remove User reference!
def save_formset(self, request, form, formset, change): def save_formset(self, request, form, formset, change):
"Run all hooks on the player object" "Run all hooks on the player object"
super(UserAdmin, self).save_formset(request, form, formset, change) super(UserAdmin, self).save_formset(request, form, formset, change)

View file

@ -3,8 +3,8 @@ The managers for the custom Player object and permissions.
""" """
import datetime import datetime
from django.contrib.auth.models import UserManager
from functools import update_wrapper from functools import update_wrapper
from django.contrib.auth.models import User
from src.typeclasses.managers import returns_typeclass_list, returns_typeclass, TypedObjectManager from src.typeclasses.managers import returns_typeclass_list, returns_typeclass, TypedObjectManager
from src.utils import logger from src.utils import logger
__all__ = ("PlayerManager",) __all__ = ("PlayerManager",)
@ -13,54 +13,7 @@ __all__ = ("PlayerManager",)
# Player Manager # Player Manager
# #
def returns_player_list(method): class PlayerManager(TypedObjectManager, UserManager):
"""
decorator that makes sure that a method
returns a Player object instead of a User
one (if you really want the User object, not
the player, use the player's 'user' property)
"""
def func(self, *args, **kwargs):
"This *always* returns a list."
match = method(self, *args, **kwargs)
if not match:
return []
try:
match = list(match)
except TypeError:
match = [match]
players = []
for user in match:
try:
players.append(user.get_profile())
except Exception:
# there is something wrong with get_profile. But
# there is a 1-1 relation between Users-Players, so we
# try to go the other way instead.
from src.players.models import PlayerDB
match = PlayerDB.objects.filter(user__id=user.id)
if match:
players.append(match[0])
else:
logger.log_trace("No connection User<->Player, maybe database was partially reset?")
return players
return update_wrapper(func, method)
def returns_player(method):
"""
Decorator: Always returns a single result or None.
"""
def func(self, *args, **kwargs):
"decorator"
rfunc = returns_player_list(method)
match = rfunc(self, *args, **kwargs)
if match:
return match[0]
else:
return None
return update_wrapper(func, method)
class PlayerManager(TypedObjectManager):
""" """
This PlayerManager implements methods for searching This PlayerManager implements methods for searching
and manipulating Players directly from the database. and manipulating Players directly from the database.
@ -87,7 +40,7 @@ class PlayerManager(TypedObjectManager):
""" """
def num_total_players(self): def num_total_players(self):
""" """
Returns the total number of registered users/players. Returns the total number of registered players.
""" """
return self.count() return self.count()
@ -99,7 +52,6 @@ class PlayerManager(TypedObjectManager):
return self.filter(db_is_connected=True) return self.filter(db_is_connected=True)
@returns_typeclass_list @returns_typeclass_list
@returns_player_list
def get_recently_created_players(self, days=7): def get_recently_created_players(self, days=7):
""" """
Returns a QuerySet containing the player User accounts that have been Returns a QuerySet containing the player User accounts that have been
@ -108,13 +60,12 @@ class PlayerManager(TypedObjectManager):
end_date = datetime.datetime.now() end_date = datetime.datetime.now()
tdelta = datetime.timedelta(days) tdelta = datetime.timedelta(days)
start_date = end_date - tdelta start_date = end_date - tdelta
return User.objects.filter(date_joined__range=(start_date, end_date)) return self.filter(date_joined__range=(start_date, end_date))
@returns_typeclass_list @returns_typeclass_list
@returns_player_list
def get_recently_connected_players(self, days=7): def get_recently_connected_players(self, days=7):
""" """
Returns a QuerySet containing the player User accounts that have been Returns a QuerySet containing the player accounts that have been
connected within the last <days> days. connected within the last <days> days.
days - number of days backwards to check days - number of days backwards to check
@ -122,33 +73,31 @@ class PlayerManager(TypedObjectManager):
end_date = datetime.datetime.now() end_date = datetime.datetime.now()
tdelta = datetime.timedelta(days) tdelta = datetime.timedelta(days)
start_date = end_date - tdelta start_date = end_date - tdelta
return User.objects.filter(last_login__range=( return self.filter(last_login__range=(
start_date, end_date)).order_by('-last_login') start_date, end_date)).order_by('-last_login')
@returns_typeclass @returns_typeclass
@returns_player
def get_player_from_email(self, uemail): def get_player_from_email(self, uemail):
""" """
Returns a player object when given an email address. Returns a player object when given an email address.
""" """
return User.objects.filter(email__iexact=uemail) return self.filter(email__iexact=uemail)
@returns_typeclass @returns_typeclass
@returns_player
def get_player_from_uid(self, uid): def get_player_from_uid(self, uid):
""" """
Returns a player object based on User id. Returns a player object based on User id.
""" """
try: try:
return User.objects.get(id=uid) return self.get(id=uid)
except User.model.DoesNotExist: except self.model.DoesNotExist:
return None return None
@returns_typeclass @returns_typeclass
def get_player_from_name(self, uname): def get_player_from_name(self, uname):
"Get player object based on name" "Get player object based on name"
try: try:
return self.get(user__username__iexact=uname) return self.get(username__iexact=uname)
except self.model.DoesNotExist: except self.model.DoesNotExist:
return None return None
@ -165,7 +114,7 @@ class PlayerManager(TypedObjectManager):
matches = self.filter(id=dbref) matches = self.filter(id=dbref)
if matches: if matches:
return matches return matches
return self.filter(user__username__iexact=ostring) return self.filter(username__iexact=ostring)
def swap_character(self, player, new_character, delete_old_character=False): def swap_character(self, player, new_character, delete_old_character=False):
""" """

View file

@ -0,0 +1,162 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models, connection
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'PlayerDBtmp'
if "auth_user" in connection.introspection.table_names():
# auth_user exists ffrom before. Use that as a base.
db.rename_table('auth_user', 'players_playerdbtmp')
else:
# from-scratch creation; no auth_user table available. Create vanilla User table
db.create_table(u'players_playerdbtmp', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('password', self.gf('django.db.models.fields.CharField')(max_length=128)),
('last_login', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),
('is_superuser', self.gf('django.db.models.fields.BooleanField')(default=False)),
('username', self.gf('django.db.models.fields.CharField')(unique=True, max_length=30)),
('first_name', self.gf('django.db.models.fields.CharField')(max_length=30, blank=True)),
('last_name', self.gf('django.db.models.fields.CharField')(max_length=30, blank=True)),
('email', self.gf('django.db.models.fields.EmailField')(max_length=75, blank=True)),
('is_staff', self.gf('django.db.models.fields.BooleanField')(default=False)),
('is_active', self.gf('django.db.models.fields.BooleanField')(default=True)),
('date_joined', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),
))
db.send_create_signal(u'players', ['PlayerDBtmp'])
# Adding M2M table for field groups on 'PlayerDBtmp'
db.create_table(u'players_playerdbtmp_groups', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('playerdbtmp', models.ForeignKey(orm[u'players.playerdbtmp'], null=False)),
('group', models.ForeignKey(orm[u'auth.group'], null=False))
))
db.create_unique(u'players_playerdbtmp_groups', ['playerdbtmp_id', 'group_id'])
# Adding M2M table for field user_permissions on 'PlayerDBtmp'
db.create_table(u'players_playerdbtmp_user_permissions', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('playerdbtmp', models.ForeignKey(orm[u'players.playerdbtmp'], null=False)),
('permission', models.ForeignKey(orm[u'auth.permission'], null=False))
))
db.create_unique(u'players_playerdbtmp_user_permissions', ['playerdbtmp_id', 'permission_id'])
# Adding field 'PlayerDB.db_is_connected'
db.add_column(u'players_playerdb', 'db_is_connected',
self.gf('django.db.models.fields.BooleanField')(default=False),
keep_default=False)
# Adding field 'PlayerDB.db_cmdset_storage'
db.add_column(u'players_playerdb', 'db_cmdset_storage',
self.gf('django.db.models.fields.CharField')(max_length=255, null=True),
keep_default=False)
# add Evennia-specific columns
db.add_column('players_playerdbtmp', 'db_key', self.gf('django.db.models.fields.CharField')(max_length=255, db_index=True, null=True))
db.add_column('players_playerdbtmp', 'db_typeclass_path', self.gf('django.db.models.fields.CharField')(max_length=255, null=True))
db.add_column('players_playerdbtmp', 'db_date_created', self.gf('django.db.models.fields.DateTimeField')(null=True, auto_now_add=True, blank=True))
db.add_column('players_playerdbtmp', 'db_permissions', self.gf('django.db.models.fields.CharField')(max_length=255, blank=True, null=True))
db.add_column('players_playerdbtmp', 'db_lock_storage', self.gf('django.db.models.fields.TextField')(blank=True, null=True))
db.add_column('players_playerdbtmp', 'db_is_connected', self.gf('django.db.models.fields.BooleanField')(default=False))
db.add_column('players_playerdbtmp', 'db_cmdset_storage', self.gf('django.db.models.fields.CharField')(max_length=255, null=True))
def backwards(self, orm):
raise RuntimeError("Cannot revert migration")
models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
u'players.playerattribute': {
'Meta': {'object_name': 'PlayerAttribute'},
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}),
'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
u'players.playerdb': {
'Meta': {'object_name': 'PlayerDB'},
'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'})
},
u'players.playerdbtmp': {
'Meta': {'ordering': "['-db_date_created', 'id', 'db_typeclass_path', 'db_key']", 'object_name': 'PlayerDBtmp'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'players.playernick': {
'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'},
'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}),
'db_real': ('django.db.models.fields.TextField', [], {}),
'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
}
}
complete_apps = ['players']

View file

@ -0,0 +1,118 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
class Migration(DataMigration):
def forwards(self, orm):
"Write your forwards methods here."
# Note: Remember to use orm['appname.ModelName'] rather than "from appname.models..."
if not db.dry_run:
for profile in orm['players.PlayerDB'].objects.all():
plyr = orm['players.PlayerDBtmp'].objects.get(id=profile.user_id)
plyr.db_cmdset_storage = profile.db_cmdset_storage
plyr.db_date_created = profile.db_date_created
plyr.db_is_connected = profile.db_is_connected
plyr.db_key = profile.db_key
plyr.db_lock_storage = profile.db_lock_storage
plyr.db_typeclass_path = profile.db_typeclass_path
plyr.db_permissions = profile.db_permissions
plyr.save()
def backwards(self, orm):
"Write your backwards methods here."
raise RuntimeError("Cannot revert this migration.")
models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
u'players.playerattribute': {
'Meta': {'object_name': 'PlayerAttribute'},
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}),
'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
u'players.playerdb': {
'Meta': {'object_name': 'PlayerDB'},
'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'})
},
u'players.playerdbtmp': {
'Meta': {'ordering': "['-db_date_created', 'id', 'db_typeclass_path', 'db_key']", 'object_name': 'PlayerDBtmp'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'players.playernick': {
'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'},
'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}),
'db_real': ('django.db.models.fields.TextField', [], {}),
'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
}
}
complete_apps = ['players']
symmetrical = True

View file

@ -0,0 +1,107 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
db.delete_table('players_playerdb')
def backwards(self, orm):
raise RuntimeError("Cannot revert this migration")
models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
u'players.playerattribute': {
'Meta': {'object_name': 'PlayerAttribute'},
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}),
'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
u'players.playerdb': {
'Meta': {'object_name': 'PlayerDB'},
'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'})
},
u'players.playerdbtmp': {
'Meta': {'ordering': "['-db_date_created', 'id', 'db_typeclass_path', 'db_key']", 'object_name': 'PlayerDBtmp'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'players.playernick': {
'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'},
'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}),
'db_real': ('django.db.models.fields.TextField', [], {}),
'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
}
}
complete_apps = ['players']

View file

@ -0,0 +1,101 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
db.rename_table('players_PlayerDBtmp', 'players_PlayerDB')
db.send_create_signal('players', ['PlayerDB'])
def backwards(self, orm):
raise RuntimeError("Cannot revert this migration.")
models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
u'players.playerattribute': {
'Meta': {'object_name': 'PlayerAttribute'},
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}),
'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
# u'players.playerdbtmp': {
# 'Meta': {'ordering': "['-db_date_created', 'id', 'db_typeclass_path', 'db_key']", 'object_name': 'PlayerDBtmp'},
# 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
# 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
# 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
# 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
# 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
# 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
# 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
# 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
# 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
# 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
# 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
# u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
# 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
# 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
# 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
# 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
# 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
# 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
# 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
# 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
# },
u'players.playerdb': {
'Meta': {'ordering': "['-db_date_created', 'id', 'db_typeclass_path', 'db_key']", 'object_name': 'PlayerDB'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'players.playernick': {
'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'},
'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}),
'db_real': ('django.db.models.fields.TextField', [], {}),
'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
}
}
complete_apps = ['players']

View file

@ -25,7 +25,7 @@ account info and OOC account configuration variables etc.
from django.conf import settings from django.conf import settings
from django.db import models from django.db import models
from django.contrib.auth.models import User from django.contrib.auth.models import AbstractUser, User
from django.utils.encoding import smart_str from django.utils.encoding import smart_str
from django.db.models.signals import post_init, pre_delete from django.db.models.signals import post_init, pre_delete
@ -95,7 +95,8 @@ class PlayerNickHandler(TypeNickHandler):
# #
#------------------------------------------------------------ #------------------------------------------------------------
class PlayerDB(TypedObject):
class PlayerDB(TypedObject, AbstractUser):
""" """
This is a special model using Django's 'profile' functionality This is a special model using Django's 'profile' functionality
and extends the default Django User model. It is defined as such and extends the default Django User model. It is defined as such
@ -130,8 +131,8 @@ class PlayerDB(TypedObject):
# this is the one-to-one link between the customized Player object and # this is the one-to-one link between the customized Player object and
# this profile model. It is required by django. # this profile model. It is required by django.
user = models.ForeignKey(User, unique=True, db_index=True, #user = models.ForeignKey(User, unique=True, db_index=True,
help_text="The <I>User</I> object holds django-specific authentication for each Player. A unique User should be created and tied to each Player, the two should never be switched or changed around. The User will be deleted automatically when the Player is.") # help_text="The <I>User</I> object holds django-specific authentication for each Player. A unique User should be created and tied to each Player, the two should never be switched or changed around. The User will be deleted automatically when the Player is.")
# store a connected flag here too, not just in sessionhandler. # store a connected flag here too, not just in sessionhandler.
# This makes it easier to track from various out-of-process locations # This makes it easier to track from various out-of-process locations
db_is_connected = models.BooleanField(default=False, verbose_name="is_connected", help_text="If player is connected to game or not") db_is_connected = models.BooleanField(default=False, verbose_name="is_connected", help_text="If player is connected to game or not")
@ -238,17 +239,19 @@ class PlayerDB(TypedObject):
#@property #@property
def __name_get(self): def __name_get(self):
"Getter. Allows for value = self.name" "Getter. Allows for value = self.name"
name = get_prop_cache(self, "_name") return self.username
if not name: #name = get_prop_cache(self, "_name")
name = _GA(self,"user").username #if not name:
set_prop_cache(self, "_name", name) # name = _GA(self,"user").username
return name # set_prop_cache(self, "_name", name)
#return name
#@name.setter #@name.setter
def __name_set(self, value): def __name_set(self, value):
"Setter. Allows for player.name = newname" "Setter. Allows for player.name = newname"
_GA(self, "user").username = value self.username = value
_GA(self, "user").save() #_GA(self, "user").username = value
set_prop_cache(self, "_name", value) #_GA(self, "user").save()
#set_prop_cache(self, "_name", value)
#@name.deleter #@name.deleter
def __name_del(self): def __name_del(self):
"Deleter. Allows for del self.name" "Deleter. Allows for del self.name"
@ -259,11 +262,12 @@ class PlayerDB(TypedObject):
#@property #@property
def __uid_get(self): def __uid_get(self):
"Getter. Retrieves the user id" "Getter. Retrieves the user id"
uid = get_prop_cache(self, "_uid") return self.id
if not uid: #uid = get_prop_cache(self, "_uid")
uid = _GA(self, "user").id #if not uid:
set_prop_cache(self, "_uid", uid) # uid = _GA(self, "user").id
return uid # set_prop_cache(self, "_uid", uid)
#return uid
def __uid_set(self, value): def __uid_set(self, value):
raise Exception("User id cannot be set!") raise Exception("User id cannot be set!")
def __uid_del(self): def __uid_del(self):
@ -271,14 +275,15 @@ class PlayerDB(TypedObject):
uid = property(__uid_get, __uid_set, __uid_del) uid = property(__uid_get, __uid_set, __uid_del)
#@property #@property
def __is_superuser_get(self): #def __is_superuser_get(self):
"Superusers have all permissions." # "Superusers have all permissions."
is_suser = get_prop_cache(self, "_is_superuser") # return self.db_is_superuser
if is_suser == None: # #is_suser = get_prop_cache(self, "_is_superuser")
is_suser = _GA(self, "user").is_superuser # #if is_suser == None:
set_prop_cache(self, "_is_superuser", is_suser) # # is_suser = _GA(self, "user").is_superuser
return is_suser # # set_prop_cache(self, "_is_superuser", is_suser)
is_superuser = property(__is_superuser_get) # #return is_suser
#is_superuser = property(__is_superuser_get)
# #
# PlayerDB class access methods # PlayerDB class access methods
@ -405,7 +410,7 @@ class PlayerDB(TypedObject):
# with a lingering player/sessid reference from an unclean server kill or similar # with a lingering player/sessid reference from an unclean server kill or similar
if normal_mode: if normal_mode:
_GA(obj.typeclass, "at_pre_puppet")(self.typeclass) _GA(obj.typeclass, "at_pre_puppet")(self.typeclass, sessid=sessid)
# do the connection # do the connection
obj.sessid = sessid obj.sessid = sessid
obj.player = self obj.player = self
@ -437,7 +442,7 @@ class PlayerDB(TypedObject):
del obj.dbobj.player del obj.dbobj.player
session.puppet = None session.puppet = None
session.puid = None session.puid = None
_GA(obj.typeclass, "at_post_unpuppet")(self) _GA(obj.typeclass, "at_post_unpuppet")(self.typeclass, sessid=sessid)
return True return True
def unpuppet_all(self): def unpuppet_all(self):
@ -500,16 +505,12 @@ class PlayerDB(TypedObject):
self.unpuppet_object(session.sessid) self.unpuppet_object(session.sessid)
session.sessionhandler.disconnect(session, reason=_("Player being deleted.")) session.sessionhandler.disconnect(session, reason=_("Player being deleted."))
try: #try:
if _GA(self, "user"): # if _GA(self, "user"):
_GA(_GA(self, "user"), "delete")() # _GA(_GA(self, "user"), "delete")()
except AssertionError: #except AssertionError:
pass # pass
try:
super(PlayerDB, self).delete(*args, **kwargs) super(PlayerDB, self).delete(*args, **kwargs)
except AssertionError:
# this means deleting the user already cleared out the Player object.
pass
def execute_cmd(self, raw_string, sessid=None): def execute_cmd(self, raw_string, sessid=None):
""" """
@ -557,3 +558,6 @@ class PlayerDB(TypedObject):
except: except:
pass pass
return matches return matches
class PlayerDBtmp(AbstractUser):
pass

View file

@ -2,6 +2,7 @@
The custom manager for Scripts. The custom manager for Scripts.
""" """
from django.db.models import Q
from src.typeclasses.managers import TypedObjectManager from src.typeclasses.managers import TypedObjectManager
from src.typeclasses.managers import returns_typeclass_list from src.typeclasses.managers import returns_typeclass_list
from src.utils.utils import make_iter from src.utils.utils import make_iter
@ -194,39 +195,24 @@ class ScriptManager(TypedObjectManager):
if dbref or dbref == 0: if dbref or dbref == 0:
# this is a dbref, try to find the script directly # this is a dbref, try to find the script directly
dbref_match = self.dbref_search(dbref) dbref_match = self.dbref_search(dbref)
if dbref_match: if dbref_match and not ((obj and obj != dbref_match.obj)
ok = True or (only_timed and dbref_match.interval)):
if obj and obj != dbref_match.obj:
ok = False
if only_timed and dbref_match.interval:
ok = False
if ok:
return [dbref_match] return [dbref_match]
if obj:
# convenience check to make sure obj is really a dbobj
obj = hasattr(obj, "dbobj") and obj.dbobj or obj
# not a dbref; normal search # not a dbref; normal search
scripts = self.filter(db_key__iexact=ostring) obj_restriction = obj and Q(db_obj=obj.dbobj) or Q()
timed_restriction = only_timed and Q(interval__gt=0) or Q()
if obj: scripts = self.filter(timed_restriction & obj_restriction & Q(db_key__iexact=ostring))
scripts = scripts.exclude(db_obj=None).filter(db_obj__db_key__iexact=ostring)
if only_timed:
scripts = scripts.exclude(interval=0)
return scripts return scripts
def copy_script(self, original_script, new_key=None, new_obj=None, new_locks=None): def copy_script(self, original_script, new_key=None, new_obj=None, new_locks=None):
""" """
Make an identical copy of the original_script Make an identical copy of the original_script
""" """
typeclass = original_script.typeclass_path typeclass = original_script.typeclass_path
if not new_key: new_key = new_key if new_key!=None else original_script.key
new_key = original_script.key new_obj = new_obj if new_obj!=None else original_script.obj
if not new_obj: new_locks = new_locks if new_locks!=None else original_script.db_lock_storage
new_obj = original_script.obj
if not new_locks:
new_locks = original_script.db_lock_storage
from src.utils import create from src.utils import create
new_script = create.create_script(typeclass, key=new_key, obj=new_obj, locks=new_locks, autostart=True) new_script = create.create_script(typeclass, key=new_key, obj=new_obj, locks=new_locks, autostart=True)

View file

@ -7,13 +7,15 @@ Everything starts at handle_setup()
""" """
import django import django
from django.contrib.auth.models import User
from django.core import management from django.core import management
from django.conf import settings from django.conf import settings
from django.core.management import call_command
from django.contrib.auth import get_user_model
from src.server.models import ServerConfig from src.server.models import ServerConfig
from src.help.models import HelpEntry from src.help.models import HelpEntry
from src.utils import create from src.utils import create
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
def create_config_values(): def create_config_values():
@ -23,11 +25,20 @@ def create_config_values():
ServerConfig.objects.conf("site_name", settings.SERVERNAME) ServerConfig.objects.conf("site_name", settings.SERVERNAME)
ServerConfig.objects.conf("idle_timeout", settings.IDLE_TIMEOUT) ServerConfig.objects.conf("idle_timeout", settings.IDLE_TIMEOUT)
def get_god_user(): def get_god_player():
""" """
Returns the initially created 'god' User object. Creates the god user.
""" """
return User.objects.get(id=1) PlayerDB = get_user_model()
try:
god_player = PlayerDB.objects.get(id=1)
except PlayerDB.DoesNotExist:
txt = "\n\nNo superuser exists yet. The superuser is the 'owner' account on the"
txt += "\nEvennia server. Create a new superuser using the command"
txt += "\n\n python manage.py createsuperuser"
txt += "\n\nFollow the prompts, then restart the server."
raise Exception(txt)
return god_player
def create_objects(): def create_objects():
""" """
@ -38,22 +49,26 @@ def create_objects():
# Set the initial User's account object's username on the #1 object. # Set the initial User's account object's username on the #1 object.
# This object is pure django and only holds name, email and password. # This object is pure django and only holds name, email and password.
god_user = get_god_user() god_player = get_god_player()
# Create a Player 'user profile' object to hold eventual # Create a Player 'user profile' object to hold eventual
# mud-specific settings for the bog standard User object. This is # mud-specific settings for the bog standard User object. This is
# accessed by user.get_profile() and can also store attributes. # accessed by user.get_profile() and can also store attributes.
# It also holds mud permissions, but for a superuser these # It also holds mud permissions, but for a superuser these
# have no effect anyhow. # have no effect anyhow.
character_typeclass = settings.BASE_CHARACTER_TYPECLASS player_typeclass = settings.BASE_PLAYER_TYPECLASS
# Create the Player object as well as the in-game god-character # run all creation hooks on god_player (we must do so manually since the manage.py command does not)
# for user #1. We can't set location and home yet since nothing god_player.typeclass_path = player_typeclass
god_player.basetype_setup()
god_player.at_player_creation()
god_player.locks.add("examine:perm(Immortals);edit:false();delete:false();boot:false();msg:all()")
# Create the in-game god-character for player #1. We can't set location and home yet since nothing
# exists. Also, all properties (name, email, password, is_superuser) # exists. Also, all properties (name, email, password, is_superuser)
# is inherited from the user so we don't specify it again here. # is inherited from the user so we don't specify it again here.
character_typeclass = settings.BASE_CHARACTER_TYPECLASS
god_player = create.create_player(god_user.username, None, None, user=god_user) god_character = create.create_object(character_typeclass, key=god_player.username)
god_character = create.create_object(character_typeclass, key=god_user.username)
god_character.id = 1 god_character.id = 1
god_character.db.desc = _('This is User #1.') god_character.db.desc = _('This is User #1.')
@ -121,7 +136,7 @@ def create_channels():
return return
# connect the god user to all these channels by default. # connect the god user to all these channels by default.
goduser = get_god_user() goduser = get_god_player()
from src.comms.models import PlayerChannelConnection from src.comms.models import PlayerChannelConnection
PlayerChannelConnection.objects.create_connection(goduser, pchan) PlayerChannelConnection.objects.create_connection(goduser, pchan)
PlayerChannelConnection.objects.create_connection(goduser, ichan) PlayerChannelConnection.objects.create_connection(goduser, ichan)

View file

@ -77,17 +77,16 @@ class ServerSession(Session):
player - the player associated with the session player - the player associated with the session
""" """
self.player = player self.player = player
self.user = player.user self.uid = self.player.id
self.uid = self.user.id self.uname = self.player.username
self.uname = self.user.username
self.logged_in = True self.logged_in = True
self.conn_time = time.time() self.conn_time = time.time()
self.puid = None self.puid = None
self.puppet = None self.puppet = None
# Update account's last login time. # Update account's last login time.
self.user.last_login = datetime.now() self.player.last_login = datetime.now()
self.user.save() self.player.save()
def at_disconnect(self): def at_disconnect(self):
""" """
@ -97,7 +96,7 @@ class ServerSession(Session):
sessid = self.sessid sessid = self.sessid
player = self.player player = self.player
_GA(player.dbobj, "unpuppet_object")(sessid) _GA(player.dbobj, "unpuppet_object")(sessid)
uaccount = _GA(player.dbobj, "user") uaccount = player.dbobj
uaccount.last_login = datetime.now() uaccount.last_login = datetime.now()
uaccount.save() uaccount.save()
# calling player hook # calling player hook

View file

@ -134,7 +134,6 @@ GAME_CACHE_TYPE = "local"
# memory. So every now and then Evennia checks the size of this cache and resets # memory. So every now and then Evennia checks the size of this cache and resets
# it if it's too big. This variable sets the maximum size (in MB). # it if it's too big. This variable sets the maximum size (in MB).
ATTRIBUTE_CACHE_MAXSIZE = 100 ATTRIBUTE_CACHE_MAXSIZE = 100
# OOB (Out-of-band
###################################################################### ######################################################################
# Evennia Database config # Evennia Database config
@ -487,11 +486,12 @@ INSTALLED_APPS = (
'src.comms', 'src.comms',
'src.help', 'src.help',
'src.scripts', 'src.scripts',
'src.web.news', #'src.web.news',
'src.web.website',) 'src.web.website',)
# The user profile extends the User object with more functionality; # The user profile extends the User object with more functionality;
# This should usually not be changed. # This should usually not be changed.
AUTH_PROFILE_MODULE = "players.PlayerDB" AUTH_USER_MODEL = "players.PlayerDB"
#AUTH_PROFILE_MODULE = "players.PlayerDB"
# Use a custom test runner that just tests Evennia-specific apps. # Use a custom test runner that just tests Evennia-specific apps.
TEST_RUNNER = 'src.utils.test_utils.EvenniaTestSuiteRunner' TEST_RUNNER = 'src.utils.test_utils.EvenniaTestSuiteRunner'

View file

@ -22,7 +22,6 @@ Models covered:
Players Players
""" """
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import User
from django.db import IntegrityError from django.db import IntegrityError
from src.utils.idmapper.models import SharedMemoryModel from src.utils.idmapper.models import SharedMemoryModel
from src.utils import utils, logger from src.utils import utils, logger
@ -387,49 +386,32 @@ channel = create_channel
# Player creation methods # Player creation methods
# #
def create_player(name, email, password, def create_player(key, email, password,
user=None,
typeclass=None, typeclass=None,
is_superuser=False, is_superuser=False,
locks=None, permissions=None, locks=None, permissions=None,
player_dbobj=None, report_to=None): report_to=None):
""" """
This creates a new player, handling the creation of the User This creates a new player.
object and its associated Player object.
If player_dbobj is given, this player object is used instead of key - the player's name. This should be unique.
creating a new one. This is called by the admin interface since it email - email on valid addr@addr.domain form.
needs to create the player object in order to relate it automatically password - password in cleartext
to the user. is_superuser - wether or not this player is to be a superuser
locks - lockstring
permission - list of permissions
report_to - an object with a msg() method to report errors to. If
not given, errors will be logged.
If create_character is Will return the Player-typeclass or None/raise Exception if the
True, a game player object with the same name as the User/Player will Typeclass given failed to load.
also be created. Its typeclass and base properties can also be given.
Returns the new game character, or the Player obj if no
character is created. For more info about the typeclass argument,
see create_objects() above.
Note: if user is supplied, it will NOT be modified (args name, email,
passw and is_superuser will be ignored). Change those properties
directly on the User instead.
If no permissions are given (None), the default permission group
as defined in settings.PERMISSION_PLAYER_DEFAULT will be
assigned. If permissions are given, no automatic assignment will
occur.
Concerning is_superuser: Concerning is_superuser:
A superuser should have access to everything
in the game and on the server/web interface. The very first user
created in the database is always a superuser (that's using
django's own creation, not this one).
Usually only the server admin should need to be superuser, all Usually only the server admin should need to be superuser, all
other access levels can be handled with more fine-grained other access levels can be handled with more fine-grained
permissions or groups. permissions or groups. A superuser bypasses all lock checking
Since superuser overrules all permissions, we don't operations and is thus not suitable for play-testing the game.
set any in this case.
""" """
global _PlayerDB, _Player global _PlayerDB, _Player
@ -440,45 +422,25 @@ def create_player(name, email, password,
if not email: if not email:
email = "dummy@dummy.com" email = "dummy@dummy.com"
if user: if _PlayerDB.objects.filter(username__iexact=key):
new_user = user raise ValueError("A Player with this name already exists.")
email = user.email
if user:
conflict_check = User.objects.filter(username__iexact=user.username)
conflict_check = len(conflict_check) > 1
else:
conflict_check = User.objects.filter(username__iexact=name)
if conflict_check:
raise ValueError("A user with this name already exists.")
if not user:
if is_superuser:
new_user = User.objects.create_superuser(name, email, password)
else:
new_user = User.objects.create_user(name, email, password)
try: try:
# create the correct Player object
if is_superuser:
new_db_player = _PlayerDB.objects.create_superuser(key, email, password)
else:
new_db_player = _PlayerDB.objects.create_user(key, email, password)
if not typeclass: if not typeclass:
typeclass = settings.BASE_PLAYER_TYPECLASS typeclass = settings.BASE_PLAYER_TYPECLASS
elif isinstance(typeclass, _PlayerDB): elif isinstance(typeclass, _PlayerDB):
# this is already an objectdb instance, extract its typeclass # this is an PlayerDB instance, extract its typeclass path
typeclass = typeclass.typeclass.path typeclass = typeclass.typeclass.path
elif isinstance(typeclass, _Player) or utils.inherits_from(typeclass, _Player): elif isinstance(typeclass, _Player) or utils.inherits_from(typeclass, _Player):
# this is already an object typeclass, extract its path # this is Player object typeclass, extract its path
typeclass = typeclass.path typeclass = typeclass.path
if player_dbobj:
try:
_GA(player_dbobj, "dbobj")
new_db_player = player_dbobj.dbobj
except AttributeError:
new_db_player = player_dbobj
# use the typeclass from this object
typeclass = new_db_player.typeclass_path
else:
new_user = User.objects.get(username=new_user.username)
new_db_player = _PlayerDB(db_key=name, user=new_user)
new_db_player.save()
# assign the typeclass # assign the typeclass
typeclass = utils.to_unicode(typeclass) typeclass = utils.to_unicode(typeclass)
new_db_player.typeclass_path = typeclass new_db_player.typeclass_path = typeclass
@ -500,26 +462,19 @@ def create_player(name, email, password,
# call hook method (may override default permissions) # call hook method (may override default permissions)
new_player.at_player_creation() new_player.at_player_creation()
print
# custom given arguments potentially overrides the hook # custom given arguments potentially overrides the hook
if permissions: if permissions:
new_player.permissions = permissions new_player.permissions = permissions
elif not new_player.permissions: elif not new_player.permissions:
new_player.permissions = settings.PERMISSION_PLAYER_DEFAULT new_player.permissions = settings.PERMISSION_PLAYER_DEFAULT
if locks: if locks:
new_player.locks.add(locks) new_player.locks.add(locks)
return new_player return new_player
except Exception: except Exception:
# a failure in creating the character # a failure in creating the player; we try to clean
if not user: # up as much as we can
# in there was a failure we clean up everything we can
logger.log_trace() logger.log_trace()
try:
new_user.delete()
except Exception:
pass
try: try:
new_player.delete() new_player.delete()
except Exception: except Exception:

View file

@ -16,11 +16,11 @@ the database model and call its 'objects' property.
Also remember that all commands in this file return lists (also if Also remember that all commands in this file return lists (also if
there is only one match) unless noted otherwise. there is only one match) unless noted otherwise.
Example: To reach the search method 'get_object_with_user' Example: To reach the search method 'get_object_with_player'
in src/objects/managers.py: in src/objects/managers.py:
> from src.objects.models import ObjectDB > from src.objects.models import ObjectDB
> match = Object.objects.get_object_with_user(...) > match = Object.objects.get_object_with_player(...)
""" """