diff --git a/newsfragments/159.bugfix.rst b/newsfragments/159.bugfix.rst new file mode 100644 index 00000000..7e4339eb --- /dev/null +++ b/newsfragments/159.bugfix.rst @@ -0,0 +1 @@ +Allow ``loop.call_later()`` to accept negative delays, matching asyncio's behavior by scheduling the callback immediately. diff --git a/tests/conftest.py b/tests/conftest.py index 40dcd0da..bbcde9cb 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -211,6 +211,17 @@ def skip(rel_id): item.add_marker(pytest.mark.skip) if sys.version_info >= (3, 11): + # CPython's SSLProtocol test intentionally leaves the two transports + # created while checking the missing-server_hostname warning without + # cleanup callbacks. pytest 9 reports their finalizer warnings as + # unraisable exceptions, even though the test itself passes. + mark( + pytest.mark.filterwarnings("ignore:.*_SSLProtocolTransport.__del__.*"), + "test_sslproto.py::SslProtoHandshakeTests::" + "test_check_hostname_requires_server_hostname", + may_be_absent=True, + ) + # This tries to use a mock ChildWatcher that does something unlikely. # We don't support it because we don't actually use the ChildWatcher # to manage subprocesses. diff --git a/tests/test_misc.py b/tests/test_misc.py index be83b047..521328df 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -168,6 +168,16 @@ async def cancel_sleep(): await trio_asyncio.aio_as_trio(cancel_sleep, loop=loop)() assert owch == 0 + @pytest.mark.trio + async def test_call_later_accepts_negative_delay(self, loop): + called = trio.Event() + + def callback(): + called.set() + + loop.call_later(-1, callback) + await called.wait() + @pytest.mark.trio async def test_wrong_context_manager_order(): diff --git a/trio_asyncio/_base.py b/trio_asyncio/_base.py index 77b00099..e74f28b0 100644 --- a/trio_asyncio/_base.py +++ b/trio_asyncio/_base.py @@ -364,7 +364,6 @@ def call_later(self, delay, callback, *args, **context): :return: a handle which may be used to cancel the timer. """ self._check_callback(callback, "call_later") - assert delay >= 0, delay h = asyncio.TimerHandle(delay + self.time(), callback, args, self, **context) self._queue_handle(h) return h