Added IN_GAME_ERRORS setting for convenient debugging during development (False by default)
This commit is contained in:
parent
4f02ec1cbe
commit
4cb19bec59
3 changed files with 106 additions and 39 deletions
|
|
@ -35,6 +35,7 @@ command line. The processing of a command works as follows:
|
||||||
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from weakref import WeakValueDictionary
|
from weakref import WeakValueDictionary
|
||||||
|
from traceback import format_exc
|
||||||
from copy import copy
|
from copy import copy
|
||||||
from twisted.internet.defer import inlineCallbacks, returnValue
|
from twisted.internet.defer import inlineCallbacks, returnValue
|
||||||
from django.conf import settings
|
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 _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
|
_IN_GAME_ERRORS = settings.IN_GAME_ERRORS
|
||||||
|
|
||||||
__all__ = ("cmdhandler",)
|
__all__ = ("cmdhandler",)
|
||||||
_GA = object.__getattribute__
|
_GA = object.__getattribute__
|
||||||
_CMDSET_MERGE_CACHE = WeakValueDictionary()
|
_CMDSET_MERGE_CACHE = WeakValueDictionary()
|
||||||
|
|
@ -76,46 +79,76 @@ CMD_LOGINSTART = "__unloggedin_look_command"
|
||||||
# Function for handling multiple command matches.
|
# Function for handling multiple command matches.
|
||||||
_SEARCH_AT_RESULT = utils.variable_from_module(*settings.SEARCH_AT_RESULT.rsplit('.', 1))
|
_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 = """
|
_ERROR_UNTRAPPED = (
|
||||||
An untrapped error occurred. Please file a bug report detailing the
|
|
||||||
steps to reproduce. Server log time stamp is '{timestamp}'.
|
|
||||||
"""
|
"""
|
||||||
|
An untrapped error occurred.
|
||||||
_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. 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
|
No command sets found! This is a sign of a critical bug. If
|
||||||
disconnecting/reconnecting doesn't" solve the problem, try to contact
|
disconnecting/reconnecting doesn't" solve the problem, try to contact
|
||||||
the server admin through" some other means for assistance. Server log
|
the server admin through" some other means for assistance.
|
||||||
time stamp is '{timestamp}'.
|
""")
|
||||||
"""
|
|
||||||
|
|
||||||
_ERROR_CMDHANDLER = """
|
_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}'.
|
|
||||||
"""
|
"""
|
||||||
|
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}) " \
|
_ERROR_RECURSION_LIMIT = "Command recursion limit ({recursion_limit}) " \
|
||||||
"reached for '{raw_string}' ({cmdclass})."
|
"reached for '{raw_string}' ({cmdclass})."
|
||||||
|
|
||||||
|
|
||||||
def _msg_err(receiver, string):
|
def _msg_err(receiver, stringtuple):
|
||||||
"""
|
"""
|
||||||
Helper function for returning an error to the caller.
|
Helper function for returning an error to the caller.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
receiver (Object): object to get the error message.
|
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
|
# custom Exceptions
|
||||||
|
|
||||||
|
|
@ -177,7 +210,6 @@ def get_and_merge_cmdsets(caller, session, player, obj, callertype):
|
||||||
channel_cmdset = yield CHANNELHANDLER.get_cmdset(player)
|
channel_cmdset = yield CHANNELHANDLER.get_cmdset(player)
|
||||||
returnValue(channel_cmdset)
|
returnValue(channel_cmdset)
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.log_trace()
|
|
||||||
_msg_err(caller, _ERROR_CMDSETS)
|
_msg_err(caller, _ERROR_CMDSETS)
|
||||||
raise ErrorReported
|
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
|
cset.duplicates = True if cset.duplicates is None else cset.duplicates
|
||||||
returnValue(local_obj_cmdsets)
|
returnValue(local_obj_cmdsets)
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.log_trace()
|
|
||||||
_msg_err(caller, _ERROR_CMDSETS)
|
_msg_err(caller, _ERROR_CMDSETS)
|
||||||
raise ErrorReported
|
raise ErrorReported
|
||||||
|
|
||||||
|
|
@ -235,7 +266,6 @@ def get_and_merge_cmdsets(caller, session, player, obj, callertype):
|
||||||
try:
|
try:
|
||||||
yield obj.at_cmdset_get()
|
yield obj.at_cmdset_get()
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.log_trace()
|
|
||||||
_msg_err(caller, _ERROR_CMDSETS)
|
_msg_err(caller, _ERROR_CMDSETS)
|
||||||
raise ErrorReported
|
raise ErrorReported
|
||||||
try:
|
try:
|
||||||
|
|
@ -323,7 +353,6 @@ def get_and_merge_cmdsets(caller, session, player, obj, callertype):
|
||||||
except ErrorReported:
|
except ErrorReported:
|
||||||
raise
|
raise
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.log_trace()
|
|
||||||
_msg_err(caller, _ERROR_CMDSETS)
|
_msg_err(caller, _ERROR_CMDSETS)
|
||||||
raise ErrorReported
|
raise ErrorReported
|
||||||
|
|
||||||
|
|
@ -449,7 +478,6 @@ def cmdhandler(called_by, raw_string, _testing=False, callertype="session", sess
|
||||||
returnValue(ret)
|
returnValue(ret)
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.log_trace()
|
|
||||||
_msg_err(caller, _ERROR_UNTRAPPED)
|
_msg_err(caller, _ERROR_UNTRAPPED)
|
||||||
raise ErrorReported
|
raise ErrorReported
|
||||||
|
|
||||||
|
|
@ -579,10 +607,8 @@ def cmdhandler(called_by, raw_string, _testing=False, callertype="session", sess
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
# We should not end up here. If we do, it's a programming bug.
|
# We should not end up here. If we do, it's a programming bug.
|
||||||
logger.log_trace()
|
|
||||||
_msg_err(error_to, _ERROR_UNTRAPPED)
|
_msg_err(error_to, _ERROR_UNTRAPPED)
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
# This catches exceptions in cmdhandler exceptions themselves
|
# This catches exceptions in cmdhandler exceptions themselves
|
||||||
logger.log_trace()
|
|
||||||
_msg_err(error_to, _ERROR_CMDHANDLER)
|
_msg_err(error_to, _ERROR_CMDHANDLER)
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ the 'Fishing' set. Fishing from a boat? No problem!
|
||||||
from builtins import object
|
from builtins import object
|
||||||
from future.utils import raise_
|
from future.utils import raise_
|
||||||
import sys
|
import sys
|
||||||
|
from traceback import format_exc
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
from inspect import trace
|
from inspect import trace
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
@ -78,6 +79,29 @@ __all__ = ("import_cmdset", "CmdSetHandler")
|
||||||
|
|
||||||
_CACHED_CMDSETS = {}
|
_CACHED_CMDSETS = {}
|
||||||
_CMDSET_PATHS = utils.make_iter(settings.CMDSET_PATHS)
|
_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):
|
class _ErrorCmdSet(CmdSet):
|
||||||
"""
|
"""
|
||||||
|
|
@ -160,25 +184,34 @@ def import_cmdset(path, cmdsetobj, emit_to_obj=None, no_logging=False):
|
||||||
cmdsetclass = cmdsetclass(cmdsetobj)
|
cmdsetclass = cmdsetclass(cmdsetobj)
|
||||||
errstring = ""
|
errstring = ""
|
||||||
return cmdsetclass
|
return cmdsetclass
|
||||||
except ImportError as e:
|
except ImportError as err:
|
||||||
logger.log_trace()
|
logger.log_trace()
|
||||||
errstring += _("\nError loading cmdset {path}: \"{error}\"")
|
errstring += _ERROR_CMDSET_IMPORT
|
||||||
errstring = errstring.format(path=python_path, error=e)
|
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
|
break
|
||||||
except KeyError:
|
except KeyError:
|
||||||
logger.log_trace()
|
logger.log_trace()
|
||||||
errstring += _("\nError in loading cmdset: No cmdset class '{classname}' in {path}.")
|
errstring += _ERROR_CMDSET_KEYERROR
|
||||||
errstring = errstring.format(classname=classname, path=python_path)
|
errstring = errstring.format(classname=classname, path=python_path, timestamp=logger.timeformat())
|
||||||
break
|
break
|
||||||
except SyntaxError as e:
|
except SyntaxError as err:
|
||||||
logger.log_trace()
|
logger.log_trace()
|
||||||
errstring += _("\nSyntaxError encountered when loading cmdset '{path}': \"{error}\".")
|
errstring += _ERROR_CMDSET_SYNTAXERROR
|
||||||
errstring = errstring.format(path=python_path, error=e)
|
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
|
break
|
||||||
except Exception as e:
|
except Exception as err:
|
||||||
logger.log_trace()
|
logger.log_trace()
|
||||||
errstring += _("\nCompile/Run error when loading cmdset '{path}': \"{error}\".")
|
errstring += _ERROR_CMDSET_EXCEPTION
|
||||||
errstring = errstring.format(path=python_path, error=e)
|
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
|
break
|
||||||
|
|
||||||
if errstring:
|
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"):
|
if emit_to_obj and not ServerConfig.objects.conf("server_starting_mode"):
|
||||||
emit_to_obj.msg(errstring)
|
emit_to_obj.msg(errstring)
|
||||||
err_cmdset = _ErrorCmdSet()
|
err_cmdset = _ErrorCmdSet()
|
||||||
err_cmdset.errmessage = errstring + _("\n (See log for details.)")
|
err_cmdset.errmessage = errstring
|
||||||
return err_cmdset
|
return err_cmdset
|
||||||
|
|
||||||
# classes
|
# classes
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,9 @@ import sys
|
||||||
|
|
||||||
# This is the name of your game. Make it catchy!
|
# This is the name of your game. Make it catchy!
|
||||||
SERVERNAME = "Evennia"
|
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
|
# Activate telnet service
|
||||||
TELNET_ENABLED = True
|
TELNET_ENABLED = True
|
||||||
# A list of ports the Evennia telnet server listens on Can be one or many.
|
# 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
|
MAX_COMMAND_RATE = 80
|
||||||
# The warning to echo back to users if they send commands too fast
|
# 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."
|
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
|
# Evennia Database config
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue