Skip to content

feat: declare and test support for Python 3.14 - #360

Merged
kkozik-amplify merged 3 commits into
mainfrom
feat-python_314_support
Sep 21, 2026
Merged

kkozik-amplify merged 3 commits into
mainfrom
feat-python_314_support

Conversation

@kkozik-amplify

@kkozik-amplify kkozik-amplify commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator

Summary

Python 3.14 is out and the package already works on it — all 1534 tests pass on 3.14.2 with no
source changes. This adds the trailing metadata so that support is declared on PyPI and enforced
in CI, rather than being true by accident.

Independent of the hcl2.cli move in #359; either can merge first.

Changes

  • Added the Programming Language :: Python :: 3.14 classifier to pyproject.toml.
    requires-python stays >=3.8.0, so no floor moves.
  • Added {py314}-unit to the tox envlist and a 3.14: py314-unit entry to the [gh-actions]
    mapping.
  • Added '3.14' to the pr_check.yml test matrix.
  • Bumped actions/setup-python from @v4 to @v5 in pr_check.yml. Left as a plain tag
    deliberately — Renovate SHA-pins uses: refs on its next run.
  • Excluded bare _children_layout: annotations from coverage in .coveragerc (see below).
  • Changelog entry under Unreleased.

No source changes.

Why the coverage config had to change

The first 3.14 run failed with every test passing: Ran 1534 tests ... FAILED, no failure or
error counts. The culprit was the coverage gate, not the suite.

Python 3.14 implements PEP 649, which defers evaluation of
annotations. A bare class-level annotation like _children_layout: Tuple[...] — used 45 times
across hcl2/rules/ and documented in CLAUDE.md as "annotation only, no assignment" — is no
longer executed during class-body evaluation; it is compiled into a lazily-invoked __annotate__
function. Coverage therefore stops counting those lines as executed:

statements missed total coverage
3.13 3956 112 95.519%
3.14 3956 156 94.712%

.coveragerc sets fail_under = 95, so 3.14 tripped it by 0.3pp and nose2's coverage plugin
marked the run unsuccessful — which surfaces as a bare FAILED with no failing test, since the
plugin sets event.success = False without adding anything to a report category.

These annotations are type declarations with no runtime behaviour, so counting them as executed
statements was always an artifact of pre-PEP-649 semantics. Excluding them makes the metric
version-independent — after the change 3.9, 3.13 and 3.14 all land at 95.4–96%.

Test plan

Verified against real interpreters using the exact CI command (nose2 --config tox.ini), not
python -m unittest:

  • 3.14.2 — Ran 1534 tests ... OK, exit 0, coverage 95.387%
  • 3.13 — Ran 1534 tests ... OK, exit 0, coverage 95.487%
  • 3.9 (low end of the matrix) — Ran 1534 tests ... OK, exit 0, coverage 96%
  • Confirmed the exclusion matches only the 43 _children_layout statements (3956 → 3913),
    not any executable code
  • GITHUB_ACTIONS=true tox -l under 3.14 resolves to exactly py314-unit
  • lark 1.3.1 and regex 2026.9.10 install cleanly on 3.14
  • bin/check_deps.py passes

Note: the 3.14 leg builds coverage from source — test-requirements.txt pins
coverage>=6.5,<7 and 6.5.0 has no cp314 wheel. It compiles fine, but adds a build step.

Follow-ups, out of scope here

  • .coveragerc omits cli/__init__.py. Once fix: move the CLI into the hcl2 namespace (cli → hcl2.cli) #359 lands that path is hcl2/cli/__init__.py, and
    the omit silently stops matching. Whichever PR merges second should fix it.
  • dependencies_check.yml still uses actions/setup-python@v4, publish.yml still uses @v2,
    and all three workflows check out with actions/checkout@master.

🤖 Co-Authored-By: Claude Opus 5 (1M context) Claude Code

The full suite passes on 3.14 unchanged, so this only adds the classifier,
the tox env, and the CI matrix entry.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@kkozik-amplify
kkozik-amplify requested a review from a team as a code owner September 21, 2026 10:12
kkozik-amplify and others added 2 commits September 21, 2026 12:15
v4 is old enough that provisioning 3.14 is not a safe assumption.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Python 3.14 implements PEP 649, so a bare `_children_layout:` class
annotation is no longer evaluated at class-body time and coverage stops
counting it as executed. That dropped the total from 95.5% to 94.7% and
tripped fail_under=95, failing the 3.14 job with every test passing.
These are type declarations with no runtime behaviour, so excluding them
makes the metric version-independent: 3.9/3.13/3.14 now agree.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@kkozik-amplify
kkozik-amplify merged commit 8a6b2ec into main Sep 21, 2026
10 checks passed
@kkozik-amplify
kkozik-amplify deleted the feat-python_314_support branch September 21, 2026 12:26
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