From 909405cc461a93379223a6728375cd1a15c9567c Mon Sep 17 00:00:00 2001 From: samypr100 <3933065+samypr100@users.noreply.github.com> Date: Sat, 4 Apr 2026 00:04:11 -0400 Subject: [PATCH] feat: support eager_start kwarg --- tests/test_base.py | 30 ++++++++++++++++++++++++++++++ uvloop/loop.pyi | 31 +++++++++++++++++++++++++------ uvloop/loop.pyx | 9 +++++++-- 3 files changed, 62 insertions(+), 8 deletions(-) diff --git a/tests/test_base.py b/tests/test_base.py index 89a82fe4..0490ee48 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -604,6 +604,36 @@ def factory(loop, coro, **kwargs): self.loop.set_task_factory(None) self.assertIsNone(self.loop.get_task_factory()) + @unittest.skipUnless( + sys.version_info >= (3, 13), + "loop.create_task with eager_start requires Python 3.13+", + ) + def test_loop_create_task_eager_start(self): + async def coro(): + return "eager" + + async def main(): + task = self.loop.create_task(coro(), eager_start=True) + self.assertTrue(task.done()) + self.assertEqual(task.result(), "eager") + + self.loop.run_until_complete(main()) + + @unittest.skipUnless( + sys.version_info >= (3, 14), + "asyncio.create_task with eager_start requires Python 3.14+", + ) + def test_asyncio_create_task_eager_start(self): + async def coro(): + return "eager" + + async def main(): + task = asyncio.create_task(coro(), eager_start=True) + self.assertTrue(task.done()) + self.assertEqual(task.result(), "eager") + + self.loop.run_until_complete(main()) + def test_shutdown_asyncgens_01(self): finalized = list() diff --git a/uvloop/loop.pyi b/uvloop/loop.pyi index 9c8c4623..80822ec0 100644 --- a/uvloop/loop.pyi +++ b/uvloop/loop.pyi @@ -1,4 +1,5 @@ import asyncio +import contextvars import ssl import sys from socket import AddressFamily, SocketKind, _Address, _RetAddress, socket @@ -46,12 +47,30 @@ class Loop: def is_running(self) -> bool: ... def is_closed(self) -> bool: ... def create_future(self) -> asyncio.Future[Any]: ... - def create_task( - self, - coro: Union[Awaitable[_T], Generator[Any, None, _T]], - *, - name: Optional[str] = ..., - ) -> asyncio.Task[_T]: ... + if sys.version_info >= (3, 13): + def create_task( + self, + coro: Union[Awaitable[_T], Generator[Any, None, _T]], + *, + name: Optional[str] = ..., + context: Optional[contextvars.Context] = ..., + eager_start: Optional[bool] = ..., + ) -> asyncio.Task[_T]: ... + elif sys.version_info >= (3, 11): + def create_task( + self, + coro: Union[Awaitable[_T], Generator[Any, None, _T]], + *, + name: Optional[str] = ..., + context: Optional[contextvars.Context] = ..., + ) -> asyncio.Task[_T]: ... + else: + def create_task( + self, + coro: Union[Awaitable[_T], Generator[Any, None, _T]], + *, + name: Optional[str] = ..., + ) -> asyncio.Task[_T]: ... def set_task_factory( self, factory: Optional[ diff --git a/uvloop/loop.pyx b/uvloop/loop.pyx index b316bd7f..442fe96c 100644 --- a/uvloop/loop.pyx +++ b/uvloop/loop.pyx @@ -1404,7 +1404,7 @@ cdef class Loop: """Create a Future object attached to the loop.""" return self._new_future() - def create_task(self, coro, *, name=None, context=None): + def create_task(self, coro, *, name=None, context=None, eager_start=None): """Schedule a coroutine object. Return a task object. @@ -1417,7 +1417,12 @@ cdef class Loop: created when no context is provided. """ self._check_closed() - if PY311: + if PY313: + if self._task_factory is None: + task = aio_Task(coro, loop=self, context=context, eager_start=eager_start) + else: + task = self._task_factory(self, coro, context=context, eager_start=eager_start) + elif PY311: if self._task_factory is None: task = aio_Task(coro, loop=self, context=context) else: