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

bot, coretasks, url: search_url_callbacks() as a public wrapper #2585

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
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
4 changes: 4 additions & 0 deletions sopel/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -1255,6 +1255,10 @@ def search_url_callbacks(self, url):
.. __: https://docs.python.org/3.11/library/re.html#match-objects

"""
return self._search_url_callbacks_impl(url)

def _search_url_callbacks_impl(self, url):
# actual implementation, usable internally without warnings
for regex, function in self._url_callbacks.items():
match = regex.search(url)
if match:
Expand Down
5 changes: 3 additions & 2 deletions sopel/builtins/url.py
Original file line number Diff line number Diff line change
Expand Up @@ -502,8 +502,9 @@ def check_callbacks(bot: SopelWrapper, url: str, use_excludes: bool = True) -> b
)
return (
excluded or
any(bot.search_url_callbacks(url)) or
bot.rules.check_url_callback(bot, url)
bot.rules.check_url_callback(bot, url) or
# don't do this in YOUR plugins
any(bot._search_url_callbacks_impl(url))
)


Expand Down
4 changes: 3 additions & 1 deletion sopel/coretasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -1608,6 +1608,8 @@ def track_topic(bot, trigger):
LOGGER.info("Channel's topic updated: %s", channel)


# TODO: This needs to go away with the rest of the obsolete manually-registered-
# URL-callback system in Sopel 9.0
@plugin.rule(r'(?u).*(.+://\S+).*')
def handle_url_callbacks(bot, trigger):
"""Dispatch callbacks on URLs
Expand All @@ -1618,7 +1620,7 @@ def handle_url_callbacks(bot, trigger):
# find URLs in the trigger
for url in trigger.urls:
# find callbacks for said URL
for function, match in bot.search_url_callbacks(url):
for function, match in bot._search_url_callbacks_impl(url):
# trigger callback defined by the `@url` decorator
if hasattr(function, 'url_regex'):
# bake the `match` argument in before passing the callback on
Expand Down
36 changes: 18 additions & 18 deletions test/test_bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -1307,7 +1307,7 @@ def url_handler(*args, **kwargs):
return None

sopel.register_url_callback(r'https://example\.com', url_handler)
results = list(sopel.search_url_callbacks('https://example.com'))
results = list(sopel._search_url_callbacks_impl('https://example.com'))
assert len(results) == 1, 'Expected 1 handler; found %d' % len(results)
assert url_handler in results[0], 'Once registered, handler must be found'

Expand All @@ -1320,11 +1320,11 @@ def url_handler(*args, **kwargs):
return None

sopel.register_url_callback(r'https://(www\.)?example\.com', url_handler)
results = list(sopel.search_url_callbacks('https://example.com'))
results = list(sopel._search_url_callbacks_impl('https://example.com'))
assert len(results) == 1, 'Expected 1 handler; found %d' % len(results)
assert url_handler in results[0], 'Once registered, handler must be found'

results = list(sopel.search_url_callbacks('https://www.example.com'))
results = list(sopel._search_url_callbacks_impl('https://www.example.com'))
assert len(results) == 1, 'Regex pattern must match both URLs'
assert url_handler in results[0]

Expand All @@ -1338,27 +1338,27 @@ def url_handler(*args, **kwargs):
return None

sopel.register_url_callback(url_regex, url_handler)
results = list(sopel.search_url_callbacks('https://example.com'))
results = list(sopel._search_url_callbacks_impl('https://example.com'))
assert len(results) == 1, 'Expected 1 handler; found %d' % len(results)
assert url_handler in results[0], 'Once registered, handler must be found'

results = list(sopel.search_url_callbacks('https://www.example.com'))
results = list(sopel._search_url_callbacks_impl('https://www.example.com'))
assert len(results) == 1, 'Regex pattern must match both URLs'
assert url_handler in results[0]


def test_search_url_callbacks_not_found(tmpconfig):
"""Test search_url_callbacks when pattern does not match."""
sopel = bot.Sopel(tmpconfig, daemon=False)
results = sopel.search_url_callbacks('https://example.com')
results = sopel._search_url_callbacks_impl('https://example.com')
assert not list(results), 'No handler registered; must return an empty list'

def url_handler(*args, **kwargs):
return None

