Skip to content
Open
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
34 changes: 22 additions & 12 deletions hcl2/transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ def attribute(self, args: List) -> Attribute:

def conditional(self, args: List) -> str:
args = self.strip_new_line_tokens(args)
args = self.process_nulls(args)
args = self.all_to_tf_inline(args)
return f"{args[0]} ? {args[1]} : {args[2]}"

def binary_op(self, args: List) -> str:
Expand All @@ -187,13 +187,13 @@ def binary_op(self, args: List) -> str:
)

def unary_op(self, args: List) -> str:
args = self.process_nulls(args)
return "".join([self.to_tf_inline(arg) for arg in args])
args = self.all_to_tf_inline(args)
return "".join(args)

def binary_term(self, args: List) -> str:
args = self.strip_new_line_tokens(args)
args = self.process_nulls(args)
return " ".join([self.to_tf_inline(arg) for arg in args])
args = self.all_to_tf_inline(args)
return " ".join(args)

def body(self, args: List) -> Dict[str, List]:
# See https://github.com/hashicorp/hcl/blob/main/hclsyntax/spec.md#bodies
Expand Down Expand Up @@ -279,20 +279,24 @@ def new_line_or_comment(self, args: List) -> _DiscardType:

def for_tuple_expr(self, args: List) -> str:
args = self.strip_new_line_tokens(args)
for_expr = " ".join([self.to_tf_inline(arg) for arg in args[1:-1]])
args = self.all_to_tf_inline(args[1:-1])
for_expr = " ".join(args)
return f"[{for_expr}]"

def for_intro(self, args: List) -> str:
args = self.strip_new_line_tokens(args)
return " ".join([self.to_tf_inline(arg) for arg in args])
args = self.all_to_tf_inline(args)
return " ".join(args)

def for_cond(self, args: List) -> str:
args = self.strip_new_line_tokens(args)
return " ".join([self.to_tf_inline(arg) for arg in args])
args = self.all_to_tf_inline(args)
return " ".join(args)

def for_object_expr(self, args: List) -> str:
args = self.strip_new_line_tokens(args)
for_expr = " ".join([self.to_tf_inline(arg) for arg in args[1:-1]])
args = self.all_to_tf_inline(args[1:-1])
for_expr = " ".join(args)
# doubled curly braces stands for inlining the braces
# and the third pair of braces is for the interpolation
# e.g. f"{2 + 2} {{2 + 2}}" == "4 {2 + 2}"
Expand All @@ -308,7 +312,7 @@ def string_part(self, args: List) -> str:
return value

def interpolation(self, args: List) -> str:
return '"${' + str(args[0]) + '}"'
return '"${' + self.to_tf_inline(args[0]) + '}"'

def strip_new_line_tokens(self, args: List) -> List:
"""
Expand Down Expand Up @@ -369,6 +373,12 @@ def process_escape_sequences(self, value: str) -> str:
def process_nulls(self, args: List) -> List:
return ["null" if arg is None else arg for arg in args]

def all_to_tf_inline(self, args: List) -> List:
"""
Convert all items in a list to "inline" HCL syntax
"""
return [self.to_tf_inline(arg) for arg in args]

def to_tf_inline(self, value: Any) -> str:
"""
Converts complex objects (e.g.) dicts to an "inline" HCL syntax
Expand All @@ -383,11 +393,11 @@ def to_tf_inline(self, value: Any) -> str:
if isinstance(value, bool):
return "true" if value else "false"
if isinstance(value, str):
return value
return self.unwrap_string_dollar(value)
if isinstance(value, (int, float)):
return str(value)
if value is None:
return "None"
return "null"

raise RuntimeError(f"Invalid type to convert to inline HCL: {type(value)}")

Expand Down
12 changes: 9 additions & 3 deletions test/unit/test_hcl2_syntax.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,7 @@ def test_function_call_and_arguments(self):
arg1, arg2,
arg3,
)
""": {
"r": "${function(arg1, arg2, arg3)}"
},
""": {"r": "${function(arg1, arg2, arg3)}"},
}

for call, expected in calls.items():
Expand Down Expand Up @@ -191,3 +189,11 @@ def test_expr_term_parenthesis(self):
for actual, expected in literals.items():
result = self.load_to_dict(actual)
self.assertDictEqual(result, expected)

def test_dict_in_conditional(self):
cond = "x = a ? { id = 1 } : null"

expected = {"x": '${a ? {"id": 1} : null}'}

result = self.load_to_dict(cond)
self.assertDictEqual(result, expected)
Loading