pallets / jinja

A very fast and expressive template engine.
https://jinja.palletsprojects.com
BSD 3-Clause "New" or "Revised" License
10.12k stars 1.6k forks source link

root_render_func not properly aclosed in Template.generate_async #1956

Closed graingert closed 2 months ago

graingert commented 3 months ago

running

import contextlib
import sys
import trio
from collections.abc import AsyncGenerator

from jinja2 import Template, select_autoescape

class MyModel:
    class objects:
        @staticmethod
        async def all() -> AsyncGenerator[str, None]:
            while True:
                yield "hello"

template = """
<html>
  <head></head>
  <body>
    {% for m in model.objects.all() %}
        {{ m }}
        {% break %}
    {% endfor %}
  </body>
</html>
"""

async def amain() -> None:
    async with contextlib.aclosing(
        Template(
            source=template, enable_async=True, extensions=["jinja2.ext.loopcontrols"]
        ).generate_async(model=MyModel)
    ) as agen:
        async for v in agen:
            print(v)
            break

def main() -> int | None:
    return trio.run(amain)

if __name__ == "__main__":
    sys.exit(main())

results in:

<html>
  <head></head>
  <body>

/home/graingert/.virtualenvs/demo-jinja-asyncgens/lib/python3.12/site-packages/jinja2/environment.py:1371: ResourceWarning: Async generator '<<template>>.root' was garbage collected before it had been exhausted. Surround its use in 'async with aclosing(...):' to ensure that it gets cleaned up as soon as you're done using it.
  yield event
ResourceWarning: Enable tracemalloc to get the object allocation traceback