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
4 changes: 2 additions & 2 deletions airbyte_cdk/sources/declarative/interpolation/jinja.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ def eval(

def _literal_eval(self, result: Optional[str], valid_types: Optional[Tuple[Type[Any]]]) -> Any:
try:
evaluated = ast.literal_eval(result) # type: ignore # literal_eval is able to handle None
except (ValueError, SyntaxError):
evaluated = ast.literal_eval(result) # type: ignore # result may be None; on error we return it unchanged
except (ValueError, SyntaxError, TypeError):
return result
if (not valid_types and not isinstance(evaluated, complex)) or (
valid_types and isinstance(evaluated, valid_types)
Expand Down
10 changes: 10 additions & 0 deletions unit_tests/sources/declarative/interpolation/test_jinja.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,16 @@ def test_interpolation_private_partition_attribute():
assert actual_output == expected_output


def test_literal_eval_handles_unhashable_set_typeerror():
"""Test that _literal_eval gracefully handles TypeError from ast.literal_eval for nested sets."""
# ast.literal_eval("{{'web'}, {'discover'}}") raises TypeError: unhashable type: 'set'
# The interpolation should return the string as-is instead of propagating the error.
config = {"query": "{{'web'}, {'discover'}}"}
s = "{{ config['query'] }}"
val = interpolation.eval(s, config)
assert val == "{{'web'}, {'discover'}}"


def test_given_complex_when_eval_then_return_string():
s = "9173710294242221J"
config = {}
Expand Down
Loading