diff --git a/tools/run-mypy b/tools/run-mypy index fd2078e..a40b9e2 100755 --- a/tools/run-mypy +++ b/tools/run-mypy @@ -40,6 +40,8 @@ force_include = [ "zulip_bots/zulip_bots/bots/followup/test_followup.py", "zulip_bots/zulip_bots/bots/giphy/giphy.py", "zulip_bots/zulip_bots/bots/giphy/test_giphy.py", + "zulip_bots/zulip_bots/bots/github_detail/github_detail.py", + "zulip_bots/zulip_bots/bots/github_detail/test_github_detail.py", ] parser = argparse.ArgumentParser(description="Run mypy on files tracked by git.") diff --git a/zulip_bots/zulip_bots/bots/github_detail/github_detail.py b/zulip_bots/zulip_bots/bots/github_detail/github_detail.py index 9f885dd..40b30cf 100644 --- a/zulip_bots/zulip_bots/bots/github_detail/github_detail.py +++ b/zulip_bots/zulip_bots/bots/github_detail/github_detail.py @@ -6,6 +6,8 @@ import six.moves.configparser import requests +from typing import Dict, Any, Tuple, Union + class GithubHandler(object): ''' This bot provides details on github issues and pull requests when they're @@ -15,21 +17,19 @@ class GithubHandler(object): GITHUB_ISSUE_URL_TEMPLATE = 'https://api.github.com/repos/{owner}/{repo}/issues/{id}' HANDLE_MESSAGE_REGEX = re.compile("(?:([\w-]+)\/)?([\w-]+)?#(\d+)") - def initialize(self, bot_handler): + def initialize(self: Any, bot_handler: Any) -> None: self.config_info = bot_handler.get_config_info('github_detail', optional=True) self.owner = self.config_info.get("owner", False) self.repo = self.config_info.get("repo", False) - def usage(self): - # type: () -> None + def usage(self: Any) -> str: return ("This plugin displays details on github issues and pull requests. " "To reference an issue or pull request usename mention the bot then " "anytime in the message type its id, for example:\n" "@**Github detail** #3212 zulip#3212 zulip/zulip#3212\n" "The default owner is {} and the default repo is {}.".format(self.owner, self.repo)) - def format_message(self, details): - # type: (Dict[Text, Union[Text, int, bool]]) -> Text + def format_message(self: Any, details: Dict[str, Any]) -> str: number = details['number'] title = details['title'] link = details['html_url'] @@ -46,21 +46,19 @@ class GithubHandler(object): 'Status - **{status}**\n```quote\n{description}\n```'.format(status=status, description=description)) return ''.join(message_string) - def get_details_from_github(self, owner, repo, number): - # type: (Text, Text, Text) -> Dict[Text, Union[Text, Int, Bool]] + def get_details_from_github(self: Any, owner: str, repo: str, number: str) -> Union[None, Dict[str, Union[str, int, bool]]]: # Gets the details of an issues or pull request - try: r = requests.get( self.GITHUB_ISSUE_URL_TEMPLATE.format(owner=owner, repo=repo, id=number)) except requests.exceptions.RequestException as e: - logging.exception(e) - return + logging.exception(str(e)) + return None if r.status_code != requests.codes.ok: - return + return None return r.json() - def get_owner_and_repo(self, issue_pr): + def get_owner_and_repo(self: Any, issue_pr: Any) -> Tuple[str, str]: owner = issue_pr.group(1) repo = issue_pr.group(2) if owner is None: @@ -69,8 +67,7 @@ class GithubHandler(object): repo = self.repo return (owner, repo) - def handle_message(self, message, bot_handler): - # type: () -> None + def handle_message(self: Any, message: Dict[str, str], bot_handler: Any) -> None: # Send help message if message['content'] == 'help': bot_handler.send_reply(message, self.usage()) diff --git a/zulip_bots/zulip_bots/bots/github_detail/test_github_detail.py b/zulip_bots/zulip_bots/bots/github_detail/test_github_detail.py index b5196b4..049596a 100755 --- a/zulip_bots/zulip_bots/bots/github_detail/test_github_detail.py +++ b/zulip_bots/zulip_bots/bots/github_detail/test_github_detail.py @@ -7,18 +7,19 @@ import json from zulip_bots.test_lib import BotTestCase +from typing import Any + class TestGithubDetailBot(BotTestCase): bot_name = "github_detail" mock_config = {'owner': 'zulip', 'repo': 'zulip'} # Overrides default test_bot_usage(). - def test_bot_usage(self): - # type: () -> None + def test_bot_usage(self: Any) -> None: with self.mock_config_info(self.mock_config): self.initialize_bot() self.assertNotEqual(self.message_handler.usage(), '') - def test_issue(self): + def test_issue(self: Any) -> None: bot_response = '**[zulip/zulip#5365](https://github.com/zulip/zulip/issues/5365)'\ ' - frontend: Enable hot-reloading of CSS in development**\n'\ 'Created by **[timabbott](https://github.com/timabbott)**\n'\ @@ -36,7 +37,7 @@ class TestGithubDetailBot(BotTestCase): expected_method='send_reply' ) - def test_pull_request(self): + def test_pull_request(self: Any) -> None: bot_response = '**[zulip/zulip#5345](https://github.com/zulip/zulip/pull/5345)'\ ' - [WIP] modal: Replace bootstrap modal with custom modal class**\n'\ 'Created by **[jackrzhang](https://github.com/jackrzhang)**\n'\ @@ -56,7 +57,7 @@ class TestGithubDetailBot(BotTestCase): expected_method='send_reply' ) - def test_404(self): + def test_404(self: Any) -> None: bot_response = 'Failed to find issue/pr: zulip/zulip#0' # This message calls the `send_reply` function of BotHandlerApi with self.mock_http_conversation('test_404'): @@ -66,7 +67,7 @@ class TestGithubDetailBot(BotTestCase): expected_method='send_reply' ) - def test_random_text(self): + def test_random_text(self: Any) -> None: bot_response = 'Failed to find any issue or PR.' # This message calls the `send_reply` function of BotHandlerApi self.assert_bot_response( @@ -75,7 +76,7 @@ class TestGithubDetailBot(BotTestCase): expected_method='send_reply' ) - def test_help_text(self): + def test_help_text(self: Any) -> None: bot_response = 'This plugin displays details on github issues and pull requests. '\ 'To reference an issue or pull request usename mention the bot then '\ 'anytime in the message type its id, for example:\n@**Github detail** '\