diff --git a/disagreement/event_dispatcher.py b/disagreement/event_dispatcher.py index 7cd6c85..1a5dce6 100644 --- a/disagreement/event_dispatcher.py +++ b/disagreement/event_dispatcher.py @@ -56,8 +56,6 @@ class EventDispatcher: "CHANNEL_CREATE": self._parse_channel_create, "PRESENCE_UPDATE": self._parse_presence_update, "TYPING_START": self._parse_typing_start, - "MESSAGE_REACTION_ADD": self._parse_message_reaction, - "MESSAGE_REACTION_REMOVE": self._parse_message_reaction, } def _parse_message_create(self, data: Dict[str, Any]) -> Message: @@ -75,10 +73,6 @@ class EventDispatcher: self._client._messages.pop(message_id, None) return data - def _parse_message_reaction(self, data: Dict[str, Any]) -> Dict[str, Any]: - """Returns the raw reaction payload.""" - return data - def _parse_interaction_create(self, data: Dict[str, Any]) -> "Interaction": """Parses raw INTERACTION_CREATE data into an Interaction object.""" from .interactions import Interaction diff --git a/disagreement/ext/loader.py b/disagreement/ext/loader.py index 8e8d790..0f14402 100644 --- a/disagreement/ext/loader.py +++ b/disagreement/ext/loader.py @@ -5,7 +5,7 @@ import sys from types import ModuleType from typing import Dict -__all__ = ["load_extension", "unload_extension"] +__all__ = ["load_extension", "unload_extension", "reload_extension"] _loaded_extensions: Dict[str, ModuleType] = {} @@ -41,3 +41,14 @@ def unload_extension(name: str) -> None: module.teardown() sys.modules.pop(name, None) + + +def reload_extension(name: str) -> ModuleType: + """Reload an extension by name. + + This is a convenience wrapper around :func:`unload_extension` followed by + :func:`load_extension`. + """ + + unload_extension(name) + return load_extension(name) diff --git a/docs/extension_loader.md b/docs/extension_loader.md new file mode 100644 index 0000000..115aff9 --- /dev/null +++ b/docs/extension_loader.md @@ -0,0 +1,15 @@ +# Extension Loader + +The `disagreement.ext.loader` module provides simple helpers to manage optional +extensions. Extensions are regular Python modules that expose a `setup` function +called when the extension is loaded. + +```python +from disagreement.ext import loader +``` + +- `loader.load_extension(name)` – Import and initialize an extension. +- `loader.unload_extension(name)` – Tear down and remove a previously loaded + extension. +- `loader.reload_extension(name)` – Convenience wrapper that unloads then loads + the extension again. diff --git a/tests/test_extension_loader.py b/tests/test_extension_loader.py index 37f45f6..7531af1 100644 --- a/tests/test_extension_loader.py +++ b/tests/test_extension_loader.py @@ -42,3 +42,36 @@ def test_load_extension_twice_raises(): loader.load_extension("repeat_ext") loader.unload_extension("repeat_ext") assert called["teardown"] is True + + +def test_reload_extension(monkeypatch): + called_first = create_dummy_module("reload_ext") + loader.load_extension("reload_ext") + + called_second = {"setup": False, "teardown": False} + module_second = types.ModuleType("reload_ext") + + def setup_second(): + called_second["setup"] = True + + def teardown_second(): + called_second["teardown"] = True + + module_second.setup = setup_second + module_second.teardown = teardown_second + + def import_stub(name): + assert name == "reload_ext" + sys.modules[name] = module_second + return module_second + + monkeypatch.setattr(loader, "import_module", import_stub) + + loader.reload_extension("reload_ext") + + assert called_first["teardown"] is True + assert called_second["setup"] is True + assert loader._loaded_extensions["reload_ext"] is module_second + + loader.unload_extension("reload_ext") + assert called_second["teardown"] is True