Changed how the Typeclass system returns errors. Instead of echoing typeclass erros to the MUD-info channel (which is not only not only very spammy for everyone but also very hard to make clean so as to avoid recursion at a stage of typeclass failing), the system instead stores a property on itself called 'typeclass_last_errmsg' that holds eventual errors. This means that the task of reporting errors does not fall on the typeclass system itself but on the calling methods, as it should be. So src.utils.create.create_* functions now takes a new optional keyword "report_to" that holds an object to receive errors. If this keyword is given, the function msg():es that object with the error and returns None as before. If report_to is not set however, the create_* methods now return an Exception containing the error text. All default commands have been changed to accomodate for this behaviour, which allows for much more control over errors.
Also, the default ADMIN_MEDIA static files changed location in Django 1.4. The initial_setup function now accounts for this.
This commit is contained in:
parent
63329f5420
commit
8c3b49e704
15 changed files with 838 additions and 785 deletions
|
|
@ -399,9 +399,8 @@ class CmdCreate(ObjManipCommand):
|
||||||
# object typeclass will automatically be used)
|
# object typeclass will automatically be used)
|
||||||
lockstring = "control:id(%s);examine:perm(Builders);delete:id(%s) or perm(Wizards);get:all()" % (caller.id, caller.id)
|
lockstring = "control:id(%s);examine:perm(Builders);delete:id(%s) or perm(Wizards);get:all()" % (caller.id, caller.id)
|
||||||
obj = create.create_object(typeclass, name, caller,
|
obj = create.create_object(typeclass, name, caller,
|
||||||
home=caller, aliases=aliases, locks=lockstring)
|
home=caller, aliases=aliases, locks=lockstring, report_to=caller)
|
||||||
if not obj:
|
if not obj:
|
||||||
string = "Error when creating object."
|
|
||||||
continue
|
continue
|
||||||
if aliases:
|
if aliases:
|
||||||
string = "You create a new %s: %s (aliases: %s)."
|
string = "You create a new %s: %s (aliases: %s)."
|
||||||
|
|
@ -416,8 +415,8 @@ class CmdCreate(ObjManipCommand):
|
||||||
if caller.location:
|
if caller.location:
|
||||||
obj.home = caller.location
|
obj.home = caller.location
|
||||||
obj.move_to(caller.location, quiet=True)
|
obj.move_to(caller.location, quiet=True)
|
||||||
if string:
|
if string:
|
||||||
caller.msg(string)
|
caller.msg(string)
|
||||||
|
|
||||||
|
|
||||||
class CmdDebug(MuxCommand):
|
class CmdDebug(MuxCommand):
|
||||||
|
|
@ -630,7 +629,7 @@ class CmdDig(ObjManipCommand):
|
||||||
lockstring = lockstring % (caller.dbref, caller.dbref, caller.dbref)
|
lockstring = lockstring % (caller.dbref, caller.dbref, caller.dbref)
|
||||||
|
|
||||||
new_room = create.create_object(typeclass, room["name"],
|
new_room = create.create_object(typeclass, room["name"],
|
||||||
aliases=room["aliases"])
|
aliases=room["aliases"], report_to=caller)
|
||||||
new_room.locks.add(lockstring)
|
new_room.locks.add(lockstring)
|
||||||
alias_string = ""
|
alias_string = ""
|
||||||
if new_room.aliases:
|
if new_room.aliases:
|
||||||
|
|
@ -659,7 +658,7 @@ class CmdDig(ObjManipCommand):
|
||||||
|
|
||||||
new_to_exit = create.create_object(typeclass, to_exit["name"], location,
|
new_to_exit = create.create_object(typeclass, to_exit["name"], location,
|
||||||
aliases=to_exit["aliases"],
|
aliases=to_exit["aliases"],
|
||||||
locks=lockstring, destination=new_room)
|
locks=lockstring, destination=new_room, report_to=caller)
|
||||||
alias_string = ""
|
alias_string = ""
|
||||||
if new_to_exit.aliases:
|
if new_to_exit.aliases:
|
||||||
alias_string = " (%s)" % ", ".join(new_to_exit.aliases)
|
alias_string = " (%s)" % ", ".join(new_to_exit.aliases)
|
||||||
|
|
@ -684,7 +683,7 @@ class CmdDig(ObjManipCommand):
|
||||||
typeclass = settings.BASE_EXIT_TYPECLASS
|
typeclass = settings.BASE_EXIT_TYPECLASS
|
||||||
new_back_exit = create.create_object(typeclass, back_exit["name"],
|
new_back_exit = create.create_object(typeclass, back_exit["name"],
|
||||||
new_room, aliases=back_exit["aliases"],
|
new_room, aliases=back_exit["aliases"],
|
||||||
locks=lockstring, destination=location)
|
locks=lockstring, destination=location, report_to=caller)
|
||||||
alias_string = ""
|
alias_string = ""
|
||||||
if new_back_exit.aliases:
|
if new_back_exit.aliases:
|
||||||
alias_string = " (%s)" % ", ".join(new_back_exit.aliases)
|
alias_string = " (%s)" % ", ".join(new_back_exit.aliases)
|
||||||
|
|
@ -1083,7 +1082,7 @@ class CmdOpen(ObjManipCommand):
|
||||||
typeclass = settings.BASE_EXIT_TYPECLASS
|
typeclass = settings.BASE_EXIT_TYPECLASS
|
||||||
exit_obj = create.create_object(typeclass, key=exit_name,
|
exit_obj = create.create_object(typeclass, key=exit_name,
|
||||||
location=location,
|
location=location,
|
||||||
aliases=exit_aliases)
|
aliases=exit_aliases, report_to=caller)
|
||||||
if exit_obj:
|
if exit_obj:
|
||||||
# storing a destination is what makes it an exit!
|
# storing a destination is what makes it an exit!
|
||||||
exit_obj.destination = destination
|
exit_obj.destination = destination
|
||||||
|
|
@ -1283,9 +1282,9 @@ class CmdTypeclass(MuxCommand):
|
||||||
@typeclass - set object typeclass
|
@typeclass - set object typeclass
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
@typclass[/switch] <object> [= <typeclass path>]
|
@typclass[/switch] <object> [= <typeclass.path>]
|
||||||
@type ''
|
@type ''
|
||||||
@parent ''
|
@parent ''
|
||||||
|
|
||||||
Switch:
|
Switch:
|
||||||
reset - clean out *all* the attributes on the object -
|
reset - clean out *all* the attributes on the object -
|
||||||
|
|
@ -1295,12 +1294,18 @@ class CmdTypeclass(MuxCommand):
|
||||||
Example:
|
Example:
|
||||||
@type button = examples.red_button.RedButton
|
@type button = examples.red_button.RedButton
|
||||||
|
|
||||||
Sets an object's typeclass. The typeclass must be identified
|
View or set an object's typeclass. If setting, the creation hooks
|
||||||
by its location using python dot-notation pointing to the correct
|
of the new typeclass will be run on the object. If you have
|
||||||
module and class. If no typeclass is given (or a wrong typeclass
|
clashing properties on the old class, use /reset. By default you
|
||||||
is given), the object will be set to the default typeclass.
|
are protected from changing to a typeclass of the same name as the
|
||||||
The location of the typeclass module is searched from
|
one you already have, use /force to override this protection.
|
||||||
the default typeclass directory, as defined in the server settings.
|
|
||||||
|
The given typeclass must be identified by its location using
|
||||||
|
python dot-notation pointing to the correct module and class. If
|
||||||
|
no typeclass is given (or a wrong typeclass is given). Errors in
|
||||||
|
the path or new typeclass will lead to the old typeclass being
|
||||||
|
kept. The location of the typeclass module is searched from the
|
||||||
|
default typeclass directory, as defined in the server settings.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
@ -1327,7 +1332,7 @@ class CmdTypeclass(MuxCommand):
|
||||||
# we did not supply a new typeclass, view the
|
# we did not supply a new typeclass, view the
|
||||||
# current one instead.
|
# current one instead.
|
||||||
if hasattr(obj, "typeclass"):
|
if hasattr(obj, "typeclass"):
|
||||||
string = "%s's current typeclass is '%s'." % (obj.name, obj.typeclass.typename)
|
string = "%s's current typeclass is '%s' (%s)." % (obj.name, obj.typeclass.typename, obj.typeclass.path)
|
||||||
else:
|
else:
|
||||||
string = "%s is not a typed object." % obj.name
|
string = "%s is not a typed object." % obj.name
|
||||||
caller.msg(string)
|
caller.msg(string)
|
||||||
|
|
@ -1344,25 +1349,31 @@ class CmdTypeclass(MuxCommand):
|
||||||
caller.msg("This object cannot have a type at all!")
|
caller.msg("This object cannot have a type at all!")
|
||||||
return
|
return
|
||||||
|
|
||||||
if obj.is_typeclass(typeclass) and not 'force' in self.switches:
|
is_same = obj.is_typeclass(typeclass)
|
||||||
string = "%s already has the typeclass '%s'." % (obj.name, typeclass)
|
if is_same and not 'force' in self.switches:
|
||||||
|
string = "%s already has the typeclass '%s'. Use /force to override." % (obj.name, typeclass)
|
||||||
else:
|
else:
|
||||||
reset = "reset" in self.switches
|
reset = "reset" in self.switches
|
||||||
old_typeclass_name = obj.typeclass.typename
|
old_typeclass_path = obj.typeclass.path
|
||||||
ok = obj.swap_typeclass(typeclass, clean_attributes=reset)
|
ok = obj.swap_typeclass(typeclass, clean_attributes=reset)
|
||||||
if ok:
|
if ok:
|
||||||
string = "%s's type is now %s (instead of %s).\n" % (obj.name,
|
if is_same:
|
||||||
obj.typeclass.typename,
|
string = "%s updated its existing typeclass (%s).\n" % (obj.name, obj.typeclass.path)
|
||||||
old_typeclass_name)
|
|
||||||
if reset:
|
|
||||||
string += "All attributes where reset."
|
|
||||||
else:
|
else:
|
||||||
string += "Note that the new class type could have overwritten "
|
string = "%s's changed typeclass from %s to %s.\n" % (obj.name,
|
||||||
string += "same-named attributes on the existing object."
|
old_typeclass_path,
|
||||||
|
obj.typeclass.path)
|
||||||
|
string += "Creation hooks were run."
|
||||||
|
if reset:
|
||||||
|
string += " All old attributes where deleted before the swap."
|
||||||
|
else:
|
||||||
|
string += " Note that the typeclassed object could have ended up with a mixture of old"
|
||||||
|
string += "\nand new attributes. Use /reset to remove old attributes if you don't want this."
|
||||||
else:
|
else:
|
||||||
string = "Could not swap '%s' (%s) to typeclass '%s'." % (obj.name,
|
string = obj.typeclass_last_errmsg
|
||||||
old_typeclass_name,
|
string += "\nCould not swap '%s' (%s) to typeclass '%s'." % (obj.name,
|
||||||
typeclass)
|
old_typeclass_path,
|
||||||
|
typeclass)
|
||||||
|
|
||||||
caller.msg(string)
|
caller.msg(string)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -588,7 +588,7 @@ class CmdAccess(MuxCommand):
|
||||||
caller = self.caller
|
caller = self.caller
|
||||||
hierarchy_full = settings.PERMISSION_HIERARCHY
|
hierarchy_full = settings.PERMISSION_HIERARCHY
|
||||||
string = "\n{wPermission Hierarchy{n (climbing):\n %s" % ", ".join(hierarchy_full)
|
string = "\n{wPermission Hierarchy{n (climbing):\n %s" % ", ".join(hierarchy_full)
|
||||||
hierarchy = [p.lower() for p in hierarchy_full]
|
#hierarchy = [p.lower() for p in hierarchy_full]
|
||||||
|
|
||||||
if self.caller.player.is_superuser:
|
if self.caller.player.is_superuser:
|
||||||
cperms = "<Superuser>"
|
cperms = "<Superuser>"
|
||||||
|
|
|
||||||
|
|
@ -8,14 +8,12 @@ import traceback
|
||||||
import os, datetime, time
|
import os, datetime, time
|
||||||
import django, twisted
|
import django, twisted
|
||||||
|
|
||||||
from django.contrib.auth.models import User
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from src.server.sessionhandler import SESSIONS
|
from src.server.sessionhandler import SESSIONS
|
||||||
from src.scripts.models import ScriptDB
|
from src.scripts.models import ScriptDB
|
||||||
from src.objects.models import ObjectDB
|
from src.objects.models import ObjectDB
|
||||||
from src.players.models import PlayerDB
|
from src.players.models import PlayerDB
|
||||||
from src.server.models import ServerConfig
|
from src.utils import logger, utils, gametime
|
||||||
from src.utils import create, logger, utils, gametime
|
|
||||||
from src.commands.default.muxcommand import MuxCommand
|
from src.commands.default.muxcommand import MuxCommand
|
||||||
|
|
||||||
# limit symbol import for API
|
# limit symbol import for API
|
||||||
|
|
|
||||||
|
|
@ -182,13 +182,14 @@ its and @/./+/-/_ only.") # this echoes the restrictions made by django's auth m
|
||||||
typeclass = settings.BASE_CHARACTER_TYPECLASS
|
typeclass = settings.BASE_CHARACTER_TYPECLASS
|
||||||
permissions = settings.PERMISSION_PLAYER_DEFAULT
|
permissions = settings.PERMISSION_PLAYER_DEFAULT
|
||||||
|
|
||||||
new_character = create.create_player(playername, email, password,
|
try:
|
||||||
permissions=permissions,
|
new_character = create.create_player(playername, email, password,
|
||||||
character_typeclass=typeclass,
|
permissions=permissions,
|
||||||
character_location=default_home,
|
character_typeclass=typeclass,
|
||||||
character_home=default_home)
|
character_location=default_home,
|
||||||
if not new_character:
|
character_home=default_home)
|
||||||
session.msg("There was an error creating the default Character/Player. This error was logged. Contact an admin.")
|
except Exception, e:
|
||||||
|
session.msg("There was an error creating the default Character/Player:\n%s\n If this problem persists, contact an admin.")
|
||||||
return
|
return
|
||||||
new_player = new_character.player
|
new_player = new_character.player
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -323,7 +323,7 @@ class Object(TypeClass):
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.dbobj.swap_typeclass(new_typeclass, clean_attributes=clean_attributes, no_default=no_default)
|
return self.dbobj.swap_typeclass(new_typeclass, clean_attributes=clean_attributes, no_default=no_default)
|
||||||
|
|
||||||
def access(self, accessing_obj, access_type='read', default=False):
|
def access(self, accessing_obj, access_type='read', default=False):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -58,9 +58,6 @@ def create_objects():
|
||||||
create_character=True,
|
create_character=True,
|
||||||
character_typeclass=character_typeclass)
|
character_typeclass=character_typeclass)
|
||||||
|
|
||||||
if not god_character:
|
|
||||||
raise Exception(_("#1 could not be created. Check the Player/Character typeclass for bugs."))
|
|
||||||
|
|
||||||
god_character.id = 1
|
god_character.id = 1
|
||||||
god_character.db.desc = _('This is User #1.')
|
god_character.db.desc = _('This is User #1.')
|
||||||
god_character.locks.add("examine:perm(Immortals);edit:false();delete:false();boot:false();msg:all();puppet:false()")
|
god_character.locks.add("examine:perm(Immortals);edit:false();delete:false();boot:false();msg:all();puppet:false()")
|
||||||
|
|
@ -164,7 +161,11 @@ def create_admin_media_links():
|
||||||
on system.
|
on system.
|
||||||
"""
|
"""
|
||||||
import django, os
|
import django, os
|
||||||
dpath = os.path.join(django.__path__[0], 'contrib', 'admin', 'media')
|
|
||||||
|
if django.get_version() < 1.4:
|
||||||
|
dpath = os.path.join(django.__path__[0], 'contrib', 'admin', 'media')
|
||||||
|
else:
|
||||||
|
dpath = os.path.join(django.__path__[0], 'contrib', 'admin', 'static', 'admin')
|
||||||
apath = os.path.join(settings.ADMIN_MEDIA_ROOT)
|
apath = os.path.join(settings.ADMIN_MEDIA_ROOT)
|
||||||
if os.path.isdir(apath):
|
if os.path.isdir(apath):
|
||||||
print _(" ADMIN_MEDIA_ROOT already exists. Ignored.")
|
print _(" ADMIN_MEDIA_ROOT already exists. Ignored.")
|
||||||
|
|
@ -177,8 +178,8 @@ def create_admin_media_links():
|
||||||
try:
|
try:
|
||||||
os.symlink(dpath, apath)
|
os.symlink(dpath, apath)
|
||||||
print _(" Admin-media symlinked to ADMIN_MEDIA_ROOT.")
|
print _(" Admin-media symlinked to ADMIN_MEDIA_ROOT.")
|
||||||
except OSError:
|
except OSError, e:
|
||||||
print _(" There was an error symlinking Admin-media to ADMIN_MEDIA_ROOT. If you see issues, link manually.")
|
print _(" There was an error symlinking Admin-media to ADMIN_MEDIA_ROOT:\n %s\n -> \n %s\n (%s)\n If you see issues, link manually." % (dpath, apath, e))
|
||||||
else:
|
else:
|
||||||
print _(" Admin-media files should be copied manually to ADMIN_MEDIA_ROOT.")
|
print _(" Admin-media files should be copied manually to ADMIN_MEDIA_ROOT.")
|
||||||
|
|
||||||
|
|
@ -194,7 +195,7 @@ def at_initial_setup():
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
mod = __import__(modname, fromlist=[None])
|
mod = __import__(modname, fromlist=[None])
|
||||||
except ImportError, ValueError:
|
except (ImportError, ValueError):
|
||||||
return
|
return
|
||||||
print _(" Running at_initial_setup() hook.")
|
print _(" Running at_initial_setup() hook.")
|
||||||
if mod.__dict__.get("at_initial_setup", None):
|
if mod.__dict__.get("at_initial_setup", None):
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ etc.
|
||||||
"""
|
"""
|
||||||
import re
|
import re
|
||||||
from src.utils.utils import make_iter
|
from src.utils.utils import make_iter
|
||||||
|
from src.utils import logger
|
||||||
|
|
||||||
# variables
|
# variables
|
||||||
MSDP = chr(69)
|
MSDP = chr(69)
|
||||||
|
|
@ -24,7 +25,7 @@ MSDP_ARRAY_CLOSE = chr(6)
|
||||||
|
|
||||||
regex_array = re.compile(r"%s(.*?)%s%s(.*?)%s" % (MSDP_VAR, MSDP_VAL, MSDP_ARRAY_OPEN, MSDP_ARRAY_CLOSE)) # return 2-tuple
|
regex_array = re.compile(r"%s(.*?)%s%s(.*?)%s" % (MSDP_VAR, MSDP_VAL, MSDP_ARRAY_OPEN, MSDP_ARRAY_CLOSE)) # return 2-tuple
|
||||||
regex_table = re.compile(r"%s(.*?)%s%s(.*?)%s" % (MSDP_VAR, MSDP_VAL, MSDP_TABLE_OPEN, MSDP_TABLE_CLOSE)) # return 2-tuple (may be nested)
|
regex_table = re.compile(r"%s(.*?)%s%s(.*?)%s" % (MSDP_VAR, MSDP_VAL, MSDP_TABLE_OPEN, MSDP_TABLE_CLOSE)) # return 2-tuple (may be nested)
|
||||||
regex_varval = re.compile(r"%s(.*?)%s(.*?)[%s]" % (MSDP_VAR, MSDP_VAL, ENDING)) # return 2-tuple
|
regex_varval = re.compile(r"%s(.*?)%s(.*?)" % (MSDP_VAR, MSDP_VAL)) # return 2-tuple
|
||||||
|
|
||||||
class Msdp(object):
|
class Msdp(object):
|
||||||
"""
|
"""
|
||||||
|
|
@ -111,8 +112,8 @@ class Msdp(object):
|
||||||
tables[table[0]] = dict(regex_varval(table[1]))
|
tables[table[0]] = dict(regex_varval(table[1]))
|
||||||
for array in regex_array.findall(data):
|
for array in regex_array.findall(data):
|
||||||
arrays[array[0]] = dict(regex_varval(array[1]))
|
arrays[array[0]] = dict(regex_varval(array[1]))
|
||||||
variables = dict(regex._varval(regex_array.sub("", regex_table.sub("", data))))
|
variables = dict(regex_varval(regex_array.sub("", regex_table.sub("", data))))
|
||||||
|
print variables
|
||||||
|
|
||||||
|
|
||||||
# MSDP Commands
|
# MSDP Commands
|
||||||
|
|
@ -125,7 +126,7 @@ class Msdp(object):
|
||||||
The List command allows for retrieving various info about the server/client
|
The List command allows for retrieving various info about the server/client
|
||||||
"""
|
"""
|
||||||
if arg == 'COMMANDS':
|
if arg == 'COMMANDS':
|
||||||
return self.func_to_msdp(arg, MSDP_COMMANDS.keys())
|
return self.func_to_msdp(arg, self.MSDP_COMMANDS.keys())
|
||||||
elif arg == 'LISTS':
|
elif arg == 'LISTS':
|
||||||
return self.func_to_msdp(arg, ("COMMANDS", "LISTS",
|
return self.func_to_msdp(arg, ("COMMANDS", "LISTS",
|
||||||
"CONFIGURABLE_VARIABLES",
|
"CONFIGURABLE_VARIABLES",
|
||||||
|
|
@ -133,11 +134,11 @@ class Msdp(object):
|
||||||
elif arg == 'CONFIGURABLE_VARIABLES':
|
elif arg == 'CONFIGURABLE_VARIABLES':
|
||||||
return self.func_to_msdp(arg, ("CLIENT_NAME", "CLIENT_VERSION", "PLUGIN_ID"))
|
return self.func_to_msdp(arg, ("CLIENT_NAME", "CLIENT_VERSION", "PLUGIN_ID"))
|
||||||
elif arg == 'REPORTABLE_VARIABLES':
|
elif arg == 'REPORTABLE_VARIABLES':
|
||||||
return self.func_to_msdp(arg, MSDP_REPORTABLE.keys())
|
return self.func_to_msdp(arg, self.MSDP_REPORTABLE.keys())
|
||||||
elif arg == 'REPORTED_VARIABLES':
|
elif arg == 'REPORTED_VARIABLES':
|
||||||
return self.func_to_msdp(arg, MSDP_REPORTED.keys())
|
return self.func_to_msdp(arg, self.MSDP_REPORTED.keys())
|
||||||
elif arg == 'SENDABLE_VARIABLES':
|
elif arg == 'SENDABLE_VARIABLES':
|
||||||
return self.func_to_msdp(arg, MSDP_SEND.keys())
|
return self.func_to_msdp(arg, self.MSDP_SEND.keys())
|
||||||
else:
|
else:
|
||||||
return self.func_to_msdp("LIST", arg)
|
return self.func_to_msdp("LIST", arg)
|
||||||
|
|
||||||
|
|
@ -147,7 +148,7 @@ class Msdp(object):
|
||||||
reportable variable to the client.
|
reportable variable to the client.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
MSDP_REPORTABLE[arg](report=True)
|
self.MSDP_REPORTABLE[arg](report=True)
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.log_trace()
|
logger.log_trace()
|
||||||
|
|
||||||
|
|
@ -156,16 +157,16 @@ class Msdp(object):
|
||||||
Unreport a previously reported variable
|
Unreport a previously reported variable
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
MSDP_REPORTABLE[arg](eport=False)
|
self.MSDP_REPORTABLE[arg](eport=False)
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.log_trace()
|
self.logger.log_trace()
|
||||||
|
|
||||||
def msdp_cmd_reset(self, arg):
|
def msdp_cmd_reset(self, arg):
|
||||||
"""
|
"""
|
||||||
The reset command resets a variable to its initial state.
|
The reset command resets a variable to its initial state.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
MSDP_REPORTABLE[arg](reset=True)
|
self.MSDP_REPORTABLE[arg](reset=True)
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.log_trace()
|
logger.log_trace()
|
||||||
|
|
||||||
|
|
@ -177,21 +178,22 @@ class Msdp(object):
|
||||||
arg - this is a list of variables the client wants.
|
arg - this is a list of variables the client wants.
|
||||||
"""
|
"""
|
||||||
ret = []
|
ret = []
|
||||||
for var in makeiter(arg):
|
for var in make_iter(arg):
|
||||||
try:
|
try:
|
||||||
ret.append(MSDP_REPORTABLE[arg](send=True))
|
ret.append(self.MSDP_REPORTABLE[arg](send=True))
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.log_trace()
|
logger.log_trace()
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
MSDP_COMMANDS = {
|
MSDP_COMMANDS = {
|
||||||
"LIST": self.msdp_list,
|
"LIST": "msdp_list",
|
||||||
"REPORT":"mspd_report",
|
"REPORT":"mspd_report",
|
||||||
"RESET":"mspd_reset",
|
"RESET":"mspd_reset",
|
||||||
"SEND":"mspd_send",
|
"SEND":"mspd_send",
|
||||||
"UNREPORT":"mspd_unreport"
|
"UNREPORT":"mspd_unreport"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# MSDP_MAP is a standard suggestions for making it easy to create generic guis.
|
# MSDP_MAP is a standard suggestions for making it easy to create generic guis.
|
||||||
# this maps MSDP command names to Evennia commands found in OOB_FUNC_MODULE. It
|
# this maps MSDP command names to Evennia commands found in OOB_FUNC_MODULE. It
|
||||||
# is up to these commands to return data on proper form.
|
# is up to these commands to return data on proper form.
|
||||||
|
|
|
||||||
|
|
@ -244,6 +244,7 @@ class ServerSession(Session):
|
||||||
else:
|
else:
|
||||||
logger.log_errmsg("oob_data_in error: funcname '%s' not found in OOB_FUNC_MODULE." % funcname)
|
logger.log_errmsg("oob_data_in error: funcname '%s' not found in OOB_FUNC_MODULE." % funcname)
|
||||||
if outdata:
|
if outdata:
|
||||||
|
# we have a result, send it back
|
||||||
self.oob_data_out(outdata)
|
self.oob_data_out(outdata)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -951,6 +951,7 @@ class TypedObject(SharedMemoryModel):
|
||||||
# If we reach this point we couldn't import any typeclasses. Return default. It's up to the calling
|
# If we reach this point we couldn't import any typeclasses. Return default. It's up to the calling
|
||||||
# method to use e.g. self.is_typeclass() to detect that the result is not the one asked for.
|
# method to use e.g. self.is_typeclass() to detect that the result is not the one asked for.
|
||||||
_GA(self, "_display_errmsg")(errstring)
|
_GA(self, "_display_errmsg")(errstring)
|
||||||
|
_SA(self, "typeclass_lasterrmsg", errstring)
|
||||||
return _GA(self, "_get_default_typeclass")(cache=False, silent=False, save=False)
|
return _GA(self, "_get_default_typeclass")(cache=False, silent=False, save=False)
|
||||||
|
|
||||||
#@typeclass.deleter
|
#@typeclass.deleter
|
||||||
|
|
@ -961,6 +962,11 @@ class TypedObject(SharedMemoryModel):
|
||||||
# typeclass property
|
# typeclass property
|
||||||
typeclass = property(__typeclass_get, fdel=__typeclass_del)
|
typeclass = property(__typeclass_get, fdel=__typeclass_del)
|
||||||
|
|
||||||
|
# the last error string will be stored here for accessing methods to access.
|
||||||
|
# It is set by _display_errmsg, which will print to log if error happens
|
||||||
|
# during server startup.
|
||||||
|
typeclass_last_errmsg = ""
|
||||||
|
|
||||||
def _path_import(self, path):
|
def _path_import(self, path):
|
||||||
"""
|
"""
|
||||||
Import a class from a python path of the
|
Import a class from a python path of the
|
||||||
|
|
@ -973,17 +979,19 @@ class TypedObject(SharedMemoryModel):
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
modpath, class_name = path.rsplit('.', 1)
|
modpath, class_name = path.rsplit('.', 1)
|
||||||
module = __import__(modpath, fromlist=[class_name])
|
module = __import__(modpath, fromlist=["none"])
|
||||||
return module.__dict__[class_name]
|
return module.__dict__[class_name]
|
||||||
except ImportError:
|
except ImportError:
|
||||||
trc = sys.exc_traceback
|
trc = sys.exc_traceback
|
||||||
if not trc.tb_next:
|
if not trc.tb_next:
|
||||||
# we separate between not finding the module, and finding a buggy one.
|
# we separate between not finding the module, and finding a buggy one.
|
||||||
errstring += "(Tried path '%s')." % path
|
errstring = "Typeclass not found trying path '%s'." % path
|
||||||
else:
|
else:
|
||||||
# a bug in the module is reported normally.
|
# a bug in the module is reported normally.
|
||||||
trc = traceback.format_exc()
|
trc = traceback.format_exc()
|
||||||
errstring += "\n%sError importing '%s'." % (trc, path)
|
errstring = "\n%sError importing '%s'." % (trc, path)
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
errstring = "Malformed typeclass path '%s'." % path
|
||||||
except KeyError:
|
except KeyError:
|
||||||
errstring = "No class '%s' was found in module '%s'."
|
errstring = "No class '%s' was found in module '%s'."
|
||||||
errstring = errstring % (class_name, modpath)
|
errstring = errstring % (class_name, modpath)
|
||||||
|
|
@ -997,26 +1005,32 @@ class TypedObject(SharedMemoryModel):
|
||||||
"""
|
"""
|
||||||
Helper function to display error.
|
Helper function to display error.
|
||||||
"""
|
"""
|
||||||
infochan = None
|
if ServerConfig.objects.conf("server_starting_mode"):
|
||||||
cmessage = message
|
print message.strip()
|
||||||
try:
|
else:
|
||||||
from src.comms.models import Channel
|
_SA(self, "typeclass_last_errmsg", message.strip())
|
||||||
infochan = settings.CHANNEL_MUDINFO
|
return
|
||||||
infochan = Channel.objects.get_channel(infochan[0])
|
|
||||||
if infochan:
|
#infochan = None
|
||||||
cname = infochan.key
|
#cmessage = message
|
||||||
cmessage = "\n".join(["[%s]: %s" % (cname, line) for line in message.split('\n') if line])
|
#try:
|
||||||
cmessage = cmessage.strip()
|
# from src.comms.models import Channel
|
||||||
infochan.msg(cmessage)
|
# infochan = settings.CHANNEL_MUDINFO
|
||||||
else:
|
# infochan = Channel.objects.get_channel(infochan[0])
|
||||||
# no mudinfo channel is found. Log instead.
|
# if infochan:
|
||||||
cmessage = "\n".join(["[NO MUDINFO CHANNEL]: %s" % line for line in message.split('\n')])
|
# cname = infochan.key
|
||||||
logger.log_errmsg(cmessage)
|
# cmessage = "\n".join(["[%s]: %s" % (cname, line) for line in message.split('\n') if line])
|
||||||
except Exception:
|
# cmessage = cmessage.strip()
|
||||||
if ServerConfig.objects.conf("server_starting_mode"):
|
# infochan.msg(cmessage)
|
||||||
print cmessage
|
# else:
|
||||||
else:
|
# # no mudinfo channel is found. Log instead.
|
||||||
logger.log_trace(cmessage)
|
# cmessage = "\n".join(["[NO MUDINFO CHANNEL]: %s" % line for line in message.split('\n')])
|
||||||
|
# logger.log_errmsg(cmessage)
|
||||||
|
#except Exception:
|
||||||
|
# if ServerConfig.objects.conf("server_starting_mode"):
|
||||||
|
# print cmessage
|
||||||
|
# else:
|
||||||
|
# logger.log_trace(cmessage)
|
||||||
|
|
||||||
def _get_default_typeclass(self, cache=False, silent=False, save=False):
|
def _get_default_typeclass(self, cache=False, silent=False, save=False):
|
||||||
"""
|
"""
|
||||||
|
|
@ -1064,7 +1078,9 @@ class TypedObject(SharedMemoryModel):
|
||||||
"""
|
"""
|
||||||
Returns true if this object has this type
|
Returns true if this object has this type
|
||||||
OR has a typeclass which is an subclass of
|
OR has a typeclass which is an subclass of
|
||||||
the given typeclass.
|
the given typeclass. This operates on the actually
|
||||||
|
loaded typeclass (this is important since a failing
|
||||||
|
typeclass may instead have its default currently loaded)
|
||||||
|
|
||||||
typeclass - can be a class object or the
|
typeclass - can be a class object or the
|
||||||
python path to such an object to match against.
|
python path to such an object to match against.
|
||||||
|
|
@ -1079,7 +1095,7 @@ class TypedObject(SharedMemoryModel):
|
||||||
pass
|
pass
|
||||||
typeclasses = [typeclass] + ["%s.%s" % (path, typeclass) for path in _GA(self, "_typeclass_paths")]
|
typeclasses = [typeclass] + ["%s.%s" % (path, typeclass) for path in _GA(self, "_typeclass_paths")]
|
||||||
if exact:
|
if exact:
|
||||||
current_path = _GA(self, "_cached_db_typeclass_path")
|
current_path = _GA(self.typeclass, "path") #"_GA(self, "_cached_db_typeclass_path")
|
||||||
return typeclass and any((current_path == typec for typec in typeclasses))
|
return typeclass and any((current_path == typec for typec in typeclasses))
|
||||||
else:
|
else:
|
||||||
# check parent chain
|
# check parent chain
|
||||||
|
|
@ -1158,10 +1174,9 @@ class TypedObject(SharedMemoryModel):
|
||||||
self.nattr(nattr, delete=True)
|
self.nattr(nattr, delete=True)
|
||||||
else:
|
else:
|
||||||
#print "deleting attrs ..."
|
#print "deleting attrs ..."
|
||||||
self.get_all_attributes()
|
|
||||||
for attr in self.get_all_attributes():
|
for attr in self.get_all_attributes():
|
||||||
attr.delete()
|
attr.delete()
|
||||||
for nattr in self.ndb.all():
|
for nattr in self.ndb.all:
|
||||||
del nattr
|
del nattr
|
||||||
|
|
||||||
# run hooks for this new typeclass
|
# run hooks for this new typeclass
|
||||||
|
|
@ -1328,8 +1343,9 @@ class TypedObject(SharedMemoryModel):
|
||||||
_GA(self, 'obj').set_attribute(attrname, value)
|
_GA(self, 'obj').set_attribute(attrname, value)
|
||||||
def __delattr__(self, attrname):
|
def __delattr__(self, attrname):
|
||||||
_GA(self, 'obj').del_attribute(attrname)
|
_GA(self, 'obj').del_attribute(attrname)
|
||||||
def all(self):
|
def get_all(self):
|
||||||
return _GA(self, 'obj').get_all_attributes()
|
return _GA(self, 'obj').get_all_attributes()
|
||||||
|
all = property(get_all)
|
||||||
self._db_holder = DbHolder(self)
|
self._db_holder = DbHolder(self)
|
||||||
return self._db_holder
|
return self._db_holder
|
||||||
#@db.setter
|
#@db.setter
|
||||||
|
|
@ -1386,9 +1402,10 @@ class TypedObject(SharedMemoryModel):
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
class NdbHolder(object):
|
class NdbHolder(object):
|
||||||
"Holder for storing non-persistent attributes."
|
"Holder for storing non-persistent attributes."
|
||||||
def all(self):
|
def get_all(self):
|
||||||
return [val for val in self.__dict__.keys()
|
return [val for val in self.__dict__.keys()
|
||||||
if not val.startswith['_']]
|
if not val.startswith('_')]
|
||||||
|
all = property(get_all)
|
||||||
def __getattribute__(self, key):
|
def __getattribute__(self, key):
|
||||||
# return None if no matching attribute was found.
|
# return None if no matching attribute was found.
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,7 @@ from django.conf import settings
|
||||||
from django.contrib.auth.models import User
|
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 logger, utils, idmapper
|
from src.utils import utils, logger
|
||||||
from src.utils.utils import is_iter, has_parent, inherits_from
|
|
||||||
|
|
||||||
# limit symbol import from API
|
# limit symbol import from API
|
||||||
__all__ = ("create_object", "create_script", "create_help_entry", "create_message", "create_channel", "create_player")
|
__all__ = ("create_object", "create_script", "create_help_entry", "create_message", "create_channel", "create_player")
|
||||||
|
|
@ -41,7 +40,7 @@ GA = object.__getattribute__
|
||||||
|
|
||||||
def create_object(typeclass, key=None, location=None,
|
def create_object(typeclass, key=None, location=None,
|
||||||
home=None, player=None, permissions=None, locks=None,
|
home=None, player=None, permissions=None, locks=None,
|
||||||
aliases=None, destination=None):
|
aliases=None, destination=None, report_to=None):
|
||||||
"""
|
"""
|
||||||
Create a new in-game object. Any game object is a combination
|
Create a new in-game object. Any game object is a combination
|
||||||
of a database object that stores data persistently to
|
of a database object that stores data persistently to
|
||||||
|
|
@ -52,6 +51,11 @@ def create_object(typeclass, key=None, location=None,
|
||||||
See src.objects.managers for methods to manipulate existing objects
|
See src.objects.managers for methods to manipulate existing objects
|
||||||
in the database. src.objects.objects holds the base typeclasses
|
in the database. src.objects.objects holds the base typeclasses
|
||||||
and src.objects.models hold the database model.
|
and src.objects.models hold the database model.
|
||||||
|
|
||||||
|
report_to is an optional object for reporting errors to in string form.
|
||||||
|
If report_to is not set, errors will be raised as en Exception
|
||||||
|
containing the error message. If set, this method will return
|
||||||
|
None upon errors.
|
||||||
"""
|
"""
|
||||||
# deferred import to avoid loops
|
# deferred import to avoid loops
|
||||||
from src.objects.objects import Object
|
from src.objects.objects import Object
|
||||||
|
|
@ -83,11 +87,15 @@ def create_object(typeclass, key=None, location=None,
|
||||||
# this will either load the typeclass or the default one
|
# this will either load the typeclass or the default one
|
||||||
new_object = new_db_object.typeclass
|
new_object = new_db_object.typeclass
|
||||||
|
|
||||||
|
if not GA(new_object, "is_typeclass")(typeclass, exact=True):
|
||||||
if not GA(new_db_object, "is_typeclass")(typeclass, exact=True):
|
|
||||||
# this will fail if we gave a typeclass as input and it still gave us a default
|
# this will fail if we gave a typeclass as input and it still gave us a default
|
||||||
SharedMemoryModel.delete(new_db_object)
|
SharedMemoryModel.delete(new_db_object)
|
||||||
return None
|
if report_to:
|
||||||
|
GA(report_to, "msg")("Error creating %s (%s):\n%s" % (new_db_object.key, typeclass,
|
||||||
|
GA(new_db_object, "typeclass_last_errmsg")))
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
raise Exception(GA(new_db_object, "typeclass_last_errmsg"))
|
||||||
|
|
||||||
# from now on we can use the typeclass object
|
# from now on we can use the typeclass object
|
||||||
# as if it was the database object.
|
# as if it was the database object.
|
||||||
|
|
@ -141,7 +149,7 @@ object = create_object
|
||||||
|
|
||||||
def create_script(typeclass, key=None, obj=None, locks=None,
|
def create_script(typeclass, key=None, obj=None, locks=None,
|
||||||
interval=None, start_delay=None, repeats=None,
|
interval=None, start_delay=None, repeats=None,
|
||||||
persistent=None, autostart=True):
|
persistent=None, autostart=True, report_to=None):
|
||||||
"""
|
"""
|
||||||
Create a new script. All scripts are a combination
|
Create a new script. All scripts are a combination
|
||||||
of a database object that communicates with the
|
of a database object that communicates with the
|
||||||
|
|
@ -160,6 +168,11 @@ def create_script(typeclass, key=None, obj=None, locks=None,
|
||||||
|
|
||||||
See src.scripts.manager for methods to manipulate existing
|
See src.scripts.manager for methods to manipulate existing
|
||||||
scripts in the database.
|
scripts in the database.
|
||||||
|
|
||||||
|
report_to is an obtional object to receive error messages.
|
||||||
|
If report_to is not set, an Exception with the
|
||||||
|
error will be raised. If set, this method will
|
||||||
|
return None upon errors.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# deferred import to avoid loops.
|
# deferred import to avoid loops.
|
||||||
|
|
@ -171,7 +184,7 @@ def create_script(typeclass, key=None, obj=None, locks=None,
|
||||||
typeclass = settings.BASE_SCRIPT_TYPECLASS
|
typeclass = settings.BASE_SCRIPT_TYPECLASS
|
||||||
elif isinstance(typeclass, ScriptDB):
|
elif isinstance(typeclass, ScriptDB):
|
||||||
# this is already an scriptdb instance, extract its typeclass
|
# this is already an scriptdb instance, extract its typeclass
|
||||||
typeclass = new_db_object.typeclass.path
|
typeclass = typeclass.typeclass.path
|
||||||
elif isinstance(typeclass, Script) or utils.inherits_from(typeclass, Script):
|
elif isinstance(typeclass, Script) or utils.inherits_from(typeclass, Script):
|
||||||
# this is already an object typeclass, extract its path
|
# this is already an object typeclass, extract its path
|
||||||
typeclass = typeclass.path
|
typeclass = typeclass.path
|
||||||
|
|
@ -195,9 +208,13 @@ def create_script(typeclass, key=None, obj=None, locks=None,
|
||||||
|
|
||||||
if not GA(new_db_script, "is_typeclass")(typeclass, exact=True):
|
if not GA(new_db_script, "is_typeclass")(typeclass, exact=True):
|
||||||
# this will fail if we gave a typeclass as input and it still gave us a default
|
# this will fail if we gave a typeclass as input and it still gave us a default
|
||||||
print "failure:", new_db_script, typeclass
|
|
||||||
SharedMemoryModel.delete(new_db_script)
|
SharedMemoryModel.delete(new_db_script)
|
||||||
return None
|
if report_to:
|
||||||
|
GA(report_to, "msg")("Error creating %s (%s): %s" % (new_db_script.key, typeclass,
|
||||||
|
GA(new_db_script, "typeclass_last_errmsg")))
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
raise Exception(GA(new_db_script, "typeclass_last_errmsg"))
|
||||||
|
|
||||||
if obj:
|
if obj:
|
||||||
try:
|
try:
|
||||||
|
|
@ -315,14 +332,14 @@ def create_message(senderobj, message, channels=None,
|
||||||
new_message.message = message
|
new_message.message = message
|
||||||
new_message.save()
|
new_message.save()
|
||||||
if channels:
|
if channels:
|
||||||
if not is_iter(channels):
|
if not utils.is_iter(channels):
|
||||||
channels = [channels]
|
channels = [channels]
|
||||||
new_message.channels = [channel for channel in
|
new_message.channels = [channel for channel in
|
||||||
[to_object(channel, objtype='channel')
|
[to_object(channel, objtype='channel')
|
||||||
for channel in channels] if channel]
|
for channel in channels] if channel]
|
||||||
if receivers:
|
if receivers:
|
||||||
#print "Found receiver:", receivers
|
#print "Found receiver:", receivers
|
||||||
if not is_iter(receivers):
|
if not utils.is_iter(receivers):
|
||||||
receivers = [receivers]
|
receivers = [receivers]
|
||||||
#print "to_player: %s" % to_player(receivers[0])
|
#print "to_player: %s" % to_player(receivers[0])
|
||||||
new_message.receivers = [to_player(receiver) for receiver in
|
new_message.receivers = [to_player(receiver) for receiver in
|
||||||
|
|
@ -356,7 +373,7 @@ def create_channel(key, aliases=None, desc=None,
|
||||||
new_channel = Channel()
|
new_channel = Channel()
|
||||||
new_channel.key = key
|
new_channel.key = key
|
||||||
if aliases:
|
if aliases:
|
||||||
if not is_iter(aliases):
|
if not utils.is_iter(aliases):
|
||||||
aliases = [aliases]
|
aliases = [aliases]
|
||||||
new_channel.aliases = ",".join([alias for alias in aliases])
|
new_channel.aliases = ",".join([alias for alias in aliases])
|
||||||
new_channel.desc = desc
|
new_channel.desc = desc
|
||||||
|
|
@ -384,7 +401,7 @@ def create_player(name, email, password,
|
||||||
locks=None, permissions=None,
|
locks=None, permissions=None,
|
||||||
create_character=True, character_typeclass=None,
|
create_character=True, character_typeclass=None,
|
||||||
character_location=None, character_home=None,
|
character_location=None, character_home=None,
|
||||||
player_dbobj=None):
|
player_dbobj=None, report_to=None):
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
@ -468,7 +485,12 @@ def create_player(name, email, password,
|
||||||
if not GA(new_db_player, "is_typeclass")(typeclass, exact=True):
|
if not GA(new_db_player, "is_typeclass")(typeclass, exact=True):
|
||||||
# this will fail if we gave a typeclass as input and it still gave us a default
|
# this will fail if we gave a typeclass as input and it still gave us a default
|
||||||
SharedMemoryModel.delete(new_db_player)
|
SharedMemoryModel.delete(new_db_player)
|
||||||
return None
|
if report_to:
|
||||||
|
GA(report_to, "msg")("Error creating %s (%s):\n%s" % (new_db_player.key, typeclass,
|
||||||
|
GA(new_db_player, "typeclass_last_errmsg")))
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
raise Exception(GA(new_db_player, "typeclass_last_errmsg"))
|
||||||
|
|
||||||
new_player.basetype_setup() # setup the basic locks and cmdset
|
new_player.basetype_setup() # setup the basic locks and cmdset
|
||||||
# call hook method (may override default permissions)
|
# call hook method (may override default permissions)
|
||||||
|
|
@ -492,10 +514,10 @@ def create_player(name, email, password,
|
||||||
new_character = create_object(character_typeclass, key=name,
|
new_character = create_object(character_typeclass, key=name,
|
||||||
location=None, home=character_location,
|
location=None, home=character_location,
|
||||||
permissions=permissions,
|
permissions=permissions,
|
||||||
player=new_player)
|
player=new_player, report_to=report_to)
|
||||||
return new_character
|
return new_character
|
||||||
return new_player
|
return new_player
|
||||||
except Exception,e:
|
except Exception:
|
||||||
# a failure in creating the character
|
# a failure in creating the character
|
||||||
if not user:
|
if not user:
|
||||||
# in there was a failure we clean up everything we can
|
# in there was a failure we clean up everything we can
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue