Added proper error handling to evmenu when trying to use persistent mode with callables that cannot be pickled, such as methods and functions defined inside other functions.

This commit is contained in:
Griatch 2016-04-17 10:33:19 +02:00
parent adc673f620
commit 039eb8c824
2 changed files with 40 additions and 15 deletions

View file

@ -36,7 +36,7 @@ and initialize it:
from builtins import object
import re
import inspect
from django.conf import settings
from evennia import Command, CmdSet
from evennia.utils import is_iter, fill, dedent, logger
@ -135,6 +135,11 @@ to non-persistent mode (which means the editor session won't survive
an eventual server reload - so save often!)|n
"""
_TRACE_PERSISTENT_SAVING = \
"EvEditor persistent-mode error. Commonly, this is because one or " \
"more of the EvEditor callbacks could not be pickled, for example " \
"because it's a class method or is defined inside another function."
_MSG_NO_UNDO = "Nothing to undo."
_MSG_NO_REDO = "Nothing to redo."
@ -662,9 +667,7 @@ class EvEditor(object):
caller.attributes.add("_eveditor_buffer_temp", (self._buffer, self._undo_buffer))
except Exception, err:
caller.msg(_ERROR_PERSISTENT_SAVING.format(error=err))
logger.log_trace("EvEditor persistent-mode error. Commonly, this is because one or "\
"more of the EvEditor callbacks could not be pickled, for example because it's "\
"a class method or is defined inside another function.")
logger.log_trace(_TRACE_PERSISTENT_SAVING)
persistent = False
# Create the commands we need

View file

@ -140,6 +140,7 @@ from textwrap import dedent
from inspect import isfunction, getargspec
from django.conf import settings
from evennia import Command, CmdSet
from evennia.utils import logger
from evennia.utils.evtable import EvTable
from evennia.utils.ansi import ANSIString, strip_ansi
from evennia.utils.utils import mod_import, make_iter, pad, m_len
@ -166,6 +167,20 @@ _HELP_NO_OPTIONS = _("Commands: help, quit")
_HELP_NO_OPTIONS_NO_QUIT = _("Commands: help")
_HELP_NO_OPTION_MATCH = _("Choose an option or try 'help'.")
_ERROR_PERSISTENT_SAVING = \
"""
{error}
|rThe menu state could not be saved for persistent mode. Switching
to non-persistent mode (which means the menu session won't survive
an eventual server reload).|n
"""
_TRACE_PERSISTENT_SAVING = \
"EvMenu persistent-mode error. Commonly, this is because one or " \
"more of the EvEditor callbacks could not be pickled, for example " \
"because it's a class method or is defined inside another function."
class EvMenuError(RuntimeError):
"""
@ -496,22 +511,29 @@ class EvMenu(object):
# store ourself on the object
self.caller.ndb._menutree = self
if persistent:
# save the menu to the database
try:
caller.attributes.add("_menutree_saved",
((menudata, ),
{"startnode": startnode,
"cmdset_mergetype": cmdset_mergetype,
"cmdset_priority": cmdset_priority,
"auto_quit": auto_quit, "auto_look": auto_look, "auto_help": auto_help,
"cmd_on_exit": cmd_on_exit, "persistent": persistent,
"nodetext_formatter": nodetext_formatter, "options_formatter": options_formatter,
"node_formatter": node_formatter, "input_parser": input_parser}))
caller.attributes.add("_menutree_saved_startnode", startnode)
except Exception as err:
caller.msg(_ERROR_PERSISTENT_SAVING.format(error=err))
logger.log_trace(_TRACE_PERSISTENT_SAVING)
persistent = False
# set up the menu command on the caller
menu_cmdset = EvMenuCmdSet()
menu_cmdset.mergetype = str(cmdset_mergetype).lower().capitalize() or "Replace"
menu_cmdset.priority = int(cmdset_priority)
self.caller.cmdset.add(menu_cmdset, permanent=persistent)
if persistent:
caller.attributes.add("_menutree_saved",
((menudata, ),
{"startnode": startnode,
"cmdset_mergetype": cmdset_mergetype,
"cmdset_priority": cmdset_priority,
"auto_quit": auto_quit, "auto_look": auto_look, "auto_help": auto_help,
"cmd_on_exit": cmd_on_exit, "persistent": persistent,
"nodetext_formatter": nodetext_formatter, "options_formatter": options_formatter,
"node_formatter": node_formatter, "input_parser": input_parser}))
caller.attributes.add("_menutree_saved_startnode", startnode)
# start the menu
self.goto(self._startnode, "")