The core issue comes from eventkit's interaction with asyncio event loops, particularly when called from synchronous contexts (e.g., tests or regular Python scripts).
- Deprecation Warning:
asyncio.get_event_loop() is deprecated. The recommended alternative is to use asyncio.get_running_loop()
def get_event_loop():
"""Get asyncio event loop or create one if it doesn't exist."""
try:
return asyncio.get_running_loop()
except RuntimeError:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
return loop
-
Broken Singleton: And updated asyncio.get_running_loop() as described above breaks the singleton patern. When trying to retrieve a running asyncio loop using asyncio.get_running_loop(). This function, only returns a loop if it's actively executing tasks. In synchronous contexts, if no loop is actively running, get_running_loop() would raise a RuntimeError, causing util.get_event_loop() to create and set a new event loop. Subsequent calls from other synchronous parts of the code (even within the same thread) could then create yet another new loop if the previous one wasn't actively running, leading to RuntimeError: Future object is attached to a different loop errors.
-
Flawed Event.run() Behavior: The original Event.run() method, designed as a synchronous entry point, uses loop.run_until_complete(self.list()). This approach is problematic because run_until_complete() itself raises a RuntimeError if called on an event loop that is already running. This meant Event.run() would fail if called from within an existing asynchronous application. when get_event_loop is updated as explained above in point (1), Event.run breaks creates the issue explained in point (2). Event.run() is not waiting for futures spawned internally by eventkit
The core issue comes from
eventkit's interaction withasyncioevent loops, particularly when called from synchronous contexts (e.g., tests or regular Python scripts).asyncio.get_event_loop()is deprecated. The recommended alternative is to useasyncio.get_running_loop()Broken Singleton: And updated
asyncio.get_running_loop()as described above breaks the singleton patern. When trying to retrieve a runningasyncioloop usingasyncio.get_running_loop(). This function, only returns a loop if it's actively executing tasks. In synchronous contexts, if no loop is actively running,get_running_loop()would raise aRuntimeError, causingutil.get_event_loop()to create and set a new event loop. Subsequent calls from other synchronous parts of the code (even within the same thread) could then create yet another new loop if the previous one wasn't actively running, leading toRuntimeError: Future object is attached to a different looperrors.Flawed
Event.run()Behavior: The originalEvent.run()method, designed as a synchronous entry point, usesloop.run_until_complete(self.list()). This approach is problematic becauserun_until_complete()itself raises aRuntimeErrorif called on an event loop that is already running. This meantEvent.run()would fail if called from within an existing asynchronous application. when get_event_loop is updated as explained above in point (1), Event.run breaks creates the issue explained in point (2).Event.run()is not waiting for futures spawned internally by eventkit