summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier Gayot <olivier.gayot@sigexec.com>2021-12-29 17:05:21 +0100
committerOlivier Gayot <olivier.gayot@sigexec.com>2021-12-29 17:06:29 +0100
commit95ca11e98c47c3e8e57093c37134a6f51bcb6f30 (patch)
tree4c10504aee30dab96e6d5836f0f35f9d6a6a9810
parent8d242a5e6c090ee8165b36fea6520d533269518e (diff)
Add type hinting everywhere so we can enable strict mypy options
Signed-off-by: Olivier Gayot <olivier.gayot@sigexec.com>
-rwxr-xr-xrun-mypy.sh8
-rw-r--r--swiftstory/__main__.py2
-rw-r--r--swiftstory/cards.py5
-rw-r--r--swiftstory/client.py7
-rw-r--r--swiftstory/game.py71
-rw-r--r--swiftstory/game_manager.py2
-rw-r--r--swiftstory/interface/ws.py11
-rw-r--r--swiftstory/player.py2
8 files changed, 60 insertions, 48 deletions
diff --git a/run-mypy.sh b/run-mypy.sh
index 6384a00..04a5135 100755
--- a/run-mypy.sh
+++ b/run-mypy.sh
@@ -1,5 +1,11 @@
#!/bin/bash
-options=(--check-untyped-defs)
+options=(
+ --check-untyped-defs
+ --disallow-untyped-calls
+ --disallow-untyped-defs
+ --disallow-incomplete-defs
+ --disallow-untyped-decorators
+)
python3 -m mypy swiftstory "${options[@]}"
diff --git a/swiftstory/__main__.py b/swiftstory/__main__.py
index 6b7111d..3e2bcff 100644
--- a/swiftstory/__main__.py
+++ b/swiftstory/__main__.py
@@ -12,7 +12,7 @@ from swiftstory.game_manager import GameManager
from swiftstory.interface.ws import WebsocketsInterface
-def main():
+def main() -> None:
""" Entry point: we create the game manager and start the Websockets
server. """
parser = argparse.ArgumentParser()
diff --git a/swiftstory/cards.py b/swiftstory/cards.py
index 62f1e37..96438cc 100644
--- a/swiftstory/cards.py
+++ b/swiftstory/cards.py
@@ -1,18 +1,19 @@
import json
import os
+from typing import List
import pkg_resources
class Cards:
@staticmethod
- def get_white_cards(lang):
+ def get_white_cards(lang: str) -> List[str]:
''' Read the file containing the white cards and return a list of cards '''
fh = pkg_resources.resource_stream(__name__, os.path.join("data/lang", lang, "cards/white.json"))
return json.load(fh)
@staticmethod
- def get_black_cards(lang):
+ def get_black_cards(lang: str) -> List[str]:
''' Read the file containing the black cards and return a list of cards '''
fh = pkg_resources.resource_stream(__name__, os.path.join("data/lang", lang, "cards/black.json"))
return json.load(fh)
diff --git a/swiftstory/client.py b/swiftstory/client.py
index 98ba530..28fd6c0 100644
--- a/swiftstory/client.py
+++ b/swiftstory/client.py
@@ -3,6 +3,7 @@ import logging
from typing import Optional
import websockets.exceptions
+from websockets.server import WebSocketServerProtocol
from swiftstory.game import Game
from swiftstory.game_manager import GameManager
@@ -14,7 +15,7 @@ class Client:
""" Represent a client.
A client manages a (web)socket to communicate with the outside world.
It also manages the associated player when in a game. """
- def __init__(self, socket, game_manager: GameManager) -> None:
+ def __init__(self, socket: WebSocketServerProtocol, game_manager: GameManager) -> None:
self.game: Optional[Game] = None
self.game_manager: GameManager = game_manager
@@ -61,7 +62,7 @@ class Client:
raise ValueError("Player is None")
return self.game.try_collect_cards(self.player)
- def designate_card(self, card_id: int) -> str:
+ def designate_card(self, card_id: Optional[int]) -> str:
if self.game is None:
raise WrongAction('You have to join a game first')
if self.player is None:
@@ -91,7 +92,7 @@ class Client:
def monitor_player(self) -> None:
""" Start monitoring the player for notifications and send them. """
- async def f():
+ async def f() -> None:
assert self.player is not None
while True:
try:
diff --git a/swiftstory/game.py b/swiftstory/game.py
index 4569a5c..c46df4b 100644
--- a/swiftstory/game.py
+++ b/swiftstory/game.py
@@ -124,59 +124,62 @@ class Game:
return self.try_view_played_cards(player)
- def try_designate_card(self, player: Player, card_id: int) -> str:
+ def try_designate_card(self, player: Player, card_id: Optional[int]) -> str:
if self.state is not GameState.WAITING_DESIGNATION:
raise WrongAction('Not now, moron !')
if self.judge is not player:
raise WrongAction('Who do you think you are !?')
- if card_id is None and len(self.board.played_cards) > 0:
- raise WrongAction('There are cards on the board, pick one !')
+ def move_on() -> str:
+ self.judge = None
- if card_id is not None or len(self.board.played_cards) > 0:
- # if there are cards on the board
- # TODO check exception
- try:
- card, winner = self.board.played_cards[card_id]
- except IndexError:
- return error('Invalid card')
+ for p in self.players:
+ if p is not player:
+ p.register_notification({'op': 'judge_needed'})
- winner.inc_score()
+ self.state = GameState.WAITING_NEW_JUDGE
+ return success(None)
- # put the cards back in the deck
- self.board.recycle_played_cards()
+ if not self.board.played_cards:
+ return move_on()
- # reset the state of the players
- for p in self.players:
- if p.has_played:
- idx = p.receive_card(self.board.pick_white_card())
-
- p.register_notification({
- 'op': 'received_card',
- 'content': {
- 'card': {
- 'id': idx,
- 'desc': p.cards[idx][1],
- },
- },
- })
- p.has_played = False
+ if card_id is None:
+ raise WrongAction('There are cards on the board, pick one !')
+
+ # TODO check exception
+ try:
+ card, winner = self.board.played_cards[card_id]
+ except IndexError:
+ return error('Invalid card')
+
+ winner.inc_score()
- self.judge = None
+ # put the cards back in the deck
+ self.board.recycle_played_cards()
+ # reset the state of the players
for p in self.players:
- if p is not player:
- p.register_notification({'op': 'judge_needed'})
+ if p.has_played:
+ idx = p.receive_card(self.board.pick_white_card())
- self.state = GameState.WAITING_NEW_JUDGE
+ p.register_notification({
+ 'op': 'received_card',
+ 'content': {
+ 'card': {
+ 'id': idx,
+ 'desc': p.cards[idx][1],
+ },
+ },
+ })
+ p.has_played = False
- return success(None)
+ return move_on()
def try_view_player_cards(self, player: Player) -> str:
return success([(idx, desc) for idx, (_, desc) in player.cards.items()])
- def try_view_played_cards(self, player: Player):
+ def try_view_played_cards(self, player: Player) -> str:
if self.state is not GameState.WAITING_DESIGNATION:
raise WrongAction('Not now, moron !')
diff --git a/swiftstory/game_manager.py b/swiftstory/game_manager.py
index 2429d92..ef57e5d 100644
--- a/swiftstory/game_manager.py
+++ b/swiftstory/game_manager.py
@@ -42,7 +42,7 @@ class GameManager:
""" List available languages based on FS. """
return pkg_resources.resource_listdir(__name__, "data/lang")
- def find_by_name(self, game_name: str, lang: str, create=True) -> Game:
+ def find_by_name(self, game_name: str, lang: str, create: bool = True) -> Game:
""" Find and return the game that matches the name and language
specified. If the game does not exist but create is set to True, a new
game will be created. """
diff --git a/swiftstory/interface/ws.py b/swiftstory/interface/ws.py
index 2485b4f..a86c730 100644
--- a/swiftstory/interface/ws.py
+++ b/swiftstory/interface/ws.py
@@ -1,6 +1,7 @@
import contextlib
import json
import logging
+from typing import Union
import websockets.exceptions
from websockets.server import WebSocketServerProtocol
@@ -16,7 +17,7 @@ class WebsocketsInterface:
def __init__(self, game_manager: GameManager):
self.game_manager = game_manager
- async def connection_handler(self, websocket: WebSocketServerProtocol, path: str):
+ async def connection_handler(self, websocket: WebSocketServerProtocol, path: str) -> None:
client = Client(websocket, self.game_manager)
with contextlib.suppress(websockets.exceptions.ConnectionClosed):
@@ -25,8 +26,8 @@ class WebsocketsInterface:
client.disconnect()
- def message_received_handler(self, client, message):
- def join_game():
+ def message_received_handler(self, client: Client, message: Union[bytes, str]) -> str:
+ def join_game() -> str:
try:
game_name = json_msg['game_name']
except KeyError:
@@ -35,7 +36,7 @@ class WebsocketsInterface:
lang = json_msg.get('lang')
return client.join_game(game_name, lang)
- def designate_card():
+ def designate_card() -> str:
card_id = None
try:
card_id = int(json_msg['card_id'])
@@ -44,7 +45,7 @@ class WebsocketsInterface:
finally:
return client.designate_card(card_id)
- def play_white_card():
+ def play_white_card() -> str:
try:
card_id = int(json_msg['card_id'])
except KeyError:
diff --git a/swiftstory/player.py b/swiftstory/player.py
index 525a4e6..7243585 100644
--- a/swiftstory/player.py
+++ b/swiftstory/player.py
@@ -30,7 +30,7 @@ class Player:
self.next_idx += 1
return self.next_idx - 1
- def register_notification(self, obj: Any):
+ def register_notification(self, obj: Any) -> None:
message = json.dumps({'type': 'notification', 'content': obj})
self.notifications.put_nowait(message)