python-hcl2 8.0.0rc2__tar.gz → 8.1.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-8.0.0rc2 → python_hcl2-8.1.0}/CHANGELOG.md +7 -6
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/CLAUDE.md +65 -5
- {python_hcl2-8.0.0rc2/python_hcl2.egg-info → python_hcl2-8.1.0}/PKG-INFO +36 -7
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/README.md +35 -6
- python_hcl2-8.1.0/cli/hcl_to_json.py +465 -0
- python_hcl2-8.1.0/cli/helpers.py +254 -0
- python_hcl2-8.1.0/cli/hq.py +870 -0
- python_hcl2-8.1.0/cli/json_to_hcl.py +462 -0
- python_hcl2-8.1.0/docs/01_getting_started.md +264 -0
- python_hcl2-8.1.0/docs/02_querying.md +221 -0
- python_hcl2-8.1.0/docs/03_advanced_api.md +147 -0
- python_hcl2-8.1.0/docs/04_hq.md +667 -0
- python_hcl2-8.1.0/docs/05_hq_examples.md +207 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/__init__.py +1 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/api.py +12 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/deserializer.py +32 -7
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/hcl2.lark +30 -2
- python_hcl2-8.1.0/hcl2/query/__init__.py +46 -0
- python_hcl2-8.1.0/hcl2/query/_base.py +120 -0
- python_hcl2-8.1.0/hcl2/query/attributes.py +51 -0
- python_hcl2-8.1.0/hcl2/query/blocks.py +100 -0
- python_hcl2-8.1.0/hcl2/query/body.py +124 -0
- python_hcl2-8.1.0/hcl2/query/builtins.py +115 -0
- python_hcl2-8.1.0/hcl2/query/containers.py +53 -0
- python_hcl2-8.1.0/hcl2/query/diff.py +88 -0
- python_hcl2-8.1.0/hcl2/query/expressions.py +27 -0
- python_hcl2-8.1.0/hcl2/query/for_exprs.py +112 -0
- python_hcl2-8.1.0/hcl2/query/functions.py +35 -0
- python_hcl2-8.1.0/hcl2/query/introspect.py +186 -0
- python_hcl2-8.1.0/hcl2/query/path.py +258 -0
- python_hcl2-8.1.0/hcl2/query/pipeline.py +474 -0
- python_hcl2-8.1.0/hcl2/query/predicate.py +570 -0
- python_hcl2-8.1.0/hcl2/query/resolver.py +350 -0
- python_hcl2-8.1.0/hcl2/query/safe_eval.py +165 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/reconstructor.py +73 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/rules/base.py +2 -2
- python_hcl2-8.1.0/hcl2/rules/directives.py +429 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/rules/expressions.py +32 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/rules/strings.py +51 -6
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/rules/tokens.py +7 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/rules/whitespace.py +40 -16
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/transformer.py +118 -0
- python_hcl2-8.1.0/hcl2/version.py +24 -0
- python_hcl2-8.1.0/hcl2/walk.py +62 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/pylintrc +4 -1
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/pyproject.toml +2 -1
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0/python_hcl2.egg-info}/PKG-INFO +36 -7
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/python_hcl2.egg-info/SOURCES.txt +25 -1
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/python_hcl2.egg-info/entry_points.txt +1 -0
- python_hcl2-8.0.0rc2/cli/hcl_to_json.py +0 -138
- python_hcl2-8.0.0rc2/cli/helpers.py +0 -96
- python_hcl2-8.0.0rc2/cli/json_to_hcl.py +0 -136
- python_hcl2-8.0.0rc2/docs/usage.md +0 -306
- python_hcl2-8.0.0rc2/hcl2/version.py +0 -34
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/.codacy.yml +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/.coveragerc +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/.github/CODEOWNERS +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/.github/ISSUE_TEMPLATE/hcl2-parsing-error.md +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/.github/workflows/codeql-analysis.yml +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/.github/workflows/dependencies_check.yml +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/.github/workflows/pr_check.yml +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/.github/workflows/publish.yml +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/.github/workflows/security.yml +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/.gitignore +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/.pre-commit-config.yaml +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/.yamllint.yml +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/LICENSE +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/MANIFEST.in +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/bin/check_deps.py +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/bin/terraform_test +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/cli/__init__.py +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/__main__.py +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/builder.py +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/const.py +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/formatter.py +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/parser.py +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/postlexer.py +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/rules/__init__.py +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/rules/abstract.py +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/rules/containers.py +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/rules/for_expressions.py +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/rules/functions.py +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/rules/indexing.py +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/rules/literal_rules.py +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/utils.py +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/mypy.ini +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/python_hcl2.egg-info/dependency_links.txt +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/python_hcl2.egg-info/not-zip-safe +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/python_hcl2.egg-info/requires.txt +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/python_hcl2.egg-info/top_level.txt +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/reports/.gitignore +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/requirements.txt +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/setup.cfg +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/test-requirements.txt +0 -0
- {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/tox.ini +0 -0
|
@@ -9,15 +9,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
|
9
9
|
|
|
10
10
|
- Nothing yet.
|
|
11
11
|
|
|
12
|
-
## \[8.
|
|
12
|
+
## \[8.1.0\] - 2026-04-07
|
|
13
13
|
|
|
14
14
|
### Added
|
|
15
15
|
|
|
16
16
|
- Full architecture overhaul: bidirectional HCL2 ↔ JSON pipeline with typed rule classes. ([#203](https://github.com/amplify-education/python-hcl2/pull/203))
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
- `hq` read-only query CLI for HCL2 files ([#277](https://github.com/amplify-education/python-hcl2/pull/277))
|
|
18
|
+
- Agent-friendly conversion CLIs: `hcl2tojson` and `jsontohcl2` ([#274](https://github.com/amplify-education/python-hcl2/pull/274))
|
|
19
|
+
- Add template directives support (`%{if}`, `%{for}`) in quoted strings ([#276](https://github.com/amplify-education/python-hcl2/pull/276))
|
|
20
|
+
- Support loading comments ([#134](https://github.com/amplify-education/python-hcl2/issues/134))
|
|
21
21
|
- CLAUDE.md ([#260](https://github.com/amplify-education/python-hcl2/pull/260))
|
|
22
22
|
|
|
23
23
|
### Fixed
|
|
@@ -34,7 +34,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
|
34
34
|
- Interpolation literals added to locals/variables in maps ([#252](https://github.com/amplify-education/python-hcl2/issues/252))
|
|
35
35
|
- Object literal expression can't be serialized ([#253](https://github.com/amplify-education/python-hcl2/issues/253))
|
|
36
36
|
- Heredocs should interpret backslash literally ([#262](https://github.com/amplify-education/python-hcl2/issues/262))
|
|
37
|
-
- Parsing a multi-line multi-conditional expression causes exception
|
|
37
|
+
- Parsing a multi-line multi-conditional expression causes exception — Unexpected token Token('QMARK', '?') ([#269](https://github.com/amplify-education/python-hcl2/issues/269))
|
|
38
|
+
- Parsing error for multiline binary operators ([#246](https://github.com/amplify-education/python-hcl2/pull/246))
|
|
38
39
|
|
|
39
40
|
### Changed
|
|
40
41
|
|
|
@@ -23,11 +23,30 @@ The **Direct** pipeline (`parse_to_tree` → `transform` → `to_lark` → `reco
|
|
|
23
23
|
| `hcl2/formatter.py` | Whitespace alignment and spacing on LarkElement trees |
|
|
24
24
|
| `hcl2/reconstructor.py` | LarkElement tree → HCL2 text via Lark |
|
|
25
25
|
| `hcl2/builder.py` | Programmatic HCL document construction |
|
|
26
|
+
| `hcl2/walk.py` | Generic tree-walking primitives for the LarkElement IR tree |
|
|
26
27
|
| `hcl2/utils.py` | `SerializationOptions`, `SerializationContext`, string helpers |
|
|
27
28
|
| `hcl2/const.py` | Constants: `IS_BLOCK`, `COMMENTS_KEY`, `INLINE_COMMENTS_KEY` |
|
|
28
29
|
| `cli/helpers.py` | File/directory/stdin conversion helpers |
|
|
29
30
|
| `cli/hcl_to_json.py` | `hcl2tojson` entry point |
|
|
30
31
|
| `cli/json_to_hcl.py` | `jsontohcl2` entry point |
|
|
32
|
+
| `cli/hq.py` | `hq` CLI entry point — query dispatch, formatting, optional operator |
|
|
33
|
+
| `hcl2/query/__init__.py` | Public query API exports |
|
|
34
|
+
| `hcl2/query/_base.py` | `NodeView` base class, view registry, `view_for()` factory |
|
|
35
|
+
| `hcl2/query/body.py` | `DocumentView`, `BodyView` facades for top-level and body queries |
|
|
36
|
+
| `hcl2/query/blocks.py` | `BlockView` facade for block queries |
|
|
37
|
+
| `hcl2/query/attributes.py` | `AttributeView` facade for attribute queries |
|
|
38
|
+
| `hcl2/query/containers.py` | `TupleView`, `ObjectView` facades for container queries |
|
|
39
|
+
| `hcl2/query/expressions.py` | `ConditionalView` facade for conditional expressions |
|
|
40
|
+
| `hcl2/query/functions.py` | `FunctionCallView` facade for function call queries |
|
|
41
|
+
| `hcl2/query/for_exprs.py` | `ForTupleView`, `ForObjectView` facades for for-expressions |
|
|
42
|
+
| `hcl2/query/path.py` | Structural path parser (`PathSegment`, `parse_path`, `[select()]`, `type:name`) |
|
|
43
|
+
| `hcl2/query/resolver.py` | Path resolver — segment-by-segment with label depth, type filter |
|
|
44
|
+
| `hcl2/query/pipeline.py` | Pipe operator — `split_pipeline`, `classify_stage`, `execute_pipeline` |
|
|
45
|
+
| `hcl2/query/builtins.py` | Built-in transforms: `keys`, `values`, `length` |
|
|
46
|
+
| `hcl2/query/diff.py` | Structural diff between two HCL documents |
|
|
47
|
+
| `hcl2/query/predicate.py` | `select()` predicate tokenizer, recursive descent parser, evaluator |
|
|
48
|
+
| `hcl2/query/safe_eval.py` | AST-validated Python expression eval for hybrid/eval modes |
|
|
49
|
+
| `hcl2/query/introspect.py` | `--describe` and `--schema` output generation |
|
|
31
50
|
|
|
32
51
|
`hcl2/__main__.py` is a thin wrapper that imports `cli.hcl_to_json:main`.
|
|
33
52
|
|
|
@@ -41,10 +60,11 @@ The **Direct** pipeline (`parse_to_tree` → `transform` → `to_lark` → `reco
|
|
|
41
60
|
| `rules/containers.py` | `TupleRule`, `ObjectRule`, `ObjectElemRule`, `ObjectElemKeyRule` |
|
|
42
61
|
| `rules/expressions.py` | `ExprTermRule`, `BinaryOpRule`, `UnaryOpRule`, `ConditionalRule` |
|
|
43
62
|
| `rules/literal_rules.py` | `IntLitRule`, `FloatLitRule`, `IdentifierRule`, `KeywordRule` |
|
|
44
|
-
| `rules/strings.py` | `StringRule`, `InterpolationRule`, `HeredocTemplateRule` |
|
|
63
|
+
| `rules/strings.py` | `StringRule`, `InterpolationRule`, `HeredocTemplateRule`, `TemplateStringRule` |
|
|
45
64
|
| `rules/functions.py` | `FunctionCallRule`, `ArgumentsRule` |
|
|
46
65
|
| `rules/indexing.py` | `GetAttrRule`, `SqbIndexRule`, splat rules |
|
|
47
66
|
| `rules/for_expressions.py` | `ForTupleExprRule`, `ForObjectExprRule`, `ForIntroRule`, `ForCondRule` |
|
|
67
|
+
| `rules/directives.py` | `TemplateIfRule`, `TemplateForRule`, and flat directive start/end rules |
|
|
48
68
|
| `rules/whitespace.py` | `NewLineOrCommentRule`, `InlineCommentMixIn` |
|
|
49
69
|
|
|
50
70
|
## Public API (`api.py`)
|
|
@@ -53,12 +73,13 @@ Follows the `json` module convention. All option parameters are keyword-only.
|
|
|
53
73
|
|
|
54
74
|
- `load/loads` — HCL2 text → Python dict
|
|
55
75
|
- `dump/dumps` — Python dict → HCL2 text
|
|
76
|
+
- `query` — HCL2 text/file → `DocumentView` for structured queries
|
|
56
77
|
- Intermediate stages: `parse/parses`, `parse_to_tree/parses_to_tree`, `transform`, `serialize`, `from_dict`, `from_json`, `reconstruct`
|
|
57
78
|
|
|
58
79
|
### Option Dataclasses
|
|
59
80
|
|
|
60
81
|
**`SerializationOptions`** (LarkElement → dict):
|
|
61
|
-
`with_comments`, `with_meta`, `wrap_objects`, `wrap_tuples`, `explicit_blocks`, `preserve_heredocs`, `force_operation_parentheses`, `preserve_scientific_notation`
|
|
82
|
+
`with_comments`, `with_meta`, `wrap_objects`, `wrap_tuples`, `explicit_blocks`, `preserve_heredocs`, `force_operation_parentheses`, `preserve_scientific_notation`, `strip_string_quotes`
|
|
62
83
|
|
|
63
84
|
**`DeserializerOptions`** (dict → LarkElement):
|
|
64
85
|
`heredocs_to_strings`, `strings_to_heredocs`, `object_elements_colon`, `object_elements_trailing_comma`
|
|
@@ -68,13 +89,52 @@ Follows the `json` module convention. All option parameters are keyword-only.
|
|
|
68
89
|
|
|
69
90
|
## CLI
|
|
70
91
|
|
|
71
|
-
Console scripts defined in `pyproject.toml`.
|
|
92
|
+
Console scripts defined in `pyproject.toml`. All three CLIs accept positional `PATH` arguments (files, directories, glob patterns, or `-` for stdin). When no `PATH` is given, stdin is read by default (like `jq`).
|
|
72
93
|
|
|
94
|
+
### Exit Codes
|
|
95
|
+
|
|
96
|
+
All CLIs use structured error output (plain text to stderr) and distinct exit codes:
|
|
97
|
+
|
|
98
|
+
| Code | `hcl2tojson` | `jsontohcl2` | `hq` |
|
|
99
|
+
|------|---|---|---|
|
|
100
|
+
| 0 | Success | Success | Success |
|
|
101
|
+
| 1 | Partial (some skipped) | JSON/encoding parse error | No results |
|
|
102
|
+
| 2 | All unparsable | Bad HCL structure | Parse error |
|
|
103
|
+
| 3 | — | — | Query error |
|
|
104
|
+
| 4 | I/O error | I/O error | I/O error |
|
|
105
|
+
| 5 | — | Differences found (`--diff` / `--semantic-diff`) | — |
|
|
106
|
+
|
|
107
|
+
### `hcl2tojson`
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
hcl2tojson file.tf # single file to stdout
|
|
111
|
+
hcl2tojson --ndjson dir/ # directory → NDJSON to stdout
|
|
112
|
+
hcl2tojson a.tf b.tf -o out/ # multiple files to output dir
|
|
113
|
+
hcl2tojson --ndjson 'modules/**/*.tf' # glob + NDJSON streaming
|
|
114
|
+
hcl2tojson --only resource,module file.tf # block type filtering
|
|
115
|
+
hcl2tojson --exclude variable file.tf # exclude block types
|
|
116
|
+
hcl2tojson --fields cpu,memory file.tf # field projection
|
|
117
|
+
hcl2tojson --compact file.tf # single-line JSON
|
|
118
|
+
hcl2tojson -q dir/ -o out/ # quiet (no stderr progress)
|
|
119
|
+
echo 'x = 1' | hcl2tojson # stdin (no args needed)
|
|
73
120
|
```
|
|
74
|
-
|
|
121
|
+
|
|
122
|
+
Key flags: `--ndjson`, `--compact`, `--only`/`--exclude`, `--fields`, `-q`/`--quiet`, `--json-indent N`, `--with-meta`, `--with-comments`, `--strip-string-quotes` (breaks round-trip). Multi-file NDJSON adds a `__file__` provenance key to each object.
|
|
123
|
+
|
|
124
|
+
### `jsontohcl2`
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
jsontohcl2 file.json # single file to stdout
|
|
128
|
+
jsontohcl2 --diff original.tf modified.json # preview text changes
|
|
129
|
+
jsontohcl2 --semantic-diff original.tf modified.json # semantic-only changes
|
|
130
|
+
jsontohcl2 --semantic-diff original.tf --diff-json m.json # semantic diff as JSON
|
|
131
|
+
jsontohcl2 --dry-run file.json # convert without writing
|
|
132
|
+
jsontohcl2 --fragment - # attribute snippets from stdin
|
|
75
133
|
jsontohcl2 --indent 4 --no-align file.json
|
|
76
134
|
```
|
|
77
135
|
|
|
136
|
+
Key flags: `--diff ORIGINAL`, `--semantic-diff ORIGINAL`, `--diff-json`, `--dry-run`, `--fragment`, `-q`/`--quiet`, `--indent N`, `--no-align`, `--colon-separator`.
|
|
137
|
+
|
|
78
138
|
Add new options as `parser.add_argument()` calls in the relevant entry point module.
|
|
79
139
|
|
|
80
140
|
## PostLexer (`postlexer.py`)
|
|
@@ -141,4 +201,4 @@ Hooks are defined in `.pre-commit-config.yaml` (includes black, mypy, pylint, an
|
|
|
141
201
|
|
|
142
202
|
## Keeping Docs Current
|
|
143
203
|
|
|
144
|
-
Update this file when architecture, modules, API surface, or testing conventions change. Also update `README.md` and `docs
|
|
204
|
+
Update this file when architecture, modules, API surface, or testing conventions change. Also update `README.md` and the docs in `docs/` (`01_getting_started.md`, `02_querying.md`, `03_advanced_api.md`, `04_hq.md`, `05_hq_examples.md`) when changes affect the public API, CLI flags, or option fields.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-hcl2
|
|
3
|
-
Version: 8.0
|
|
3
|
+
Version: 8.1.0
|
|
4
4
|
Summary: A parser for HCL2
|
|
5
5
|
Author-email: Amplify Education <github@amplify.com>
|
|
6
6
|
License: MIT
|
|
@@ -34,8 +34,9 @@ Dynamic: license-file
|
|
|
34
34
|
# Python HCL2
|
|
35
35
|
|
|
36
36
|
A parser for [HCL2](https://github.com/hashicorp/hcl/blob/hcl2/hclsyntax/spec.md) written in Python using
|
|
37
|
-
[Lark](https://github.com/lark-parser/lark).
|
|
38
|
-
|
|
37
|
+
[Lark](https://github.com/lark-parser/lark). It can be used as a Python library or through its CLI tools:
|
|
38
|
+
`hcl2tojson`, `jsontohcl2`, and `hq` — a jq-like query tool for HCL files.
|
|
39
|
+
Supports HCL2 only (not backwards compatible with HCL v1) and works with any HCL2 config file such as Terraform.
|
|
39
40
|
|
|
40
41
|
## About Amplify
|
|
41
42
|
|
|
@@ -60,6 +61,12 @@ This package can be installed using `pip`
|
|
|
60
61
|
pip3 install python-hcl2
|
|
61
62
|
```
|
|
62
63
|
|
|
64
|
+
To install the CLI tools (`hcl2tojson`, `jsontohcl2`, `hq`) globally without affecting your project environments, use [pipx](https://pipx.pypa.io/):
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
pipx install python-hcl2
|
|
68
|
+
```
|
|
69
|
+
|
|
63
70
|
### Usage
|
|
64
71
|
|
|
65
72
|
**HCL2 to Python dict:**
|
|
@@ -94,12 +101,19 @@ res.block("tags", Name="HelloWorld")
|
|
|
94
101
|
hcl_string = hcl2.dumps(doc.build())
|
|
95
102
|
```
|
|
96
103
|
|
|
97
|
-
|
|
98
|
-
|
|
104
|
+
### Documentation
|
|
105
|
+
|
|
106
|
+
| Guide | Contents |
|
|
107
|
+
|---|---|
|
|
108
|
+
| [Getting Started](docs/01_getting_started.md) | Installation, load/dump, options, CLI converters |
|
|
109
|
+
| [Querying HCL (Python)](docs/02_querying.md) | DocumentView, BlockView, tree walking, view hierarchy |
|
|
110
|
+
| [Advanced API](docs/03_advanced_api.md) | Pipeline stages, Builder |
|
|
111
|
+
| [hq Reference](docs/04_hq.md) | `hq` CLI — structural queries, hybrid/eval, introspection |
|
|
112
|
+
| [hq Examples](docs/05_hq_examples.md) | Real-world queries for discovery, compliance, extraction |
|
|
99
113
|
|
|
100
114
|
### CLI Tools
|
|
101
115
|
|
|
102
|
-
python-hcl2 ships
|
|
116
|
+
python-hcl2 ships three command-line tools:
|
|
103
117
|
|
|
104
118
|
```sh
|
|
105
119
|
# HCL2 → JSON
|
|
@@ -111,9 +125,13 @@ hcl2tojson terraform/ output/ # converts a directory
|
|
|
111
125
|
jsontohcl2 output.json # prints HCL2 to stdout
|
|
112
126
|
jsontohcl2 output.json main.tf # writes to file
|
|
113
127
|
jsontohcl2 output/ terraform/ # converts a directory
|
|
128
|
+
|
|
129
|
+
# Query HCL2 files
|
|
130
|
+
hq 'resource.aws_instance.main.ami' main.tf
|
|
131
|
+
hq 'variable[*]' variables.tf --json
|
|
114
132
|
```
|
|
115
133
|
|
|
116
|
-
|
|
134
|
+
All commands accept `-` as PATH to read from stdin. Run `--help` on any command for the full list of flags.
|
|
117
135
|
|
|
118
136
|
## Building From Source
|
|
119
137
|
|
|
@@ -136,6 +154,17 @@ To create a new release go to Releases page, press 'Draft a new release', create
|
|
|
136
154
|
with a version you want to be released, fill the release notes and press 'Publish release'.
|
|
137
155
|
Github actions will take care of publishing it to PyPi.
|
|
138
156
|
|
|
157
|
+
## Roadmap
|
|
158
|
+
|
|
159
|
+
Planned features, roughly in priority order:
|
|
160
|
+
|
|
161
|
+
- **MCP server** — expose parsing, querying, and formatting as MCP tools for AI agents
|
|
162
|
+
- **Predictable formatting** — source-derived formatting heuristics and stable whitespace defaults
|
|
163
|
+
- **In-place tree edits** — `hq set`, `hq delete` for programmatic HCL modification
|
|
164
|
+
- **Comment deserialization** — comments survive JSON round-trips and tree edits
|
|
165
|
+
- **Expression intelligence** — variable reference tracking, unused variable detection, cross-file analysis
|
|
166
|
+
- **Refactoring operations** — `hq rename`, `hq extract-module`, `hq sort` for high-level code transforms
|
|
167
|
+
|
|
139
168
|
## Responsible Disclosure
|
|
140
169
|
|
|
141
170
|
If you have any security issue to report, contact project maintainers privately.
|
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
# Python HCL2
|
|
8
8
|
|
|
9
9
|
A parser for [HCL2](https://github.com/hashicorp/hcl/blob/hcl2/hclsyntax/spec.md) written in Python using
|
|
10
|
-
[Lark](https://github.com/lark-parser/lark).
|
|
11
|
-
|
|
10
|
+
[Lark](https://github.com/lark-parser/lark). It can be used as a Python library or through its CLI tools:
|
|
11
|
+
`hcl2tojson`, `jsontohcl2`, and `hq` — a jq-like query tool for HCL files.
|
|
12
|
+
Supports HCL2 only (not backwards compatible with HCL v1) and works with any HCL2 config file such as Terraform.
|
|
12
13
|
|
|
13
14
|
## About Amplify
|
|
14
15
|
|
|
@@ -33,6 +34,12 @@ This package can be installed using `pip`
|
|
|
33
34
|
pip3 install python-hcl2
|
|
34
35
|
```
|
|
35
36
|
|
|
37
|
+
To install the CLI tools (`hcl2tojson`, `jsontohcl2`, `hq`) globally without affecting your project environments, use [pipx](https://pipx.pypa.io/):
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
pipx install python-hcl2
|
|
41
|
+
```
|
|
42
|
+
|
|
36
43
|
### Usage
|
|
37
44
|
|
|
38
45
|
**HCL2 to Python dict:**
|
|
@@ -67,12 +74,19 @@ res.block("tags", Name="HelloWorld")
|
|
|
67
74
|
hcl_string = hcl2.dumps(doc.build())
|
|
68
75
|
```
|
|
69
76
|
|
|
70
|
-
|
|
71
|
-
|
|
77
|
+
### Documentation
|
|
78
|
+
|
|
79
|
+
| Guide | Contents |
|
|
80
|
+
|---|---|
|
|
81
|
+
| [Getting Started](docs/01_getting_started.md) | Installation, load/dump, options, CLI converters |
|
|
82
|
+
| [Querying HCL (Python)](docs/02_querying.md) | DocumentView, BlockView, tree walking, view hierarchy |
|
|
83
|
+
| [Advanced API](docs/03_advanced_api.md) | Pipeline stages, Builder |
|
|
84
|
+
| [hq Reference](docs/04_hq.md) | `hq` CLI — structural queries, hybrid/eval, introspection |
|
|
85
|
+
| [hq Examples](docs/05_hq_examples.md) | Real-world queries for discovery, compliance, extraction |
|
|
72
86
|
|
|
73
87
|
### CLI Tools
|
|
74
88
|
|
|
75
|
-
python-hcl2 ships
|
|
89
|
+
python-hcl2 ships three command-line tools:
|
|
76
90
|
|
|
77
91
|
```sh
|
|
78
92
|
# HCL2 → JSON
|
|
@@ -84,9 +98,13 @@ hcl2tojson terraform/ output/ # converts a directory
|
|
|
84
98
|
jsontohcl2 output.json # prints HCL2 to stdout
|
|
85
99
|
jsontohcl2 output.json main.tf # writes to file
|
|
86
100
|
jsontohcl2 output/ terraform/ # converts a directory
|
|
101
|
+
|
|
102
|
+
# Query HCL2 files
|
|
103
|
+
hq 'resource.aws_instance.main.ami' main.tf
|
|
104
|
+
hq 'variable[*]' variables.tf --json
|
|
87
105
|
```
|
|
88
106
|
|
|
89
|
-
|
|
107
|
+
All commands accept `-` as PATH to read from stdin. Run `--help` on any command for the full list of flags.
|
|
90
108
|
|
|
91
109
|
## Building From Source
|
|
92
110
|
|
|
@@ -109,6 +127,17 @@ To create a new release go to Releases page, press 'Draft a new release', create
|
|
|
109
127
|
with a version you want to be released, fill the release notes and press 'Publish release'.
|
|
110
128
|
Github actions will take care of publishing it to PyPi.
|
|
111
129
|
|
|
130
|
+
## Roadmap
|
|
131
|
+
|
|
132
|
+
Planned features, roughly in priority order:
|
|
133
|
+
|
|
134
|
+
- **MCP server** — expose parsing, querying, and formatting as MCP tools for AI agents
|
|
135
|
+
- **Predictable formatting** — source-derived formatting heuristics and stable whitespace defaults
|
|
136
|
+
- **In-place tree edits** — `hq set`, `hq delete` for programmatic HCL modification
|
|
137
|
+
- **Comment deserialization** — comments survive JSON round-trips and tree edits
|
|
138
|
+
- **Expression intelligence** — variable reference tracking, unused variable detection, cross-file analysis
|
|
139
|
+
- **Refactoring operations** — `hq rename`, `hq extract-module`, `hq sort` for high-level code transforms
|
|
140
|
+
|
|
112
141
|
## Responsible Disclosure
|
|
113
142
|
|
|
114
143
|
If you have any security issue to report, contact project maintainers privately.
|