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 = {}
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']
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):
253 contest: bool
254 invite: bool
257@message
258@dataclass
259class CreateRoom(Message, ClientToServer):
260 name: str
261 mode: str
262 flags: CreateRoomFlags
265@message
266@dataclass
267class JoinRoom(Message, ClientToServer):
268 gid: int
269 slot: Optional[int]
272@message
273@dataclass
274class LeaveRoom(Message, ClientToServer):
275 pass
278@message
279@dataclass
280class GetRoomUsers(Message, ClientToServer):
281 gid: int
284@message
285@dataclass
286class GetReady(Message, ClientToServer):
287 pass
290@message
291@dataclass
292class CancelReady(Message, ClientToServer):
293 pass
296@message
297@dataclass
298class ChangeLocation(Message, ClientToServer):
299 loc: int
302# ----- observe -----
303@message
304@dataclass
305class Observe(Message, ClientToServer):
306 uid: int
309@message
310@dataclass
311class GrantObserve(Message, ClientToServer):
312 uid: int
313 grant: bool
316@message
317@dataclass
318class KickObserver(Message, ClientToServer):
319 uid: int
322@message
323@dataclass
324class ObserverEnter(Message, ServerToClient):
325 observer: int
326 observee: int
329@message
330@dataclass
331class ObserverLeave(Message, ServerToClient):
332 observer: int
333 observee: int
336# ----- invite -----
337@message
338@dataclass
339class Invite(Message, ClientToServer):
340 uid: int
343@message
344@dataclass
345class Kick(Message, ClientToServer):
346 uid: int
349# ----- item -----
350@message
351@dataclass
352class UseItem(Message, ClientToServer):
353 sku: str
356# ----- admin -----
357@message
358@dataclass
359class AdminStacktrace(Message, ClientToServer):
360 pass
363@message
364@dataclass
365class AdminClearZombies(Message, ClientToServer):
366 pass
369@message
370@dataclass
371class AdminMigrate(Message, ClientToServer):
372 pass
375@message
376@dataclass
377class AdminKick(Message, ClientToServer):
378 uid: int
381@message
382@dataclass
383class AdminKillGame(Message, ClientToServer):
384 gid: int
387@message
388@dataclass
389class AdminAdd(Message, ClientToServer):
390 uid: int
393@message
394@dataclass
395class AdminRemove(Message, ClientToServer):
396 uid: int
399@message
400@dataclass
401class AdminAddBigbrother(Message, ClientToServer):
402 uid: int
405@message
406@dataclass
407class AdminRemoveBigbrother(Message, ClientToServer):
408 uid: int
411# ----- contest -----
412@message
413@dataclass
414class SetupContest(Message, ClientToServer):
415 name: str
416 mode: str
417 uids: List[int]