Coverage for wire/msg.py : 97%
Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# -*- coding: utf-8 -*-
2from __future__ import annotations
4# -- stdlib --
5from typing import Any, ClassVar, Dict, List, Optional, Type, TypeVar
6from typing_extensions import TypedDict
8# -- third party --
9from dataclasses import dataclass
10import dataclasses
12# -- own --
13from . import model
16# -- code --
17class ServerToClient:
18 pass
21class ClientToServer:
22 pass
25class BiDirectional(ServerToClient, ClientToServer):
26 pass
29class Message:
30 types: ClassVar[Dict[str, Type[Message]]] = {}
31 op: str
33 def __init__(self, *args, **kwargs):
34 raise Exception('Abstract')
36 def encode(self) -> dict:
37 ...
39 @classmethod
40 def decode(cls, data: dict) -> Optional[Message]:
41 data = dict(data)
42 op = data.pop('op', '')
43 if op not in cls.types: 43 ↛ 44line 43 didn't jump to line 44, because the condition on line 43 was never true
44 return None
46 return cls.types[op](**data)
49def message(cls: Type[Message]) -> Type[Message]:
50 assert issubclass(cls, ServerToClient) or issubclass(cls, ClientToServer)
51 cls.op = cls.__name__
52 assert cls.op not in Message.types, cls.op
53 Message.types[cls.op] = cls
55 if cls.encode is Message.encode: 55 ↛ 68line 55 didn't jump to line 68, because the condition on line 55 was never false
56 env: Any = {}
57 fields = [f" '{i.name}': self.{i.name}," for i in dataclasses.fields(cls)]
58 code = (
59 "def encode(self) -> dict:"
60 " return {"
61 " 'op': self.op,"
62 " %s"
63 " }"
64 ) % '\n'.join(fields)
65 exec(code, env)
66 cls.encode = env['encode'] # type: ignore
68 return cls
71T = TypeVar('T', bound=Message)
74def cast(typ: Type[T], msg: Message) -> Optional[T]:
75 if msg.op == typ.op:
76 return msg # type: ignore
78 return None
81# ----------------------------
82@message
83@dataclass
84class Info(Message, ServerToClient):
85 msg: str
88@message
89@dataclass
90class Error(Message, ServerToClient):
91 msg: str
94@message
95@dataclass
96class SystemMsg(Message, ServerToClient):
97 msg: str
100@message
101@dataclass
102class CurrentGames(Message, ServerToClient):
103 games: List[model.Game]
106@message
107@dataclass
108class CurrentUsers(Message, ServerToClient):
109 users: List[model.User]
112@message
113@dataclass
114class RoomUsers(Message, ServerToClient):
115 gid: int
116 users: List[model.User]
119@message
120@dataclass
121class GameJoined(Message, ServerToClient):
122 game: model.GameDetail
125@message
126@dataclass
127class GameStarted(Message, ServerToClient):
128 game: model.GameDetail
131@message
132@dataclass
133class PlayerPresence(Message, ServerToClient):
134 '''
135 Indicates if player is still in the game
136 '''
137 gid: int
138 presence: Dict[int, bool]
141@message
142@dataclass
143class GameEnded(Message, ServerToClient):
144 gid: int
147@message
148@dataclass
149class GameParams(Message, ServerToClient):
150 gid: int
151 params: Dict[str, Any]
154@message
155@dataclass
156class SetGameParam(Message, BiDirectional):
157 gid: int
158 key: str
159 value: Any
162@message
163@dataclass
164class GameData(Message, BiDirectional):
165 gid: int
166 tag: str
167 data: Any
170@message
171@dataclass
172class InviteRequest(Message, ServerToClient):
173 uid: int
174 name: str
175 gid: int
176 type: str
179@message
180@dataclass
181class ObserveRequest(Message, ServerToClient):
182 uid: int
185@message
186@dataclass
187class KickRequest(Message, ServerToClient):
188 uid: int
189 victim: int
190 votes: int
193@message
194@dataclass
195class ObserveStarted(Message, ServerToClient):
196 game: model.GameDetail
197 observee: int
200@message
201@dataclass
202class GameLeft(Message, ServerToClient):
203 gid: int
206@message
207@dataclass
208class Greeting(Message, ServerToClient):
209 node: str
210 version: str
213@message
214@dataclass
215class AuthError(Message, ServerToClient):
216 reason: str
219@message
220@dataclass
221class AuthSuccess(Message, ServerToClient):
222 uid: int
225@message
226@dataclass
227class Ping(Message, ServerToClient):
228 pass
231# --------------------------------
232# ----- system -----
233@message
234@dataclass
235class Beat(Message, ClientToServer):
236 pass
239@message
240@dataclass
241class Pong(Message, ClientToServer):
242 pass
245@message
246@dataclass
247class Auth(Message, ClientToServer):
248 token: str
251# ----- room -----
252class CreateRoomFlags(TypedDict, total=False):
253 contest: bool
254 invite: bool
255 chat: bool
258@message
259@dataclass
260class CreateRoom(Message, ClientToServer):
261 name: str
262 mode: str
263 flags: CreateRoomFlags
266@message
267@dataclass
268class JoinRoom(Message, ClientToServer):
269 gid: int
270 slot: Optional[int]
273@message
274@dataclass
275class LeaveRoom(Message, ClientToServer):
276 pass
279@message
280@dataclass
281class GetRoomUsers(Message, ClientToServer):
282 gid: int
285@message
286@dataclass
287class GetReady(Message, ClientToServer):
288 pass
291@message
292@dataclass
293class CancelReady(Message, ClientToServer):
294 pass
297@message
298@dataclass
299class ChangeLocation(Message, ClientToServer):
300 loc: int
303# ----- matching -----
304@message
305@dataclass
306class StartMatching(Message, BiDirectional):
307 modes: List[str]
310# ----- observe -----
311@message
312@dataclass
313class Observe(Message, ClientToServer):
314 uid: int
317@message
318@dataclass
319class GrantObserve(Message, ClientToServer):
320 uid: int
321 grant: bool
324@message
325@dataclass
326class KickObserver(Message, ClientToServer):
327 uid: int
330@message
331@dataclass
332class ObserverEnter(Message, ServerToClient):
333 observer: int
334 observee: int
337@message
338@dataclass
339class ObserverLeave(Message, ServerToClient):
340 observer: int
341 observee: int
344# ----- invite -----
345@message
346@dataclass
347class Invite(Message, ClientToServer):
348 uid: int
351@message
352@dataclass
353class Kick(Message, ClientToServer):
354 uid: int
357# ----- item -----
358@message
359@dataclass
360class UseItem(Message, ClientToServer):
361 sku: str
364# ----- admin -----
365@message
366@dataclass
367class AdminStacktrace(Message, ClientToServer):
368 pass
371@message
372@dataclass
373class AdminClearZombies(Message, ClientToServer):
374 pass
377@message
378@dataclass
379class AdminMigrate(Message, ClientToServer):
380 pass
383@message
384@dataclass
385class AdminKick(Message, ClientToServer):
386 uid: int
389@message
390@dataclass
391class AdminKillGame(Message, ClientToServer):
392 gid: int
395@message
396@dataclass
397class AdminAdd(Message, ClientToServer):
398 uid: int
401@message
402@dataclass
403class AdminRemove(Message, ClientToServer):
404 uid: int
407@message
408@dataclass
409class AdminAddBigbrother(Message, ClientToServer):
410 uid: int
413@message
414@dataclass
415class AdminRemoveBigbrother(Message, ClientToServer):
416 uid: int
419# ----- contest -----
420@message
421@dataclass
422class SetupContest(Message, ClientToServer):
423 name: str
424 mode: str
425 uids: List[int]