Skip to content

Conversation

@JasperSui
Copy link
Owner

@JasperSui JasperSui commented Oct 18, 2025

Purpose

Fix Python 3.14+ compatibility where asyncio.get_event_loop() now raises RuntimeError instead of returning a loop when none exists in the current thread.

Changes

TL;DR

Updated LoopManager to use asyncio.get_running_loop() first, with a graceful fallback to policy-based loop retrieval/creation for Python 3.14+ compatibility. Added comprehensive test coverage for the fallback mechanism.


Add compatibility layer for Python 3.14+ where asyncio.get_event_loop()
raises RuntimeError when no event loop exists in the current thread.

  • Add _get_or_create_current_loop() method to LoopManager class that
    attempts to get loop via policy, falling back to creating new loop if
    RuntimeError is raised
  • Update get_loop() to prioritize asyncio.get_running_loop() for
    'current' strategy, falling back to policy-based approach when no
    running loop exists
  • Modify _get_isolated_loop() to use get_event_loop_policy().new_event_loop()
    for consistency with policy-based approach
  • Update test_get_loop_current_strategy to mock get_running_loop()
    instead of deprecated get_event_loop()
  • Update test_get_loop_isolated_strategy to mock policy instead of
    direct new_event_loop() call
  • Add test_get_loop_current_strategy_fallback to verify fallback to
    policy when no running loop exists
  • Add test_get_loop_current_strategy_fallback_create_new to verify
    new loop creation when policy raises RuntimeError (Python 3.14+)

Fixes: RuntimeError: There is no current event loop in thread 'MainThread'

Add compatibility layer for Python 3.14+ where `asyncio.get_event_loop()`
raises `RuntimeError` when no event loop exists in the current thread.

- Add `_get_or_create_current_loop()` method to `LoopManager` class that
  attempts to get loop via policy, falling back to creating new loop if
  `RuntimeError` is raised
- Update `get_loop()` to prioritize `asyncio.get_running_loop()` for
  'current' strategy, falling back to policy-based approach when no
  running loop exists
- Modify `_get_isolated_loop()` to use `get_event_loop_policy().new_event_loop()`
  for consistency with policy-based approach
- Update `test_get_loop_current_strategy` to mock `get_running_loop()`
  instead of deprecated `get_event_loop()`
- Update `test_get_loop_isolated_strategy` to mock policy instead of
  direct `new_event_loop()` call
- Add `test_get_loop_current_strategy_fallback` to verify fallback to
  policy when no running loop exists
- Add `test_get_loop_current_strategy_fallback_create_new` to verify
  new loop creation when policy raises `RuntimeError` (Python 3.14+)

Fixes: RuntimeError: There is no current event loop in thread 'MainThread'
@JasperSui JasperSui closed this Oct 18, 2025
@JasperSui JasperSui reopened this Oct 18, 2025
@codecov
Copy link

codecov bot commented Oct 18, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (78e5347) to head (7293c8f).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##              main      #175   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            9         9           
  Lines          322       326    +4     
  Branches        36        36           
=========================================
+ Hits           322       326    +4     
Files with missing lines Coverage Δ
src/fastapi_injectable/concurrency.py 100.00% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@JasperSui JasperSui merged commit 2c956e7 into main Oct 18, 2025
78 checks passed
@JasperSui JasperSui deleted the fix/event-loop-creation-for-python-3-14 branch October 18, 2025 04:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant