Skip to content

Commit d8effbd

Browse files
authored
Use get_running_loop instead of get_event_loop (#1204)
1 parent 741c924 commit d8effbd

File tree

4 files changed

+28
-16
lines changed

4 files changed

+28
-16
lines changed

pydantic_ai_slim/pydantic_ai/agent.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from typing_extensions import TypeGuard, TypeVar, deprecated
1414

1515
from pydantic_graph import End, Graph, GraphRun, GraphRunContext
16-
from pydantic_graph._utils import get_event_loop
16+
from pydantic_graph._utils import run_until_complete
1717

1818
from . import (
1919
_agent_graph,
@@ -567,7 +567,7 @@ def run_sync(
567567
"""
568568
if infer_name and self.name is None:
569569
self._infer_name(inspect.currentframe())
570-
return get_event_loop().run_until_complete(
570+
return run_until_complete(
571571
self.run(
572572
user_prompt,
573573
result_type=result_type,

pydantic_graph/pydantic_graph/_utils.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
from __future__ import annotations as _annotations
22

33
import asyncio
4+
import sys
45
import types
6+
from collections.abc import Coroutine
57
from functools import partial
68
from typing import Any, Callable, TypeVar
79

@@ -10,15 +12,6 @@
1012
from typing_inspection.introspection import is_union_origin
1113

1214

13-
def get_event_loop():
14-
try:
15-
event_loop = asyncio.get_event_loop()
16-
except RuntimeError:
17-
event_loop = asyncio.new_event_loop()
18-
asyncio.set_event_loop(event_loop)
19-
return event_loop
20-
21-
2215
def get_union_args(tp: Any) -> tuple[Any, ...]:
2316
"""Extract the arguments of a Union type if `response_type` is a union, otherwise return an empty tuple."""
2417
# similar to `pydantic_ai_slim/pydantic_ai/_result.py:get_union_args`
@@ -100,3 +93,15 @@ async def run_in_executor(func: Callable[_P, _R], *args: _P.args, **kwargs: _P.k
10093
return await asyncio.get_running_loop().run_in_executor(None, partial(func, *args, **kwargs))
10194
else:
10295
return await asyncio.get_running_loop().run_in_executor(None, func, *args) # type: ignore
96+
97+
98+
def run_until_complete(coro: Coroutine[None, None, _R]) -> _R:
99+
if sys.version_info < (3, 11):
100+
try:
101+
loop = asyncio.new_event_loop()
102+
return loop.run_until_complete(coro)
103+
finally:
104+
loop.close()
105+
else:
106+
with asyncio.runners.Runner(loop_factory=asyncio.new_event_loop) as runner:
107+
return runner.run(coro)

pydantic_graph/pydantic_graph/graph.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ def run_sync(
202202
if infer_name and self.name is None:
203203
self._infer_name(inspect.currentframe())
204204

205-
return _utils.get_event_loop().run_until_complete(
205+
return _utils.run_until_complete(
206206
self.run(start_node, state=state, deps=deps, persistence=persistence, infer_name=False)
207207
)
208208

tests/graph/test_utils.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
from threading import Thread
22

3-
from pydantic_graph._utils import get_event_loop
3+
from pydantic_graph._utils import run_until_complete
44

55

6-
def test_get_event_loop_in_thread():
6+
def test_run_until_complete_in_main_thread():
7+
async def run(): ...
8+
9+
run_until_complete(run())
10+
11+
12+
def test_run_until_complete_in_thread():
13+
async def run(): ...
14+
715
def get_and_close_event_loop():
8-
event_loop = get_event_loop()
9-
event_loop.close()
16+
run_until_complete(run())
1017

1118
thread = Thread(target=get_and_close_event_loop)
1219
thread.start()

0 commit comments

Comments
 (0)