Make persistent EvMenus not create extra cmdsets. Resolve #3154

This commit is contained in:
Griatch 2026-02-15 13:18:33 +01:00
parent ff283072ec
commit 6fea92196d
3 changed files with 41 additions and 0 deletions

View file

@ -42,6 +42,7 @@
- [Fix][issue3194]: Make filtering on AttributeProperties consistent across typeclasses (Griatch)
- [Fix][issue2774]: Properly support `\n` in `evennia connections` long descriptions (Griatch)
- [Fix][issue3312]: Handle all edge cases breaking `monitor/monitored` `input_funcs` (Griatch)
- [Fix][issue3154]: Persistent EvMenu caused multiple cmdsets on reload (Griatch)
- [Doc][pull3801]: Move Evennia doc build system to latest Sphinx/myST
(PowershellNinja, also honorary mention to electroglyph)
- [Doc][pull3800]: Describe support for Telnet SSH in HAProxy documentation (holl0wstar)
@ -77,6 +78,7 @@
[issue3194]: https://github.com/evennia/evennia/issues/3194
[issue2774]: https://github.com/evennia/evennia/issues/2774
[issue3312]: https://github.com/evennia/evennia/issues/3312
[issue3154]: https://github.com/evennia/evennia/issues/3154
## Evennia 5.0.1

View file

@ -691,6 +691,10 @@ class EvMenu:
logger.log_trace(_TRACE_PERSISTENT_SAVING)
persistent = False
# Make sure to not stack menu cmdsets across reload-restore cycles.
# On reload, ndb is cleared so we can't always close an old menu cleanly first.
self.caller.cmdset.remove(EvMenuCmdSet)
# set up the menu command on the caller
menu_cmdset = EvMenuCmdSet()
menu_cmdset.mergetype = str(cmdset_mergetype).lower().capitalize() or "Replace"

View file

@ -338,3 +338,38 @@ class TestMenuTemplateParse(BaseEvenniaTest):
"""
with self.assertRaises(RuntimeError):
evmenu.parse_menu_template(self.char1, template, self.goto_callables)
def _reload_menu_start(caller, raw_string, **kwargs):
return "start text", {"key": "next", "desc": "go next", "goto": "end"}
def _reload_menu_end(caller, raw_string, **kwargs):
return "end text", {"key": "back", "desc": "go back", "goto": "start"}
class TestEvMenuPersistentReloadRegression(BaseEvenniaTest):
"""
Regression tests for persistent EvMenu reload behavior.
"""
def test_persistent_restore_does_not_duplicate_cmdset(self):
menutree = {"start": _reload_menu_start, "end": _reload_menu_end}
evmenu.EvMenu(
self.char1, menutree, persistent=True, cmdset_mergetype="Union", session=self.session
)
menu_cmdsets = [cmdset for cmdset in self.char1.cmdset.get() if cmdset.key == "menu_cmdset"]
self.assertEqual(len(menu_cmdsets), 1)
# Simulate reload behavior where ndb is cleared but cmdset persists.
del self.char1.ndb._evmenu
del self.char1.ndb._menutree
evmenu.EvMenu(
self.char1, menutree, persistent=True, cmdset_mergetype="Union", session=self.session
)
menu_cmdsets = [cmdset for cmdset in self.char1.cmdset.get() if cmdset.key == "menu_cmdset"]
self.assertEqual(len(menu_cmdsets), 1)
self.assertEqual(self.char1.cmdset_storage.count("evennia.utils.evmenu.EvMenuCmdSet"), 1)