Added IN_GAME_ERRORS setting for convenient debugging during development (False by default)

This commit is contained in:
Griatch 2016-04-05 22:04:16 +02:00
parent 4f02ec1cbe
commit 4cb19bec59
3 changed files with 106 additions and 39 deletions

View file

@ -35,6 +35,7 @@ command line. The processing of a command works as follows:
from collections import defaultdict
from weakref import WeakValueDictionary
from traceback import format_exc
from copy import copy
from twisted.internet.defer import inlineCallbacks, returnValue
from django.conf import settings
@ -44,6 +45,8 @@ from evennia.utils.utils import string_suggestions, to_unicode
from django.utils.translation import ugettext as _
_IN_GAME_ERRORS = settings.IN_GAME_ERRORS
__all__ = ("cmdhandler",)
_GA = object.__getattribute__
_CMDSET_MERGE_CACHE = WeakValueDictionary()
@ -76,46 +79,76 @@ CMD_LOGINSTART = "__unloggedin_look_command"
# Function for handling multiple command matches.
_SEARCH_AT_RESULT = utils.variable_from_module(*settings.SEARCH_AT_RESULT.rsplit('.', 1))
# Output strings
# Output strings. The first is the IN_GAME_ERRORS return, the second
# is the normal "production message to echo to the player.
_ERROR_UNTRAPPED = """
An untrapped error occurred. Please file a bug report detailing the
steps to reproduce. Server log time stamp is '{timestamp}'.
_ERROR_UNTRAPPED = (
"""
_ERROR_CMDSETS = """
A cmdset merger error occurred. Please file a bug report detailing the
steps to reproduce. Server log time stamp is '{timestamp}'.
An untrapped error occurred.
""",
"""
An untrapped error occurred. Please file a bug report detailing the steps to reproduce.
""")
_ERROR_NOCMDSETS = """
_ERROR_CMDSETS = (
"""
A cmdset merger-error occurred. This is often due to a syntax
error in one of the cmdsets to merge.
""",
"""
A cmdset merger-error occurred. Please file a bug report detailing the
steps to reproduce.
""")
_ERROR_NOCMDSETS = (
"""
No command sets found! This is a critical bug that can have
multiple causes.
""",
"""
No command sets found! This is a sign of a critical bug. If
disconnecting/reconnecting doesn't" solve the problem, try to contact
the server admin through" some other means for assistance. Server log
time stamp is '{timestamp}'.
"""
the server admin through" some other means for assistance.
""")
_ERROR_CMDHANDLER = """
A command handler bug occurred. Please file a bug report with the
Evennia project. Include the relvant traceback from the server log at
time stamp '{timestamp}'.
_ERROR_CMDHANDLER = (
"""
A command handler bug occurred. If this is not due to a local change,
please file a bug report with the Evennia project, including the
traceback and steps to reproduce.
""",
"""
A command handler bug occurred. Please notify staff - they should
likely file a bug report with the Evennia project.
""")
_ERROR_RECURSION_LIMIT = "Command recursion limit ({recursion_limit}) " \
"reached for '{raw_string}' ({cmdclass})."
def _msg_err(receiver, string):
def _msg_err(receiver, stringtuple):
"""
Helper function for returning an error to the caller.
Args:
receiver (Object): object to get the error message.
string (str): string which will be shown to the user.
stringtuple (tuple): tuple with two strings - one for the
_IN_GAME_ERRORS mode (with the traceback) and one with the
production string (with a timestamp) to be shown to the user.
"""
receiver.msg(string.format(timestamp=logger.timeformat()).strip())
string = "{traceback}\n{errmsg}\n(Traceback was logged {timestamp})."
timestamp = logger.timeformat()
tracestring = format_exc()
#logger.log_trace()
if _IN_GAME_ERRORS:
receiver.msg(string.format(traceback=tracestring,
errmsg=stringtuple[0].strip(),
timestamp=timestamp).strip())
else:
receiver.msg(string.format(traceback=tracestring.splitlines()[-1],
errmsg=stringtuple[1].strip(),
timestamp=timestamp).strip())
# custom Exceptions
@ -177,7 +210,6 @@ def get_and_merge_cmdsets(caller, session, player, obj, callertype):
channel_cmdset = yield CHANNELHANDLER.get_cmdset(player)
returnValue(channel_cmdset)
except Exception:
logger.log_trace()
_msg_err(caller, _ERROR_CMDSETS)
raise ErrorReported
@ -221,7 +253,6 @@ def get_and_merge_cmdsets(caller, session, player, obj, callertype):
cset.duplicates = True if cset.duplicates is None else cset.duplicates
returnValue(local_obj_cmdsets)
except Exception:
logger.log_trace()
_msg_err(caller, _ERROR_CMDSETS)
raise ErrorReported
@ -235,7 +266,6 @@ def get_and_merge_cmdsets(caller, session, player, obj, callertype):
try:
yield obj.at_cmdset_get()
except Exception:
logger.log_trace()
_msg_err(caller, _ERROR_CMDSETS)
raise ErrorReported
try:
@ -323,7 +353,6 @@ def get_and_merge_cmdsets(caller, session, player, obj, callertype):
except ErrorReported:
raise
except Exception:
logger.log_trace()
_msg_err(caller, _ERROR_CMDSETS)
raise ErrorReported
@ -449,7 +478,6 @@ def cmdhandler(called_by, raw_string, _testing=False, callertype="session", sess
returnValue(ret)
except Exception:
logger.log_trace()
_msg_err(caller, _ERROR_UNTRAPPED)
raise ErrorReported
@ -579,10 +607,8 @@ def cmdhandler(called_by, raw_string, _testing=False, callertype="session", sess
except Exception:
# We should not end up here. If we do, it's a programming bug.
logger.log_trace()
_msg_err(error_to, _ERROR_UNTRAPPED)
except Exception:
# This catches exceptions in cmdhandler exceptions themselves
logger.log_trace()
_msg_err(error_to, _ERROR_CMDHANDLER)

View file

@ -66,6 +66,7 @@ the 'Fishing' set. Fishing from a boat? No problem!
from builtins import object
from future.utils import raise_
import sys
from traceback import format_exc
from importlib import import_module
from inspect import trace
from django.conf import settings
@ -78,6 +79,29 @@ __all__ = ("import_cmdset", "CmdSetHandler")
_CACHED_CMDSETS = {}
_CMDSET_PATHS = utils.make_iter(settings.CMDSET_PATHS)
_IN_GAME_ERRORS = settings.IN_GAME_ERRORS
# Output strings
_ERROR_CMDSET_IMPORT = _(
"""{traceback}
Error loading cmdset '{path}'
(Traceback was logged {timestamp})""")
_ERROR_CMDSET_KEYERROR = _(
"""Error loading cmdset: No cmdset class '{classname}' in '{path}'.
(Traceback was logged {timestamp})""")
_ERROR_CMDSET_SYNTAXERROR = _(
"""{traceback}
SyntaxError encountered when loading cmdset '{path}'.
(Traceback was logged {timestamp})""")
_ERROR_CMDSET_EXCEPTION = _(
"""{traceback}
Compile/Run error when loading cmdset '{path}'.",
(Traceback was logged {timestamp})""")
class _ErrorCmdSet(CmdSet):
"""
@ -160,25 +184,34 @@ def import_cmdset(path, cmdsetobj, emit_to_obj=None, no_logging=False):
cmdsetclass = cmdsetclass(cmdsetobj)
errstring = ""
return cmdsetclass
except ImportError as e:
except ImportError as err:
logger.log_trace()
errstring += _("\nError loading cmdset {path}: \"{error}\"")
errstring = errstring.format(path=python_path, error=e)
errstring += _ERROR_CMDSET_IMPORT
if _IN_GAME_ERRORS:
errstring = errstring.format(path=python_path, traceback=format_exc(), timestamp=logger.timeformat())
else:
errstring = errstring.format(path=python_path, traceback=err, timestamp=logger.timeformat())
break
except KeyError:
logger.log_trace()
errstring += _("\nError in loading cmdset: No cmdset class '{classname}' in {path}.")
errstring = errstring.format(classname=classname, path=python_path)
errstring += _ERROR_CMDSET_KEYERROR
errstring = errstring.format(classname=classname, path=python_path, timestamp=logger.timeformat())
break
except SyntaxError as e:
except SyntaxError as err:
logger.log_trace()
errstring += _("\nSyntaxError encountered when loading cmdset '{path}': \"{error}\".")
errstring = errstring.format(path=python_path, error=e)
errstring += _ERROR_CMDSET_SYNTAXERROR
if _IN_GAME_ERRORS:
errstring = errstring.format(path=python_path, traceback=format_exc(), timestamp=logger.timeformat())
else:
errstring = errstring.format(path=python_path, traceback=err, timestamp=logger.timeformat())
break
except Exception as e:
except Exception as err:
logger.log_trace()
errstring += _("\nCompile/Run error when loading cmdset '{path}': \"{error}\".")
errstring = errstring.format(path=python_path, error=e)
errstring += _ERROR_CMDSET_EXCEPTION
if _IN_GAME_ERRORS:
errstring = errstring.format(path=python_path, traceback=format_exc(), timestamp=logger.timeformat())
else:
errstring = errstring.format(path=python_path, traceback=err, timestamp=logger.timeformat())
break
if errstring:
@ -189,7 +222,7 @@ def import_cmdset(path, cmdsetobj, emit_to_obj=None, no_logging=False):
if emit_to_obj and not ServerConfig.objects.conf("server_starting_mode"):
emit_to_obj.msg(errstring)
err_cmdset = _ErrorCmdSet()
err_cmdset.errmessage = errstring + _("\n (See log for details.)")
err_cmdset.errmessage = errstring
return err_cmdset
# classes

View file

@ -23,6 +23,9 @@ import sys
# This is the name of your game. Make it catchy!
SERVERNAME = "Evennia"
# Lockdown mode will cut off the game from any external connections
# and only allow connections from localhost. Requires a cold reboot.
LOCKDOWN_MODE = False
# Activate telnet service
TELNET_ENABLED = True
# A list of ports the Evennia telnet server listens on Can be one or many.
@ -204,6 +207,11 @@ MAX_CONNECTION_RATE = 2
MAX_COMMAND_RATE = 80
# The warning to echo back to users if they send commands too fast
COMMAND_RATE_WARNING ="You entered commands too fast. Wait a moment and try again."
# If this is true, errors and tracebacks from the engine will be
# echoed as text in-game as well as to the log. This can speed up
# debugging. Showing full tracebacks to regular users could be a
# security problem - this should *not* be active in a production game!
IN_GAME_ERRORS = False
######################################################################
# Evennia Database config