0.53 prefix changes may break rendering JinjaX components in Jinja2 templates
I'm sorry I don't have the time to make a minimal reproduction, so feel free to close this if you cannot reproduce or believe the error is elsewhere.
I suspect that the prefix changes in 0.53 breaks for projects where the Jinja2 env is configured with:
jinja2.Environment(
...
undefined=jinja2.StrictUndefined,
...
)
Here's the output from one of our test cases when using JinjaX 0.54 (the test passes on 0.52):
.venv/lib/python3.13/site-packages/jinja2/environment.py:1295: in render
self.environment.handle_exception()
.venv/lib/python3.13/site-packages/jinja2/environment.py:942: in handle_exception
raise rewrite_traceback_stack(source=source)
<template>:1: in top-level template code
???
src/common/jinjax.py:33: in irender
return super().irender( # pyright: ignore[reportUnknownMemberType]
.venv/lib/python3.13/site-packages/jinjax/catalog.py:434: in irender
component = self._get_component(__name, **kw)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <common.jinjax.Catalog object at 0x7f0e3ec51bd0>, cname = 'Py.Tests.Card', kw = {'title': 'my-title'}, source = ''
file_ext = '.j2', caller_prefix = Undefined, prefix = '', name = 'Py.Tests.Card', component = None
get_from = <bound method Catalog._get_from_cache of <common.jinjax.Catalog object at 0x7f0e3ec51bd0>>
def _get_component(self, cname: str, **kw) -> Component:
source = kw.pop("_source", kw.pop("__source", ""))
file_ext = kw.pop("_file_ext", kw.pop("__file_ext", "")) or self.file_ext
caller_prefix = kw.pop("__prefix", "")
prefix, name = self._split_name(cname)
component = None
if source:
logger.debug("Rendering from source %s", cname)
self.jinja_env.loader = self.prefixes[prefix]
return self._get_from_source(prefix=prefix, name=name, source=source)
logger.debug("Rendering from cache or file %s", cname)
get_from = self._get_from_cache if self.use_cache else self._get_from_file
> if caller_prefix:
E jinja2.exceptions.UndefinedError: '__prefix' is undefined
.venv/lib/python3.13/site-packages/jinjax/catalog.py:620: UndefinedError
@jodal Sorry I'm unable to replicate this error with any end-to-end test, maybe is the way your test is written?
In the latest release (0.55) I've moved the __prefix injection to the Component.render method (https://github.com/jpsca/jinjax/blob/main/src/jinjax/component.py#L257), could you test if that solves the issue?
I'm on vacation with spotty internet access now, but I'll try it out before next weekend. Thanks!
@jodal Sorry I'm unable to replicate this error with any end-to-end test, maybe is the way your test is written?
In the latest release (0.55) I've moved the
__prefixinjection to theComponent.rendermethod (main/src/jinjax/component.py#L257), could you test if that solves the issue?
The issue seems to persist in jinjax==0.55, unfortunately.
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.venv/lib/python3.13/site-packages/jinja2/environment.py:1295: in render
self.environment.handle_exception()
.venv/lib/python3.13/site-packages/jinja2/environment.py:942: in handle_exception
raise rewrite_traceback_stack(source=source)
<template>:1: in top-level template code
???
.venv/lib/python3.13/site-packages/jinjax/catalog.py:443: in irender
component = self._get_component(__name, **kw)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <common.jinjax.Catalog object at 0x7adf5ae872d0>, cname = 'Py.Tests.Card', kw = {'title': 'my-title'}, source = '', file_ext = '.j2', caller_prefix = Undefined, prefix = '', name = 'Py.Tests.Card', component = None, get_from = <bound method Catalog._get_from_cache of <common.jinjax.Catalog object at 0x7adf5ae872d0>>
def _get_component(self, cname: str, **kw) -> Component:
source = kw.pop("_source", kw.pop("__source", ""))
file_ext = kw.pop("_file_ext", kw.pop("__file_ext", "")) or self.file_ext
caller_prefix = kw.pop(ARGS_PREFIX, "")
prefix, name = self._split_name(cname)
component = None
if source:
logger.debug("Rendering from source %s", cname)
self.jinja_env.loader = self.prefixes[prefix]
return self._get_from_source(prefix=prefix, name=name, source=source)
logger.debug("Rendering from cache or file %s", cname)
get_from = self._get_from_cache if self.use_cache else self._get_from_file
> if caller_prefix:
E jinja2.exceptions.UndefinedError: '__prefix' is undefined
.venv/lib/python3.13/site-packages/jinjax/catalog.py:628: UndefinedError
=================================================================================================================================================================================== short test summary info ====================================================================================================================================================================================
FAILED tests/hub/core/test_htpy.py::test_jinjax_rendering_of_component_with_children - jinja2.exceptions.UndefinedError: '__prefix' is undefined
I tried hunting down the issue for a while longer, but I don't know enough Jinja2 and JinjaX internals to understand everything I'm looking at.
I can at least confirm that jinja2.StrictUndefined does not seem to be related in any way.
In the end I ended up rewriting a part of our test from rendering a Jinja2 template with a JinjaX component:
template = catalog.jinja_env.from_string(
'<Py.Tests.MyComponent title="my-title">my-content</Py.Tests.MyComponent>'
)
assert template.render() == "..."
To rendering the JinjaX component directly:
result = catalog.render(
"Py.Tests.MyComponent",
title="my-title",
_content="my-content",
)
assert result == "..."
This is good enough for our test case to cover what we need it to cover. I have not found any other issues through manual testing with JinjaX 0.53-0.55.
Unless you immediately see the issue here and this is something you want to keep working as it used to do, feel free to close this issue.