Skip to content

Commit df60050

Browse files
committed
Refactor _callEvent into RoomManager
for easier testing overriding the method cleanly and resetting back
1 parent dac5d3c commit df60050

File tree

2 files changed

+60
-57
lines changed

2 files changed

+60
-57
lines changed

ch/__init__.py

+57-56
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,15 @@ def _yield_tasks(now: float) -> Generator[Task, None, None]:
456456
yield from Task._tasks_once
457457
Task._tasks_once.clear()
458458

459+
@staticmethod
460+
def get_next_tick_target() -> float | None:
461+
while Task._tasks_queue:
462+
target, _tid, task = Task._tasks_queue[0]
463+
if task.cancelled:
464+
heapq.heappop(Task._tasks_queue)
465+
continue
466+
return target
467+
459468
@staticmethod
460469
def tick() -> float | None:
461470
"""
@@ -482,11 +491,7 @@ def tick() -> float | None:
482491

483492
Task.running_task = None
484493

485-
while Task._tasks_queue:
486-
target, _tid, task = Task._tasks_queue[0]
487-
if task.cancelled:
488-
heapq.heappop(Task._tasks_queue)
489-
continue
494+
if target := Task.get_next_tick_target():
490495
return target - now
491496

492497

@@ -597,7 +602,7 @@ def _getAuth(self, name: str, password: str) -> str | None:
597602
def _auth(self):
598603
auid = self._getAuth(self._mgr.name, self._mgr.password)
599604
if auid is None:
600-
self._callEvent("onLoginFail")
605+
self._mgr._callEvent(self, "onLoginFail")
601606
return False
602607
self._sendCommand("tlogin", auid, "2")
603608
self._setWriteLock(True)
@@ -606,7 +611,7 @@ def _auth(self):
606611
def disconnect(self):
607612
"""Disconnect the bot from PM"""
608613
self._disconnect()
609-
self._callEvent("onPMDisconnect")
614+
self._mgr._callEvent(self, "onPMDisconnect")
610615

611616
def _disconnect(self):
612617
self.connected = False
@@ -674,7 +679,7 @@ def _process(self, data: str):
674679
if not self.connected:
675680
return
676681

677-
self._callEvent("onRaw", data)
682+
self._mgr._callEvent(self, "onRaw", data)
678683
cmd, *args = data.split(":")
679684
func = "_rcmd_" + cmd
680685
try:
@@ -690,7 +695,7 @@ def _rcmd_OK(self, _args: list[str]):
690695
self._setWriteLock(False)
691696
self._sendCommand("wl")
692697
self._sendCommand("getblock")
693-
self._callEvent("onPMConnect")
698+
self._mgr._callEvent(self, "onPMConnect")
694699

695700
def _rcmd_wl(self, args: list[str]):
696701
self.contacts = set()
@@ -707,14 +712,14 @@ def _rcmd_wl(self, args: list[str]):
707712
print(" -> ", name, last_on, is_on, idle)
708713
continue
709714
self.contacts.add(user)
710-
self._callEvent("onPMContactlistReceive")
715+
self._mgr._callEvent(self, "onPMContactlistReceive")
711716

712717
def _rcmd_block_list(self, args: list[str]):
713718
new_blocklist = {User(name) for name in args if name != ""}
714719
if self.blocklist:
715720
for user in new_blocklist-self.blocklist:
716721
self.blocklist.add(user)
717-
self._callEvent("onPMBlock", user)
722+
self._mgr._callEvent(self, "onPMBlock", user)
718723
self.blocklist = new_blocklist
719724

720725
def _rcmd_idleupdate(self, args: list[str]):
@@ -736,7 +741,7 @@ def _rcmd_status(self, args: list[str]):
736741

737742
def _rcmd_DENIED(self, _args: list[str]):
738743
self._disconnect()
739-
self._callEvent("onLoginFail")
744+
self._mgr._callEvent(self, "onLoginFail")
740745

741746
def _rcmd_msg(self, args: list[str]):
742747
user = User(args[0])
@@ -763,40 +768,40 @@ def _rcmd_msg(self, args: list[str]):
763768
)
764769

765770
self.msgs[msgtime] = msg
766-
self._callEvent("onPMMessage", user, msg)
771+
self._mgr._callEvent(self, "onPMMessage", user, msg)
767772

768773
def _rcmd_msgoff(self, args: list[str]):
769774
user = User(args[0])
770775
body = _strip_html(":".join(args[5:]))
771-
self._callEvent("onPMOfflineMessage", user, body)
776+
self._mgr._callEvent(self, "onPMOfflineMessage", user, body)
772777

773778
def _rcmd_wladd(self, args: list[str]):
774779
user = User(args[0])
775780
self._updateStatus(user, args[1], int(args[2]), args[2])
776781
self.contacts.add(user)
777-
self._callEvent("onPMContactAdd", user)
782+
self._mgr._callEvent(self, "onPMContactAdd", user)
778783

779784
def _rcmd_wldelete(self, args: list[str]):
780785
user = User(args[0])
781786
del self.status[user]
782787
self.contacts.remove(user)
783-
self._callEvent("onPMContactRemove", user)
788+
self._mgr._callEvent(self, "onPMContactRemove", user)
784789

785790
def _rcmd_wlapp(self, args: list[str]):
786791
user = User(args[0])
787792
self.status[user] = (0, True)
788-
self._callEvent("onPMContactOnline", user)
793+
self._mgr._callEvent(self, "onPMContactOnline", user)
789794

790795
def _rcmd_wlonline(self, args: list[str]):
791796
user = User(args[0])
792797
self.status[user] = (0, True)
793-
self._callEvent("onPMContactOnline", user)
798+
self._mgr._callEvent(self, "onPMContactOnline", user)
794799

795800
def _rcmd_wloffline(self, args: list[str]):
796801
user = User(args[0])
797802
last_on = int(float(args[1]))
798803
self.status[user] = (last_on, False)
799-
self._callEvent("onPMContactOffline", user)
804+
self._mgr._callEvent(self, "onPMContactOffline", user)
800805

801806
def _rcmd_kickingoff(self, _args: list[str]):
802807
self.disconnect()
@@ -809,15 +814,15 @@ def _rcmd_unblocked(self, args: list[str]):
809814
user = User(args[0])
810815
if user in self.blocklist:
811816
self.blocklist.remove(user)
812-
self._callEvent("onPMUnblock", user)
817+
self._mgr._callEvent(self, "onPMUnblock", user)
813818

814819
####
815820
# Commands
816821
####
817822
def ping(self):
818823
"""send a ping"""
819824
self._sendCommand("")
820-
self._callEvent("onPMPing")
825+
self._mgr._callEvent(self, "onPMPing")
821826

822827
def message(self, user: User, msg: str):
823828
"""send a pm to a user"""
@@ -875,10 +880,6 @@ def getIdle(self, user: User):
875880
####
876881
# Util
877882
####
878-
def _callEvent(self, evt: str, *args: Any, **kw: Any):
879-
getattr(self._mgr, evt)(self, *args, **kw)
880-
self._mgr.onEventCalled(self, evt, *args, **kw)
881-
882883
def _write(self, data: bytes):
883884
if self._wlock:
884885
self._wlockbuf += data
@@ -994,7 +995,7 @@ def reconnect(self):
994995
def disconnect(self):
995996
"""Disconnect."""
996997
self._disconnect()
997-
self._callEvent("onDisconnect")
998+
self._mgr._callEvent(self, "onDisconnect")
998999

9991000
def _disconnect(self):
10001001
"""Disconnect from the server."""
@@ -1111,7 +1112,7 @@ def _process(self, line: str):
11111112
if not self.connected:
11121113
return
11131114

1114-
self._callEvent("onRaw", line)
1115+
self._mgr._callEvent(self, "onRaw", line)
11151116
cmd, *args = line.split(":")
11161117
func = "_rcmd_" + cmd
11171118
if hasattr(self, func):
@@ -1142,7 +1143,7 @@ def _rcmd_ok(self, args: list[str]):
11421143
self._sendCommand("blogin", self._mgr.name)
11431144
# if name and password is provided but fail to login
11441145
elif args[2] != "M": # unsuccessful login
1145-
self._callEvent("onLoginFail")
1146+
self._mgr._callEvent(self, "onLoginFail")
11461147
self.disconnect()
11471148
# Successful login
11481149
elif args[2] == "M":
@@ -1161,23 +1162,23 @@ def _rcmd_pwdok(self, _args: list[str]):
11611162

11621163
def _rcmd_denied(self, _args: list[str]):
11631164
self._disconnect()
1164-
self._callEvent("onConnectFail")
1165+
self._mgr._callEvent(self, "onConnectFail")
11651166

11661167
def _rcmd_inited(self, _args: list[str]):
11671168
self._sendCommand("g_participants", "start")
11681169
self._sendCommand("getpremium", "1")
11691170
self.requestBanlist()
11701171
self.requestUnBanlist()
11711172
if self._connectAmount == 0:
1172-
self._callEvent("onConnect")
1173+
self._mgr._callEvent(self, "onConnect")
11731174
for msg in reversed(self._i_log):
11741175
user = msg.user
1175-
self._callEvent("onHistoryMessage", user, msg)
1176+
self._mgr._callEvent(self, "onHistoryMessage", user, msg)
11761177
self._addHistory(msg)
11771178
self._i_log.clear()
1178-
self._callEvent("onHistoryMessageUpdate")
1179+
self._mgr._callEvent(self, "onHistoryMessageUpdate")
11791180
else:
1180-
self._callEvent("onReconnect")
1181+
self._mgr._callEvent(self, "onReconnect")
11811182
# we do not repeat onHistoryMessage calls but we still need to clear the log
11821183
# in case the users uses getMoreHistory
11831184
self._i_log.clear()
@@ -1200,11 +1201,11 @@ def _rcmd_mods(self, args: list[str]):
12001201
premods = self._mods
12011202
for user in mods - premods: # modded
12021203
self._mods.add(user)
1203-
self._callEvent("onModAdd", user)
1204+
self._mgr._callEvent(self, "onModAdd", user)
12041205
for user in premods - mods: # demodded
12051206
self._mods.remove(user)
1206-
self._callEvent("onModRemove", user)
1207-
self._callEvent("onModChange")
1207+
self._mgr._callEvent(self, "onModRemove", user)
1208+
self._mgr._callEvent(self, "onModChange")
12081209

12091210
def _rcmd_b(self, args: list[str]):
12101211
mtime = float(args[0])
@@ -1254,7 +1255,7 @@ def _rcmd_u(self, args: list[str]):
12541255
if msg := self._mqueue.pop(args[0], None):
12551256
msg.attach(self, args[1])
12561257
self._addHistory(msg)
1257-
self._callEvent("onMessage", msg.user, msg)
1258+
self._mgr._callEvent(self, "onMessage", msg.user, msg)
12581259

12591260
def _rcmd_i(self, args: list[str]):
12601261
mtime = float(args[0])
@@ -1304,10 +1305,10 @@ def _rcmd_gotmore(self, _args: list[str]):
13041305
self._gettingmorehistory = False
13051306
for msg in reversed(self._i_log):
13061307
user = msg.user
1307-
self._callEvent("onHistoryMessage", user, msg)
1308+
self._mgr._callEvent(self, "onHistoryMessage", user, msg)
13081309
self._addHistory(msg)
13091310
self._i_log.clear()
1310-
self._callEvent("onHistoryMessageUpdate")
1311+
self._mgr._callEvent(self, "onHistoryMessageUpdate")
13111312

13121313
def _rcmd_nomore(self, _args: list[str]):
13131314
self._ihistoryIndex = None
@@ -1353,7 +1354,7 @@ def _rcmd_participant(self, args: list[str]):
13531354
user.removeSessionId(self, args[1])
13541355
self._userlist.remove(user)
13551356
if user not in self._userlist or not self._mgr.userlistEventUnique:
1356-
self._callEvent("onLeave", user, puid)
1357+
self._mgr._callEvent(self, "onLeave", user, puid)
13571358
else: # join
13581359
user.addSessionId(self, args[1])
13591360
if user not in self._userlist:
@@ -1362,23 +1363,23 @@ def _rcmd_participant(self, args: list[str]):
13621363
doEvent = False
13631364
self._userlist.append(user)
13641365
if doEvent or not self._mgr.userlistEventUnique:
1365-
self._callEvent("onJoin", user, puid)
1366+
self._mgr._callEvent(self, "onJoin", user, puid)
13661367

13671368
def _rcmd_show_fw(self, _args: list[str]):
1368-
self._callEvent("onFloodWarning")
1369+
self._mgr._callEvent(self, "onFloodWarning")
13691370

13701371
def _rcmd_show_tb(self, _args: list[str]):
1371-
self._callEvent("onFloodBan")
1372+
self._mgr._callEvent(self, "onFloodBan")
13721373

13731374
def _rcmd_tb(self, _args: list[str]):
1374-
self._callEvent("onFloodBanRepeat")
1375+
self._mgr._callEvent(self, "onFloodBanRepeat")
13751376

13761377
def _rcmd_delete(self, args: list[str]):
13771378
msg = self.msgs.get(args[0])
13781379
if msg:
13791380
if msg in self.history:
13801381
self.history.remove(msg)
1381-
self._callEvent("onMessageDelete", msg.user, msg)
1382+
self._mgr._callEvent(self, "onMessageDelete", msg.user, msg)
13821383
msg.detach()
13831384

13841385
def _rcmd_deleteall(self, args: list[str]):
@@ -1387,7 +1388,7 @@ def _rcmd_deleteall(self, args: list[str]):
13871388

13881389
def _rcmd_n(self, args: list[str]):
13891390
self.usercount = int(args[0], 16)
1390-
self._callEvent("onUserCountChange")
1391+
self._mgr._callEvent(self, "onUserCountChange")
13911392

13921393
def _rcmd_blocklist(self, args: list[str]):
13931394
self._banlist = dict()
@@ -1400,7 +1401,7 @@ def _rcmd_blocklist(self, args: list[str]):
14001401
continue
14011402
user = User(p[2])
14021403
self._banlist[user] = BanRecord(p[0], p[1], user, float(p[3]), User(p[4]))
1403-
self._callEvent("onBanlistUpdate")
1404+
self._mgr._callEvent(self, "onBanlistUpdate")
14041405

14051406
def _rcmd_unblocklist(self, args: list[str]):
14061407
self._unbanlist = dict()
@@ -1413,7 +1414,7 @@ def _rcmd_unblocklist(self, args: list[str]):
14131414
continue
14141415
user = User(p[2])
14151416
self._unbanlist[user] = BanRecord(p[0], p[1], user, float(p[3]), User(p[4]))
1416-
self._callEvent("onUnBanlistUpdate")
1417+
self._mgr._callEvent(self, "onUnBanlistUpdate")
14171418

14181419
def _rcmd_blocked(self, args: list[str]):
14191420
if args[2] == "":
@@ -1422,7 +1423,7 @@ def _rcmd_blocked(self, args: list[str]):
14221423
user = User(args[3])
14231424
self._banlist[target] = BanRecord(args[0], args[1], target, float(args[4]), user)
14241425

1425-
self._callEvent("onBan", user, target)
1426+
self._mgr._callEvent(self, "onBan", user, target)
14261427

14271428
def _rcmd_unblocked(self, args: list[str]):
14281429
if args[2] == "":
@@ -1431,7 +1432,7 @@ def _rcmd_unblocked(self, args: list[str]):
14311432
user = User(args[3])
14321433
del self._banlist[target]
14331434
self._unbanlist[user] = BanRecord(args[0], args[1], target, float(args[4]), user)
1434-
self._callEvent("onUnban", user, target)
1435+
self._mgr._callEvent(self, "onUnban", user, target)
14351436

14361437
####
14371438
# Commands
@@ -1452,7 +1453,7 @@ def logout(self):
14521453
def ping(self):
14531454
"""Send a ping."""
14541455
self._sendCommand("")
1455-
self._callEvent("onPing")
1456+
self._mgr._callEvent(self, "onPing")
14561457

14571458
def rawMessage(self, msg: str):
14581459
"""
@@ -1680,10 +1681,6 @@ def _getBanRecord(self, user: User):
16801681
return self._banlist[user]
16811682
return None
16821683

