Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .code-samples.meilisearch.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -610,3 +610,16 @@ update_embedders_1: |-
})
reset_embedders_1: |-
client.index('INDEX_NAME').reset_embedders()
post_render_template_1: |-
client.update_experimental_features({"renderRoute": True})

client.render_template(
template={
'kind': 'inlineDocumentTemplate',
'inline': 'An inline document template rendered on {{doc.id}}'
},
input={
'kind': 'inlineDocument',
'inline': {'id': 'this document'}
}
)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
39 changes: 39 additions & 0 deletions meilisearch/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,45 @@ def multi_search(
body={"queries": queries, "federation": federation},
)

def render_template(
self,
template: Mapping[str, Any],
input: Mapping[str, Any] | None = None,
) -> dict[str, Any]:
"""Render a template against an input document.

This is an experimental route. Enable the ``renderRoute`` feature on your
Meilisearch instance before calling it, for example
``client.update_experimental_features({"renderRoute": True})``.

https://www.meilisearch.com/docs/reference/api/template

Parameters
----------
template:
Dictionary describing the template or fragment to render, for example
{"kind": "inlineDocumentTemplate", "inline": "Rendered on {{doc.id}}"}.
input (optional):
Dictionary describing what to render the template with, for example
{"kind": "inlineDocument", "inline": {"id": "this document"}}. When omitted
the route returns the unrendered template and ``rendered`` is null.

Returns
-------
rendered:
Dictionary with the unrendered ``template`` and the ``rendered`` result.

Raises
------
MeilisearchApiError
An error containing details about why Meilisearch can't process your request. Meilisearch error codes are described here: https://www.meilisearch.com/docs/reference/errors/error_codes#meilisearch-errors
"""
body: dict[str, Any] = {"template": template}
if input is not None:
body["input"] = input

return self.http.post(self.config.paths.render_template, body=body)

def update_documents_by_function(
self, index_uid: str, queries: dict[str, list[dict[str, Any]]]
) -> dict[str, Any]:
Expand Down
1 change: 1 addition & 0 deletions meilisearch/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class Paths:
experimental_features = "experimental-features"
webhooks = "webhooks"
export = "export"
render_template = "render-template"

def __init__(
self,
Expand Down
55 changes: 55 additions & 0 deletions tests/client/test_client_render_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from unittest.mock import patch

import pytest


def test_render_template_calls_route(client):
"""The SDK posts template and input to the render-template route."""
template = {"kind": "inlineDocumentTemplate", "inline": "Rendered on {{doc.id}}"}
document = {"kind": "inlineDocument", "inline": {"id": "42"}}

with patch.object(
client.http, "post", return_value={"template": "x", "rendered": "y"}
) as mock_post:
client.render_template(template=template, input=document)

mock_post.assert_called_once_with(
"render-template",
body={"template": template, "input": document},
)


def test_render_template_omits_input_when_none(client):
"""Without an input the body only carries the template."""
template = {"kind": "inlineDocumentTemplate", "inline": "Rendered on {{doc.id}}"}

with patch.object(
client.http, "post", return_value={"template": "x", "rendered": None}
) as mock_post:
client.render_template(template=template)

mock_post.assert_called_once_with("render-template", body={"template": template})


@pytest.mark.usefixtures("enable_render_route")
def test_render_template_inline(client):
"""Renders an inline template with an inline document."""
response = client.render_template(
template={"kind": "inlineDocumentTemplate", "inline": "Rendered on {{doc.id}}"},
input={"kind": "inlineDocument", "inline": {"id": "42"}},
)

assert isinstance(response, dict)
assert {"template", "rendered"} <= set(response)
assert "42" in response["rendered"]


@pytest.mark.usefixtures("enable_render_route")
def test_render_template_without_input(client):
"""Omitting the input returns the unrendered template and a null result."""
response = client.render_template(
template={"kind": "inlineDocumentTemplate", "inline": "Rendered on {{doc.id}}"},
)

assert isinstance(response, dict)
assert response["rendered"] is None
17 changes: 17 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,3 +352,20 @@ def enable_network_options():
json={"network": False},
timeout=10,
)


@fixture
def enable_render_route():
requests.patch(
f"{common.BASE_URL}/experimental-features",
headers={"Authorization": f"Bearer {common.MASTER_KEY}"},
json={"renderRoute": True},
timeout=10,
)
yield
requests.patch(
f"{common.BASE_URL}/experimental-features",
headers={"Authorization": f"Bearer {common.MASTER_KEY}"},
json={"renderRoute": False},
timeout=10,
)