Added an error_check_python_modules function to evennia.py. This basically imports a host of critical modules and quits with tracebacks if there are problems. This catches pure python-syntax errors (i.e. cases where the source-file itself is malformed), something which is hard to properly handle in the running server (where there's also an issue as to how to best report it). Best they fail out already at an early stage.

This commit is contained in:
Griatch 2011-11-06 21:32:00 +01:00
parent e379816866
commit 703accdd60
7 changed files with 59 additions and 9 deletions

View file

@ -1,7 +1,7 @@
""" """
Menu-driven login system Menu-driven login system
Contribution 2011 - Griatch Contribution - Griatch 2011
This is an alternative login system for Evennia, using the This is an alternative login system for Evennia, using the

View file

@ -355,6 +355,10 @@ def handle_args(options, mode, service):
errmsg = _("The %s does not seem to be running.") errmsg = _("The %s does not seem to be running.")
if mode == 'start': if mode == 'start':
# launch the error checker. Best to catch the errors already here.
error_check_python_modules()
# starting one or many services # starting one or many services
if service == 'server': if service == 'server':
if inter: if inter:
@ -397,6 +401,42 @@ def handle_args(options, mode, service):
kill(SERVER_PIDFILE, SIG, _("Server stopped."), errmsg % 'Server', restart=False) kill(SERVER_PIDFILE, SIG, _("Server stopped."), errmsg % 'Server', restart=False)
return None return None
def error_check_python_modules():
"""
Import settings modules in settings. This will raise exceptions on
pure python-syntax issues which are hard to catch gracefully
with exceptions in the engine (since they are formatting errors in
the python source files themselves). Best they fail already here
before we get any further.
"""
def imp(path, split=True):
mod, fromlist = path, "None"
if split:
mod, fromlist = path.rsplit('.', 1)
__import__(mod, fromlist=[fromlist])
# core modules
imp(settings.COMMAND_PARSER)
imp(settings.SEARCH_AT_RESULT)
imp(settings.SEARCH_AT_MULTIMATCH_INPUT)
imp(settings.CONNECTION_SCREEN_MODULE, split=False)
imp(settings.AT_INITIAL_SETUP_HOOK_MODULE, split=False)
for path in settings.LOCK_FUNC_MODULES:
imp(path, split=False)
# cmdsets
from src.commands import cmdsethandler
cmdsethandler.import_cmdset(settings.CMDSET_UNLOGGEDIN, None)
cmdsethandler.import_cmdset(settings.CMDSET_DEFAULT, None)
cmdsethandler.import_cmdset(settings.CMDSET_OOC, None)
# typeclasses
imp(settings.BASE_PLAYER_TYPECLASS)
imp(settings.BASE_OBJECT_TYPECLASS)
imp(settings.BASE_CHARACTER_TYPECLASS)
imp(settings.BASE_ROOM_TYPECLASS)
imp(settings.BASE_EXIT_TYPECLASS)
imp(settings.BASE_SCRIPT_TYPECLASS)
def main(): def main():
""" """
This handles command line input. This handles command line input.
@ -438,6 +478,7 @@ def main():
Popen(cmdstr) Popen(cmdstr)
if __name__ == '__main__': if __name__ == '__main__':
from src.utils.utils import check_evennia_dependencies from src.utils.utils import check_evennia_dependencies
if check_evennia_dependencies(): if check_evennia_dependencies():
main() main()

View file

@ -24,6 +24,7 @@ from game.gamesrc.commands.basecommand import Command
from contrib import menusystem, lineeditor from contrib import menusystem, lineeditor
#from contrib import misc_commands #from contrib import misc_commands
#from contrib import character_creation
class DefaultCmdSet(cmdset_default.DefaultCmdSet): class DefaultCmdSet(cmdset_default.DefaultCmdSet):
""" """

View file

@ -243,10 +243,10 @@ class CmdSet(object):
# add all commands # add all commands
if not hasattr(cmd, 'obj'): if not hasattr(cmd, 'obj'):
cmd.obj = self.cmdsetobj cmd.obj = self.cmdsetobj
ic = [i for i, oldcmd in enumerate(self.commands) if oldcmd.match(cmd)] try:
if ic: ic = self.commands.index(cmd)
self.commands[ic[0]] = cmd # replace self.commands[ic] = cmd # replace
else: except ValueError:
self.commands.append(cmd) self.commands.append(cmd)
# extra run to make sure to avoid doublets # extra run to make sure to avoid doublets
self.commands = list(set(self.commands)) self.commands = list(set(self.commands))

View file

@ -121,7 +121,8 @@ def import_cmdset(python_path, cmdsetobj, emit_to_obj=None, no_logging=False):
logger.log_trace() logger.log_trace()
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)
#raise # have to raise, or we will not see any errors in some situations! logger.log_errmsg("Error: %s" % errstring)
raise # have to raise, or we will not see any errors in some situations!
# classes # classes
@ -246,8 +247,8 @@ class CmdSetHandler(object):
def add(self, cmdset, emit_to_obj=None, permanent=False): def add(self, cmdset, emit_to_obj=None, permanent=False):
""" """
Add a cmdset to the handler, on top of the old ones. Add a cmdset to the handler, on top of the old ones.
Default is to not make this permanent (i.e. no script Default is to not make this permanent, i.e. the set
will be added to add the cmdset every server start/login). will not survive a server reset.
cmdset - can be a cmdset object or the python path to cmdset - can be a cmdset object or the python path to
such an object. such an object.

View file

@ -616,7 +616,7 @@ class CmdOOCLook(CmdLook):
self.character = None self.character = None
if utils.inherits_from(self.caller, "src.objects.objects.Object"): if utils.inherits_from(self.caller, "src.objects.objects.Object"):
# An object of some type is calling. Convert to player. # An object of some type is calling. Convert to player.
print self.caller, self.caller.__class__ #print self.caller, self.caller.__class__
self.character = self.caller self.character = self.caller
if hasattr(self.caller, "player"): if hasattr(self.caller, "player"):
self.caller = self.caller.player self.caller = self.caller.player

View file

@ -68,6 +68,13 @@ class ObjectManager(TypedObjectManager):
# use the id to find the player # use the id to find the player
return self.get_object_with_user(dbref) return self.get_object_with_user(dbref)
@returns_typeclass_list
def get_objs_with_key_and_typeclass(oname, otypeclass_path):
"""
Returns objects based on simultaneous key and typeclass match.
"""
return self.filter(db_key__iexact=oname).filter(db_typeclass_path_exact=otypeclass_path)
# attr/property related # attr/property related
@returns_typeclass_list @returns_typeclass_list