Skip to content

Commit 77674b9

Browse files
authored
Merge pull request #1444 from pallets/event-loop
use asyncio.run
2 parents 94a6423 + 7d0b7ac commit 77674b9

File tree

4 files changed

+45
-15
lines changed

4 files changed

+45
-15
lines changed

CHANGES.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ Unreleased
1313
extensions shows more relevant context. :issue:`1429`
1414
- Fixed calling deprecated ``jinja2.Markup`` without an argument.
1515
Use ``markupsafe.Markup`` instead. :issue:`1438`
16+
- Calling sync ``render`` for an async template uses ``asyncio.run``
17+
on Python >= 3.7. This fixes a deprecation that Python 3.10
18+
introduces. :issue:`1443`
1619

1720

1821
Version 3.0.0

docs/api.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -513,12 +513,12 @@ handle async and sync code in an asyncio event loop. This has the
513513
following implications:
514514

515515
- Template rendering requires an event loop to be available to the
516-
current thread. :func:`asyncio.get_event_loop` must return an event
517-
loop.
516+
current thread. :func:`asyncio.get_running_loop` must return an
517+
event loop.
518518
- The compiled code uses ``await`` for functions and attributes, and
519519
uses ``async for`` loops. In order to support using both async and
520520
sync functions in this context, a small wrapper is placed around
521-
all calls and access, which add overhead compared to purely async
521+
all calls and access, which adds overhead compared to purely async
522522
code.
523523
- Sync methods and filters become wrappers around their corresponding
524524
async implementations where needed. For example, ``render`` invokes

src/jinja2/environment.py

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
options.
33
"""
44
import os
5+
import sys
56
import typing
67
import typing as t
78
import weakref
@@ -1278,8 +1279,22 @@ def render(self, *args: t.Any, **kwargs: t.Any) -> str:
12781279
if self.environment.is_async:
12791280
import asyncio
12801281

1281-
loop = asyncio.get_event_loop()
1282-
return loop.run_until_complete(self.render_async(*args, **kwargs))
1282+
close = False
1283+
1284+
if sys.version_info < (3, 7):
1285+
loop = asyncio.get_event_loop()
1286+
else:
1287+
try:
1288+
loop = asyncio.get_running_loop()
1289+
except RuntimeError:
1290+
loop = asyncio.new_event_loop()
1291+
close = True
1292+
1293+
try:
1294+
return loop.run_until_complete(self.render_async(*args, **kwargs))
1295+
finally:
1296+
if close:
1297+
loop.close()
12831298

12841299
ctx = self.new_context(dict(*args, **kwargs))
12851300

@@ -1326,14 +1341,17 @@ def generate(self, *args: t.Any, **kwargs: t.Any) -> t.Iterator[str]:
13261341
if self.environment.is_async:
13271342
import asyncio
13281343

1329-
loop = asyncio.get_event_loop()
1330-
async_gen = self.generate_async(*args, **kwargs)
1344+
async def to_list() -> t.List[str]:
1345+
return [x async for x in self.generate_async(*args, **kwargs)]
13311346

1332-
try:
1333-
while True:
1334-
yield loop.run_until_complete(async_gen.__anext__())
1335-
except StopAsyncIteration:
1336-
return
1347+
if sys.version_info < (3, 7):
1348+
loop = asyncio.get_event_loop()
1349+
out = loop.run_until_complete(to_list())
1350+
else:
1351+
out = asyncio.run(to_list())
1352+
1353+
yield from out
1354+
return
13371355

13381356
ctx = self.new_context(dict(*args, **kwargs))
13391357

tests/test_async.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import asyncio
2+
import sys
23

34
import pytest
45

@@ -13,9 +14,17 @@
1314
from jinja2.nativetypes import NativeEnvironment
1415

1516

16-
def run(coro):
17-
loop = asyncio.get_event_loop()
18-
return loop.run_until_complete(coro)
17+
if sys.version_info < (3, 7):
18+
19+
def run(coro):
20+
loop = asyncio.get_event_loop()
21+
return loop.run_until_complete(coro)
22+
23+
24+
else:
25+
26+
def run(coro):
27+
return asyncio.run(coro)
1928

2029

2130
def test_basic_async():

0 commit comments

Comments
 (0)