Skip to content

Commit

Permalink
bot, plugins: deprecate bot.{add|remove}_plugin
Browse files Browse the repository at this point in the history
Both methods to add/remove plugins rely on values direct from
`loader.clean_module`, which is inconvenient at time. In order to rework
smoothly this interface, these methods are now deprecated and they will
be removed in Sopel 9.0.

We still need methods to record the plugin handler to the plugin name in
`bot.plugins`, but they don't do more than that. Everything else is now
directly handled and controlled by the plugin handler.

For good measure, I've fully type check `sopel.plugins.handlers`.
  • Loading branch information
Exirel committed Oct 19, 2024
1 parent 0e5c976 commit 5fe3de1
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 66 deletions.
65 changes: 61 additions & 4 deletions sopel/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@
if TYPE_CHECKING:
from collections.abc import Iterable, Mapping

from sopel.plugins.handlers import AbstractPluginHandler
from sopel.plugins.handlers import (
AbstractPluginHandler, PluginMetaDescription,
)
from sopel.trigger import PreTrigger


Expand Down Expand Up @@ -342,6 +344,37 @@ def post_setup(self) -> None:

# plugins management

def store_plugin_handler(
self,
handler: AbstractPluginHandler,
) -> None:
"""Record a plugin ``handler``.
:param handler: the plugin handler to record
Recording a plugin handler associates only its name to :attr:`plugins`.
To register a plugin handler's callables, jobs, etc., you should use
its :meth:`~sopel.plugins.handlers.AbstractPluginHandler.register`
method.
.. versionadded:: 8.1
"""
self._plugins[handler.name] = handler

def remove_plugin_handler(self, name: str) -> None:
"""Remove a plugin handler from ``name``.
:param name: plugin name to forget
Removing a plugin handler removes only its name from :attr:``plugins``.
To unregister a plugin handler's callables, jobs, etc. you should use
its :meth:`~sopel.plugins.handlers.AbstractPluginHandler.unregister`
method.
.. versionadded:: 8.1
"""
del self._plugins[name]

def reload_plugin(self, name: str) -> None:
"""Reload a plugin.
Expand All @@ -357,10 +390,12 @@ def reload_plugin(self, name: str) -> None:
raise plugins.exceptions.PluginNotRegistered(name)

plugin_handler = self._plugins[name]

# tear down
plugin_handler.shutdown(self)
plugin_handler.unregister(self)
LOGGER.info("Unloaded plugin %s", name)

# reload & setup
plugin_handler.reload()
plugin_handler.setup(self)
Expand Down Expand Up @@ -392,8 +427,13 @@ def reload_plugins(self) -> None:
LOGGER.info("Reloaded %s plugin %s from %s",
meta['type'], name, meta['source'])

# TODO: deprecate both add_plugin and remove_plugin; see #2425
# TODO: Remove in Sopel 9.0

@deprecated(
'Use direct access to add rules, jobs, etc.',
version='8.1',
removed_in='9.0',
)
def add_plugin(
self,
plugin: AbstractPluginHandler,
Expand All @@ -412,13 +452,24 @@ def add_plugin(
should be called on shutdown
:param urls: an iterable of functions from the ``plugin`` to call when
matched against a URL
.. deprecated:: 8.1
This method is deprecated and replaced by direct call to register
methods. It will be removed in Sopel 9.0.
"""
self._plugins[plugin.name] = plugin
self.register_callables(callables)
self.register_jobs(jobs)
self.register_shutdowns(shutdowns)
self.register_urls(urls)

@deprecated(
'Use direct access to remove rules, jobs, etc.',
version='8.1',
removed_in='9.0',
)
def remove_plugin(
self,
plugin: AbstractPluginHandler,
Expand All @@ -437,6 +488,12 @@ def remove_plugin(
should be called on shutdown
:param urls: an iterable of functions from the ``plugin`` to call when
matched against a URL
.. deprecated:: 8.1
This method is deprecated and replaced by direct call to unregister
methods. It will be removed in Sopel 9.0.
"""
name = plugin.name
if not self.has_plugin(name):
Expand All @@ -459,7 +516,7 @@ def has_plugin(self, name: str) -> bool:
"""
return name in self._plugins

def get_plugin_meta(self, name: str) -> dict:
def get_plugin_meta(self, name: str) -> PluginMetaDescription:
"""Get info about a registered plugin by its name.
:param str name: name of the plugin about which to get info
Expand Down Expand Up @@ -569,7 +626,7 @@ def register_shutdowns(self, shutdowns: Iterable) -> None:
# call on shutdown
self.shutdown_methods = self.shutdown_methods + list(shutdowns)

def unregister_shutdowns(self, shutdowns: Iterable) -> None:
def unregister_shutdowns(self, shutdowns: Iterable[Callable]) -> None:
self.shutdown_methods = [
shutdown
for shutdown in self.shutdown_methods
Expand Down
Loading

0 comments on commit 5fe3de1

Please sign in to comment.