Browse Source

add more types

Getty Ritter 4 years ago
parent
commit
933379cc9b
3 changed files with 52 additions and 34 deletions
  1. 26 11
      messages.py
  2. 13 16
      parley.py
  3. 13 7
      storage.py

+ 26 - 11
messages.py

@@ -1,48 +1,63 @@
+from abc import abstractmethod
 import json
+from typing import Dict, Type
 
 class Message:
-    MESSAGE_TYPES = {}
+    MESSAGE_TYPES: Dict[str, Type['Message']] = {}
 
     @classmethod
-    def decode(cls, raw):
+    @abstractmethod
+    def from_hash(cls: Type['Message'], d: Dict): pass
+
+    @abstractmethod
+    def to_hash(self) -> Dict: pass
+
+    @classmethod
+    def decode(cls: Type['Message'], raw: str):
         hash = json.loads(raw)
         tag = hash['tag']
         return cls.MESSAGE_TYPES[tag].from_hash(hash)
 
-    def json(self):
+    def json(self) -> str:
         hash = self.to_hash()
         return json.dumps(self.to_hash())
 
-def message(name):
-    def decorate(class_decl):
+def message(name: str):
+    def decorate(class_decl: Type['Message']) -> Type['Message']:
         Message.MESSAGE_TYPES[name] = class_decl
         return class_decl
     return decorate
 
 @message('config')
 class InitialConfig(Message):
-    def __init__(self, user, game):
+    user: str
+    game: str
+
+    def __init__(self, user: str, game: str):
         self.user = user
         self.game = game
 
     @classmethod
-    def from_hash(cls, d):
+    def from_hash(cls, d: Dict):
         return cls(user=d['user'], game=d['game'])
 
-    def to_hash(self):
+    def to_hash(self) -> Dict:
         return {'user': self.user, 'game': self.game}
 
 @message('post')
 class Post(Message):
-    def __init__(self, author, content):
+    author: str
+    content: str
+
+    def __init__(self, author: str, content: str):
         self.author = author
         self.content = content
 
     @classmethod
-    def from_hash(cls, d):
+    def from_hash(cls, d: Dict):
         return cls(author=d['author'], content=d['content'])
 
-    def to_hash(self):
+    def to_hash(self) -> Dict:
         return {
             'tag': 'post',
             'author': self.author,

+ 13 - 16
parley.py

@@ -1,4 +1,4 @@
-import sanic
+import sanic # type: ignore
 
 import messages
 import storage
@@ -9,34 +9,31 @@ cache = storage.Cache()
 db = storage.Storage()
 
 @app.route("/static/<f>")
-async def static(request, f):
+async def static(request: sanic.request.Request, f: str) -> sanic.response.Response:
     return await sanic.response.file('static/{}'.format(f))
 
 @app.route("/")
-async def index(request):
+async def index(request: sanic.request.Request) -> sanic.response.Response:
     return await sanic.response.file('static/index.html')
 
 @app.websocket("/socket")
-async def socket(request, ws):
+async def socket(request: sanic.request.Request, ws: sanic.websocket.WebSocketConnection) -> sanic.response.Response:
     initial = await ws.recv()
-    config = messages.Message.decode(initial)
-    user = config.user
-    game = config.game
-    sanic.log.logger.info(f'connected websocket for {user} in game {game}')
-
-    cache.add_connection(game, ws)
+    config: messages.InitialConfig = messages.Message.decode(initial)
+    sanic.log.logger.info(f'connected websocket for {config.user} in game {config.game}')
+    cache.add_connection(config.game, ws)
 
     try:
-        for (author, content) in db.get_backlog(game):
+        for (author, content) in db.get_backlog(config.game):
             await ws.send(messages.Post(author, content).json())
         async for payload in ws:
             msg = messages.Message.decode(payload)
-            db.add_msg(user, msg.content, game)
-            for w in cache.get_connections(game):
-                await w.send(messages.Post(user, msg.content).json())
+            db.add_msg(config.user, msg.content, config.game)
+            for w in cache.get_connections(config.game):
+                await w.send(messages.Post(config.user, msg.content).json())
     finally:
-        sanic.log.logger.info('removing websocket for {}'.format(game))
-        cache.remove_connection(game, ws)
+        sanic.log.logger.info(f'removing websocket for {config.game}')
+        cache.remove_connection(config.game, ws)
 
 if __name__ == '__main__':
     try:

+ 13 - 7
storage.py

@@ -1,26 +1,32 @@
+from sanic import WebSocketConnection # type: ignore
 import sqlite3 as sql
+from typing import Dict, List, Optional, Tuple
 
 class Cache:
+    connections: Dict[str, WebSocketConnection]
+
     def __init__(self):
         self.connections = {}
 
-    def add_connection(self, game: str, ws):
+    def add_connection(self, game: str, ws: WebSocketConnection):
         if game not in self.connections:
             self.connections[game] = set()
         self.connections[game].add(ws)
 
-    def remove_connection(self, game: str, ws):
+    def remove_connection(self, game: str, ws: WebSocketConnection):
         if game in self.connections:
             self.connections[game].remove(ws)
 
-    def get_connections(self, game: str):
+    def get_connections(self, game: str) -> List[WebSocketConnection]:
         return self.connections.get(game, [])
 
 class Storage:
+    db: sql.Connection
+
     def __init__(self):
         self.db = sql.connect('samp.db')
 
-    def get_backlog(self, game: str, c=None) -> [(str, str)]:
+    def get_backlog(self, game: str, c: Optional[sql.Cursor]=None) -> List[Tuple[str, str]]:
         if c is None:
             c = self.db.cursor()
 
@@ -29,7 +35,7 @@ class Storage:
                   'WHERE c.game = g.id AND g.name = ?', [game])
         return list(c)
 
-    def get_game_id(self, game: str, c=None) -> int:
+    def get_game_id(self, game: str, c: Optional[sql.Cursor]=None) -> int:
         if c is None:
             c = self.db.cursor()
 
@@ -43,11 +49,11 @@ class Storage:
             c.execute('SELECT id FROM games WHERE name = ?', [game])
             return c.fetchone()[0]
 
-    def add_msg(self, user: str, content: str, game: str, c=None):
+    def add_msg(self, user: str, content: str, game: str, c: Optional[sql.Cursor]=None):
         if c is None:
             c = self.db.cursor()
 
-        game_id = self.get_game_id(game, c)
+        game_id: int = self.get_game_id(game, c)
         c.execute('INSERT INTO chat (game, user, content) '
                   'VALUES (?, ?, ?)', [game_id, user, content])
         self.db.commit()