mypy: Add --disallow-any=generics & extend typing accordingly.

Also reset typing of ExternalBotHandler to Any after discussion.
This commit is contained in:
neiljp (Neil Pilgrim) 2017-12-11 13:30:47 -08:00 committed by showell
parent 424a4bb631
commit 28687f18ca
10 changed files with 54 additions and 51 deletions

View file

@ -124,6 +124,7 @@ mypy_command = "mypy"
extra_args = ["--check-untyped-defs", extra_args = ["--check-untyped-defs",
"--follow-imports=silent", "--follow-imports=silent",
"--scripts-are-modules", "--scripts-are-modules",
"--disallow-any=generics",
"-i"] "-i"]
if args.disallow_untyped_defs: if args.disallow_untyped_defs:
extra_args.append("--disallow-untyped-defs") extra_args.append("--disallow-untyped-defs")

View file

@ -301,10 +301,10 @@ class ZulipToJabberBot(object):
def get_rooms(zulipToJabber): def get_rooms(zulipToJabber):
# type: (ZulipToJabberBot) -> List[str] # type: (ZulipToJabberBot) -> List[str]
def get_stream_infos(key, method): def get_stream_infos(key, method):
# type: (str, Callable) -> Any # type: (str, Callable[[], Dict[str, Any]]) -> Any
ret = method() ret = method()
if ret.get("result") != "success": if ret.get("result") != "success":
logging.error(ret) logging.error(str(ret))
sys.exit("Could not get initial list of Zulip %s" % (key,)) sys.exit("Could not get initial list of Zulip %s" % (key,))
return ret[key] return ret[key]

View file

@ -252,7 +252,7 @@ def maybe_restart_mirroring_script():
time.sleep(1) time.sleep(1)
def process_loop(log): def process_loop(log):
# type: (IO) -> None # type: (IO[Any]) -> None
restart_check_count = 0 restart_check_count = 0
last_check_time = time.time() last_check_time = time.time()
while True: while True:
@ -362,7 +362,7 @@ def decrypt_zephyr(zephyr_class, instance, body):
return decrypted return decrypted
def process_notice(notice, log): def process_notice(notice, log):
# type: (zulip, IO) -> None # type: (zulip, IO[Any]) -> None
(zsig, body) = parse_zephyr_body(notice.message, notice.format) (zsig, body) = parse_zephyr_body(notice.message, notice.format)
is_personal = False is_personal = False
is_huddle = False is_huddle = False
@ -579,7 +579,7 @@ def zephyr_to_zulip(options):
process_loop(None) process_loop(None)
def send_zephyr(zwrite_args, content): def send_zephyr(zwrite_args, content):
# type: (List, str) -> Tuple[int, str] # type: (List[str], str) -> Tuple[int, str]
p = subprocess.Popen(zwrite_args, stdin=subprocess.PIPE, p = subprocess.Popen(zwrite_args, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate(input=content.encode("utf-8")) stdout, stderr = p.communicate(input=content.encode("utf-8"))
@ -969,7 +969,7 @@ def configure_logger(logger, direction_name):
handler.setFormatter(formatter) handler.setFormatter(formatter)
def parse_args(): def parse_args():
# type: () -> Tuple # type: () -> Tuple[Any, ...]
parser = optparse.OptionParser() parser = optparse.OptionParser()
parser.add_option('--forward-class-messages', parser.add_option('--forward-class-messages',
default=False, default=False,

View file

@ -435,7 +435,7 @@ class Client(object):
) )
def do_api_query(self, orig_request, url, method="POST", longpolling=False, files=None): def do_api_query(self, orig_request, url, method="POST", longpolling=False, files=None):
# type: (Mapping[str, Any], str, str, bool, List[IO]) -> Dict[str, Any] # type: (Mapping[str, Any], str, str, bool, List[IO[Any]]) -> Dict[str, Any]
if files is None: if files is None:
files = [] files = []
@ -568,14 +568,14 @@ class Client(object):
"status_code": res.status_code} "status_code": res.status_code}
def call_endpoint(self, url=None, method="POST", request=None, longpolling=False, files=None): def call_endpoint(self, url=None, method="POST", request=None, longpolling=False, files=None):
# type: (str, str, Dict[str, Any], bool, List[IO]) -> Dict[str, Any] # type: (str, str, Dict[str, Any], bool, List[IO[Any]]) -> Dict[str, Any]
if request is None: if request is None:
request = dict() request = dict()
return self.do_api_query(request, API_VERSTRING + url, method=method, return self.do_api_query(request, API_VERSTRING + url, method=method,
longpolling=longpolling, files=files) longpolling=longpolling, files=files)
def call_on_each_event(self, callback, event_types=None, narrow=None): def call_on_each_event(self, callback, event_types=None, narrow=None):
# type: (Callable, Optional[List[str]], Any) -> None # type: (Callable[[Any], None], Optional[List[str]], Any) -> None
if narrow is None: if narrow is None:
narrow = [] narrow = []
@ -635,7 +635,7 @@ class Client(object):
callback(event) callback(event)
def call_on_each_message(self, callback): def call_on_each_message(self, callback):
# type: (Callable) -> None # type: (Callable[[Any], None]) -> None
def event_callback(event): def event_callback(event):
# type: (Dict[str, str]) -> None # type: (Dict[str, str]) -> None
if event['type'] == 'message': if event['type'] == 'message':
@ -653,7 +653,7 @@ class Client(object):
) )
def upload_file(self, file): def upload_file(self, file):
# type: (IO) -> Dict[str, Any] # type: (IO[Any]) -> Dict[str, Any]
''' '''
See examples/upload-file for example usage. See examples/upload-file for example usage.
''' '''

