Skip to content

fix(tests): use asyncio.run instead of get_event_loop in middleware tests - #1804

Merged
Pouyanpi merged 1 commit into
developfrom
fix/tests-asyncio-run
Apr 21, 2026
Merged

fix(tests): use asyncio.run instead of get_event_loop in middleware tests#1804
Pouyanpi merged 1 commit into
developfrom
fix/tests-asyncio-run

Conversation

@Pouyanpi

@Pouyanpi Pouyanpi commented Apr 20, 2026

Copy link
Copy Markdown
Collaborator

Python 3.13 removed auto creation of an event loop in asyncio.get_event_loop() when none is set on the thread. The pattern

asyncio.get_event_loop().run_until_complete(coro)

now raises RuntimeError("There is no current event loop in thread 'MainThread'") whenever a previous test ran asyncio.run() and closed its loop. This test-ordering race is flaky across CI runs (for ref: https://github.com/NVIDIA-NeMo/Guardrails/actions/runs/24666672357).

Replaces all nine occurrences across tests/integrations/langchain/test_middleware.py (eight) and tests/guardrails/test_iorails.py (one) with asyncio.run(...), which creates and owns its own loop. Behavior preserving python 313 compatible, independent of prior test loop state.

Test plan

tests/integrations/langchain/test_middleware.py:

92 passed in 0.74s

tests/guardrails/test_iorails.py:

28 passed in 1.42s

Summary by CodeRabbit

  • Tests
    • Updated test infrastructure to use modern async event loop management patterns for improved test reliability.

Note: This release contains no user-facing changes. Updates are limited to internal testing infrastructure.

…ests

Python 3.13 dropped auto-creation of an event loop in
asyncio.get_event_loop() when none is set on the thread, so the pattern

    asyncio.get_event_loop().run_until_complete(coro)

now raises RuntimeError("There is no current event loop in thread
'MainThread'") whenever a previous test ran asyncio.run() and closed its
loop (the langchain_framework fixture triggers this on teardown via
_reset_frameworks).

Replaces all eight call sites in test_middleware.py with asyncio.run(),
which creates and owns its own loop. Behavior-equivalent, Python 3.13
compatible, and independent of prior test loop state.

Will be cherry-picked onto develop and merged first; then stack-10
and its descendants rebase.
@Pouyanpi Pouyanpi added this to the v0.22.0 milestone Apr 20, 2026
@Pouyanpi Pouyanpi self-assigned this Apr 20, 2026
@Pouyanpi Pouyanpi added bug Something isn't working CI labels Apr 20, 2026
@greptile-apps

greptile-apps Bot commented Apr 20, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Replaces nine occurrences of asyncio.get_event_loop().run_until_complete(coro) with asyncio.run(coro) across two test files to fix a Python 3.13 compatibility issue where asyncio.get_event_loop() no longer auto-creates an event loop when none is set. The fix is minimal, correct, and behavior-preserving.

Confidence Score: 5/5

Safe to merge — purely mechanical test-compatibility fix with no behavioral changes.

All nine replacements are straightforward and correct. asyncio.run() creates and owns its own loop, propagates exceptions identically to run_until_complete, and is compatible with Python 3.10–3.13. No logic, security, or data-integrity concerns.

No files require special attention.

Important Files Changed

Filename Overview
tests/guardrails/test_iorails.py Single replacement of asyncio.get_event_loop().run_until_complete() with asyncio.run() inside a pytest.raises(RuntimeError) block; exception propagation is identical.
tests/integrations/langchain/test_middleware.py Eight replacements of asyncio.get_event_loop().run_until_complete() with asyncio.run() across TestSyncMethods and TestGuardrailViolationException; all are sync test methods so no nested-loop issue.

Sequence Diagram

sequenceDiagram
    participant Test as Test (sync)
    participant Old as asyncio.get_event_loop().run_until_complete()
    participant New as asyncio.run()
    participant Coro as Coroutine

    Note over Test,Old: Python ≤ 3.12 (old pattern)
    Test->>Old: get_event_loop()
    Old-->>Test: returns existing/new loop
    Test->>Old: run_until_complete(coro)
    Old->>Coro: execute
    Coro-->>Old: result / exception
    Old-->>Test: result / propagated exception

    Note over Test,New: Python 3.13+ (new pattern)
    Test->>New: asyncio.run(coro)
    New->>New: create fresh event loop
    New->>Coro: execute
    Coro-->>New: result / exception
    New->>New: close event loop
    New-->>Test: result / propagated exception
Loading

Reviews (1): Last reviewed commit: "fix(tests): use asyncio.run instead of g..." | Re-trigger Greptile

@coderabbitai

coderabbitai Bot commented Apr 20, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 794d72ff-c566-4073-b679-673d9799fd6c

📥 Commits

Reviewing files that changed from the base of the PR and between 032a661 and 14cdca9.

📒 Files selected for processing (2)
  • tests/guardrails/test_iorails.py
  • tests/integrations/langchain/test_middleware.py

📝 Walkthrough

Walkthrough

This PR updates test infrastructure in two test files by replacing deprecated asyncio.get_event_loop().run_until_complete() calls with the modern asyncio.run() approach for executing asynchronous test code, affecting guardrails and langchain middleware tests.

Changes

Cohort / File(s) Summary
Test Infrastructure Updates
tests/guardrails/test_iorails.py, tests/integrations/langchain/test_middleware.py
Replaced asyncio.get_event_loop().run_until_complete(...) with asyncio.run(...) for managing async coroutine execution in synchronous test contexts. Changes affect event-loop handling without altering test assertions or production logic.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and accurately summarizes the main change: replacing asyncio.get_event_loop() calls with asyncio.run() in test files for Python 3.13 compatibility.
Test Results For Major Changes ✅ Passed PR contains only minor test infrastructure changes (9 lines total) with no production code modifications, addressing Python 3.13 compatibility. Test results are documented showing 92 and 28 tests passing.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/tests-asyncio-run

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov

codecov Bot commented Apr 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@Pouyanpi
Pouyanpi requested a review from tgasser-nv April 20, 2026 15:02
@Pouyanpi
Pouyanpi merged commit 56b97c5 into develop Apr 21, 2026
24 of 25 checks passed
@Pouyanpi
Pouyanpi deleted the fix/tests-asyncio-run branch April 21, 2026 07:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working CI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant