From 703accdd60a61961fc41e79d98c557885955ca62 Mon Sep 17 00:00:00 2001 From: Griatch Date: Sun, 6 Nov 2011 21:32:00 +0100 Subject: [PATCH] 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. --- contrib/menu_login.py | 2 +- game/evennia.py | 41 +++++++++++++++++++++++++++++ game/gamesrc/commands/basecmdset.py | 1 + src/commands/cmdset.py | 8 +++--- src/commands/cmdsethandler.py | 7 ++--- src/commands/default/general.py | 2 +- src/objects/manager.py | 7 +++++ 7 files changed, 59 insertions(+), 9 deletions(-) diff --git a/contrib/menu_login.py b/contrib/menu_login.py index 9ac06a0502..e82ca5b37f 100644 --- a/contrib/menu_login.py +++ b/contrib/menu_login.py @@ -1,7 +1,7 @@ """ Menu-driven login system -Contribution 2011 - Griatch +Contribution - Griatch 2011 This is an alternative login system for Evennia, using the diff --git a/game/evennia.py b/game/evennia.py index 9349920852..05032b3724 100755 --- a/game/evennia.py +++ b/game/evennia.py @@ -355,6 +355,10 @@ def handle_args(options, mode, service): errmsg = _("The %s does not seem to be running.") if mode == 'start': + + # launch the error checker. Best to catch the errors already here. + error_check_python_modules() + # starting one or many services if service == 'server': if inter: @@ -397,6 +401,42 @@ def handle_args(options, mode, service): kill(SERVER_PIDFILE, SIG, _("Server stopped."), errmsg % 'Server', restart=False) 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(): """ This handles command line input. @@ -438,6 +478,7 @@ def main(): Popen(cmdstr) if __name__ == '__main__': + from src.utils.utils import check_evennia_dependencies if check_evennia_dependencies(): main() diff --git a/game/gamesrc/commands/basecmdset.py b/game/gamesrc/commands/basecmdset.py index 5870a6fa9b..c45e8f6837 100644 --- a/game/gamesrc/commands/basecmdset.py +++ b/game/gamesrc/commands/basecmdset.py @@ -24,6 +24,7 @@ from game.gamesrc.commands.basecommand import Command from contrib import menusystem, lineeditor #from contrib import misc_commands +#from contrib import character_creation class DefaultCmdSet(cmdset_default.DefaultCmdSet): """ diff --git a/src/commands/cmdset.py b/src/commands/cmdset.py index 8bdaed3db1..b6e8b9cee9 100644 --- a/src/commands/cmdset.py +++ b/src/commands/cmdset.py @@ -243,10 +243,10 @@ class CmdSet(object): # add all commands if not hasattr(cmd, 'obj'): cmd.obj = self.cmdsetobj - ic = [i for i, oldcmd in enumerate(self.commands) if oldcmd.match(cmd)] - if ic: - self.commands[ic[0]] = cmd # replace - else: + try: + ic = self.commands.index(cmd) + self.commands[ic] = cmd # replace + except ValueError: self.commands.append(cmd) # extra run to make sure to avoid doublets self.commands = list(set(self.commands)) diff --git a/src/commands/cmdsethandler.py b/src/commands/cmdsethandler.py index 2395312da7..9025c3ca08 100644 --- a/src/commands/cmdsethandler.py +++ b/src/commands/cmdsethandler.py @@ -121,7 +121,8 @@ def import_cmdset(python_path, cmdsetobj, emit_to_obj=None, no_logging=False): logger.log_trace() if emit_to_obj and not ServerConfig.objects.conf("server_starting_mode"): 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 @@ -246,8 +247,8 @@ class CmdSetHandler(object): def add(self, cmdset, emit_to_obj=None, permanent=False): """ Add a cmdset to the handler, on top of the old ones. - Default is to not make this permanent (i.e. no script - will be added to add the cmdset every server start/login). + Default is to not make this permanent, i.e. the set + will not survive a server reset. cmdset - can be a cmdset object or the python path to such an object. diff --git a/src/commands/default/general.py b/src/commands/default/general.py index f48ab6bc78..dc73b91f1d 100644 --- a/src/commands/default/general.py +++ b/src/commands/default/general.py @@ -616,7 +616,7 @@ class CmdOOCLook(CmdLook): self.character = None if utils.inherits_from(self.caller, "src.objects.objects.Object"): # 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 if hasattr(self.caller, "player"): self.caller = self.caller.player diff --git a/src/objects/manager.py b/src/objects/manager.py index 51d98513e4..52b1427cc7 100644 --- a/src/objects/manager.py +++ b/src/objects/manager.py @@ -68,6 +68,13 @@ class ObjectManager(TypedObjectManager): # use the id to find the player 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 @returns_typeclass_list