View file

@ -25,7 +25,7 @@ from __future__ import print_function
import argparse import argparse
from six.moves import StringIO as _StringIO from six.moves import StringIO as _StringIO
from typing import IO from typing import IO, Any
import zulip import zulip
class StringIO(_StringIO): class StringIO(_StringIO):
@ -47,7 +47,7 @@ options = parser.parse_args()
client = zulip.init_from_options(options) client = zulip.init_from_options(options)
file = None # type: IO file = None # type: IO[Any]
if options.file_path: if options.file_path:
file = open(options.file_path, 'rb') file = open(options.file_path, 'rb')
else: else:

View file

@ -2,8 +2,7 @@ import chess
import chess.uci import chess.uci
import re import re
import copy import copy
from typing import Any, Optional from typing import Any, Optional, Dict
from zulip_bots.lib import ExternalBotHandler
START_REGEX = re.compile('start with other user$') START_REGEX = re.compile('start with other user$')
START_COMPUTER_REGEX = re.compile( START_COMPUTER_REGEX = re.compile(
@ -23,7 +22,7 @@ class ChessHandler(object):
'Stockfish program on this computer.' 'Stockfish program on this computer.'
) )
def initialize(self, bot_handler: ExternalBotHandler) -> None: def initialize(self, bot_handler: Any) -> None:
self.config_info = bot_handler.get_config_info('chess') self.config_info = bot_handler.get_config_info('chess')
try: try:
@ -38,8 +37,8 @@ class ChessHandler(object):
def handle_message( def handle_message(
self, self,
message: dict, message: Dict[str, str],
bot_handler: ExternalBotHandler bot_handler: Any
) -> None: ) -> None:
content = message['content'] content = message['content']
@ -94,7 +93,7 @@ class ChessHandler(object):
last_fen last_fen
) )
def start(self, message: dict, bot_handler: ExternalBotHandler) -> None: def start(self, message: Dict[str, str], bot_handler: Any) -> None:
"""Starts a game with another user, with the current user as white. """Starts a game with another user, with the current user as white.
Replies to the bot handler. Replies to the bot handler.
@ -115,8 +114,8 @@ class ChessHandler(object):
def start_computer( def start_computer(
self, self,
message: dict, message: Dict[str, str],
bot_handler: ExternalBotHandler, bot_handler: Any,
is_white_user: bool is_white_user: bool
) -> None: ) -> None:
"""Starts a game with the computer. Replies to the bot handler. """Starts a game with the computer. Replies to the bot handler.
@ -151,8 +150,8 @@ class ChessHandler(object):
def validate_board( def validate_board(
self, self,
message: dict, message: Dict[str, str],
bot_handler: ExternalBotHandler, bot_handler: Any,
fen: str fen: str
) -> Optional[chess.Board]: ) -> Optional[chess.Board]:
"""Validates a board based on its FEN string. Replies to the bot """Validates a board based on its FEN string. Replies to the bot
@ -179,8 +178,8 @@ class ChessHandler(object):
def validate_move( def validate_move(
self, self,
message: dict, message: Dict[str, str],
bot_handler: ExternalBotHandler, bot_handler: Any,
last_board: chess.Board, last_board: chess.Board,
move_san: str, move_san: str,
is_computer: object is_computer: object
@ -223,8 +222,8 @@ class ChessHandler(object):
def check_game_over( def check_game_over(
self, self,
message: dict, message: Dict[str, str],
bot_handler: ExternalBotHandler, bot_handler: Any,
new_board: chess.Board new_board: chess.Board
) -> bool: ) -> bool:
"""Checks if a game is over due to """Checks if a game is over due to
@ -280,8 +279,8 @@ class ChessHandler(object):
def move( def move(
self, self,
message: dict, message: Dict[str, str],
bot_handler: ExternalBotHandler, bot_handler: Any,
last_fen: str, last_fen: str,
move_san: str move_san: str
) -> None: ) -> None:
@ -325,8 +324,8 @@ class ChessHandler(object):
def move_computer( def move_computer(
self, self,
message: dict, message: Dict[str, str],
bot_handler: ExternalBotHandler, bot_handler: Any,
last_fen: str, last_fen: str,
move_san: str move_san: str
) -> None: ) -> None:
@ -396,8 +395,8 @@ class ChessHandler(object):
def move_computer_first( def move_computer_first(
self, self,
message: dict, message: Dict[str, str],
bot_handler: ExternalBotHandler, bot_handler: Any,
last_fen: str last_fen: str
) -> None: ) -> None:
"""Preforms a move for the computer without having the user go first in """Preforms a move for the computer without having the user go first in
@ -447,8 +446,8 @@ class ChessHandler(object):
def resign( def resign(
self, self,
message: dict, message: Dict[str, str],
bot_handler: ExternalBotHandler, bot_handler: Any,
last_fen: str last_fen: str
) -> None: ) -> None:
"""Resigns the game for the current player. """Resigns the game for the current player.

View file

@ -1,6 +1,6 @@
# See readme.md for instructions on running this code. # See readme.md for instructions on running this code.
from zulip_bots.lib import ExternalBotHandler from typing import Dict, Any
class IncrementorHandler(object): class IncrementorHandler(object):
META = { META = {
@ -16,13 +16,13 @@ class IncrementorHandler(object):
is @-mentioned, this number will be incremented in the same message. is @-mentioned, this number will be incremented in the same message.
''' '''
def initialize(self, bot_handler: ExternalBotHandler) -> None: def initialize(self, bot_handler: Any) -> None:
storage = bot_handler.storage storage = bot_handler.storage
if not storage.contains('number') or not storage.contains('message_id'): if not storage.contains('number') or not storage.contains('message_id'):
storage.put('number', 0) storage.put('number', 0)
storage.put('message_id', None) storage.put('message_id', None)
def handle_message(self, message: dict, bot_handler: ExternalBotHandler) -> None: def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None:
storage = bot_handler.storage storage = bot_handler.storage
num = storage.get('number') num = storage.get('number')

View file

@ -4,8 +4,9 @@ import requests
import logging import logging
import re import re
from six.moves import urllib from six.moves import urllib
from zulip_bots.lib import ExternalBotHandler from zulip_bots.lib import Any
from typing import Optional
from typing import Optional, Any, Dict
# See readme.md for instructions on running this code. # See readme.md for instructions on running this code.
@ -34,11 +35,11 @@ class WikipediaHandler(object):
should preface searches with "@mention-bot". should preface searches with "@mention-bot".
@mention-bot <name of article>''' @mention-bot <name of article>'''
def handle_message(self, message: dict, bot_handler: ExternalBotHandler) -> None: def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None:
bot_response = self.get_bot_wiki_response(message, bot_handler) bot_response = self.get_bot_wiki_response(message, bot_handler)
bot_handler.send_reply(message, bot_response) bot_handler.send_reply(message, bot_response)
def get_bot_wiki_response(self, message: dict, bot_handler: ExternalBotHandler) -> Optional[str]: def get_bot_wiki_response(self, message: Dict[str, str], bot_handler: Any) -> Optional[str]:
'''This function returns the URLs of the requested topic.''' '''This function returns the URLs of the requested topic.'''
help_text = 'Please enter your search term after @mention-bot' help_text = 'Please enter your search term after @mention-bot'

View file

@ -2,7 +2,8 @@ import random
import logging import logging
import requests import requests
from zulip_bots.lib import ExternalBotHandler
from typing import Any, Dict
XKCD_TEMPLATE_URL = 'https://xkcd.com/%s/info.0.json' XKCD_TEMPLATE_URL = 'https://xkcd.com/%s/info.0.json'
LATEST_XKCD_URL = 'https://xkcd.com/info.0.json' LATEST_XKCD_URL = 'https://xkcd.com/info.0.json'
@ -33,7 +34,7 @@ class XkcdHandler(object):
`<comic_id>`, e.g `@mention-bot 1234`. `<comic_id>`, e.g `@mention-bot 1234`.
''' '''
def handle_message(self, message: dict, bot_handler: ExternalBotHandler) -> None: def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None:
xkcd_bot_response = get_xkcd_bot_response(message) xkcd_bot_response = get_xkcd_bot_response(message)
bot_handler.send_reply(message, xkcd_bot_response) bot_handler.send_reply(message, xkcd_bot_response)
@ -48,7 +49,7 @@ class XkcdNotFoundError(Exception):
class XkcdServerError(Exception): class XkcdServerError(Exception):
pass pass
def get_xkcd_bot_response(message: dict) -> str: def get_xkcd_bot_response(message: Dict[str, str]) -> str:
original_content = message['content'].strip() original_content = message['content'].strip()
command = original_content.strip() command = original_content.strip()
@ -83,7 +84,7 @@ def get_xkcd_bot_response(message: dict) -> str:
fetched['alt'], fetched['alt'],
fetched['img'])) fetched['img']))
def fetch_xkcd_query(mode: int, comic_id: str = None) -> dict: def fetch_xkcd_query(mode: int, comic_id: str = None) -> Dict[str, str]:
try: try:
if mode == XkcdBotCommand.LATEST: # Fetch the latest comic strip. if mode == XkcdBotCommand.LATEST: # Fetch the latest comic strip.
url = LATEST_XKCD_URL url = LATEST_XKCD_URL