1683-
def _callEvent(self, evt: str, *args: ..., **kw: ...):
1684-
getattr(self._mgr, evt)(self, *args, **kw)
1685-
self._mgr.onEventCalled(self, evt, *args, **kw)
1686-
16871684
def _write(self, data: bytes):
16881685
if self._wlock:
16891686
self._wlockbuf += data
@@ -1880,6 +1877,10 @@ def safePrint(self, text: str):
18801877
except UnicodeEncodeError as ex:
18811878
text = (text[0:ex.start]+'(unicode)'+text[ex.end:])
18821879

1880+
def _callEvent(self, conn: Conn, evt: str, *args: ..., **kw: ...):
1881+
getattr(self, evt)(conn, *args, **kw)
1882+
self.onEventCalled(conn, evt, *args, **kw)
1883+
18831884
def onConnect(self, room: Room):
18841885
"""
18851886
Called when connected to the room.
@@ -2163,7 +2164,7 @@ def onPMContactOffline(self, pm: PM, user: User):
21632164
@param user: the user that went offline
21642165
"""
21652166

2166-
def onEventCalled(self, room: Room | PM, evt: str, *args: ..., **kw: ...):
2167+
def onEventCalled(self, room: Conn, evt: str, *args: ..., **kw: ...):
21672168
"""
21682169
Called on every room-based event.
21692170

ch/mixin/windows_mainloop.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,10 @@ def main(self):
4646
if time_to_next_task is None:
4747
time_to_next_task = self._TimerResolution
4848

49+
next_target = ch.Task.get_next_tick_target()
50+
4951
for _ in range(int((time_to_next_task/0.2)+0.5)):
50-
if not self._running:
52+
if not self._running or conns != self.getConnections() or next_target != ch.Task.get_next_tick_target():
5153
break
5254
rd, wr, _ = select.select(conns, wsocks, [], 0.2)
5355
if rd or wr:

0 commit comments

Comments
 (0)