sopel.register_url_callback(r'https://(www\.)?example\.com', url_handler)

results = sopel.search_url_callbacks('https://not-example.com')
results = sopel._search_url_callbacks_impl('https://not-example.com')
assert not list(results), 'URL must not match any pattern'


Expand All @@ -1375,12 +1375,12 @@ def url_handler_replacement(*args, **kwargs):
sopel = bot.Sopel(tmpconfig, daemon=False)
sopel.register_url_callback(test_pattern, url_handler)

results = list(sopel.search_url_callbacks('https://www.example.com'))
results = list(sopel._search_url_callbacks_impl('https://www.example.com'))
assert url_handler in results[0]

sopel.register_url_callback(test_pattern, url_handler_replacement)

results = list(sopel.search_url_callbacks('https://www.example.com'))
results = list(sopel._search_url_callbacks_impl('https://www.example.com'))
assert len(results) == 1, 'There must be one and only one callback'
assert url_handler_replacement in results[0], (
'Handler must have been replaced')
Expand All @@ -1397,13 +1397,13 @@ def url_handler(*args, **kwargs):

# now register a pattern, make sure it still work
sopel.register_url_callback(test_pattern, url_handler)
assert list(sopel.search_url_callbacks('https://www.example.com'))
assert list(sopel._search_url_callbacks_impl('https://www.example.com'))

# unregister this pattern
sopel.unregister_url_callback(test_pattern, url_handler)

# now it is not possible to find a callback for this pattern
results = list(sopel.search_url_callbacks('https://www.example.com'))
results = list(sopel._search_url_callbacks_impl('https://www.example.com'))
assert not results, 'Unregistered URL callback must not work anymore'


Expand All @@ -1430,13 +1430,13 @@ def url_handler(*args, **kwargs):

# now register a pattern, make sure it still work
sopel.register_url_callback(test_pattern, url_handler)
assert list(sopel.search_url_callbacks('https://www.example.com'))
assert list(sopel._search_url_callbacks_impl('https://www.example.com'))

# unregister another pattern (that doesn't exist)
sopel.unregister_url_callback(r'http://localhost', url_handler)

# the existing pattern still work
assert list(sopel.search_url_callbacks('https://www.example.com'))
assert list(sopel._search_url_callbacks_impl('https://www.example.com'))


def test_unregister_url_callback_compiled_pattern(tmpconfig):
Expand All @@ -1451,12 +1451,12 @@ def url_handler(*args, **kwargs):

# now register a pattern, make sure it still work
sopel.register_url_callback(test_pattern, url_handler)
assert list(sopel.search_url_callbacks('https://www.example.com'))
assert list(sopel._search_url_callbacks_impl('https://www.example.com'))

# unregister using the compiled version
sopel.unregister_url_callback(url_regex, url_handler)

assert not list(sopel.search_url_callbacks('https://www.example.com'))
assert not list(sopel._search_url_callbacks_impl('https://www.example.com'))


def test_multiple_url_callback(tmpconfig):
Expand All @@ -1474,7 +1474,7 @@ def url_handler_global(*args, **kwargs):
sopel.register_url_callback(test_pattern_example, url_handler)
sopel.register_url_callback(test_pattern_global, url_handler_global)

results = list(sopel.search_url_callbacks('https://example.com'))
results = list(sopel._search_url_callbacks_impl('https://example.com'))
assert len(results) == 2
handlers = [result[0] for result in results]

Expand All @@ -1484,7 +1484,7 @@ def url_handler_global(*args, **kwargs):
# now unregister one of them: the other must still work
sopel.unregister_url_callback(test_pattern_example, url_handler)

results = list(sopel.search_url_callbacks('https://example.com'))
results = list(sopel._search_url_callbacks_impl('https://example.com'))
assert len(results) == 1, 'Exactly one handler must remain'
assert url_handler_global in results[0], 'Wrong remaining handler'

Expand All @@ -1504,7 +1504,7 @@ def url_handler(*args, **kwargs):

# register a callback manually
sopel.memory['url_callbacks'][re.compile(test_pattern)] = url_handler
results = list(sopel.search_url_callbacks("https://www.example.com"))
results = list(sopel._search_url_callbacks_impl("https://www.example.com"))
assert not results, "Manually registered callback must not be found"


Expand Down