extensions shows more relevant context. :issue:`1429`
- Fixed calling deprecated ``jinja2.Markup`` without an argument.
Use ``markupsafe.Markup`` instead. :issue:`1438`
+- Calling sync ``render`` for an async template uses ``asyncio.run``
+ on Python >= 3.7. This fixes a deprecation that Python 3.10
+ introduces. :issue:`1443`
Version 3.0.0
following implications:
- Template rendering requires an event loop to be available to the
- current thread. :func:`asyncio.get_event_loop` must return an event
- loop.
+ current thread. :func:`asyncio.get_running_loop` must return an
+ event loop.
- The compiled code uses ``await`` for functions and attributes, and
uses ``async for`` loops. In order to support using both async and
sync functions in this context, a small wrapper is placed around
- all calls and access, which add overhead compared to purely async
+ all calls and access, which adds overhead compared to purely async
code.
- Sync methods and filters become wrappers around their corresponding
async implementations where needed. For example, ``render`` invokes
options.
"""
import os
+import sys
import typing
import typing as t
import weakref
if self.environment.is_async:
import asyncio
- loop = asyncio.get_event_loop()
- return loop.run_until_complete(self.render_async(*args, **kwargs))
+ close = False
+
+ if sys.version_info < (3, 7):
+ loop = asyncio.get_event_loop()
+ else:
+ try:
+ loop = asyncio.get_running_loop()
+ except RuntimeError:
+ loop = asyncio.new_event_loop()
+ close = True
+
+ try:
+ return loop.run_until_complete(self.render_async(*args, **kwargs))
+ finally:
+ if close:
+ loop.close()
ctx = self.new_context(dict(*args, **kwargs))
if self.environment.is_async:
import asyncio
- loop = asyncio.get_event_loop()
- async_gen = self.generate_async(*args, **kwargs)
+ async def to_list() -> t.List[str]:
+ return [x async for x in self.generate_async(*args, **kwargs)]
- try:
- while True:
- yield loop.run_until_complete(async_gen.__anext__())
- except StopAsyncIteration:
- return
+ if sys.version_info < (3, 7):
+ loop = asyncio.get_event_loop()
+ out = loop.run_until_complete(to_list())
+ else:
+ out = asyncio.run(to_list())
+
+ yield from out
+ return
ctx = self.new_context(dict(*args, **kwargs))
import asyncio
+import sys
import pytest
from jinja2.nativetypes import NativeEnvironment
-def run(coro):
- loop = asyncio.get_event_loop()
- return loop.run_until_complete(coro)
+if sys.version_info < (3, 7):
+
+ def run(coro):
+ loop = asyncio.get_event_loop()
+ return loop.run_until_complete(coro)
+
+
+else:
+
+ def run(coro):
+ return asyncio.run(coro)
def test_basic_async():