Skip to content

Commit 8fcdca0

Browse files
committed
fix linter
1 parent 88f0f04 commit 8fcdca0

File tree

5 files changed

+248
-135
lines changed

5 files changed

+248
-135
lines changed

pybotx/bot/callbacks/callback_memory_repo.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from pybotx.models.method_callbacks import BotXMethodCallback
1010

1111
if TYPE_CHECKING:
12-
from asyncio import Future # noqa: WPS458
12+
from asyncio import Future
1313

1414

1515
class CallbackWrapper:
@@ -20,8 +20,8 @@ def __init__(
2020
):
2121
self.sync_id = sync_id
2222
self.main_loop = main_loop
23-
self._result = None
24-
self._exception = None
23+
self._result: Optional[BotXMethodCallback] = None
24+
self._exception: Optional[Exception] = None
2525
self._event = threading.Event()
2626
self._future: Optional["Future[BotXMethodCallback]"] = None
2727

@@ -34,14 +34,14 @@ def create_future(self) -> None:
3434
self._future = asyncio.Future()
3535
else:
3636

37-
def create_future():
37+
def create_future() -> None:
3838
self._future = asyncio.Future()
3939

4040
self.main_loop.call_soon_threadsafe(create_future)
4141
except RuntimeError:
4242
if self.main_loop is not None:
4343

44-
def create_future():
44+
def create_future() -> None:
4545
self._future = asyncio.Future()
4646

4747
self.main_loop.call_soon_threadsafe(create_future)
@@ -50,7 +50,7 @@ def create_future():
5050
else:
5151
self._future = asyncio.Future()
5252

53-
def set_result(self, result) -> None:
53+
def set_result(self, result: BotXMethodCallback) -> None:
5454
"""Set the result in a thread-safe manner."""
5555
self._result = result
5656
self._event.set()
@@ -70,7 +70,7 @@ def set_result(self, result) -> None:
7070
else:
7171
self._future.set_result(result)
7272

73-
def set_exception(self, exception) -> None:
73+
def set_exception(self, exception: Exception) -> None:
7474
"""Set an exception in a thread-safe manner."""
7575
self._exception = exception
7676
self._event.set()
@@ -93,7 +93,7 @@ def set_exception(self, exception) -> None:
9393
else:
9494
self._future.set_exception(exception)
9595

96-
async def wait_for_result(self, timeout: float):
96+
async def wait_for_result(self, timeout: float) -> BotXMethodCallback:
9797
"""Wait for the result with timeout."""
9898
try:
9999
current_loop = asyncio.get_running_loop()
@@ -105,7 +105,7 @@ async def wait_for_result(self, timeout: float):
105105
return await asyncio.wait_for(self._future, timeout=timeout)
106106
else:
107107

108-
def wait_with_timeout():
108+
def wait_with_timeout() -> bool:
109109
return self._event.wait(timeout)
110110

111111
loop = asyncio.get_running_loop()
@@ -117,6 +117,9 @@ def wait_with_timeout():
117117
if self._exception is not None:
118118
raise self._exception
119119

120+
assert self._result is not None, (
121+
"Result should be set when no exception occurred"
122+
)
120123
return self._result
121124
except RuntimeError:
122125
success = self._event.wait(timeout)
@@ -126,6 +129,9 @@ def wait_with_timeout():
126129
if self._exception is not None:
127130
raise self._exception
128131

132+
assert self._result is not None, (
133+
"Result should be set when no exception occurred"
134+
)
129135
return self._result
130136

131137
def get_future(self) -> "Future[BotXMethodCallback]":
@@ -174,7 +180,7 @@ async def wait_botx_method_callback(
174180
try:
175181
return await wrapper.wait_for_result(timeout)
176182
except asyncio.TimeoutError as exc:
177-
del self._callback_wrappers[sync_id] # noqa: WPS420
183+
del self._callback_wrappers[sync_id]
178184
raise CallbackNotReceivedError(sync_id) from exc
179185

180186
async def pop_botx_method_callback(

tests/bot/callbacks/test_callback_manager.py

Lines changed: 57 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import asyncio
2+
from typing import Any, List, Union, overload
3+
from uuid import UUID, uuid4
4+
25
import pytest
3-
from uuid import uuid4
6+
from typing_extensions import Literal
7+
8+
from pybotx.models.method_callbacks import BotXMethodCallback
49

510
from pybotx.bot.callbacks.callback_manager import (
611
CallbackManager,
@@ -11,27 +16,36 @@
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

Comments
 (0)