python-hcl2 7.3.0__tar.gz → 8.0.0rc1__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.
Files changed (78) hide show
  1. python_hcl2-8.0.0rc1/.coveragerc +15 -0
  2. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/.github/ISSUE_TEMPLATE/hcl2-parsing-error.md +9 -5
  3. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/.github/workflows/codeql-analysis.yml +1 -1
  4. python_hcl2-8.0.0rc1/.github/workflows/dependencies_check.yml +27 -0
  5. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/.github/workflows/pr_check.yml +2 -2
  6. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/.github/workflows/publish.yml +2 -2
  7. python_hcl2-8.0.0rc1/.github/workflows/security.yml +23 -0
  8. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/.pre-commit-config.yaml +1 -0
  9. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/CHANGELOG.md +31 -0
  10. python_hcl2-8.0.0rc1/CLAUDE.md +121 -0
  11. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/PKG-INFO +55 -28
  12. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/README.md +50 -23
  13. python_hcl2-8.0.0rc1/bin/check_deps.py +54 -0
  14. python_hcl2-8.0.0rc1/cli/hcl_to_json.py +132 -0
  15. python_hcl2-8.0.0rc1/cli/helpers.py +96 -0
  16. python_hcl2-8.0.0rc1/cli/json_to_hcl.py +136 -0
  17. python_hcl2-8.0.0rc1/docs/usage.md +306 -0
  18. python_hcl2-8.0.0rc1/hcl2/__init__.py +28 -0
  19. python_hcl2-8.0.0rc1/hcl2/__main__.py +5 -0
  20. python_hcl2-8.0.0rc1/hcl2/api.py +222 -0
  21. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/hcl2/builder.py +7 -10
  22. python_hcl2-8.0.0rc1/hcl2/const.py +5 -0
  23. python_hcl2-8.0.0rc1/hcl2/deserializer.py +369 -0
  24. python_hcl2-8.0.0rc1/hcl2/formatter.py +320 -0
  25. python_hcl2-8.0.0rc1/hcl2/hcl2.lark +206 -0
  26. python_hcl2-8.0.0rc1/hcl2/parser.py +20 -0
  27. python_hcl2-8.0.0rc1/hcl2/reconstructor.py +255 -0
  28. python_hcl2-8.0.0rc1/hcl2/rules/__init__.py +0 -0
  29. python_hcl2-8.0.0rc1/hcl2/rules/abstract.py +139 -0
  30. python_hcl2-8.0.0rc1/hcl2/rules/base.py +172 -0
  31. python_hcl2-8.0.0rc1/hcl2/rules/containers.py +229 -0
  32. python_hcl2-8.0.0rc1/hcl2/rules/expressions.py +295 -0
  33. python_hcl2-8.0.0rc1/hcl2/rules/for_expressions.py +321 -0
  34. python_hcl2-8.0.0rc1/hcl2/rules/functions.py +113 -0
  35. python_hcl2-8.0.0rc1/hcl2/rules/indexing.py +293 -0
  36. python_hcl2-8.0.0rc1/hcl2/rules/literal_rules.py +86 -0
  37. python_hcl2-8.0.0rc1/hcl2/rules/strings.py +181 -0
  38. python_hcl2-8.0.0rc1/hcl2/rules/tokens.py +150 -0
  39. python_hcl2-8.0.0rc1/hcl2/rules/whitespace.py +87 -0
  40. python_hcl2-8.0.0rc1/hcl2/transformer.py +270 -0
  41. python_hcl2-8.0.0rc1/hcl2/utils.py +77 -0
  42. python_hcl2-8.0.0rc1/hcl2/version.py +34 -0
  43. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/pylintrc +1 -1
  44. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/pyproject.toml +10 -6
  45. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/python_hcl2.egg-info/PKG-INFO +55 -28
  46. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/python_hcl2.egg-info/SOURCES.txt +24 -2
  47. python_hcl2-8.0.0rc1/python_hcl2.egg-info/entry_points.txt +3 -0
  48. python_hcl2-8.0.0rc1/python_hcl2.egg-info/requires.txt +2 -0
  49. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/python_hcl2.egg-info/top_level.txt +1 -0
  50. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/tox.ini +2 -3
  51. python_hcl2-7.3.0/.coveragerc +0 -9
  52. python_hcl2-7.3.0/hcl2/__init__.py +0 -18
  53. python_hcl2-7.3.0/hcl2/__main__.py +0 -106
  54. python_hcl2-7.3.0/hcl2/api.py +0 -67
  55. python_hcl2-7.3.0/hcl2/const.py +0 -4
  56. python_hcl2-7.3.0/hcl2/hcl2.lark +0 -108
  57. python_hcl2-7.3.0/hcl2/parser.py +0 -42
  58. python_hcl2-7.3.0/hcl2/reconstructor.py +0 -734
  59. python_hcl2-7.3.0/hcl2/transformer.py +0 -399
  60. python_hcl2-7.3.0/hcl2/version.py +0 -21
  61. python_hcl2-7.3.0/python_hcl2.egg-info/entry_points.txt +0 -2
  62. python_hcl2-7.3.0/python_hcl2.egg-info/requires.txt +0 -1
  63. python_hcl2-7.3.0/tree-to-hcl2-reconstruction.md +0 -248
  64. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/.codacy.yml +0 -0
  65. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/.github/CODEOWNERS +0 -0
  66. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/.gitignore +0 -0
  67. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/.yamllint.yml +0 -0
  68. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/LICENSE +0 -0
  69. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/MANIFEST.in +0 -0
  70. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/bin/terraform_test +0 -0
  71. /python_hcl2-7.3.0/hcl2/py.typed → /python_hcl2-8.0.0rc1/cli/__init__.py +0 -0
  72. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/mypy.ini +0 -0
  73. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/python_hcl2.egg-info/dependency_links.txt +0 -0
  74. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/python_hcl2.egg-info/not-zip-safe +0 -0
  75. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/reports/.gitignore +0 -0
  76. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/requirements.txt +0 -0
  77. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/setup.cfg +0 -0
  78. {python_hcl2-7.3.0 → python_hcl2-8.0.0rc1}/test-requirements.txt +0 -0
