Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

loader, plugin: load decorated callables only #1936

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions sopel/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,11 @@ def clean_module(module, config):
urls = []
for obj in itervalues(vars(module)):
if callable(obj):
is_sopel_callable = getattr(obj, '_sopel_callable', False) is True
if getattr(obj, '__name__', None) == 'shutdown':
shutdowns.append(obj)
elif not is_sopel_callable:
continue
elif is_triggerable(obj):
clean_callable(obj, config)
callables.append(obj)
Expand Down
11 changes: 11 additions & 0 deletions sopel/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ def spam_every_5s(bot):

"""
def add_attribute(function):
function._sopel_callable = True
if not hasattr(function, "interval"):
function.interval = []
for arg in intervals:
Expand Down Expand Up @@ -201,6 +202,7 @@ def rule(*patterns):

"""
def add_attribute(function):
function._sopel_callable = True
if not hasattr(function, "rule"):
function.rule = []
for value in patterns:
Expand Down Expand Up @@ -255,6 +257,7 @@ def find(*patterns):

"""
def add_attribute(function):
function._sopel_callable = True
if not hasattr(function, "find_rules"):
function.find_rules = []
for value in patterns:
Expand Down Expand Up @@ -312,6 +315,7 @@ def search(*patterns):

"""
def add_attribute(function):
function._sopel_callable = True
if not hasattr(function, "search_rules"):
function.search_rules = []
for value in patterns:
Expand Down Expand Up @@ -441,6 +445,7 @@ def command(*command_list):

"""
def add_attribute(function):
function._sopel_callable = True
if not hasattr(function, "commands"):
function.commands = []
for command in command_list:
Expand Down Expand Up @@ -486,6 +491,7 @@ def nickname_command(*command_list):

"""
def add_attribute(function):
function._sopel_callable = True
if not hasattr(function, 'nickname_commands'):
function.nickname_commands = []
for cmd in command_list:
Expand Down Expand Up @@ -540,6 +546,7 @@ def action_command(*command_list):

"""
def add_attribute(function):
function._sopel_callable = True
if not hasattr(function, 'action_commands'):
function.action_commands = []
for cmd in command_list:
Expand Down Expand Up @@ -608,6 +615,7 @@ def event(*event_list):

"""
def add_attribute(function):
function._sopel_callable = True
if not hasattr(function, "event"):
function.event = []
for name in event_list:
Expand All @@ -632,6 +640,7 @@ def intent(*intent_list):

"""
def add_attribute(function):
function._sopel_callable = True
if not hasattr(function, "intents"):
function.intents = []
for name in intent_list:
Expand Down Expand Up @@ -945,6 +954,7 @@ def handle_example_bugs(bot, trigger):

"""
def actual_decorator(function):
function._sopel_callable = True
if not hasattr(function, 'url_regex'):
function.url_regex = []
for url_rule in url_rules:
Expand Down Expand Up @@ -995,6 +1005,7 @@ def my_url_handler(bot, trigger):

"""
def decorator(function):
function._sopel_callable = True
if not hasattr(function, 'url_lazy_loaders'):
function.url_lazy_loaders = []
function.url_lazy_loaders.extend(loaders)
Expand Down
36 changes: 36 additions & 0 deletions test/test_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,25 @@ def shutdown():
def ignored():
pass


@sopel.module.rate(10)
def ignored_rate():
pass


class Ignored:
def __init__(self):
self.rule = [r'.*']

def __call__(self, bot, trigger):
pass

ignored_obj = Ignored()

def ignored_trickster():
pass

ignored_trickster._sopel_callable = True
"""


Expand Down Expand Up @@ -185,6 +204,23 @@ def test_clean_module(testplugin, tmpconfig):
assert test_mod.ignored not in jobs
assert test_mod.ignored not in shutdowns
assert test_mod.ignored not in urls
# @rate doesn't create a callable and is ignored
assert test_mod.ignored_rate not in callables
assert test_mod.ignored_rate not in jobs
assert test_mod.ignored_rate not in shutdowns
assert test_mod.ignored_rate not in urls
# object with a triggerable attribute are ignored by default
assert loader.is_triggerable(test_mod.ignored_obj)
assert test_mod.ignored_obj not in callables
assert test_mod.ignored_obj not in jobs
assert test_mod.ignored_obj not in shutdowns
assert test_mod.ignored_obj not in urls
# trickster function is ignored: it's still not a proper plugin callable
assert not loader.is_triggerable(test_mod.ignored_trickster)
assert test_mod.ignored_trickster not in callables
assert test_mod.ignored_trickster not in jobs
assert test_mod.ignored_trickster not in shutdowns
assert test_mod.ignored_trickster not in urls


def test_clean_module_idempotency(testplugin, tmpconfig):
Expand Down