View file

@ -4,13 +4,14 @@ from __future__ import print_function
import logging import logging
import ssl import ssl
import sys import sys
from zulip_bots.lib import ExternalBotHandler
try: try:
import requests import requests
except ImportError as e: except ImportError as e:
logging.error("Dependency missing!!\n{}".format(e)) logging.error("Dependency missing!!\n{}".format(e))
sys.exit(0) sys.exit(0)
from typing import Any, Dict
HELP_MESSAGE = ''' HELP_MESSAGE = '''
This bot allows users to translate a sentence into This bot allows users to translate a sentence into
'Yoda speak'. 'Yoda speak'.
@ -38,7 +39,7 @@ class YodaSpeakHandler(object):
This bot will allow users to translate a sentence into 'Yoda speak'. This bot will allow users to translate a sentence into 'Yoda speak'.
It looks for messages starting with '@mention-bot'. It looks for messages starting with '@mention-bot'.
''' '''
def initialize(self, bot_handler: ExternalBotHandler) -> None: def initialize(self, bot_handler: Any) -> None:
self.api_key = bot_handler.get_config_info('yoda')['api_key'] self.api_key = bot_handler.get_config_info('yoda')['api_key']
def usage(self) -> str: def usage(self) -> str:
@ -55,7 +56,7 @@ class YodaSpeakHandler(object):
@mention-bot You will learn how to speak like me someday. @mention-bot You will learn how to speak like me someday.
''' '''
def handle_message(self, message: dict, bot_handler: ExternalBotHandler) -> None: def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None:
self.handle_input(message, bot_handler) self.handle_input(message, bot_handler)
def send_to_yoda_api(self, sentence: str) -> str: def send_to_yoda_api(self, sentence: str) -> str:
@ -88,7 +89,7 @@ class YodaSpeakHandler(object):
sentence = message_content.replace(' ', '+') sentence = message_content.replace(' ', '+')
return sentence return sentence
def handle_input(self, message: dict, bot_handler: ExternalBotHandler) -> None: def handle_input(self, message: Dict[str, str], bot_handler: Any) -> None:
original_content = message['content'] original_content = message['content']
if self.is_help(original_content) or (original_content == ""): if self.is_help(original_content) or (original_content == ""):
@ -113,7 +114,7 @@ class YodaSpeakHandler(object):
bot_handler.send_reply(message, reply_message) bot_handler.send_reply(message, reply_message)
def send_message(self, bot_handler: ExternalBotHandler, message: str, stream: str, subject: str) -> None: def send_message(self, bot_handler: Any, message: str, stream: str, subject: str) -> None:
# function for sending a message # function for sending a message
bot_handler.send_message(dict( bot_handler.send_message(dict(
type='stream', type='stream',