@@ -0,0 +1,15 @@
1
+ [run]
2
+ branch = true
3
+ omit =
4
+ hcl2/lark_parser.py
5
+ hcl2/version.py
6
+ hcl2/__main__.py
7
+ hcl2/__init__.py
8
+ hcl2/rules/__init__.py
9
+ cli/__init__.py
10
+
11
+ [report]
12
+ show_missing = true
13
+ fail_under = 95
14
+ exclude_lines =
15
+ raise NotImplementedError
@@ -1,27 +1,31 @@
1
- ---
1
+ ______________________________________________________________________
2
+
2
3
  name: HCL2 parsing error
3
4
  about: Template for reporting a bug related to parsing HCL2 code
4
5
  title: ''
5
6
  labels: bug
6
7
  assignees: kkozik-amplify
7
8
 
8
- ---
9
+ ______________________________________________________________________
9
10
 
10
11
  **Describe the bug**
11
12
 
12
13
  A clear and concise description of what the bug is.
13
14
 
14
15
  **Software:**
15
- - OS: [macOS / Windows / Linux]
16
- - Python version (e.g. 3.9.21)
17
- - python-hcl2 version (e.g. 7.0.0)
16
+
17
+ - OS: \[macOS / Windows / Linux\]
18
+ - Python version (e.g. 3.9.21)
19
+ - python-hcl2 version (e.g. 7.0.0)
18
20
 
19
21
  **Snippet of HCL2 code causing the unexpected behaviour:**
22
+
20
23
  ```terraform
21
24
  locals {
22
25
  foo = "bar"
23
26
  }
24
27
  ```
28
+
25
29
  **Expected behavior**
26
30
 
27
31
  A clear and concise description of what you expected to happen, e.g. python dictionary or JSON you expected to receive as a result of parsing.
@@ -13,7 +13,7 @@ on:
13
13
  jobs:
14
14
  analyse:
15
15
  name: Analyse
16
- runs-on: ubuntu-latest
16
+ runs-on: github-hosted-static-ip
17
17
 
18
18
  steps:
19
19
  - name: Checkout repository
@@ -0,0 +1,27 @@
1
+ ---
2
+ name: Dependencies Check
3
+ on:
4
+ pull_request:
5
+ types:
6
+ - opened
7
+ - reopened
8
+ - synchronize
9
+ paths:
10
+ - pyproject.toml
11
+ - requirements.txt
12
+ - scripts/check_deps.py
13
+
14
+ jobs:
15
+ test:
16
+ name: Check dependencies sync between pyproject.toml and requirements.txt
17
+ runs-on: github-hosted-static-ip
18
+ steps:
19
+ - uses: actions/checkout@master
20
+ - name: Set up Python 3.13
21
+ uses: actions/setup-python@v4
22
+ with:
23
+ python-version: 3.13
24
+ - name: Install dependencies
25
+ run: python -m pip install --upgrade tomli
26
+ - name: Run script
27
+ run: python3 bin/check_deps.py
@@ -10,10 +10,10 @@ on:
10
10
  jobs:
