Centria: Pass boolean and integer template values in HTTP Block (#4435)
This commit is contained in:
@@ -107,6 +107,28 @@ else:
|
|||||||
jinja_sandbox_env = SandboxedEnvironment()
|
jinja_sandbox_env = SandboxedEnvironment()
|
||||||
|
|
||||||
|
|
||||||
|
# Sentinel marker for native JSON type injection via | json filter.
|
||||||
|
_JSON_TYPE_MARKER = "__SKYVERN_RAW_JSON__"
|
||||||
|
|
||||||
|
|
||||||
|
def _json_type_filter(value: Any) -> str:
|
||||||
|
"""Jinja filter that marks a value for native JSON type injection.
|
||||||
|
|
||||||
|
Usage in templates: {{ some_bool | json }}
|
||||||
|
|
||||||
|
The filter serializes the value to JSON and wraps it with sentinel markers.
|
||||||
|
When _render_templates_in_json() detects these markers, it unwraps and
|
||||||
|
parses the JSON to get the native typed value (bool, int, list, etc.).
|
||||||
|
|
||||||
|
Args:
|
||||||
|
value: Any JSON-serializable value (bool, int, float, str, list, dict, None).
|
||||||
|
"""
|
||||||
|
return f"{_JSON_TYPE_MARKER}{json.dumps(value)}{_JSON_TYPE_MARKER}"
|
||||||
|
|
||||||
|
|
||||||
|
jinja_sandbox_env.filters["json"] = _json_type_filter
|
||||||
|
|
||||||
|
|
||||||
# Mapping from TaskV2Status to the corresponding BlockStatus. Declared once at
|
# Mapping from TaskV2Status to the corresponding BlockStatus. Declared once at
|
||||||
# import time so it is not recreated on each block execution.
|
# import time so it is not recreated on each block execution.
|
||||||
TASKV2_TO_BLOCK_STATUS: dict[TaskV2Status, BlockStatus] = {
|
TASKV2_TO_BLOCK_STATUS: dict[TaskV2Status, BlockStatus] = {
|
||||||
@@ -4032,11 +4054,30 @@ class HttpRequestBlock(Block):
|
|||||||
|
|
||||||
This is required because HTTP request bodies are often deeply nested
|
This is required because HTTP request bodies are often deeply nested
|
||||||
dict/list structures, and templates may appear at any depth.
|
dict/list structures, and templates may appear at any depth.
|
||||||
|
|
||||||
|
Supports {{ expr | json }} filter for type-preserving JSON injection.
|
||||||
"""
|
"""
|
||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
return self.format_block_parameter_template_from_workflow_run_context(
|
rendered = self.format_block_parameter_template_from_workflow_run_context(
|
||||||
value, workflow_run_context, **template_kwargs
|
value, workflow_run_context, **template_kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if rendered.startswith(_JSON_TYPE_MARKER) and rendered.endswith(_JSON_TYPE_MARKER):
|
||||||
|
json_str = rendered[len(_JSON_TYPE_MARKER) : -len(_JSON_TYPE_MARKER)]
|
||||||
|
try:
|
||||||
|
return json.loads(json_str)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
raise FailedToFormatJinjaStyleParameter(
|
||||||
|
value, f"Raw JSON filter produced invalid JSON: {json_str}"
|
||||||
|
)
|
||||||
|
elif _JSON_TYPE_MARKER in rendered:
|
||||||
|
raise FailedToFormatJinjaStyleParameter(
|
||||||
|
value,
|
||||||
|
"The '| json' filter can only be used for complete value replacement. "
|
||||||
|
"It cannot be combined with other text (e.g., 'prefix-{{ val | json }}'). "
|
||||||
|
"Remove the surrounding text or remove the '| json' filter.",
|
||||||
|
)
|
||||||
|
return rendered
|
||||||
if isinstance(value, list):
|
if isinstance(value, list):
|
||||||
return [_render_templates_in_json(item) for item in value]
|
return [_render_templates_in_json(item) for item in value]
|
||||||
if isinstance(value, dict):
|
if isinstance(value, dict):
|
||||||
|
|||||||
4
uv.lock
generated
4
uv.lock
generated
@@ -1,5 +1,5 @@
|
|||||||
version = 1
|
version = 1
|
||||||
revision = 2
|
revision = 3
|
||||||
requires-python = ">=3.11, <3.14"
|
requires-python = ">=3.11, <3.14"
|
||||||
resolution-markers = [
|
resolution-markers = [
|
||||||
"python_full_version >= '3.13'",
|
"python_full_version >= '3.13'",
|
||||||
@@ -5244,7 +5244,7 @@ requires-dist = [
|
|||||||
{ name = "types-toml", specifier = ">=0.10.8.7,<0.11" },
|
{ name = "types-toml", specifier = ">=0.10.8.7,<0.11" },
|
||||||
{ name = "urllib3", specifier = ">=2.6.0" },
|
{ name = "urllib3", specifier = ">=2.6.0" },
|
||||||
{ name = "uvicorn", extras = ["standard"], specifier = ">=0.24.0.post1,<0.25" },
|
{ name = "uvicorn", extras = ["standard"], specifier = ">=0.24.0.post1,<0.25" },
|
||||||
{ name = "websockets", specifier = "~=12.0" },
|
{ name = "websockets", specifier = ">=12.0,<15.1" },
|
||||||
{ name = "zstandard", specifier = ">=0.25.0" },
|
{ name = "zstandard", specifier = ">=0.25.0" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user