diff --git a/CHANGELOG.md b/CHANGELOG.md index 4dc8d44511..056759665a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ - [Fix][issue3601]: `CmdSet.add(..., allow_duplicates=True)` didn't allow duplicate cmd keys (Griatch) - [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) - [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) @@ -75,6 +76,7 @@ [issue3601]: https://github.com/evennia/evennia/issues/3601 [issue3194]: https://github.com/evennia/evennia/issues/3194 [issue2774]: https://github.com/evennia/evennia/issues/2774 +[issue3312]: https://github.com/evennia/evennia/issues/3312 ## Evennia 5.0.1 diff --git a/evennia/server/inputfuncs.py b/evennia/server/inputfuncs.py index 0c56d20ea8..79b240d30f 100644 --- a/evennia/server/inputfuncs.py +++ b/evennia/server/inputfuncs.py @@ -499,9 +499,20 @@ def monitored(session, *args, **kwargs): """ from evennia.scripts.monitorhandler import MONITOR_HANDLER + import pickle + + def _safe_pickle(value): + try: + pickle.dumps(value, pickle.HIGHEST_PROTOCOL) + return value + except Exception: + return str(value) obj = session.puppet - monitors = MONITOR_HANDLER.all(obj=obj) + monitors = [] + for mon_obj, fieldname, idstring, persistent, monitor_kwargs in MONITOR_HANDLER.all(obj=obj): + safe_kwargs = {key: _safe_pickle(val) for key, val in monitor_kwargs.items()} + monitors.append((_safe_pickle(mon_obj), fieldname, idstring, persistent, safe_kwargs)) session.msg(monitored=(monitors, {})) diff --git a/evennia/server/tests/test_inputfuncs.py b/evennia/server/tests/test_inputfuncs.py new file mode 100644 index 0000000000..58f9b24be9 --- /dev/null +++ b/evennia/server/tests/test_inputfuncs.py @@ -0,0 +1,34 @@ +""" +Tests for server input functions. +""" + +import pickle + +import evennia +from evennia.server import inputfuncs +from evennia.utils.test_resources import BaseEvenniaTest + + +class TestMonitoredInputfunc(BaseEvenniaTest): + """ + Regressions for monitor/monitored inputfunc handling. + """ + + def test_monitored_payload_is_pickleable(self): + """ + The monitored payload sent over AMP must not include raw Session objects. + """ + + self.session.puppet = self.char1 + inputfuncs.monitor(self.session, name="location") + inputfuncs.monitored(self.session) + + sent_session = evennia.SESSION_HANDLER.data_out.call_args.args[0] + sent_kwargs = evennia.SESSION_HANDLER.data_out.call_args.kwargs + monitors = sent_kwargs["monitored"][0] + monitor_kwargs = monitors[0][4] + + self.assertEqual(sent_session, self.session) + self.assertIn("session", monitor_kwargs) + self.assertIsInstance(monitor_kwargs["session"], str) + pickle.dumps((self.session.sessid, sent_kwargs), pickle.HIGHEST_PROTOCOL)