11
11
  test:
12
12
  name: Check code against linter/unit tests
13
- runs-on: ubuntu-22.04
13
+ runs-on: github-hosted-static-ip
14
14
  strategy:
15
15
  matrix:
16
- python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12', '3.13']
16
+ python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13']
17
17
  steps:
18
18
  - uses: actions/checkout@master
19
19
  - name: Set up Python ${{ matrix.python-version }}
@@ -2,12 +2,12 @@
2
2
  name: Publish
3
3
  on:
4
4
  release:
5
- types: [released]
5
+ types: [published]
6
6
 
7
7
  jobs:
8
8
  build-publish:
9
9
  name: Build and publish Python distributions
10
- runs-on: ubuntu-22.04
10
+ runs-on: github-hosted-static-ip
11
11
  steps:
12
12
  - uses: actions/checkout@master
13
13
  - name: Set up Python
@@ -0,0 +1,23 @@
1
+ ---
2
+ name: Security Review
3
+
4
+ permissions:
5
+ pull-requests: write # Needed for leaving PR comments
6
+ contents: read
7
+
8
+ on:
9
+ pull_request:
10
+
11
+ jobs:
12
+ security:
13
+ runs-on: github-hosted-static-ip
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ with:
17
+ ref: ${{ github.event.pull_request.head.sha || github.sha }}
18
+ fetch-depth: 2
19
+
20
+ - uses: anthropics/claude-code-security-review@main
21
+ with:
22
+ comment-pr: true
23
+ claude-api-key: ${{ secrets.ANTHROPIC_CLAUDE_API_KEY }}
@@ -6,6 +6,7 @@ repos:
6
6
  rev: v4.3.0
7
7
  hooks:
8
8
  - id: trailing-whitespace
9
+ exclude: ^test/integration/(hcl2_reconstructed|specialized)/
9
10
  - id: end-of-file-fixer
10
11
  - id: check-added-large-files
11
12
  - id: no-commit-to-branch # Prevent commits directly to master
@@ -9,6 +9,37 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
9
9
 
10
10
  - Nothing yet.
11
11
 
