fix: handle Python 3.12+ get_event_loop RuntimeError in VirtualKernelContext#1156
Open
maartenbreddels wants to merge 4 commits intomasterfrom
Open
fix: handle Python 3.12+ get_event_loop RuntimeError in VirtualKernelContext#1156maartenbreddels wants to merge 4 commits intomasterfrom
maartenbreddels wants to merge 4 commits intomasterfrom
Conversation
…alKernelContext On Python 3.12+, asyncio.run() calls set_event_loop(None) in cleanup, which puts the policy into a state where a subsequent asyncio.get_event_loop() raises RuntimeError instead of implicitly creating a new loop. The VirtualKernelContext.event_loop field used asyncio.get_event_loop as its default_factory, so any test running after a test that used asyncio.run() (e.g. starlette_lifespan_test) failed in the autouse kernel_context fixture that constructs a VirtualKernelContext. Wrap the factory to create and set a new loop when get_event_loop() raises. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Windows unit-test jobs were hanging for hours after pytest finished successfully — the shell step never received "process completed" because a lingering thread/process kept Python alive. Without a job timeout, the runner waits the full default (6h). - timeout-minutes: 15 on the unit-test job so a hang fails fast instead of sitting for hours. - --session-timeout=600 makes pytest-timeout abort the whole session and dump a stack trace before the job timeout fires, so we see what hung. - -v prints test names as they run, so the last test before a hang is visible in the log. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
On Windows CI the Python process hangs for hours after pytest prints its passing summary, because non-daemon threads from ipykernel/websockets keep the interpreter alive. Force-exit in pytest_sessionfinish so the shell step completes with pytest's exit code. Gated on CI=true so local runs still cleanup normally. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The 0.001s bound was too tight for CI runners — observed delta of 0.0016s on mac 3.8 CI. 0.05s still clearly distinguishes "cancelled immediately" from "waited out the ~0.05s remaining cull window". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Unit tests on master are failing on Python 3.12 across macOS and Ubuntu with:
Every test after
tests/unit/starlette_lifespan_test.py(~30% of the suite) errors out at setup of the autousekernel_contextfixture.Why
tests/unit/starlette_lifespan_test.py(added in 1a19f8a) callsasyncio.run(...). On Python 3.12+,asyncio.run()cleans up by callingset_event_loop(None), which puts the event-loop policy into a state where a subsequentasyncio.get_event_loop()call from the main thread raisesRuntimeErrorinstead of silently creating a new loop.VirtualKernelContext.event_loopusedasyncio.get_event_loopas itsdefault_factory, so every test after the lifespan test failed when thekernel_contextfixture constructed a newVirtualKernelContext.Fix
Wrap the factory in a small helper that falls back to
new_event_loop()+set_event_loop()whenget_event_loop()raises. This matches the pre-3.12 auto-create behavior that the rest of the code was implicitly relying on.Reproducer on 3.12:
Test plan
🤖 Generated with Claude Code