Fix compatibility with Python 3.8-3.9 (#1162)

* Try to fix compatibility with Python 3.8-3.9

* Added changelog
This commit is contained in:
Alex Root Junior 2023-04-21 00:17:06 +03:00 committed by GitHub
parent 399ccb2b00
commit fb3076d40f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 49 additions and 5 deletions

1
CHANGES/1162.bugfix.rst Normal file
View file

@ -0,0 +1 @@
Fixed compatibility with Python 3.8-3.9

View file

@ -92,8 +92,8 @@ class Dispatcher(Router):
self.workflow_data: Dict[str, Any] = kwargs self.workflow_data: Dict[str, Any] = kwargs
self._running_lock = Lock() self._running_lock = Lock()
self._stop_signal = Event() self._stop_signal: Optional[Event] = None
self._stopped_signal = Event() self._stopped_signal: Optional[Event] = None
def __getitem__(self, item: str) -> Any: def __getitem__(self, item: str) -> Any:
return self.workflow_data[item] return self.workflow_data[item]
@ -430,6 +430,8 @@ class Dispatcher(Router):
""" """
if not self._running_lock.locked(): if not self._running_lock.locked():
raise RuntimeError("Polling is not started") raise RuntimeError("Polling is not started")
if not self._stop_signal or not self._stopped_signal:
return
self._stop_signal.set() self._stop_signal.set()
await self._stopped_signal.wait() await self._stopped_signal.wait()
@ -438,6 +440,8 @@ class Dispatcher(Router):
return return
loggers.dispatcher.warning("Received %s signal", sig.name) loggers.dispatcher.warning("Received %s signal", sig.name)
if not self._stop_signal:
return
self._stop_signal.set() self._stop_signal.set()
async def start_polling( async def start_polling(
@ -473,6 +477,11 @@ class Dispatcher(Router):
) )
async with self._running_lock: # Prevent to run this method twice at a once async with self._running_lock: # Prevent to run this method twice at a once
if self._stop_signal is None:
self._stop_signal = Event()
if self._stopped_signal is None:
self._stopped_signal = Event()
self._stop_signal.clear() self._stop_signal.clear()
self._stopped_signal.clear() self._stopped_signal.clear()

View file

@ -151,6 +151,13 @@ extra-dependencies = [
"butcher @ git+https://github.com/aiogram/butcher.git@v0.1.14" "butcher @ git+https://github.com/aiogram/butcher.git@v0.1.14"
] ]
[tool.hatch.envs.dev.scripts]
update = [
"butcher parse",
"butcher refresh",
"butcher apply all",
]
[tool.hatch.envs.test] [tool.hatch.envs.test]
features = [ features = [
"fast", "fast",

View file

@ -708,10 +708,15 @@ class TestDispatcher:
with pytest.raises(RuntimeError): with pytest.raises(RuntimeError):
await dispatcher.stop_polling() await dispatcher.stop_polling()
assert not dispatcher._stop_signal.is_set() assert not dispatcher._stop_signal
assert not dispatcher._stopped_signal.is_set() assert not dispatcher._stopped_signal
with patch("asyncio.locks.Event.wait", new_callable=AsyncMock) as mocked_wait: with patch("asyncio.locks.Event.wait", new_callable=AsyncMock) as mocked_wait:
async with dispatcher._running_lock: async with dispatcher._running_lock:
await dispatcher.stop_polling()
assert not dispatcher._stop_signal
dispatcher._stop_signal = Event()
dispatcher._stopped_signal = Event()
await dispatcher.stop_polling() await dispatcher.stop_polling()
assert dispatcher._stop_signal.is_set() assert dispatcher._stop_signal.is_set()
mocked_wait.assert_awaited() mocked_wait.assert_awaited()
@ -723,6 +728,11 @@ class TestDispatcher:
mocked_set.assert_not_called() mocked_set.assert_not_called()
async with dispatcher._running_lock: async with dispatcher._running_lock:
dispatcher._signal_stop_polling(signal.SIGINT)
mocked_set.assert_not_called()
dispatcher._stop_signal = Event()
dispatcher._stopped_signal = Event()
dispatcher._signal_stop_polling(signal.SIGINT) dispatcher._signal_stop_polling(signal.SIGINT)
mocked_set.assert_called() mocked_set.assert_called()
@ -764,12 +774,29 @@ class TestDispatcher:
def test_run_polling(self, bot: MockedBot): def test_run_polling(self, bot: MockedBot):
dispatcher = Dispatcher() dispatcher = Dispatcher()
async def stop():
await asyncio.sleep(0.5)
await dispatcher.stop_polling()
start_called = False
@dispatcher.startup()
async def startup():
nonlocal start_called
start_called = True
asyncio.create_task(stop())
original_start_polling = dispatcher.start_polling
with patch( with patch(
"aiogram.dispatcher.dispatcher.Dispatcher.start_polling" "aiogram.dispatcher.dispatcher.Dispatcher.start_polling",
side_effect=original_start_polling,
) as patched_start_polling: ) as patched_start_polling:
dispatcher.run_polling(bot) dispatcher.run_polling(bot)
patched_start_polling.assert_awaited_once() patched_start_polling.assert_awaited_once()
assert start_called
async def test_feed_webhook_update_fast_process(self, bot: MockedBot): async def test_feed_webhook_update_fast_process(self, bot: MockedBot):
dispatcher = Dispatcher() dispatcher = Dispatcher()
dispatcher.message.register(simple_message_handler) dispatcher.message.register(simple_message_handler)