12
+ ## \[8.0.0\] - rc1
13
+
14
+ ### Added
15
+
16
+ - Full architecture overhaul: bidirectional HCL2 ↔ JSON pipeline with typed rule classes. ([#203](https://github.com/amplify-education/python-hcl2/pull/203))
17
+ - CLAUDE.md ([#260](https://github.com/amplify-education/python-hcl2/pull/260))
18
+
19
+ ### Fixed
20
+
21
+ - Ternary with strings parse error ([#55](https://github.com/amplify-education/python-hcl2/issues/55))
22
+ - reverse_transform not working with object-type variables ([#231](https://github.com/amplify-education/python-hcl2/issues/231))
23
+ - reverse_transform not handling nested functions ([#235](https://github.com/amplify-education/python-hcl2/issues/235))
24
+ - `writes` omits quotes around map keys with `/` ([#236](https://github.com/amplify-education/python-hcl2/issues/236))
25
+ - Operator precedence bug ([#248](https://github.com/amplify-education/python-hcl2/issues/248))
26
+ - Empty string dictionary keys can't be parsed twice ([#249](https://github.com/amplify-education/python-hcl2/issues/249))
27
+ - jsonencode not deserialized correctly ([#250](https://github.com/amplify-education/python-hcl2/issues/250))
28
+ - Literal string "string" incorrectly quoted ([#251](https://github.com/amplify-education/python-hcl2/issues/251))
29
+ - Interpolation literals added to locals/variables in maps ([#252](https://github.com/amplify-education/python-hcl2/issues/252))
30
+ - Object literal expression can't be serialized ([#253](https://github.com/amplify-education/python-hcl2/issues/253))
31
+ - Heredocs should interpret backslash literally ([#262](https://github.com/amplify-education/python-hcl2/issues/262))
32
+
33
+ ### Changed
34
+
35
+ - Updated package metadata: development status, dropped Python 3.7 support. ([#263](https://github.com/amplify-education/python-hcl2/pull/263))
36
+
37
+ ## \[7.3.1\] - 2025-07-24
38
+
39
+ ### Fixed
40
+
41
+ - Updated pyproject.toml dependencies. Thanks, @kkorlyak ([#244](https://github.com/amplify-education/python-hcl2/pull/244))
42
+
12
43
  ## \[7.3.0\] - 2025-07-23
13
44
 
14
45
  ### Fixed
@@ -0,0 +1,121 @@
1
+ # HCL2 Parser — CLAUDE.md
2
+
3
+ ## Pipeline
4
+
5
+ ```
6
+ Forward: HCL2 Text → Lark Parse Tree → LarkElement Tree → Python Dict/JSON
7
+ Reverse: Python Dict/JSON → LarkElement Tree → Lark Tree → HCL2 Text
8
+ ```
9
+
10
+ ## Module Map
11
+
12
+ | Module | Role |
13
+ |---|---|
14
+ | `hcl2/hcl2.lark` | Lark grammar definition |
15
+ | `hcl2/api.py` | Public API (`load/loads/dump/dumps` + intermediate stages) |
16
+ | `hcl2/parser.py` | Lark parser factory with caching |
17
+ | `hcl2/transformer.py` | Lark parse tree → LarkElement tree |
18
+ | `hcl2/deserializer.py` | Python dict → LarkElement tree |
19
+ | `hcl2/formatter.py` | Whitespace alignment and spacing on LarkElement trees |
20
+ | `hcl2/reconstructor.py` | LarkElement tree → HCL2 text via Lark |
21
+ | `hcl2/builder.py` | Programmatic HCL document construction |
22
+ | `hcl2/utils.py` | `SerializationOptions`, `SerializationContext`, string helpers |
23
+ | `hcl2/const.py` | Constants: `IS_BLOCK`, `COMMENTS_KEY`, `INLINE_COMMENTS_KEY` |
24
+ | `cli/helpers.py` | File/directory/stdin conversion helpers |
25
+ | `cli/hcl_to_json.py` | `hcl2tojson` entry point |
26
+ | `cli/json_to_hcl.py` | `jsontohcl2` entry point |
27
+
28
+ `hcl2/__main__.py` is a thin wrapper that imports `cli.hcl_to_json:main`.
29
+
30
+ ### Rules (one class per grammar rule)
31
+
32
+ | File | Domain |
33
+ |---|---|
34
+ | `rules/abstract.py` | `LarkElement`, `LarkRule`, `LarkToken` base classes |
35
+ | `rules/tokens.py` | `StringToken` (cached factory), `StaticStringToken`, punctuation constants |
36
+ | `rules/base.py` | `StartRule`, `BodyRule`, `BlockRule`, `AttributeRule` |
37
+ | `rules/containers.py` | `TupleRule`, `ObjectRule`, `ObjectElemRule`, `ObjectElemKeyRule` |
38
+ | `rules/expressions.py` | `ExprTermRule`, `BinaryOpRule`, `UnaryOpRule`, `ConditionalRule` |
39
+ | `rules/literal_rules.py` | `IntLitRule`, `FloatLitRule`, `IdentifierRule`, `KeywordRule` |
40
+ | `rules/strings.py` | `StringRule`, `InterpolationRule`, `HeredocTemplateRule` |
41
+ | `rules/functions.py` | `FunctionCallRule`, `ArgumentsRule` |
42
+ | `rules/indexing.py` | `GetAttrRule`, `SqbIndexRule`, splat rules |
43
+ | `rules/for_expressions.py` | `ForTupleExprRule`, `ForObjectExprRule`, `ForIntroRule`, `ForCondRule` |
44
+ | `rules/whitespace.py` | `NewLineOrCommentRule`, `InlineCommentMixIn` |
45
+
46
+ ## Public API (`api.py`)
47
+
48
+ Follows the `json` module convention. All option parameters are keyword-only.
49
+
50
+ - `load/loads` — HCL2 text → Python dict
51
+ - `dump/dumps` — Python dict → HCL2 text
52
+ - Intermediate stages: `parse/parses`, `parse_to_tree/parses_to_tree`, `transform`, `serialize`, `from_dict`, `from_json`, `reconstruct`
53
+
54
+ ### Option Dataclasses
55
+
56
+ **`SerializationOptions`** (LarkElement → dict):
57
+ `with_comments`, `with_meta`, `wrap_objects`, `wrap_tuples`, `explicit_blocks`, `preserve_heredocs`, `force_operation_parentheses`, `preserve_scientific_notation`
58
+
59
+ **`DeserializerOptions`** (dict → LarkElement):
60
+ `heredocs_to_strings`, `strings_to_heredocs`, `object_elements_colon`, `object_elements_trailing_comma`
61
+
62
+ **`FormatterOptions`** (whitespace/alignment):
63
+ `indent_length`, `open_empty_blocks`, `open_empty_objects`, `open_empty_tuples`, `vertically_align_attributes`, `vertically_align_object_elements`
64
+
65
+ ## CLI
66
+
67
+ Console scripts defined in `pyproject.toml`. Each uses argparse flags that map directly to the option dataclass fields above.
68
+
69
+ ```
70
+ hcl2tojson --json-indent 2 --with-meta file.tf
71
+ jsontohcl2 --indent 4 --no-align file.json
72
+ ```
73
+
74
+ Add new options as `parser.add_argument()` calls in the relevant entry point module.
75
+
76
+ ## Hard Rules
77
+
78
+ These are project-specific constraints that must not be violated:
79
+
80
+ 1. **Always use the LarkElement IR.** Never transform directly from Lark parse tree to Python dict or vice versa.
81
+ 1. **Block vs object distinction.** Use `__is_block__` markers (`const.IS_BLOCK`) to preserve semantic intent during round-trips. The deserializer must distinguish blocks from regular objects.
82
+ 1. **Bidirectional completeness.** Every serialization path must have a corresponding deserialization path. Test round-trip integrity: Parse → Serialize → Deserialize → Serialize produces identical results.
83
+ 1. **One grammar rule = one `LarkRule` class.** Each class implements `lark_name()`, typed property accessors, `serialize()`, and declares `_children_layout: Tuple[...]` (annotation only, no assignment) to document child structure.
84
+ 1. **Token caching.** Use the `StringToken` factory in `rules/tokens.py` — never create token instances directly.
85
+ 1. **Interpolation context.** `${...}` generation depends on nesting depth — always pass and respect `SerializationContext`.
86
+ 1. **Update both directions.** When adding language features, update transformer.py, deserializer.py, formatter.py and reconstructor.py.
87
+
88
+ ## Adding a New Language Construct
89
+
90
+ 1. Add grammar rules to `hcl2.lark`
91
+ 1. Create rule class(es) in the appropriate `rules/` file
92
+ 1. Add transformer method(s) in `transformer.py`
93
+ 1. Implement `serialize()` in the rule class
94
+ 1. Update `deserializer.py`, `formatter.py` and `reconstructor.py` for round-trip support
95
+
96
+ ## Testing
97
+
98
+ Framework: `unittest.TestCase` (not pytest).
99
+
100
+ ```
101
+ python -m unittest discover -s test -p "test_*.py" -v
102
+ ```
103
+
104
+ **Unit tests** (`test/unit/`): instantiate rule objects directly (no parsing).
105
+
106
+ - `test/unit/rules/` — one file per rules module
107
+ - `test/unit/cli/` — one file per CLI module
108
+ - `test/unit/test_api.py`, `test_builder.py`, `test_deserializer.py`, `test_formatter.py`, `test_reconstructor.py`, `test_utils.py`
109
+
110
+ Use concrete stubs when testing ABCs (e.g., `StubExpression(ExpressionRule)`).
111
+
112
+ **Integration tests** (`test/integration/`): full-pipeline tests with golden files.
113
+
114
+ - `test_round_trip.py` — iterates over all suites in `hcl2_original/`, tests HCL→JSON, JSON→JSON, JSON→HCL, and full round-trip
115
+ - `test_specialized.py` — feature-specific tests with golden files in `specialized/`
116
+
117
+ Always run round-trip full test suite after any modification.
118
+
119
+ ## Keeping Docs Current
120
+
121
+ Update this file when architecture, modules, API surface, or testing conventions change. Also update `README.md` and `docs/usage.md` when changes affect the public API, CLI flags, or option fields.
@@ -1,32 +1,31 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-hcl2
3
- Version: 7.3.0
3
+ Version: 8.0.0rc1
4
4
  Summary: A parser for HCL2
5
5
  Author-email: Amplify Education <github@amplify.com>
6
6
  License: MIT
7
7
  Project-URL: Homepage, https://github.com/amplify-education/python-hcl2
8
- Classifier: Development Status :: 4 - Beta
8
+ Classifier: Development Status :: 5 - Production/Stable
9
9
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
10
10
  Classifier: Intended Audience :: Developers
11
11
  Classifier: License :: OSI Approved :: MIT License
12
12
  Classifier: Operating System :: OS Independent
13
13
  Classifier: Programming Language :: Python
14
14
  Classifier: Programming Language :: Python :: 3
15
- Classifier: Programming Language :: Python :: 3.7
16
15
  Classifier: Programming Language :: Python :: 3.8
17
16
  Classifier: Programming Language :: Python :: 3.9
18
17
  Classifier: Programming Language :: Python :: 3.10
19
18
  Classifier: Programming Language :: Python :: 3.11
20
19
  Classifier: Programming Language :: Python :: 3.12
21
20
  Classifier: Programming Language :: Python :: 3.13
22
- Requires-Python: >=3.7.0
21
+ Requires-Python: >=3.8.0
23
22
  Description-Content-Type: text/markdown
24
23
  License-File: LICENSE
25
- Requires-Dist: lark<2,>=1
24
+ Requires-Dist: lark<2.0,>=1.1.5
25
+ Requires-Dist: regex>=2024.4.16
26
26
  Dynamic: license-file
27
27
 
28
28
  [![Codacy Badge](https://app.codacy.com/project/badge/Grade/2e2015f9297346cbaa788c46ab957827)](https://app.codacy.com/gh/amplify-education/python-hcl2/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
29
- [![Build Status](https://travis-ci.org/amplify-education/python-hcl2.svg?branch=master)](https://travis-ci.org/amplify-education/python-hcl2)
30
29
  [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/amplify-education/python-hcl2/master/LICENSE)
31
30
  [![PyPI](https://img.shields.io/pypi/v/python-hcl2.svg)](https://pypi.org/project/python-hcl2/)
32
31
  [![Python Versions](https://img.shields.io/pypi/pyversions/python-hcl2.svg)](https://pypi.python.org/pypi/python-hcl2)
@@ -51,7 +50,7 @@ Learn more at <https://www.amplify.com>
51
50
 
52
51
  ### Prerequisites
53
52
 
54
- python-hcl2 requires Python 3.7 or higher to run.
53
+ python-hcl2 requires Python 3.8 or higher to run.
55
54
 
56
55
  ### Installing
57
56
 
@@ -63,19 +62,58 @@ pip3 install python-hcl2
63
62
 
64
63
  ### Usage
65
64
 
65
+ **HCL2 to Python dict:**
66
+
66
67
  ```python
67
68
  import hcl2
68
- with open('foo.tf', 'r') as file:
69
- dict = hcl2.load(file)
69
+
70
+ with open("main.tf") as f:
71
+ data = hcl2.load(f)
70
72
  ```
71
73
 
72
- ### Parse Tree to HCL2 reconstruction
74
+ **Python dict to HCL2:**
75
+
76
+ ```python
77
+ import hcl2
78
+
79
+ hcl_string = hcl2.dumps(data)
80
+
81
+ with open("output.tf", "w") as f:
82
+ hcl2.dump(data, f)
83
+ ```
73
84
 
74
- With version 6.x the possibility of HCL2 reconstruction from the Lark Parse Tree and Python dictionaries directly was introduced.
85
+ **Building HCL from scratch:**
75
86
 
76
- Documentation and an example of manipulating Lark Parse Tree and reconstructing it back into valid HCL2 can be found in [tree-to-hcl2-reconstruction.md](https://github.com/amplify-education/python-hcl2/blob/main/tree-to-hcl2-reconstruction.md) file.
87
+ ```python
88
+ import hcl2
89
+
90
+ doc = hcl2.Builder()
91
+ res = doc.block("resource", labels=["aws_instance", "web"], ami="abc-123", instance_type="t2.micro")
92
+ res.block("tags", Name="HelloWorld")
93
+
94
+ hcl_string = hcl2.dumps(doc.build())
95
+ ```
96
+
97
+ For the full API reference, option dataclasses, intermediate pipeline stages, and more examples
98
+ see [docs/usage.md](https://github.com/amplify-education/python-hcl2/blob/main/docs/usage.md).
99
+
100
+ ### CLI Tools
101
+
102
+ python-hcl2 ships two command-line converters:
103
+
104
+ ```sh
105
+ # HCL2 → JSON
106
+ hcl2tojson main.tf # prints JSON to stdout
107
+ hcl2tojson main.tf output.json # writes to file
108
+ hcl2tojson terraform/ output/ # converts a directory
109
+
110
+ # JSON → HCL2
111
+ jsontohcl2 output.json # prints HCL2 to stdout
112
+ jsontohcl2 output.json main.tf # writes to file
113
+ jsontohcl2 output/ terraform/ # converts a directory
114
+ ```
77
115
 
78
- More details about reconstruction implementation can be found in PRs #169 and #177.
116
+ Both commands accept `-` as PATH to read from stdin. Run `hcl2tojson --help` or `jsontohcl2 --help` for the full list of flags.
79
117
 
80
118
  ## Building From Source
81
119
 
@@ -88,7 +126,7 @@ Running `tox` will automatically execute linters as well as the unit tests.
88
126
 
89
127
  You can also run them individually with the `-e` argument.
90
128
 
91
- For example, `tox -e py37-unit` will run the unit tests for python 3.7
129
+ For example, `tox -e py310-unit` will run the unit tests for python 3.10
92
130
 
93
131
  To see all the available options, run `tox -l`.
94
132
 
@@ -108,21 +146,10 @@ You can reach us at <mailto:github@amplify.com>
108
146
  We welcome pull requests! For your pull request to be accepted smoothly, we suggest that you:
109
147
 
110
148
  - For any sizable change, first open a GitHub issue to discuss your idea.
111
- - Create a pull request. Explain why you want to make the change and what its for.
149
+ - Create a pull request. Explain why you want to make the change and what it's for.
112
150
 
113
- Well try to answer any PRs promptly.
151
+ We'll try to answer any PR's promptly.
114
152
 
115
153
  ## Limitations
116
154
 
117
- ### Using inline expression as an object key
118
-
119
- - Object key can be an expression as long as it is wrapped in parentheses:
120
- ```terraform
121
- locals {
122
- foo = "bar"
123
- baz = {
124
- (format("key_prefix_%s", local.foo)) : "value"
125
- # format("key_prefix_%s", local.foo) : "value" this will fail
126
- }
127
- }
128
- ```
155
+ None that are known.
@@ -1,5 +1,4 @@
1
1
  [![Codacy Badge](https://app.codacy.com/project/badge/Grade/2e2015f9297346cbaa788c46ab957827)](https://app.codacy.com/gh/amplify-education/python-hcl2/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
2
- [![Build Status](https://travis-ci.org/amplify-education/python-hcl2.svg?branch=master)](https://travis-ci.org/amplify-education/python-hcl2)
3
2
  [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/amplify-education/python-hcl2/master/LICENSE)
4
3
  [![PyPI](https://img.shields.io/pypi/v/python-hcl2.svg)](https://pypi.org/project/python-hcl2/)
5
4
  [![Python Versions](https://img.shields.io/pypi/pyversions/python-hcl2.svg)](https://pypi.python.org/pypi/python-hcl2)
@@ -24,7 +23,7 @@ Learn more at <https://www.amplify.com>
24
23
 
25
24
  ### Prerequisites
26
25
 
27
- python-hcl2 requires Python 3.7 or higher to run.
26
+ python-hcl2 requires Python 3.8 or higher to run.
28
27
 
29
28
  ### Installing
30
29
 
@@ -36,19 +35,58 @@ pip3 install python-hcl2
36
35
 
37
36
  ### Usage
38
37
 
38
+ **HCL2 to Python dict:**
39
+
39
40
  ```python
40
41
  import hcl2
41
- with open('foo.tf', 'r') as file:
42
- dict = hcl2.load(file)
42
+
43
+ with open("main.tf") as f:
44
+ data = hcl2.load(f)
43
45
  ```
44
46
 
45
- ### Parse Tree to HCL2 reconstruction
47
+ **Python dict to HCL2:**
48
+
49
+ ```python
50
+ import hcl2
51
+
52
+ hcl_string = hcl2.dumps(data)
53
+
54
+ with open("output.tf", "w") as f:
55
+ hcl2.dump(data, f)
56
+ ```
46
57
 
47
- With version 6.x the possibility of HCL2 reconstruction from the Lark Parse Tree and Python dictionaries directly was introduced.
58
+ **Building HCL from scratch:**
48
59
 
49
- Documentation and an example of manipulating Lark Parse Tree and reconstructing it back into valid HCL2 can be found in [tree-to-hcl2-reconstruction.md](https://github.com/amplify-education/python-hcl2/blob/main/tree-to-hcl2-reconstruction.md) file.
60
+ ```python
61
+ import hcl2
62
+
63
+ doc = hcl2.Builder()
64
+ res = doc.block("resource", labels=["aws_instance", "web"], ami="abc-123", instance_type="t2.micro")
65
+ res.block("tags", Name="HelloWorld")
66
+
67
+ hcl_string = hcl2.dumps(doc.build())
68
+ ```
69
+
70
+ For the full API reference, option dataclasses, intermediate pipeline stages, and more examples
71
+ see [docs/usage.md](https://github.com/amplify-education/python-hcl2/blob/main/docs/usage.md).
72
+
73
+ ### CLI Tools
74
+
75
+ python-hcl2 ships two command-line converters:
76
+
77
+ ```sh
78
+ # HCL2 → JSON
79
+ hcl2tojson main.tf # prints JSON to stdout
80
+ hcl2tojson main.tf output.json # writes to file
81
+ hcl2tojson terraform/ output/ # converts a directory
82
+
83
+ # JSON → HCL2
84
+ jsontohcl2 output.json # prints HCL2 to stdout
85
+ jsontohcl2 output.json main.tf # writes to file
86
+ jsontohcl2 output/ terraform/ # converts a directory
87
+ ```
50
88
 
51
- More details about reconstruction implementation can be found in PRs #169 and #177.
89
+ Both commands accept `-` as PATH to read from stdin. Run `hcl2tojson --help` or `jsontohcl2 --help` for the full list of flags.
52
90
 
53
91
  ## Building From Source
54
92
 
@@ -61,7 +99,7 @@ Running `tox` will automatically execute linters as well as the unit tests.
61
99
 
62
100
  You can also run them individually with the `-e` argument.
63
101
 
64
- For example, `tox -e py37-unit` will run the unit tests for python 3.7
102
+ For example, `tox -e py310-unit` will run the unit tests for python 3.10
65
103
 
66
104
  To see all the available options, run `tox -l`.
67
105
 
@@ -81,21 +119,10 @@ You can reach us at <mailto:github@amplify.com>
81
119
  We welcome pull requests! For your pull request to be accepted smoothly, we suggest that you:
82
120
 
83
121
  - For any sizable change, first open a GitHub issue to discuss your idea.
84
- - Create a pull request. Explain why you want to make the change and what its for.
122
+ - Create a pull request. Explain why you want to make the change and what it's for.
85
123
 
86
- Well try to answer any PRs promptly.
124
+ We'll try to answer any PR's promptly.
87
125
 
88
126
  ## Limitations
89
127
 
90
- ### Using inline expression as an object key
91
-
92
- - Object key can be an expression as long as it is wrapped in parentheses:
93
- ```terraform
94
- locals {
95
- foo = "bar"
96
- baz = {
97
- (format("key_prefix_%s", local.foo)) : "value"
98
- # format("key_prefix_%s", local.foo) : "value" this will fail
99
- }
100
- }
101
- ```
128
+ None that are known.
@@ -0,0 +1,54 @@
1
+ """Used by dependencies_check.yml to verify if dependencies between pyproject.yml and requirements.txt are in sync"""
2
+ import sys
3
+ from typing import Set
4
+ import difflib
5
+ import tomli
6
+
7
+
8
+ def get_pyproject_deps() -> Set[str]:
9
+ with open("pyproject.toml", "rb") as f:
10
+ pyproject_data = tomli.load(f)
11
+ return set(pyproject_data.get("project", {}).get("dependencies", set()))
12
+
13
+
14
+ def get_requirements_deps() -> Set[str]:
15
+ result = set()
16
+ with open("requirements.txt", "r") as f:
17
+ for line in f:
18
+ line = line.strip()
19
+ if line and not line.startswith("#"):
20
+ result.add(line)
21
+ return result
22
+
23
+
24
+ def main():
25
+
26
+ pyproject_deps = get_pyproject_deps()
27
+ requirements_deps = get_requirements_deps()
28
+
29
+ pyproject_lines = list(sorted(pyproject_deps))
30
+
31
+ if pyproject_deps == requirements_deps:
32
+ print("All dependencies are in sync:")
33
+ for line in pyproject_lines:
34
+ print(line)
35
+ sys.exit(0)
36
+
37
+ print("Failed, dependencies mismatch:")
38
+ requirements_lines = list(sorted(requirements_deps))
39
+
40
+ diff = difflib.unified_diff(
41
+ pyproject_lines,
42
+ requirements_lines,
43
+ fromfile="pyproject.toml",
44
+ tofile="requirements.txt",
45
+ lineterm="",
46
+ )
47
+ for line in diff:
48
+ print(line)
49
+
50
+ sys.exit(1)
51
+
52
+
53
+ if __name__ == "__main__":
54
+ main()