python-hcl2 4.3.4__tar.gz → 5.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/.gitignore +3 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/PKG-INFO +1 -1
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/hcl2/__init__.py +1 -1
- python-hcl2-5.0.0/hcl2/api.py +69 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/hcl2/hcl2.lark +15 -7
- python-hcl2-5.0.0/hcl2/reconstructor.py +162 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/hcl2/transformer.py +6 -3
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/hcl2/version.py +2 -2
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/python_hcl2.egg-info/PKG-INFO +1 -1
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/python_hcl2.egg-info/SOURCES.txt +1 -0
- python-hcl2-4.3.4/hcl2/api.py +0 -28
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/.codacy.yml +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/.coveragerc +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/.github/CODEOWNERS +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/.github/workflows/codeql-analysis.yml +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/.github/workflows/pr_check.yml +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/.github/workflows/publish.yml +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/.pre-commit-config.yaml +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/.yamllint.yml +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/CHANGELOG.md +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/LICENSE +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/MANIFEST.in +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/README.md +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/bin/terraform_test +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/hcl2/__main__.py +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/hcl2/parser.py +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/hcl2/py.typed +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/mypy.ini +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/pylintrc +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/pyproject.toml +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/python_hcl2.egg-info/dependency_links.txt +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/python_hcl2.egg-info/entry_points.txt +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/python_hcl2.egg-info/not-zip-safe +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/python_hcl2.egg-info/requires.txt +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/python_hcl2.egg-info/top_level.txt +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/reports/.gitignore +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/requirements.txt +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/setup.cfg +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/test-requirements.txt +0 -0
- {python-hcl2-4.3.4 → python-hcl2-5.0.0}/tox.ini +0 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""The API that will be exposed to users of this package"""
|
|
2
|
+
from typing import TextIO
|
|
3
|
+
|
|
4
|
+
from lark.tree import Tree as AST
|
|
5
|
+
from hcl2.parser import hcl2
|
|
6
|
+
from hcl2.transformer import DictTransformer
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def load(file: TextIO, with_meta=False) -> dict:
|
|
10
|
+
"""Load a HCL2 file.
|
|
11
|
+
:param file: File with hcl2 to be loaded as a dict.
|
|
12
|
+
:param with_meta: If set to true then adds `__start_line__` and `__end_line__`
|
|
13
|
+
parameters to the output dict. Default to false.
|
|
14
|
+
"""
|
|
15
|
+
return loads(file.read(), with_meta=with_meta)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def loads(text: str, with_meta=False) -> dict:
|
|
19
|
+
"""Load HCL2 from a string.
|
|
20
|
+
:param text: Text with hcl2 to be loaded as a dict.
|
|
21
|
+
:param with_meta: If set to true then adds `__start_line__` and `__end_line__`
|
|
22
|
+
parameters to the output dict. Default to false.
|
|
23
|
+
"""
|
|
24
|
+
# append new line as a workaround for https://github.com/lark-parser/lark/issues/237
|
|
25
|
+
# Lark doesn't support a EOF token so our grammar can't look for "new line or end of file"
|
|
26
|
+
# This means that all blocks must end in a new line even if the file ends
|
|
27
|
+
# Append a new line as a temporary fix
|
|
28
|
+
tree = hcl2.parse(text + "\n")
|
|
29
|
+
return DictTransformer(with_meta=with_meta).transform(tree)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def parse(file: TextIO) -> AST:
|
|
33
|
+
"""Load HCL2 syntax tree from a file.
|
|
34
|
+
:param file: File with hcl2 to be loaded as a dict.
|
|
35
|
+
"""
|
|
36
|
+
return parses(file.read())
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def parses(text: str) -> AST:
|
|
40
|
+
"""Load HCL2 syntax tree from a string.
|
|
41
|
+
:param text: Text with hcl2 to be loaded as a dict.
|
|
42
|
+
"""
|
|
43
|
+
# defer this import until this method is called, due to the performance hit
|
|
44
|
+
# of rebuilding the grammar without cache
|
|
45
|
+
from hcl2.reconstructor import ( # pylint: disable=import-outside-toplevel
|
|
46
|
+
hcl2 as uncached_hcl2,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
return uncached_hcl2.parse(text)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def transform(ast: AST, with_meta=False) -> dict:
|
|
53
|
+
"""Convert an HCL2 AST to a dictionary.
|
|
54
|
+
:param ast: HCL2 syntax tree, output from `parse` or `parses`
|
|
55
|
+
"""
|
|
56
|
+
return DictTransformer(with_meta=with_meta).transform(ast)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def writes(ast: AST) -> str:
|
|
60
|
+
"""Convert an HCL2 syntax tree to a string.
|
|
61
|
+
:param ast: HCL2 syntax tree, output from `parse` or `parses`
|
|
62
|
+
"""
|
|
63
|
+
# defer this import until this method is called, due to the performance hit
|
|
64
|
+
# of rebuilding the grammar without cache
|
|
65
|
+
from hcl2.reconstructor import ( # pylint: disable=import-outside-toplevel
|
|
66
|
+
hcl2_reconstructor,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
return hcl2_reconstructor.reconstruct(ast)
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
start : body
|
|
2
2
|
body : (new_line_or_comment? (attribute | block))* new_line_or_comment?
|
|
3
|
-
attribute : identifier
|
|
3
|
+
attribute : identifier EQ expression
|
|
4
4
|
block : identifier (identifier | STRING_LIT)* new_line_or_comment? "{" body "}"
|
|
5
5
|
new_line_and_or_comma: new_line_or_comment | "," | "," new_line_or_comment
|
|
6
|
-
new_line_or_comment: (
|
|
6
|
+
new_line_or_comment: ( NL_OR_COMMENT )+
|
|
7
|
+
NL_OR_COMMENT: /\n[ \t]*/ | /#.*\n/ | /\/\/.*\n/ | /\/\*(.|\n)*?(\*\/)/
|
|
7
8
|
|
|
8
|
-
identifier :
|
|
9
|
+
identifier : NAME | IN | FOR | IF | FOR_EACH
|
|
10
|
+
NAME : /[a-zA-Z_][a-zA-Z0-9_-]*/
|
|
11
|
+
IF : "if"
|
|
12
|
+
IN : "in"
|
|
13
|
+
FOR : "for"
|
|
14
|
+
FOR_EACH : "for_each"
|
|
9
15
|
|
|
10
16
|
?expression : expr_term | operation | conditional
|
|
11
17
|
|
|
@@ -14,8 +20,9 @@ conditional : expression "?" new_line_or_comment? expression new_line_or_comment
|
|
|
14
20
|
?operation : unary_op | binary_op
|
|
15
21
|
!unary_op : ("-" | "!") expr_term
|
|
16
22
|
binary_op : expression binary_term new_line_or_comment?
|
|
17
|
-
!binary_operator :
|
|
23
|
+
!binary_operator : BINARY_OP
|
|
18
24
|
binary_term : binary_operator new_line_or_comment? expression
|
|
25
|
+
BINARY_OP : "==" | "!=" | "<" | ">" | "<=" | ">=" | "-" | "*" | "/" | "%" | "&&" | "||" | "+"
|
|
19
26
|
|
|
20
27
|
expr_term : "(" new_line_or_comment? expression new_line_or_comment? ")"
|
|
21
28
|
| float_lit
|
|
@@ -27,7 +34,7 @@ expr_term : "(" new_line_or_comment? expression new_line_or_comment? ")"
|
|
|
27
34
|
| index_expr_term
|
|
28
35
|
| get_attr_expr_term
|
|
29
36
|
| identifier
|
|
30
|
-
| provider_function_call
|
|
37
|
+
| provider_function_call
|
|
31
38
|
| heredoc_template
|
|
32
39
|
| heredoc_template_trim
|
|
33
40
|
| attr_splat_expr_term
|
|
@@ -46,10 +53,12 @@ int_lit : DECIMAL+
|
|
|
46
53
|
| DECIMAL+ ("." DECIMAL+)? EXP_MARK DECIMAL+
|
|
47
54
|
DECIMAL : "0".."9"
|
|
48
55
|
EXP_MARK : ("e" | "E") ("+" | "-")?
|
|
56
|
+
EQ : /[ \t]*=(?!=|>)/
|
|
49
57
|
|
|
50
58
|
tuple : "[" (new_line_or_comment* expression new_line_or_comment* ",")* (new_line_or_comment* expression)? new_line_or_comment* "]"
|
|
51
59
|
object : "{" new_line_or_comment? (object_elem (new_line_and_or_comma object_elem )* new_line_and_or_comma?)? "}"
|
|
52
|
-
object_elem : (identifier | expression) (
|
|
60
|
+
object_elem : (identifier | expression) ( EQ | ":") expression
|
|
61
|
+
|
|
53
62
|
|
|
54
63
|
heredoc_template : /<<(?P<heredoc>[a-zA-Z][a-zA-Z0-9._-]+)\n(?:.|\n)*?(?P=heredoc)/
|
|
55
64
|
heredoc_template_trim : /<<-(?P<heredoc_trim>[a-zA-Z][a-zA-Z0-9._-]+)\n(?:.|\n)*?(?P=heredoc_trim)/
|
|
@@ -74,4 +83,3 @@ full_splat : "[*]" (get_attr | index)*
|
|
|
74
83
|
!for_cond : "if" new_line_or_comment? expression
|
|
75
84
|
|
|
76
85
|
%ignore /[ \t]+/
|
|
77
|
-
%ignore /\/\*(.|\n)*?(\*\/)/
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"""A reconstructor for HCL2 implemented using Lark's experimental reconstruction functionality"""
|
|
2
|
+
|
|
3
|
+
from lark import Lark
|
|
4
|
+
from lark.reconstruct import Reconstructor
|
|
5
|
+
from lark.utils import is_id_continue
|
|
6
|
+
|
|
7
|
+
# this is duplicated from `parser` because we need different options here for
|
|
8
|
+
# the reconstructor. please make sure changes are kept in sync between the two
|
|
9
|
+
# if necessary.
|
|
10
|
+
hcl2 = Lark.open(
|
|
11
|
+
"hcl2.lark",
|
|
12
|
+
parser="lalr",
|
|
13
|
+
# Caching must be disabled to allow for reconstruction until lark-parser/lark#1472 is fixed:
|
|
14
|
+
#
|
|
15
|
+
# https://github.com/lark-parser/lark/issues/1472
|
|
16
|
+
#
|
|
17
|
+
# cache=str(PARSER_FILE), # Disable/Delete file to effect changes to the grammar
|
|
18
|
+
rel_to=__file__,
|
|
19
|
+
propagate_positions=True,
|
|
20
|
+
maybe_placeholders=False, # Needed for reconstruction
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
CHAR_SPACE_AFTER = set(',~@<>="|?)]:')
|
|
24
|
+
CHAR_SPACE_BEFORE = (CHAR_SPACE_AFTER - set(",=")) | set("'")
|
|
25
|
+
KEYWORDS_SPACE_AFTER = [
|
|
26
|
+
"if",
|
|
27
|
+
"in",
|
|
28
|
+
"for",
|
|
29
|
+
"for_each",
|
|
30
|
+
"==",
|
|
31
|
+
"!=",
|
|
32
|
+
"<",
|
|
33
|
+
">",
|
|
34
|
+
"<=",
|
|
35
|
+
">=",
|
|
36
|
+
"-",
|
|
37
|
+
"*",
|
|
38
|
+
"/",
|
|
39
|
+
"%",
|
|
40
|
+
"&&",
|
|
41
|
+
"||",
|
|
42
|
+
"+",
|
|
43
|
+
]
|
|
44
|
+
KEYWORDS_SPACE_BEFORE = KEYWORDS_SPACE_AFTER
|
|
45
|
+
DIGITS = set("0123456789")
|
|
46
|
+
NEVER_SPACE_AFTER = set("[(")
|
|
47
|
+
NEVER_SPACE_BEFORE = set("]),.")
|
|
48
|
+
NEVER_COMMA_BEFORE = set("])}")
|
|
49
|
+
# characters that are OK to come right after an identifier with no space between
|
|
50
|
+
IDENT_NO_SPACE = set("()[]")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _add_extra_space(prev_item, item):
|
|
54
|
+
# pylint: disable=too-many-boolean-expressions, too-many-return-statements
|
|
55
|
+
|
|
56
|
+
##### the scenarios where explicitly disallow spaces: #####
|
|
57
|
+
|
|
58
|
+
# if we already have a space, don't add another
|
|
59
|
+
if prev_item[-1].isspace() or item[0].isspace():
|
|
60
|
+
return False
|
|
61
|
+
|
|
62
|
+
# none of the following should be separated by spaces:
|
|
63
|
+
# - groups of digits
|
|
64
|
+
# - namespaced::function::calls
|
|
65
|
+
# - characters within an identifier like array[0]()
|
|
66
|
+
if (
|
|
67
|
+
(prev_item[-1] in DIGITS and item[0] in DIGITS)
|
|
68
|
+
or item == "::"
|
|
69
|
+
or prev_item == "::"
|
|
70
|
+
or (prev_item[-1] in IDENT_NO_SPACE and item[0] in IDENT_NO_SPACE)
|
|
71
|
+
):
|
|
72
|
+
return False
|
|
73
|
+
|
|
74
|
+
# specific characters are also blocklisted from having spaces
|
|
75
|
+
if prev_item[-1] in NEVER_SPACE_AFTER or item[0] in NEVER_SPACE_BEFORE:
|
|
76
|
+
return False
|
|
77
|
+
|
|
78
|
+
##### the scenarios where we add spaces: #####
|
|
79
|
+
|
|
80
|
+
# scenario 1, the prev token ended with an identifier character
|
|
81
|
+
# and the next character is not an "IDENT_NO_SPACE" character
|
|
82
|
+
if is_id_continue(prev_item[-1]) and not item[0] in IDENT_NO_SPACE:
|
|
83
|
+
return True
|
|
84
|
+
|
|
85
|
+
# scenario 2, the prev token or the next token should be followed by a space
|
|
86
|
+
if (
|
|
87
|
+
prev_item[-1] in CHAR_SPACE_AFTER
|
|
88
|
+
or prev_item in KEYWORDS_SPACE_AFTER
|
|
89
|
+
or item[0] in CHAR_SPACE_BEFORE
|
|
90
|
+
or item in KEYWORDS_SPACE_BEFORE
|
|
91
|
+
):
|
|
92
|
+
return True
|
|
93
|
+
|
|
94
|
+
# scenario 3, the previous token was a block opening brace and
|
|
95
|
+
# the next token is not a closing brace (so the block is on one
|
|
96
|
+
# line and not empty)
|
|
97
|
+
if prev_item[-1] == "{" and item[0] != "}":
|
|
98
|
+
return True
|
|
99
|
+
|
|
100
|
+
##### otherwise, we don't add a space #####
|
|
101
|
+
return False
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _postprocess_reconstruct(items):
|
|
105
|
+
"""
|
|
106
|
+
Postprocess the stream of tokens derived from the AST during reconstruction.
|
|
107
|
+
|
|
108
|
+
For HCL2, this is used exclusively for adding whitespace in the right locations.
|
|
109
|
+
"""
|
|
110
|
+
prev_item = ""
|
|
111
|
+
for item in items:
|
|
112
|
+
# first, handle any deferred tokens
|
|
113
|
+
if isinstance(prev_item, tuple) and prev_item[0] == "_deferred":
|
|
114
|
+
prev_item = prev_item[1]
|
|
115
|
+
|
|
116
|
+
# if the deferred token was a comma, see if we're ending a block
|
|
117
|
+
if prev_item == ",":
|
|
118
|
+
if item[0] not in NEVER_COMMA_BEFORE:
|
|
119
|
+
yield prev_item
|
|
120
|
+
else:
|
|
121
|
+
yield prev_item
|
|
122
|
+
|
|
123
|
+
# if we're between two tokens, determine if we need to add an extra space
|
|
124
|
+
# we need the previous item and the current item to exist to evaluate these rules
|
|
125
|
+
if prev_item and item and _add_extra_space(prev_item, item):
|
|
126
|
+
yield " "
|
|
127
|
+
|
|
128
|
+
# in some cases, we may want to defer printing the next token
|
|
129
|
+
defer_item = False
|
|
130
|
+
|
|
131
|
+
# prevent the inclusion of extra commas if they are not intended
|
|
132
|
+
if item[0] == ",":
|
|
133
|
+
item = ("_deferred", item)
|
|
134
|
+
defer_item = True
|
|
135
|
+
|
|
136
|
+
# print the actual token
|
|
137
|
+
if not defer_item:
|
|
138
|
+
yield item
|
|
139
|
+
|
|
140
|
+
# store the previous item for the next token
|
|
141
|
+
prev_item = item
|
|
142
|
+
|
|
143
|
+
# if the last token was deferred, print it before continuing
|
|
144
|
+
if isinstance(prev_item, tuple) and prev_item[0] == "_deferred":
|
|
145
|
+
yield prev_item[1]
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
class HCLReconstructor:
|
|
149
|
+
"""This class converts a Lark.Tree AST back into a string representing the underlying HCL code."""
|
|
150
|
+
def __init__(self, parser):
|
|
151
|
+
self._recons = Reconstructor(parser)
|
|
152
|
+
|
|
153
|
+
def reconstruct(self, tree):
|
|
154
|
+
"""Convert a Lark.Tree AST back into a string representation of HCL."""
|
|
155
|
+
return self._recons.reconstruct(
|
|
156
|
+
tree,
|
|
157
|
+
_postprocess_reconstruct,
|
|
158
|
+
insert_spaces=False,
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
hcl2_reconstructor = HCLReconstructor(hcl2)
|
|
@@ -93,7 +93,10 @@ class DictTransformer(Transformer):
|
|
|
93
93
|
# This returns a dict with a single key/value pair to make it easier to merge these
|
|
94
94
|
# into a bigger dict that is returned by the "object" function
|
|
95
95
|
key = self.strip_quotes(args[0])
|
|
96
|
-
|
|
96
|
+
if len(args) == 3:
|
|
97
|
+
value = self.to_string_dollar(args[2])
|
|
98
|
+
else:
|
|
99
|
+
value = self.to_string_dollar(args[1])
|
|
97
100
|
|
|
98
101
|
return {key: value}
|
|
99
102
|
|
|
@@ -116,7 +119,7 @@ class DictTransformer(Transformer):
|
|
|
116
119
|
args_str = ""
|
|
117
120
|
if len(args) > 5:
|
|
118
121
|
args_str = ", ".join([str(arg) for arg in args[5] if arg is not Discard])
|
|
119
|
-
provider_func = "::".join([args[0],args[2],args[4]])
|
|
122
|
+
provider_func = "::".join([args[0], args[2], args[4]])
|
|
120
123
|
return f"{provider_func}({args_str})"
|
|
121
124
|
|
|
122
125
|
def arguments(self, args: List) -> List:
|
|
@@ -148,7 +151,7 @@ class DictTransformer(Transformer):
|
|
|
148
151
|
key = str(args[0])
|
|
149
152
|
if key.startswith('"') and key.endswith('"'):
|
|
150
153
|
key = key[1:-1]
|
|
151
|
-
value = self.to_string_dollar(args[
|
|
154
|
+
value = self.to_string_dollar(args[2])
|
|
152
155
|
return Attribute(key, value)
|
|
153
156
|
|
|
154
157
|
def conditional(self, args: List) -> str:
|
python-hcl2-4.3.4/hcl2/api.py
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
"""The API that will be exposed to users of this package"""
|
|
2
|
-
from typing import TextIO
|
|
3
|
-
|
|
4
|
-
from hcl2.parser import hcl2
|
|
5
|
-
from hcl2.transformer import DictTransformer
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def load(file: TextIO, with_meta=False) -> dict:
|
|
9
|
-
"""Load a HCL2 file.
|
|
10
|
-
:param file: File with hcl2 to be loaded as a dict.
|
|
11
|
-
:param with_meta: If set to true then adds `__start_line__` and `__end_line__`
|
|
12
|
-
parameters to the output dict. Default to false.
|
|
13
|
-
"""
|
|
14
|
-
return loads(file.read(), with_meta=with_meta)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def loads(text: str, with_meta=False) -> dict:
|
|
18
|
-
"""Load HCL2 from a string.
|
|
19
|
-
:param text: Text with hcl2 to be loaded as a dict.
|
|
20
|
-
:param with_meta: If set to true then adds `__start_line__` and `__end_line__`
|
|
21
|
-
parameters to the output dict. Default to false.
|
|
22
|
-
"""
|
|
23
|
-
# append new line as a workaround for https://github.com/lark-parser/lark/issues/237
|
|
24
|
-
# Lark doesn't support a EOF token so our grammar can't look for "new line or end of file"
|
|
25
|
-
# This means that all blocks must end in a new line even if the file ends
|
|
26
|
-
# Append a new line as a temporary fix
|
|
27
|
-
tree = hcl2.parse(text + "\n")
|
|
28
|
-
return DictTransformer(with_meta=with_meta).transform(tree)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|