Skip to content

Commit 52da8cc

Browse files
HCLReverseTransformer - rework logic recognizing blocks (#216)
1 parent 3ef6ffd commit 52da8cc

File tree

4 files changed

+26
-32
lines changed

4 files changed

+26
-32
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
1414
### Fixed
1515

1616
- Issue parsing parenthesesed identifier (reference) as an object key ([#212](https://github.com/amplify-education/python-hcl2/pull/212))
17+
- Issue discarding empty lists when transforming python dictionary into Lark Tree ([#216](https://github.com/amplify-education/python-hcl2/pull/216))
1718

1819
## \[7.0.1\] - 2025-03-31
1920

hcl2/reconstructor.py

Lines changed: 20 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -409,40 +409,29 @@ def _newline(self, level: int, count: int = 1) -> Tree:
409409
[Token("NL_OR_COMMENT", f"\n{' ' * level}") for _ in range(count)],
410410
)
411411

412-
# rules: the value of a block is always an array of dicts,
413-
# the key is the block type
414-
def _list_is_a_block(self, value: list) -> bool:
415-
for obj in value:
416-
if not self._dict_is_a_block(obj):
417-
return False
418-
419-
return True
420-
421-
def _dict_is_a_block(self, sub_obj: Any) -> bool:
422-
# if the list doesn't contain dictionaries, it's not a block
423-
if not isinstance(sub_obj, dict):
424-
return False
412+
def _is_block(self, value: Any) -> bool:
413+
if isinstance(value, dict):
414+
block_body = value
415+
if (
416+
START_LINE_KEY in block_body.keys()
417+
or END_LINE_KEY in block_body.keys()
418+
):
419+
return True
425420

426-
# if the sub object has "start_line" and "end_line" metadata,
427-
# the block itself is unlabeled, but it is a block
428-
if START_LINE_KEY in sub_obj.keys() or END_LINE_KEY in sub_obj.keys():
429-
return True
421+
try:
422+
# if block is labeled, actual body might be nested
423+
# pylint: disable=W0612
424+
block_label, block_body = next(iter(value.items()))
425+
except StopIteration:
426+
# no more potential labels = nothing more to check
427+
return False
430428

431-
# if the objects in the array have no metadata and more than 2 keys and
432-
# no metadata, it's just an array of objects, not a block
433-
if len(list(sub_obj)) != 1:
434-
return False
429+
return self._is_block(block_body)
435430

436-
# if the sub object has a single string key whose value is an object,
437-
# it _could_ be a labeled block... but we'd have to check if the sub
438-
# object is a block (recurse)
439-
label = list(sub_obj)[0]
440-
sub_sub_obj = sub_obj[label]
441-
if self._dict_is_a_block(sub_sub_obj):
442-
return True
431+
if isinstance(value, list):
432+
if len(value) > 0:
433+
return self._is_block(value[0])
443434

444-
# if the objects in the array have a single key whose child is not a
445-
# block, the array is just an array of objects, not a block
446435
return False
447436

448437
def _calculate_block_labels(self, block: dict) -> Tuple[List[str], dict]:
@@ -483,7 +472,7 @@ def _transform_dict_to_body(self, hcl_dict: dict, level: int) -> Tree:
483472
identifier_name = self._name_to_identifier(key)
484473

485474
# first, check whether the value is a "block"
486-
if isinstance(value, list) and self._list_is_a_block(value):
475+
if self._is_block(value):
487476
for block_v in value:
488477
block_labels, block_body_dict = self._calculate_block_labels(
489478
block_v

test/helpers/terraform-config-json/variables.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@
4848
"bar": {
4949
"baz": 1,
5050
"${(var.account)}": 2
51-
}
51+
},
52+
"tuple": ["${local.foo}"],
53+
"empty_tuple": []
5254
},
5355
{
5456
"route53_forwarding_rule_shares": "${{for forwarding_rule_key in keys(var.route53_resolver_forwarding_rule_shares) : \"${forwarding_rule_key}\" => {\"aws_account_ids\": \"${[for account_name in var.route53_resolver_forwarding_rule_shares[forwarding_rule_key].aws_account_names : module.remote_state_subaccounts.map[account_name].outputs[\"aws_account_id\"]]}\"}}}",

test/helpers/terraform-config/variables.tf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ locals {
1010
baz : 1
1111
(var.account) : 2
1212
}
13+
tuple = [local.foo]
14+
empty_tuple = []
1315
}
1416

1517
variable "azs" {

0 commit comments

Comments
 (0)