zulip-run-bot: Add the ability to run a bot by the module name.
This commit is contained in:
parent
f4bea72557
commit
3448d9c9c1
|
@ -23,12 +23,22 @@ def import_module_from_source(path: Text, name: Text) -> Any:
|
||||||
|
|
||||||
return module
|
return module
|
||||||
|
|
||||||
def resolve_bot_path(name: Text) -> Tuple[Text, Text]:
|
def import_module_by_name(name: Text) -> Any:
|
||||||
|
import importlib
|
||||||
|
try:
|
||||||
|
return importlib.import_module(name)
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def resolve_bot_path(name: Text) -> Optional[Tuple[Text, Text]]:
|
||||||
if os.path.isfile(name):
|
if os.path.isfile(name):
|
||||||
bot_path = os.path.abspath(name)
|
bot_path = os.path.abspath(name)
|
||||||
bot_name = splitext(basename(bot_path))[0]
|
bot_name = splitext(basename(bot_path))[0]
|
||||||
|
return (bot_path, bot_name)
|
||||||
else:
|
else:
|
||||||
bot_path = os.path.abspath(os.path.join(current_dir, 'bots', name, name + '.py'))
|
|
||||||
bot_name = name
|
bot_name = name
|
||||||
|
bot_path = os.path.abspath(os.path.join(current_dir, 'bots', bot_name, bot_name + '.py'))
|
||||||
|
if os.path.isfile(bot_path):
|
||||||
|
return (bot_path, bot_name)
|
||||||
|
|
||||||
return (bot_path, bot_name)
|
return None
|
||||||
|
|
|
@ -81,25 +81,34 @@ def exit_gracefully_if_bot_config_file_does_not_exist(bot_config_file: str) -> N
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
args = parse_args()
|
args = parse_args()
|
||||||
|
|
||||||
bot_path, bot_name = finder.resolve_bot_path(args.bot)
|
result = finder.resolve_bot_path(args.bot)
|
||||||
sys.path.insert(0, os.path.dirname(bot_path))
|
if result:
|
||||||
|
bot_path, bot_name = result
|
||||||
|
sys.path.insert(0, os.path.dirname(bot_path))
|
||||||
|
|
||||||
if args.provision:
|
if args.provision:
|
||||||
provision_bot(os.path.dirname(bot_path), args.force)
|
provision_bot(os.path.dirname(bot_path), args.force)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
lib_module = finder.import_module_from_source(bot_path, bot_name)
|
lib_module = finder.import_module_from_source(bot_path, bot_name)
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
req_path = os.path.join(os.path.dirname(bot_path), "requirements.txt")
|
req_path = os.path.join(os.path.dirname(bot_path), "requirements.txt")
|
||||||
with open(req_path) as fp:
|
with open(req_path) as fp:
|
||||||
deps_list = fp.read()
|
deps_list = fp.read()
|
||||||
|
|
||||||
dep_err_msg = ("ERROR: The following dependencies for the {bot_name} bot are not installed:\n\n"
|
dep_err_msg = ("ERROR: The following dependencies for the {bot_name} bot are not installed:\n\n"
|
||||||
"{deps_list}\n"
|
"{deps_list}\n"
|
||||||
"If you'd like us to install these dependencies, run:\n"
|
"If you'd like us to install these dependencies, run:\n"
|
||||||
" zulip-run-bot {bot_name} --provision")
|
" zulip-run-bot {bot_name} --provision")
|
||||||
print(dep_err_msg.format(bot_name=bot_name, deps_list=deps_list))
|
print(dep_err_msg.format(bot_name=bot_name, deps_list=deps_list))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
else:
|
||||||
|
lib_module = finder.import_module_by_name(args.bot)
|
||||||
|
if lib_module:
|
||||||
|
bot_name = lib_module.__name__
|
||||||
|
if args.provision:
|
||||||
|
print("ERROR: Could not load bot's module for '{}'. Exiting now.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
if lib_module is None:
|
if lib_module is None:
|
||||||
print("ERROR: Could not load bot module. Exiting now.")
|
print("ERROR: Could not load bot module. Exiting now.")
|
||||||
|
|
|
@ -42,7 +42,7 @@ class TestDefaultArguments(TestCase):
|
||||||
quiet=False)
|
quiet=False)
|
||||||
|
|
||||||
def test_adding_bot_parent_dir_to_sys_path_when_bot_name_specified(self) -> None:
|
def test_adding_bot_parent_dir_to_sys_path_when_bot_name_specified(self) -> None:
|
||||||
bot_name = 'any_bot_name'
|
bot_name = 'helloworld' # existing bot's name
|
||||||
expected_bot_dir_path = os.path.join(
|
expected_bot_dir_path = os.path.join(
|
||||||
os.path.dirname(zulip_bots.run.__file__),
|
os.path.dirname(zulip_bots.run.__file__),
|
||||||
'bots',
|
'bots',
|
||||||
|
@ -66,6 +66,18 @@ class TestDefaultArguments(TestCase):
|
||||||
|
|
||||||
self.assertIn(bot_dir_path, sys.path)
|
self.assertIn(bot_dir_path, sys.path)
|
||||||
|
|
||||||
|
@patch('os.path.isfile', return_value=False)
|
||||||
|
def test_run_bot_by_module_name(self, mock_os_path_isfile: mock.Mock) -> None:
|
||||||
|
bot_module_name = 'bot.module.name'
|
||||||
|
mock_bot_module = mock.Mock()
|
||||||
|
mock_bot_module.__name__ = bot_module_name
|
||||||
|
with patch('sys.argv', ['zulip-run-bot', 'bot.module.name', '--config-file', '/path/to/config']):
|
||||||
|
with patch('importlib.import_module', return_value=mock_bot_module) as mock_import_module:
|
||||||
|
with patch('zulip_bots.run.run_message_handler_for_bot'):
|
||||||
|
with patch('zulip_bots.run.exit_gracefully_if_zulip_config_file_does_not_exist'):
|
||||||
|
zulip_bots.run.main()
|
||||||
|
mock_import_module.assert_called_once_with(bot_module_name)
|
||||||
|
|
||||||
|
|
||||||
class TestBotLib(TestCase):
|
class TestBotLib(TestCase):
|
||||||
def test_extract_query_without_mention(self) -> None:
|
def test_extract_query_without_mention(self) -> None:
|
||||||
|
|
Loading…
Reference in a new issue