zulip_botserver: Get rid of some global variables.

This commit is contained in:
Guitar1st 2018-05-15 14:55:58 +00:00 committed by Tim Abbott
parent 7b6da265ea
commit f90913d54c
3 changed files with 35 additions and 23 deletions

View file

@ -1,9 +1,11 @@
import json import json
from typing import Any, List, Dict, Optional from typing import Any, List, Dict, Optional, Union
from unittest import TestCase from unittest import TestCase
from werkzeug.exceptions import BadRequest
from zulip_botserver import server from zulip_botserver import server
class BotServerTestCase(TestCase): class BotServerTestCase(TestCase):
def setUp(self) -> None: def setUp(self) -> None:
@ -12,17 +14,21 @@ class BotServerTestCase(TestCase):
def assert_bot_server_response(self, def assert_bot_server_response(self,
available_bots: Optional[List[str]]=None, available_bots: Optional[List[str]]=None,
bots_config: Optional[Dict[str, Any]]=None, bots_config: Optional[Dict[str, Dict[str, str]]]=None,
bots_lib_module: Optional[Dict[str, Any]]=None, bots_lib_module: Optional[Dict[str, Any]]=None,
bot_handlers: Optional[Dict[str, Any]]=None, bot_handlers: Optional[Union[Dict[str, Any], BadRequest]]=None,
payload_url: str="/bots/helloworld", payload_url: str="/bots/helloworld",
message: Optional[Dict[str, Any]]=dict(message={'key': "test message"}), message: Optional[Dict[str, Any]]=dict(message={'key': "test message"}),
check_success: bool=False, check_success: bool=False,
) -> None: ) -> None:
if available_bots is not None: if available_bots is not None and bots_config is not None:
server.available_bots = available_bots server.available_bots = available_bots
server.load_lib_modules() bots_lib_modules = server.load_lib_modules()
server.load_bot_handlers(bots_config) server.app.config["BOTS_LIB_MODULES"] = bots_lib_modules
if bot_handlers is None:
bot_handlers = server.load_bot_handlers(bots_config, bots_lib_modules)
if not isinstance(bot_handlers, BadRequest):
server.app.config["BOT_HANDLERS"] = bot_handlers
response = self.app.post(payload_url, data=json.dumps(message)) response = self.app.post(payload_url, data=json.dumps(message))

View file

@ -4,6 +4,7 @@ import unittest
from .server_test_lib import BotServerTestCase from .server_test_lib import BotServerTestCase
import six import six
class BotServerTests(BotServerTestCase): class BotServerTests(BotServerTestCase):
class MockMessageHandler(object): class MockMessageHandler(object):
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None:

View file

