Skip to content

Terraform: upgrade python-hcl2 to 8.1.4 - #23740

Merged
tdyas merged 1 commit into
pantsbuild:mainfrom
adamcrews:terraform/python-hcl2-8
Nov 5, 2026
Merged

tdyas merged 1 commit into
pantsbuild:mainfrom
adamcrews:terraform/python-hcl2-8

Conversation

@adamcrews

@adamcrews adamcrews commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Upgrade the python-hcl2 version bundled with the terraform-hcl2-parser subsystem from 4.3.0 to 8.1.4.

4.3.0 rejects some valid Terraform, and one unparseable file fails dependency inference for its whole terraform_module. 8.1.4 parses all of these:

python-hcl2 8.x keeps the quotes around string values by default, so source = "./foo" comes back as "\"./foo\"". With the current hcl2_parser.py, that means no source ever looks like a local path, and Pants silently infers no module dependencies at all. The parser now passes SerializationOptions(strip_string_quotes=True). default_requirements is now python-hcl2>=8.1.4,<9, and hcl2.lock was regenerated with generate_builtin_lockfiles.py, which also adds regex, a new dependency of 8.x.

As suggested in review, older releases are deprecated for one version instead of being dropped right away. A resolve set with [terraform-hcl2-parser].install_from_resolve can still provide python-hcl2 older than 8.0. Those releases have no SerializationOptions and strip the quotes themselves, so the parser falls back to plain hcl2.loads(content) and prints a marker to stderr. When dependency inference sees the marker, it logs a deprecation warning, scheduled for removal in 2.35.0.dev0, that tells users to upgrade that resolve to 8.1.4 or newer. docs/notes/2.34.x.md covers both the upgrade and the deprecation.

Pants pinned 4.3.0 in #21361 because of parse regressions in 4.3.1+. To check for regressions, I ran the patched parser over a private codebase with ~900 .tf files. 8.1.4 inferred the same 106 module dependencies as 4.3.0 and parsed every file that belongs to a terraform_module.

Testing:

  • New test test_hcl_parser_handles_keywords_and_multiline_conditionals parses the three constructs above with the bundled 8.1.4.
  • test_hcl_parser_wrapper_runs passes on Python 3.10 through 3.14. It and the new test also check that 8.1.4 isn't reported as a deprecated release.
  • In hcl2_parser_test.py, test_main_strips_string_quotes and test_main_falls_back_for_legacy_hcl2 use stand-in hcl2 modules to check that the parser asks 8.x to strip quotes, and that it falls back and prints the marker for releases without SerializationOptions.
  • test_warn_if_legacy_hcl2 checks that the marker produces the deprecation warning.
  • pants fmt lint check passes on the changed files.

This code was generated with Claude code, however I am using this on my internal systems and so far it is working well in my pipelines.

@adamcrews
adamcrews force-pushed the terraform/python-hcl2-8 branch 2 times, most recently from a33468d to 826b6f4 Compare October 30, 2026 22:55

@tdyas tdyas left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for fixing!

Would it make sense to just require the newer version and thus avoid the need to check for SerializationOptions?

@adamcrews

Copy link
Copy Markdown
Contributor Author

Thanks for fixing!

Would it make sense to just require the newer version and thus avoid the need to check for SerializationOptions?

Yeah, probably. I was a little worried about breaking anyone that had this pinned, but with other similar breaking changes it looks like the pattern is to just leave a note in the release notes/upgrade instructions. I'll rework this a bit to pin to the current version or better.

@tdyas

tdyas commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

Thanks for fixing!
Would it make sense to just require the newer version and thus avoid the need to check for SerializationOptions?

Yeah, probably. I was a little worried about breaking anyone that had this pinned, but with other similar breaking changes it looks like the pattern is to just leave a note in the release notes/upgrade instructions. I'll rework this a bit to pin to the current version or better.

We could also deprecate for one version, and then remove in the subsequent version. Maybe add a deprecation warning using pants.base.deprecated.warn_or_error?

@adamcrews
adamcrews force-pushed the terraform/python-hcl2-8 branch 4 times, most recently from fd0f6cf to 082104a Compare November 2, 2026 23:16
@adamcrews

adamcrews commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor Author

We could also deprecate for one version, and then remove in the subsequent version. Maybe add a deprecation warning using pants.base.deprecated.warn_or_error?

I reworked things to use the deprecation code/messaging. I'm happy with this current state and I think this is good to go now.

@adamcrews
adamcrews requested a review from tdyas November 3, 2026 19:36

# Printed to stderr when the installed python-hcl2 is older than 8.0, so that Pants can warn that
# support for it is deprecated.
LEGACY_HCL2_MARKER = "__pants_legacy_python_hcl2__"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be a bytes b"" constant and then the various LEGACY_HCL2_MARKER.encode() calls can be avoided.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just the change and the PR otherwise looks good to go.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed & pushed.

python-hcl2 8.x keeps the quotes around string values unless
`SerializationOptions(strip_string_quotes=True)` is passed, so the parser
script now passes it. Without it, module `source` values never matched a
local path and no module dependencies were inferred.

Raise the default requirement to `python-hcl2>=8.1.4,<9` and upgrade the
bundled lockfile from 4.3.0 to 8.1.4, the first 8.x release that parses
`for` as an attribute name (pantsbuild#21845), `in` as a block name (pantsbuild#22401), and
conditional expressions split over multiple lines.

A resolve set with `[terraform-hcl2-parser].install_from_resolve` can
still provide a python-hcl2 release older than 8.0, but that is
deprecated: the parser falls back to the old API, which has no
`SerializationOptions`, and Pants logs a deprecation warning. Support is
scheduled for removal in 2.35.0.dev0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@adamcrews
adamcrews force-pushed the terraform/python-hcl2-8 branch from 082104a to 028ef85 Compare November 4, 2026 17:55
@adamcrews
adamcrews requested a review from tdyas November 4, 2026 18:00
@tdyas
tdyas merged commit 24f9d99 into pantsbuild:main Nov 5, 2026
28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants