Skip to content

Commit

Permalink
Cleanup after unloading extension. (#3226)
Browse files Browse the repository at this point in the history
* Cleanup after unloading extension, resolve #3223.

* Remove leftover modules loaded from `plugins` path when purging.

---------

Co-authored-by: Taku <[email protected]>
  • Loading branch information
Jerrie-Aries and Taaku18 authored Jul 15, 2023
1 parent 43fbc31 commit a784f82
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s
- `?alias make/create` as aliases to `?alias add`. This improves continuity between the bot and its command structure. ([PR #3195](https://github.com/kyb3r/modmail/pull/3195))
- Loading the blocked list with the `?blocked` command takes a long time when the list is large. ([PR #3242](https://github.com/kyb3r/modmail/pull/3242))
- Reply not being forwarded from DM. (PR [#3239](https://github.com/modmail-dev/modmail/pull/3239))
- Cleanup imports after removing/unloading a plugin. ([PR #3226](https://github.com/modmail-dev/Modmail/pull/3226))

### Added
- `?log key <key>` to retrieve the log link and view a preview using a log key. ([PR #3196](https://github.com/modmail-dev/Modmail/pull/3196))
Expand Down
37 changes: 26 additions & 11 deletions cogs/plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,17 @@ async def load_plugin(self, plugin):
logger.error("Plugin load failure: %s", plugin.ext_string, exc_info=True)
raise InvalidPluginError("Cannot load extension, plugin invalid.") from exc

async def unload_plugin(self, plugin: Plugin) -> None:
try:
await self.bot.unload_extension(plugin.ext_string)
except commands.ExtensionError as exc:
raise exc

ext_parent = ".".join(plugin.ext_string.split(".")[:-1])
for module in list(sys.modules.keys()):
if module == ext_parent or module.startswith(ext_parent + "."):
del sys.modules[module]

async def parse_user_input(self, ctx, plugin_name, check_version=False):

if not self.bot.config["enable_plugins"]:
Expand Down Expand Up @@ -378,7 +389,7 @@ async def plugins_add(self, ctx, *, plugin_name: str):
logger.warning("Unable to download plugin %s.", plugin, exc_info=True)

embed = discord.Embed(
description=f"Failed to download plugin, check logs for error.\n{type(e)}: {e}",
description=f"Failed to download plugin, check logs for error.\n{type(e).__name__}: {e}",
color=self.bot.error_color,
)

Expand All @@ -397,7 +408,7 @@ async def plugins_add(self, ctx, *, plugin_name: str):
logger.warning("Unable to load plugin %s.", plugin, exc_info=True)

embed = discord.Embed(
description=f"Failed to download plugin, check logs for error.\n{type(e)}: {e}",
description=f"Failed to load plugin, check logs for error.\n{type(e).__name__}: {e}",
color=self.bot.error_color,
)

Expand Down Expand Up @@ -438,7 +449,7 @@ async def plugins_remove(self, ctx, *, plugin_name: str):

if self.bot.config.get("enable_plugins"):
try:
await self.bot.unload_extension(plugin.ext_string)
await self.unload_plugin(plugin)
self.loaded_plugins.remove(plugin)
except (commands.ExtensionNotLoaded, KeyError):
logger.warning("Plugin was never loaded.")
Expand Down Expand Up @@ -480,9 +491,10 @@ async def update_plugin(self, ctx, plugin_name):
await self.download_plugin(plugin, force=True)
if self.bot.config.get("enable_plugins"):
try:
await self.bot.unload_extension(plugin.ext_string)
await self.unload_plugin(plugin)
except commands.ExtensionError:
logger.warning("Plugin unload fail.", exc_info=True)

try:
await self.load_plugin(plugin)
except Exception:
Expand Down Expand Up @@ -529,17 +541,20 @@ async def plugins_reset(self, ctx):
for ext in list(self.bot.extensions):
if not ext.startswith("plugins."):
continue
logger.error("Unloading plugin: %s.", ext)
try:
logger.error("Unloading plugin: %s.", ext)
await self.bot.unload_extension(ext)
except Exception:
logger.error("Failed to unload plugin: %s.", ext)
else:
if not self.loaded_plugins:
continue
plugin = next((p for p in self.loaded_plugins if p.ext_string == ext), None)
if plugin:
await self.unload_plugin(plugin)
self.loaded_plugins.remove(plugin)
else:
await self.bot.unload_extension(ext)
except Exception:
logger.error("Failed to unload plugin: %s.", ext)

for module in list(sys.modules.keys()):
if module.startswith("plugins."):
del sys.modules[module]

self.bot.config["plugins"].clear()
await self.bot.config.update()
Expand Down

0 comments on commit a784f82

Please sign in to comment.