From b127e1d3641baacaff1fdb56500862aa41cec443 Mon Sep 17 00:00:00 2001 From: Matvey Kukuy Date: Wed, 15 Jan 2025 17:31:59 +0100 Subject: [PATCH] feat: render_without_execution (#3027) Signed-off-by: Matvey Kukuy --- docs/workflows/syntax/functions.mdx | 22 ++++++++++++++++++++++ keep/iohandler/iohandler.py | 10 +++++++++- tests/test_functions.py | 23 +++++++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/docs/workflows/syntax/functions.mdx b/docs/workflows/syntax/functions.mdx index ccbd899f1..9a52cc78b 100644 --- a/docs/workflows/syntax/functions.mdx +++ b/docs/workflows/syntax/functions.mdx @@ -119,6 +119,28 @@ steps: ``` +### `raw_render_without_execution` + +**Description:** Renders the string without execution of keep instructions inside this string. +**Example:** + +```yaml +consts: + yaml: | + keep.is_business_hours(2024-03-25T14:00:00Z) +steps: + - name: example-step + provider: + type: mock + with: + message: "raw_render_without_execution(My yaml is: {{ yaml }}!)" +``` + +Will output: +``` +My yaml is: keep.is_business_hours(2024-03-25T14:00:00Z)! +``` + ## List and Dictionary Functions ### `first` diff --git a/keep/iohandler/iohandler.py b/keep/iohandler/iohandler.py index d13af5318..3bb5cd16e 100644 --- a/keep/iohandler/iohandler.py +++ b/keep/iohandler/iohandler.py @@ -164,7 +164,15 @@ def parse(self, string, safe=False, default=""): # Now, extract the token if exists - parsed_string = copy.copy(string) - tokens = self.extract_keep_functions(parsed_string) + + if string.startswith("raw_render_without_execution(") and string.endswith(")"): + tokens = [] + string = string.replace("raw_render_without_execution(", "", 1) + string = string[::-1].replace(")", "", 1)[::-1] # Remove the last ')' + parsed_string = copy.copy(string) + else: + tokens = self.extract_keep_functions(parsed_string) + if len(tokens) == 0: return parsed_string elif len(tokens) == 1: diff --git a/tests/test_functions.py b/tests/test_functions.py index 667f09651..c13972987 100644 --- a/tests/test_functions.py +++ b/tests/test_functions.py @@ -11,6 +11,7 @@ from keep.api.core.dependencies import SINGLE_TENANT_UUID from keep.api.models.alert import AlertStatus from keep.api.models.db.alert import ActionType +from keep.iohandler.iohandler import IOHandler @pytest.mark.parametrize( @@ -757,3 +758,25 @@ def test_is_business_hours_string_input_with_timezone(): assert ( functions.is_business_hours("2024-03-25T20:00:00Z", timezone=paris_tz) == False ) + + +def test_render_without_execution(mocked_context_manager): + """ + Test rendering a template without executing it's internal keep functions. + """ + template = "My yaml is: {{ yaml }}!" + context = {"yaml": "keep.is_business_hours(2024-03-25T14:00:00Z)"} + mocked_context_manager.get_full_context.return_value = context + iohandler = IOHandler(mocked_context_manager) + with pytest.raises(Exception): + iohandler.render( + template, + safe=True, + ) + + template = "raw_render_without_execution(My yaml is: {{ yaml }}!)" + rendered = iohandler.render( + template, + safe=True, + ) + assert rendered == "My yaml is: keep.is_business_hours(2024-03-25T14:00:00Z)!" \ No newline at end of file