from abc import abstractmethod import json from typing import Dict, Type class Message: MESSAGE_TYPES: Dict[str, Type['Message']] = {} @classmethod @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) -> str: hash = self.to_hash() return json.dumps(self.to_hash()) 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): user: str game: str def __init__(self, user: str, game: str): self.user = user self.game = game @classmethod def from_hash(cls, d: Dict): return cls(user=d['user'], game=d['game']) def to_hash(self) -> Dict: return {'user': self.user, 'game': self.game} @message('post') class Post(Message): author: str content: str def __init__(self, author: str, content: str): self.author = author self.content = content @classmethod def from_hash(cls, d: Dict): return cls(author=d['author'], content=d['content']) def to_hash(self) -> Dict: return { 'tag': 'post', 'author': self.author, 'content': self.content, }