Skip to content

Commit

Permalink
feat: add async methods to environment
Browse files Browse the repository at this point in the history
  • Loading branch information
phil65 committed Feb 20, 2025
1 parent 0d71624 commit e9d3f2e
Showing 1 changed file with 123 additions and 0 deletions.
123 changes: 123 additions & 0 deletions src/jinjarope/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,31 @@ def render_condition(
result = self.render_string(string=string, variables=variables, **kwargs)
return result not in ["None", "False", ""]

async def render_condition_async(
self,
string: str,
variables: dict[str, Any] | None = None,
**kwargs: Any,
) -> bool:
"""Render a template condition.
This function renders a template string and evaluates its
result as a boolean. It returns True if the result is truthy
(not None, False, or an empty string), otherwise False.
Args:
string: String to evaluate for True-ishness
variables: Extra variables for the rendering
kwargs: Further extra variables for rendering
Returns:
True if the rendered string is truthy, False otherwise.
"""
result = await self.render_string_async(
string=string, variables=variables, **kwargs
)
return result not in ["None", "False", ""]

def render_string(
self,
string: str,
Expand Down Expand Up @@ -420,6 +445,34 @@ def render_string(
raise SyntaxError(msg) from e
return template.render(**variables)

async def render_string_async(
self,
string: str,
variables: dict[str, Any] | None = None,
**kwargs: Any,
) -> str:
"""Render a template string.
This function renders the given template string using the
current environment's configuration and globals.
Args:
string: String to render
variables: Extra variables for the rendering
kwargs: Further extra variables for rendering
Returns:
The rendered string.
"""
variables = (variables or {}) | kwargs
cls = self.template_class
try:
template = cls.from_code(self, self.compile(string), self.globals, None)
except TemplateSyntaxError as e:
msg = f"Error when evaluating \n{string}\n (extra globals: {variables})"
raise SyntaxError(msg) from e
return await template.render_async(**variables)

def render_file(
self,
file: str | os.PathLike[str],
Expand Down Expand Up @@ -447,6 +500,33 @@ def render_file(
content = envglobals.load_file_cached(str(file))
return self.render_string(content, variables, **kwargs)

async def render_file_async(
self,
file: str | os.PathLike[str],
variables: dict[str, Any] | None = None,
**kwargs: Any,
) -> str:
"""Helper to directly render a template from filesystem.
This function renders a template file directly from the
filesystem using the current environment's configuration and
globals.
!!! info
The file content is cached, which is generally acceptable
for common use cases.
Args:
file: Template file to load
variables: Extra variables for the rendering
kwargs: Further extra variables for rendering
Returns:
The rendered string.
"""
content = envglobals.load_file_cached(str(file))
return await self.render_string_async(content, variables, **kwargs)

def render_template(
self,
template_name: str,
Expand Down Expand Up @@ -489,6 +569,49 @@ def render_template(
# except Exception:
# self.handle_exception()

async def render_template_async(
self,
template_name: str,
variables: dict[str, Any] | None = None,
block_name: str | None = None,
parent_template: str | None = None,
**kwargs: Any,
) -> str:
"""Render a loaded template (or a block of a template).
This function renders a loaded template or a specific block from
a template. It allows for the inclusion of parent templates and
provides the flexibility to render individual blocks.
Args:
template_name: Template name
variables: Extra variables for rendering
block_name: Render specific block from the template
parent_template: The name of the parent template importing this template
kwargs: Further extra variables for rendering
Returns:
The rendered string.
Raises:
BlockNotFoundError: If the specified block is not found in the
template.
"""
variables = (variables or {}) | kwargs
template = self.get_template(template_name, parent=parent_template)
if not block_name:
return await template.render_async(**variables)
try:
block_render_func = template.blocks[block_name]
except KeyError:
raise BlockNotFoundError(block_name, template_name) from KeyError

ctx = template.new_context(variables)
return self.concat( # type: ignore
[n async for n in block_render_func(ctx)] # type: ignore
)
# return self.concat(block_render_func(ctx))

@contextlib.contextmanager
def with_globals(self, **kwargs: Any):
"""Context manager to temporarily set globals for the environment.
Expand Down

0 comments on commit e9d3f2e

Please sign in to comment.