@ -6,7 +6,7 @@ import sys
from flask import Flask, request from flask import Flask, request
from importlib import import_module from importlib import import_module
from typing import Any, Dict, Union, List, Optional from typing import Any, Dict, Union, List
from werkzeug.exceptions import BadRequest from werkzeug.exceptions import BadRequest
from zulip import Client from zulip import Client
@ -14,8 +14,7 @@ from zulip_bots.custom_exceptions import ConfigValidationError
from zulip_bots.lib import ExternalBotHandler, StateHandler from zulip_bots.lib import ExternalBotHandler, StateHandler
available_bots = [] # type: List[str] available_bots = [] # type: List[str]
bots_lib_module = {} # type: Dict[str, Any]
bot_handlers = {} # type: Dict[str, ExternalBotHandler]
def read_config_file(config_file_path: str) -> Dict[str, Dict[str, str]]: def read_config_file(config_file_path: str) -> Dict[str, Dict[str, str]]:
config_file_path = os.path.abspath(os.path.expanduser(config_file_path)) config_file_path = os.path.abspath(os.path.expanduser(config_file_path))
@ -33,7 +32,9 @@ def read_config_file(config_file_path: str) -> Dict[str, Dict[str, str]]:
} }
return bots_config return bots_config
def load_lib_modules() -> None:
def load_lib_modules() -> Dict[str, Any]:
bots_lib_module = {}
for bot in available_bots: for bot in available_bots:
try: try:
module_name = 'zulip_bots.bots.{bot}.{bot}'.format(bot=bot) module_name = 'zulip_bots.bots.{bot}.{bot}'.format(bot=bot)
@ -41,13 +42,17 @@ def load_lib_modules() -> None:
bots_lib_module[bot] = lib_module bots_lib_module[bot] = lib_module
except ImportError: except ImportError:
raise ImportError( raise ImportError(
"\n Import Error: Bot \"{}\" doesn't exists. Please make sure you have set up the flaskbotrc " "\nImport Error: Bot \"{}\" doesn't exists. "
"file correctly.\n".format(bot) "Please make sure you have set up the flaskbotrc file correctly.\n".format(bot)
) )
return bots_lib_module
def load_bot_handlers( def load_bot_handlers(
bots_config: Dict[str, Dict[str, str]], bots_config: Dict[str, Dict[str, str]],
) -> Optional[BadRequest]: bots_lib_module: Dict[str, Any],
) -> Union[Dict[str, ExternalBotHandler], BadRequest]:
bot_handlers = {}
for bot in available_bots: for bot in available_bots:
client = Client(email=bots_config[bot]["email"], client = Client(email=bots_config[bot]["email"],
api_key=bots_config[bot]["key"], api_key=bots_config[bot]["key"],
@ -64,7 +69,7 @@ def load_bot_handlers(
) )
bot_handlers[bot] = bot_handler bot_handlers[bot] = bot_handler
lib_module = get_bot_lib_module(bot) lib_module = bots_lib_module[bot]
message_handler = lib_module.handler_class() message_handler = lib_module.handler_class()
if hasattr(message_handler, 'validate_config'): if hasattr(message_handler, 'validate_config'):
config_data = bot_handlers[bot].get_config_info(bot) config_data = bot_handlers[bot].get_config_info(bot)
@ -79,18 +84,15 @@ def load_bot_handlers(
except SystemExit: except SystemExit:
return BadRequest("Cannot fetch user profile for bot {}, make sure you have set up the flaskbotrc " return BadRequest("Cannot fetch user profile for bot {}, make sure you have set up the flaskbotrc "
"file correctly.".format(bot)) "file correctly.".format(bot))
return None return bot_handlers
def get_bot_lib_module(bot: str) -> Any:
if bot in bots_lib_module.keys():
return bots_lib_module[bot]
return None
app = Flask(__name__) app = Flask(__name__)
@app.route('/bots/<bot>', methods=['POST']) @app.route('/bots/<bot>', methods=['POST'])
def handle_bot(bot: str) -> Union[str, BadRequest]: def handle_bot(bot: str) -> Union[str, BadRequest]:
lib_module = get_bot_lib_module(bot) lib_module = app.config.get("BOTS_LIB_MODULES", {}).get(bot)
if lib_module is None: if lib_module is None:
return BadRequest("Can't find the configuration or Bot Handler code for bot {}. " return BadRequest("Can't find the configuration or Bot Handler code for bot {}. "
"Make sure that the `zulip_bots` package is installed, and " "Make sure that the `zulip_bots` package is installed, and "
@ -99,9 +101,10 @@ def handle_bot(bot: str) -> Union[str, BadRequest]:
event = request.get_json(force=True) event = request.get_json(force=True)
message_handler.handle_message(message=event["message"], message_handler.handle_message(message=event["message"],
bot_handler=bot_handlers[bot]) bot_handler=app.config["BOT_HANDLERS"].get(bot))
return json.dumps("") return json.dumps("")
def parse_args() -> argparse.Namespace: def parse_args() -> argparse.Namespace:
usage = ''' usage = '''
zulip-bot-server --config-file <path to flaskbotrc> --hostname <address> --port <port> zulip-bot-server --config-file <path to flaskbotrc> --hostname <address> --port <port>
@ -139,8 +142,10 @@ def main() -> None:
bots_config = read_config_file(options.config_file) bots_config = read_config_file(options.config_file)
global available_bots global available_bots
available_bots = list(bots_config.keys()) available_bots = list(bots_config.keys())
load_lib_modules() bots_lib_modules = load_lib_modules()
load_bot_handlers(bots_config) bot_handlers = load_bot_handlers(bots_config, bots_lib_modules)
app.config["BOTS_LIB_MODULES"] = bots_lib_modules
app.config["BOT_HANDLERS"] = bot_handlers
app.run(host=options.hostname, port=int(options.port), debug=True) app.run(host=options.hostname, port=int(options.port), debug=True)
if __name__ == '__main__': if __name__ == '__main__':