Skip to content

Commit

Permalink
bot, plugins: fix per-channel configuration by plugin name
Browse files Browse the repository at this point in the history
When this feature was first implemented, core plugins and user plugins
(from `~/.sopel/modules`) both loaded in a similar way. Their Python
module names matched the file names, and nobody thought to test how this
feature worked (or might not) for `sopel_modules` packages. Certainly,
no one thought to test entry-point plugins (new in 7.0, implemented
*after* this was).

To make a long story short (the full narrative is summarized in #1839),
this feature was never going to work as intended in all cases. Changes
to the plugin machinery simply made it *also* not work for core plugins,
which made the shortcomings of its implementation much more obvious.

Before passing the module contents back to `bot` during registration,
the `plugins.handlers.PyModulePlugin` class (and derivatives) now adds a
`plugin_name` attribute to each "relevant part" (callable). This is
immediately useful for improving the per-channel filtering so it works
as expected, and will likely find more use in the future (e.g. as a
substitute for the long-deprecated `bot.command_groups` property).

In `bot`, in addition to using the new callable attribute instead of
Python's module name for per-channel filtering, I also added log output
to debug mode for completeness.
  • Loading branch information
dgw committed Apr 9, 2020
1 parent fd610c8 commit 8776354
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 3 deletions.
18 changes: 15 additions & 3 deletions sopel/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -574,16 +574,28 @@ def call(self, func, sopel, trigger):

# if "*" is used, we are disabling all plugins on provided channel
if '*' in disabled_plugins:
LOGGER.debug(
"All plugins disabled in %s; skipping execution of %s.%s",
trigger.sender, func.plugin_name, func.__name__
)
return
if func.__module__ in disabled_plugins:
if func.plugin_name in disabled_plugins:
LOGGER.debug(
"Plugin %s is disabled in %s; skipping execution of %s",
func.plugin_name, trigger.sender, func.__name__
)
return

# disable chosen methods from plugins
if 'disable_commands' in channel_config:
disabled_commands = literal_eval(channel_config.disable_commands)

if func.__module__ in disabled_commands:
if func.__name__ in disabled_commands[func.__module__]:
if func.plugin_name in disabled_commands:
if func.__name__ in disabled_commands[func.plugin_name]:
LOGGER.debug(
"Skipping execution of %s.%s in %s: disabled_commands matched",
func.plugin_name, func.__name__, trigger.sender
)
return

try:
Expand Down
5 changes: 5 additions & 0 deletions sopel/plugins/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import inspect
import imp
import importlib
import itertools
import os

from sopel import loader
Expand Down Expand Up @@ -259,6 +260,10 @@ def has_setup(self):

def register(self, bot):
relevant_parts = loader.clean_module(self._module, bot.config)
for part in itertools.chain(*relevant_parts):
# annotate all callables in relevant_parts with `plugin_name`
# attribute to make per-channel config work; see #1839
setattr(part, 'plugin_name', self.name)
bot.add_plugin(self, *relevant_parts)

def unregister(self, bot):
Expand Down

0 comments on commit 8776354

Please sign in to comment.