From 0bee0170216f42dafbe76d561b942b3c12e0b761 Mon Sep 17 00:00:00 2001 From: ekenyon676 <162503709+ekenyon676@users.noreply.github.com> Date: Mon, 13 Jul 2026 09:22:50 -0400 Subject: [PATCH 1/2] fix asyncio deprecation warning --- src/evdev/eventio_async.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/evdev/eventio_async.py b/src/evdev/eventio_async.py index 4af1aab..ca7dc41 100644 --- a/src/evdev/eventio_async.py +++ b/src/evdev/eventio_async.py @@ -36,7 +36,7 @@ def __aiter__(self) -> Self: return self def __anext__(self) -> "asyncio.Future[InputEvent]": - future = asyncio.Future() + future = asyncio.get_running_loop().create_future() try: # Read from the previous batch of events. future.set_result(next(self.current_batch)) @@ -55,7 +55,10 @@ def next_batch_ready(batch): class EventIO(eventio.EventIO): def _do_when_readable(self, callback): - loop = asyncio.get_event_loop() + # Remember the loop the reader is registered on so that close() can + # remove it later, even when called without a running event loop. + loop = asyncio.get_running_loop() + self._loop = loop def ready(): loop.remove_reader(self.fileno()) @@ -74,7 +77,7 @@ def async_read_one(self): Asyncio coroutine to read and return a single input event as an instance of :class:`InputEvent `. """ - future = asyncio.Future() + future = asyncio.get_running_loop().create_future() self._do_when_readable(lambda: self._set_result(future, self.read_one)) return future @@ -84,7 +87,7 @@ def async_read(self): a generator object that yields :class:`InputEvent ` instances. """ - future = asyncio.Future() + future = asyncio.get_running_loop().create_future() self._do_when_readable(lambda: self._set_result(future, self.read)) return future @@ -97,10 +100,11 @@ def async_read_loop(self) -> ReadIterator: return ReadIterator(self) def close(self): - try: - loop = asyncio.get_event_loop() - loop.remove_reader(self.fileno()) - except RuntimeError: - # no event loop present, so there is nothing to - # remove the reader from. Ignore - pass + # A reader is only registered once an async read has been awaited, in + # which case _do_when_readable recorded the loop it was added to. + loop = getattr(self, "_loop", None) + if loop is None or loop.is_closed(): + # No reader was ever registered, or its loop is already gone, so + # there is nothing to remove the reader from. + return + loop.remove_reader(self.fileno()) From 200b627609b291404ffc06434ac1549bd9fd05d1 Mon Sep 17 00:00:00 2001 From: ekenyon676 <162503709+ekenyon676@users.noreply.github.com> Date: Wed, 15 Jul 2026 11:23:10 -0400 Subject: [PATCH 2/2] use class attribute --- src/evdev/eventio_async.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/evdev/eventio_async.py b/src/evdev/eventio_async.py index ca7dc41..89a2ede 100644 --- a/src/evdev/eventio_async.py +++ b/src/evdev/eventio_async.py @@ -54,6 +54,10 @@ def next_batch_ready(batch): class EventIO(eventio.EventIO): + # The event loop a reader was last registered on, or None if no async read + # has been awaited yet. Set in _do_when_readable, used by close(). + _loop: "asyncio.AbstractEventLoop | None" = None + def _do_when_readable(self, callback): # Remember the loop the reader is registered on so that close() can # remove it later, even when called without a running event loop. @@ -102,7 +106,7 @@ def async_read_loop(self) -> ReadIterator: def close(self): # A reader is only registered once an async read has been awaited, in # which case _do_when_readable recorded the loop it was added to. - loop = getattr(self, "_loop", None) + loop = self._loop if loop is None or loop.is_closed(): # No reader was ever registered, or its loop is already gone, so # there is nothing to remove the reader from.