fix(iorails): avoid IORails sync generate coroutine warning#1968
fix(iorails): avoid IORails sync generate coroutine warning#1968Pouyanpi wants to merge 1 commit into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Greptile SummaryThis PR fixes a
|
| Filename | Overview |
|---|---|
| nemoguardrails/guardrails/iorails.py | Adds an early running-loop guard to generate(); the check is placed after an unnecessary deep copy of config that runs even on the error path. |
| tests/guardrails/test_iorails.py | Test upgraded to assert no RuntimeWarning is emitted and to match the new error message; gc.collect() ensures any zombie coroutines are flushed before the assertion. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["IORails.generate(messages)"] --> B["model_copy(deep=True)\n+ disable tracing/metrics"]
B --> C{"asyncio.get_running_loop()"}
C -- "RuntimeError\n(no loop running)" --> D["define _run_sync_iorails()"]
D --> E["asyncio.run(_run_sync_iorails())"]
E --> F["IORails engine\ngenerate_async()"]
F --> G["return LLMMessage"]
C -- "loop found\n(no exception)" --> H["raise RuntimeError\n'Use generate_async() instead'"]
Comments Outside Diff (1)
-
nemoguardrails/guardrails/iorails.py, line 265-279 (link)The deep copy of
sync_config(and the two attribute mutations that follow) runs unconditionally before the running-loop check. Whengenerate()is called from an async context the copy is allocated and then immediately discarded on theraise. Moving the guard to the top of the method avoids unnecessary work on the error path.Prompt To Fix With AI
This is a comment left during a code review. Path: nemoguardrails/guardrails/iorails.py Line: 265-279 Comment: The deep copy of `sync_config` (and the two attribute mutations that follow) runs unconditionally before the running-loop check. When `generate()` is called from an async context the copy is allocated and then immediately discarded on the `raise`. Moving the guard to the top of the method avoids unnecessary work on the error path. How can I resolve this? If you propose a fix, please make it concise.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
nemoguardrails/guardrails/iorails.py:265-279
The deep copy of `sync_config` (and the two attribute mutations that follow) runs unconditionally before the running-loop check. When `generate()` is called from an async context the copy is allocated and then immediately discarded on the `raise`. Moving the guard to the top of the method avoids unnecessary work on the error path.
```suggestion
try:
asyncio.get_running_loop()
except RuntimeError:
pass
else:
raise RuntimeError(
"IORails.generate() cannot be called from a running event loop. Use generate_async() instead."
)
# Disable tracing and metrics for synchronous generation calls
sync_config = self.config.model_copy(deep=True)
if sync_config.tracing is not None:
sync_config.tracing.enabled = False
if sync_config.metrics is not None:
sync_config.metrics.enabled = False
```
Reviews (1): Last reviewed commit: "fix: avoid IORails sync generate corouti..." | Re-trigger Greptile
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Enterprise Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthrough
ChangesEvent-loop guard in generate()
🎯 2 (Simple) | ⏱️ ~10 minutes 🚥 Pre-merge checks | ✅ 5 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
tgasser-nv
left a comment
There was a problem hiding this comment.
LGTM! Just a tiny nit to move the check before config copying and mutaton
| if sync_config.metrics is not None: | ||
| sync_config.metrics.enabled = False | ||
|
|
||
| try: |
There was a problem hiding this comment.
nit: Could you move this up to start at line 265 so we don't mutate any of the tracing config if we're going to raise an error?
Summary
Fix
IORails.generate()so calling the synchronous API from inside an already-running event loop fails cleanly without leaking an unawaited coroutine warning.Reproduction
On the current behavior, the focused test passes but emits a runtime warning:
The warning appears as:
In a larger test run, it can surface from pytest internals, for example:
Fix
IORails.generate()now checks for a running event loop before constructing the internal coroutine. If called from async code, it raises the existingRuntimeErrorpath cleanly and tells callers to usegenerate_async().The test now also asserts that this path does not emit a
RuntimeWarning.Validation
Summary by CodeRabbit
Bug Fixes
Tests