Skip to content

Unable to combine the map and sort filters using the async renderer #2081

@ogenstad

Description

@ogenstad

I would expect this script to return the same output for both the sync and async version:

import asyncio

from jinja2 import DictLoader, Environment, Template, select_autoescape

template_str = """
sorted_letters={{ letters
    | map(attribute='value')
    | sort
 }}
"""

sample_data = [
    {"value": "a"},
    {"value": "d"},
    {"value": "c"},
    {"value": "b"},
]


def get_template(is_async: bool) -> Template:
    env = Environment(
        loader=DictLoader({"template.j2": template_str}),
        autoescape=select_autoescape(),
        enable_async=is_async,
    )

    return env.get_template("template.j2")


def test_sync_render() -> None:
    print("Sync Render:")
    template = get_template(is_async=False)
    result = template.render(letters=sample_data)
    print(result)


async def test_async_render() -> None:
    print("Async Render:")
    template = get_template(is_async=True)
    result = await template.render_async(letters=sample_data)
    print(result)


if __name__ == "__main__":
    test_sync_render()
    asyncio.run(test_async_render())

Output from sync version:

Sync Render:

sorted_letters=['a', 'b', 'c', 'd']

Output from async version:

Async Render:
Traceback (most recent call last):
  File "/Users/patrick/Code/opsmill/infrahub/jinja2_issue.py", line 46, in <module>
    asyncio.run(test_async_render())
  File "/Users/patrick/.nix-profile/lib/python3.12/asyncio/runners.py", line 194, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "/Users/patrick/.nix-profile/lib/python3.12/asyncio/runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/patrick/.nix-profile/lib/python3.12/asyncio/base_events.py", line 686, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "/Users/patrick/Code/opsmill/infrahub/jinja2_issue.py", line 40, in test_async_render
    result = await template.render_async(letters=sample_data)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/patrick/.virtualenvs/infrahub/lib/python3.12/site-packages/jinja2/environment.py", line 1318, in render_async
    return self.environment.handle_exception()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/patrick/.virtualenvs/infrahub/lib/python3.12/site-packages/jinja2/environment.py", line 942, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "<template>", line 4, in top-level template code
  File "/Users/patrick/.virtualenvs/infrahub/lib/python3.12/site-packages/jinja2/filters.py", line 438, in do_sort
    return sorted(value, key=key_func, reverse=reverse)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: 'async_generator' object is not iterable

Environment:

  • Python version: v3.12.8
  • Jinja version:3.1.6

As a workaround changing the template to look like this makes it work on both of the variants:

template_str = """
sorted_letters={{ letters
    | map(attribute='value')
    | list
    | sort
 }}
"""

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions