Skip to content

Commit 66434d0

Browse files
PIG208timabbott
authored andcommitted
bots: Indicate source of bot (from source/module/registry) upon startup.
Amend tests to include new parameter.
1 parent 4bc0c60 commit 66434d0

File tree

5 files changed

+47
-9
lines changed

5 files changed

+47
-9
lines changed

zulip_bots/zulip_bots/finder.py

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class DuplicateRegisteredBotName(Exception):
3232
pass
3333

3434

35-
def import_module_from_zulip_bot_registry(name: str) -> Optional[ModuleType]:
35+
def import_module_from_zulip_bot_registry(name: str) -> Tuple[str, Optional[ModuleType]]:
3636
# Prior to Python 3.10, calling importlib.metadata.entry_points returns a
3737
# SelectableGroups object when no parameters is given. Currently we use
3838
# the importlib_metadata library for compatibility, but we need to migrate
@@ -42,12 +42,38 @@ def import_module_from_zulip_bot_registry(name: str) -> Optional[ModuleType]:
4242
matching_bots = [bot for bot in registered_bots if bot.name == name]
4343

4444
if len(matching_bots) == 1: # Unique matching entrypoint
45-
return matching_bots[0].load()
45+
"""We expect external bots to be registered using entry_points in the
46+
group "zulip_bots.registry", where the name of the entry point should
47+
match the name of the module containing the bot handler and the value
48+
of it should be the package containing the bot handler module.
49+
50+
E.g, an Python package for a bot called "packaged_bot" should have an
51+
`entry_points` setup like the following:
52+
53+
setup(
54+
...
55+
entry_points={
56+
"zulip_bots.registry":[
57+
"packaged_bot=packaged_bot.packaged_bot"
58+
]
59+
}
60+
...
61+
)
62+
"""
63+
bot = matching_bots[0]
64+
bot_name = bot.name
65+
bot_module = bot.load()
66+
bot_version = bot_module.__version__
67+
68+
if bot_version is not None:
69+
return f"{bot_name}: {bot_version}", bot_module
70+
else:
71+
return f"editable package: {bot_name}", bot_module
4672

4773
if len(matching_bots) > 1:
4874
raise DuplicateRegisteredBotName(name)
4975

50-
return None # no matches in registry
76+
return "", None # no matches in registry
5177

5278

5379
def resolve_bot_path(name: str) -> Optional[Tuple[Path, str]]:

zulip_bots/zulip_bots/lib.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,7 @@ def run_message_handler_for_bot(
443443
config_file: str,
444444
bot_config_file: str,
445445
bot_name: str,
446+
bot_source: str,
446447
) -> Any:
447448
"""
448449
lib_module is of type Any, since it can contain any bot's
@@ -473,7 +474,7 @@ def run_message_handler_for_bot(
473474
message_handler = prepare_message_handler(bot_name, restricted_client, lib_module)
474475

475476
if not quiet:
476-
print("Running {} Bot:".format(bot_details["name"]))
477+
print("Running {} Bot (from {}):".format(bot_details["name"], bot_source))
477478
if bot_details["description"] != "":
478479
print("\n\t{}".format(bot_details["description"]))
479480
if hasattr(message_handler, "usage"):

zulip_bots/zulip_bots/run.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ def main() -> None:
118118

119119
if args.registry:
120120
try:
121-
lib_module = finder.import_module_from_zulip_bot_registry(args.bot)
121+
bot_source, lib_module = finder.import_module_from_zulip_bot_registry(args.bot)
122122
except finder.DuplicateRegisteredBotName as error:
123123
print(
124124
f'ERROR: Found duplicate entries for "{error}" in zulip bots registry.\n'
@@ -151,10 +151,12 @@ def main() -> None:
151151
)
152152
print(dep_err_msg.format(bot_name=bot_name, deps_list=deps_list))
153153
sys.exit(1)
154+
bot_source = "source"
154155
else:
155156
lib_module = finder.import_module_by_name(args.bot)
156157
if lib_module:
157158
bot_name = lib_module.__name__
159+
bot_source = "named module"
158160
if args.provision:
159161
print("ERROR: Could not load bot's module for '{}'. Exiting now.")
160162
sys.exit(1)
@@ -179,6 +181,7 @@ def main() -> None:
179181
bot_config_file=args.bot_config_file,
180182
quiet=args.quiet,
181183
bot_name=bot_name,
184+
bot_source=bot_source,
182185
)
183186
except NoBotConfigException:
184187
print(

zulip_bots/zulip_bots/tests/test_lib.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ def test_message(message, flags):
197197
config_file=None,
198198
bot_config_file=None,
199199
bot_name="testbot",
200+
bot_source="bot code location",
200201
)
201202

202203
def test_upload_file(self):

zulip_bots/zulip_bots/tests/test_run.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,24 @@
22
import os
33
import sys
44
import unittest
5-
from importlib.metadata import EntryPoint
65
from pathlib import Path
76
from typing import Optional
87
from unittest import TestCase, mock
9-
from unittest.mock import patch
8+
from unittest.mock import MagicMock, patch
109

1110
import zulip_bots.run
11+
from zulip_bots.finder import metadata
1212
from zulip_bots.lib import extract_query_without_mention
1313

1414

1515
class TestDefaultArguments(TestCase):
1616

1717
our_dir = os.path.dirname(__file__)
1818
path_to_bot = os.path.abspath(os.path.join(our_dir, "../bots/giphy/giphy.py"))
19-
packaged_bot_entrypoint = EntryPoint("packaged_bot", "module_name", "zulip_bots.registry")
19+
packaged_bot_module = MagicMock(__version__="1.0.0")
20+
packaged_bot_entrypoint = metadata.EntryPoint(
21+
"packaged_bot", "module_name", "zulip_bots.registry"
22+
)
2023

2124
@patch("sys.argv", ["zulip-run-bot", "giphy", "--config-file", "/foo/bar/baz.conf"])
2225
@patch("zulip_bots.run.run_message_handler_for_bot")
@@ -31,6 +34,7 @@ def test_argument_parsing_with_bot_name(
3134
config_file="/foo/bar/baz.conf",
3235
bot_config_file=None,
3336
lib_module=mock.ANY,
37+
bot_source="source",
3438
quiet=False,
3539
)
3640

@@ -47,6 +51,7 @@ def test_argument_parsing_with_bot_path(
4751
config_file="/foo/bar/baz.conf",
4852
bot_config_file=None,
4953
lib_module=mock.ANY,
54+
bot_source="source",
5055
quiet=False,
5156
)
5257

@@ -58,7 +63,8 @@ def test_argument_parsing_with_zulip_bot_registry(
5863
self, mock_run_message_handler_for_bot: mock.Mock
5964
) -> None:
6065
with patch("zulip_bots.run.exit_gracefully_if_zulip_config_is_missing"), patch(
61-
"zulip_bots.finder.metadata.EntryPoint.load"
66+
"zulip_bots.finder.metadata.EntryPoint.load",
67+
return_value=self.packaged_bot_module,
6268
), patch(
6369
"zulip_bots.finder.metadata.entry_points",
6470
return_value=(self.packaged_bot_entrypoint,),
@@ -70,6 +76,7 @@ def test_argument_parsing_with_zulip_bot_registry(
7076
config_file="/foo/bar/baz.conf",
7177
bot_config_file=None,
7278
lib_module=mock.ANY,
79+
bot_source="packaged_bot: 1.0.0",
7380
quiet=False,
7481
)
7582

0 commit comments

Comments
 (0)