11import asyncio
2+ from typing import Any , List , Union , overload
3+ from uuid import UUID , uuid4
4+
25import pytest
3- from uuid import uuid4
6+ from typing_extensions import Literal
7+
8+ from pybotx .models .method_callbacks import BotXMethodCallback
49
510from pybotx .bot .callbacks .callback_manager import (
611 CallbackManager ,
1116
1217
1318@pytest .mark .asyncio
14- async def test_delegation_to_repo_methods (monkeypatch ) :
19+ async def test_delegation_to_repo_methods (monkeypatch : pytest . MonkeyPatch ) -> None :
1520 """Проверяем, что CallbackManager делегирует все вызовы в CallbackRepoProto."""
1621 sync_id = uuid4 ()
17- calls = []
22+ calls : List [ Any ] = []
1823
1924 class DummyRepo :
20- async def create_botx_method_callback (self , sid ) :
25+ async def create_botx_method_callback (self , sid : UUID ) -> None :
2126 calls .append (("create" , sid ))
2227
23- async def set_botx_method_callback_result (self , cb ) :
28+ async def set_botx_method_callback_result (self , cb : BotXMethodCallback ) -> None :
2429 calls .append (("set" , cb ))
2530
26- async def wait_botx_method_callback (self , sid , timeout ):
31+ async def wait_botx_method_callback (
32+ self , sid : UUID , timeout : float
33+ ) -> BotXMethodCallback :
2734 calls .append (("wait" , sid , timeout ))
28- return "result"
35+ # Create a mock BotXMethodCallback
36+ mock_callback = type ("MockCallback" , (), {"sync_id" : sid })()
37+ return mock_callback # type: ignore
2938
30- async def pop_botx_method_callback (self , sid ):
39+ async def pop_botx_method_callback (
40+ self , sid : UUID
41+ ) -> "asyncio.Future[BotXMethodCallback]" :
3142 calls .append (("pop" , sid ))
32- return "future"
43+ # Create a mock Future
44+ future : "asyncio.Future[BotXMethodCallback]" = asyncio .Future ()
45+ future .set_result (type ("MockCallback" , (), {"sync_id" : sid })())
46+ return future
3347
34- async def stop_callbacks_waiting (self ):
48+ async def stop_callbacks_waiting (self ) -> None :
3549 calls .append (("stop" ,))
3650
3751 repo = DummyRepo ()
@@ -43,10 +57,10 @@ async def stop_callbacks_waiting(self):
4357 await mgr .set_botx_method_callback_result (dummy_cb )
4458 # wait
4559 res = await mgr .wait_botx_method_callback (sync_id , timeout = 2.5 )
46- assert res == "result"
60+ assert hasattr ( res , "sync_id" )
4761 # pop
4862 fut = await mgr .pop_botx_method_callback (sync_id )
49- assert fut == "future"
63+ assert isinstance ( fut , asyncio . Future )
5064 # stop
5165 await mgr .stop_callbacks_waiting ()
5266
@@ -59,7 +73,7 @@ async def stop_callbacks_waiting(self):
5973 ]
6074
6175
62- def test_get_event_loop_prefers_main_loop ():
76+ def test_get_event_loop_prefers_main_loop () -> None :
6377 """Если задан основной луп, _get_event_loop возвращает именно его."""
6478 repo = type ("R" , (), {})()
6579 mgr = CallbackManager (repo )
@@ -68,7 +82,7 @@ def test_get_event_loop_prefers_main_loop():
6882 assert mgr ._get_event_loop () is loop
6983
7084
71- def test_get_event_loop_fallback_to_current ():
85+ def test_get_event_loop_fallback_to_current () -> None :
7286 """Если основной луп не задан, _get_event_loop возвращает текущий луп."""
7387 repo = type ("R" , (), {})()
7488 mgr = CallbackManager (repo )
@@ -80,7 +94,7 @@ def test_get_event_loop_fallback_to_current():
8094
8195
8296@pytest .mark .asyncio
83- async def test_setup_and_cancel_alarm_default_and_with_return ():
97+ async def test_setup_and_cancel_alarm_default_and_with_return () -> None :
8498 """
8599 Проверяем, что setup_callback_timeout_alarm создаёт задачу,
86100 а cancel_callback_timeout_alarm:
@@ -133,7 +147,7 @@ async def test_setup_and_cancel_alarm_default_and_with_return():
133147 alarm2 .task .result ()
134148
135149
136- def test_cancel_nonexistent_raises ():
150+ def test_cancel_nonexistent_raises () -> None :
137151 """Если нет такого таймера, должно быть BotXMethodCallbackNotFoundError."""
138152 repo = type ("R" , (), {})()
139153 mgr = CallbackManager (repo )
@@ -142,39 +156,57 @@ def test_cancel_nonexistent_raises():
142156
143157
144158@pytest .mark .asyncio
145- async def test_callback_timeout_alarm_triggers (monkeypatch ) :
159+ async def test_callback_timeout_alarm_triggers (monkeypatch : pytest . MonkeyPatch ) -> None :
146160 """
147161 Проверяем логику _callback_timeout_alarm:
148162 - после await sleep вызывает cancel_callback_timeout_alarm и pop_botx_method_callback;
149163 - логирует ошибку.
150164 """
151165 sid = uuid4 ()
152- calls = []
166+ calls : List [ Any ] = []
153167
154168 class DummyMgr (CallbackManager ):
155- def __init__ (self ):
156- super ().__init__ (None )
169+ def __init__ (self ) -> None :
170+ super ().__init__ (None ) # type: ignore
171+
172+ @overload
173+ def cancel_callback_timeout_alarm (self , sync_id : UUID ) -> None : ...
174+
175+ @overload
176+ def cancel_callback_timeout_alarm (
177+ self , sync_id : UUID , return_remaining_time : Literal [True ]
178+ ) -> float : ...
157179
158- def cancel_callback_timeout_alarm (self , sync_id ):
180+ def cancel_callback_timeout_alarm (
181+ self , sync_id : UUID , return_remaining_time : bool = False
182+ ) -> Union [None , float ]:
159183 calls .append (("cancel" , sync_id ))
184+ if return_remaining_time :
185+ return 0.0
186+ return None
160187
161- async def pop_botx_method_callback (self , sync_id ):
188+ async def pop_botx_method_callback (
189+ self , sync_id : UUID
190+ ) -> "asyncio.Future[BotXMethodCallback]" :
162191 calls .append (("pop" , sync_id ))
192+ future : "asyncio.Future[BotXMethodCallback]" = asyncio .Future ()
193+ future .set_result (type ("MockCallback" , (), {"sync_id" : sync_id })())
194+ return future
163195
164196 mgr = DummyMgr ()
165197
166198 # Подменяем sleep, чтобы не ждать реальное время
167- async def fake_sleep (t ) :
199+ async def fake_sleep (t : float ) -> None :
168200 calls .append (("sleep" , t ))
169201 # не ждём
170202
171203 monkeypatch .setattr (asyncio , "sleep" , fake_sleep )
172204
173205 # Подменяем logger.error
174- logged = {}
206+ logged : dict [ str , Any ] = {}
175207 from pybotx .logger import logger
176208
177- def fake_error (msg , ** kwargs ) :
209+ def fake_error (msg : str , ** kwargs : Any ) -> None :
178210 logged ["msg" ] = msg
179211 logged ["kwargs" ] = kwargs
180212
0 commit comments