Python Compatibility & Runtime Matrix

This document defines the formal Python runtime compatibility matrix for findfmt, detailing verified runtimes, dependency constraints, language-level requirements, and technical justifications across Python 3.6 through 3.16.


1. Compatibility Overview & Runtime Matrix

findfmt enforces requires-python = ">=3.11". The runtime compatibility status across modern and legacy Python interpreters is summarized below:

Python Version

Release / EOL Status

Tested on Fedora 44

Build & CLI Execution

Test Suite & 100% Coverage

Compatibility Verdict & Primary Rationale

3.6

EOL (Dec 2021)

Yes (3.6.15)

Blocked

N/A

Unsupported: Missing @dataclass(slots=True); identify>=2.6 and typer>=0.12 drop 3.6; lacks runtime PEP 604 type support.

3.7

EOL (Jun 2023)

N/A

Blocked

N/A

Unsupported: Missing @dataclass(slots=True); identify>=2.6 and typer>=0.12 drop 3.7.

3.8

EOL (Oct 2024)

N/A

Blocked

N/A

Unsupported: Missing @dataclass(slots=True); identify>=2.6.2 drops 3.8; lacks standard library typing.Annotated.

3.9

EOL (Oct 2025)

Yes (3.9.25)

Blocked

N/A

Unsupported: @dataclass(slots=True) raises TypeError; identify>=2.6.16 and typer>=0.24 require >=3.10; runtime PEP 604 reflection fails.

3.10

EOL (Oct 2026)

Yes (3.10.21)

Blocked

N/A

Unsupported: Reached EOL on 2026-10-01; required the tomli and typing_extensions.Self shims; security fixes for dependencies such as filelock no longer support 3.10.

3.11

Security (to Oct 2027)

Yes (3.11.16)

Passed

Passed

Supported (Minimum): Baseline runtime and wheel smoke test; native tomllib (PEP 680) and typing.Self (PEP 673); typing.override (PEP 698) still comes from typing-extensions.

3.12

Bugfix / Security

Yes (3.12.14)

Passed

Passed

Supported: Full native support; standard CI testing target.

3.13

Bugfix / Security

Yes (3.13.15)

Passed

Passed

Supported: Full native support; gating CI on Linux, macOS, and Windows.

3.14

Bugfix

Yes (3.14.8)

Passed

Passed

Supported: Container image runtime (python:3.14-slim-bookworm); gating CI on Linux, macOS, and Windows.

3.15

Current (Bugfix)

Yes (3.15.0)

Passed

Passed

Supported (Maximum): Primary target for the CI quality gate, docs build, release, and wheel smoke test; gating CI on Linux, macOS, and Windows; PyPI Trove classifier active.

3.16

Future (Oct 2027)

N/A

N/A

Non-gating CI

Not advertised (Preview): Experimental 3.16-dev CI job that never blocks a merge; no Trove classifier until 3.16.0 ships and is certified.


2. Minimum Python Version Analysis (3.6 – 3.10)

2.1. Upstream Dependency Ecosystem Floors

A critical factor in determining the minimum supported runtime is the upstream dependency ecosystem:

  1. identify (pre-commit team):

    • identify>=2.6.16 explicitly specifies requires-python = ">=3.10".

    • Versions 2.6.2 to 2.6.15 require >=3.9.

    • Versions 2.6.0 to 2.6.1 require >=3.8.

    • No version within the identify>=2.6 range supports Python 3.6 or 3.7. Attempting to install dependencies on Python 3.6 fails immediately at the resolver stage.

  2. typer (CLI Framework):

    • typer>=0.24.0 specifies requires-python = ">=3.10".

    • typer>=0.21.0 requires >=3.9.

    • typer>=0.19.2 requires >=3.8.

    • Python 3.6 is unsupported by any modern Typer release.

  3. pathspec & rich:

    • pathspec>=0.12 requires Python >=3.8.

    • rich releases drop Python <3.8 and leverage modern terminal and typing enhancements.

2.2. Language Features and Runtime Typing Constraints

  1. @dataclass(slots=True) (PEP 557 / PEP 654):

    • src/findfmt/models.py defines core data structures (FileInfo, TraversalStats) using @dataclass(frozen=True, slots=True) for high performance and reduced memory footprint.

    • The slots argument was introduced in Python 3.10. On Python 3.9 and earlier, invoking @dataclass(slots=True) raises TypeError: dataclass() got an unexpected keyword argument 'slots'.

  2. PEP 604 Union Syntax (str | None, Path | str):

    • While from __future__ import annotations postpones evaluation of type annotations in standard code on Python 3.7+, frameworks like Typer and Click inspect type annotations at runtime to construct CLI options and type coercion logic.

    • Evaluating union syntax (str | None) at runtime in Python 3.9 and earlier triggers TypeError: unsupported operand type(s) for |: 'type' and 'type'.

  3. Standard Library Configuration Parsing:

    • Python 3.11+ includes tomllib (PEP 680) in the standard library, so findfmt imports it directly. The tomli shim that Python 3.10 required has been removed.

  4. typing.Self (PEP 673):

    • Python 3.11+ provides typing.Self, which findfmt uses for context-manager return types. The typing_extensions.Self fallback that Python 3.10 required has been removed.

    • typing.override (PEP 698) only arrived in Python 3.12, so typing-extensions remains a dependency on Python 3.11.

2.3. Tooling and Linter Floors

The project’s verification suite relies on modern developer tooling:

  • sphinx>=8 requires Python >=3.10.

  • deptry>=0.20 requires Python >=3.10.

  • ty>=0.0.80, radon, xenon, and vulture require modern AST parsers and Python >=3.10.

2.4. Maintenance Cost vs. Upstream EOL Status

  • Python 3.6 reached End-of-Life (EOL) in December 2021.

  • Python 3.7 reached EOL in June 2023.

  • Python 3.8 reached EOL in October 2024.

  • Python 3.9 reached EOL in October 2025.

  • Python 3.10 reached EOL on October 1, 2026.

  • Python 3.11 is the oldest currently maintained Python version receiving security updates (through October 2027).

Supporting Python < 3.10 would require downgrading data models, discarding slots=True, introducing verbose typing.Union constructs, and freezing dependencies to outdated versions with unpatched vulnerabilities. Python 3.10 itself no longer receives security fixes, and dependencies have started shipping security fixes only for Python 3.11+ (for example, filelock 4.2.1). Supporting it would also keep the tomli and typing_extensions.Self shims alive. Therefore, requires-python = ">=3.11" is technically sound and necessary.


3. Modern & Future Python Certification (3.15 – 3.16)

3.1. Python 3.15 Certification

Python 3.15 is the maximum supported version and a certified tier-1 runtime:

  • CI Quality Gate: Serves as the Python version for the quality-gate, documentation build, and release verification and build jobs in GitHub Actions. The packaging smoke test installs the built wheel on both the minimum (3.11) and maximum (3.15) versions.

  • CI Test Matrix: Runs as a gating python-version: '3.15' job on ubuntu-latest, macos-latest, and windows-latest, and uploads coverage like the other supported versions.

  • Local Testing: Verified under Fedora 44 with CPython 3.15.0: all 904 unit and integration tests pass with 100.00% statement and branch coverage, including with DeprecationWarning treated as an error. The full quality gate (tools/verify_quality.py) and the strict Sphinx build also pass.

  • Trove Classifier: Officially published on PyPI as Programming Language :: Python :: 3.15, and pyproject-fmt --max-supported-python is set to 3.15.

3.2. Python 3.16 Preview

Python 3.16 (first release scheduled for October 2027) is tracked only as a preview that gives early warning:

  • CI Test Matrix: Runs as an experimental 3.16-dev job on ubuntu-latest that may use pre-release interpreters, never blocks a merge, and skips the Codecov upload. Until a 3.16 build is available on the runners, the job reports a warning and skips the test run.

  • Trove Classifier: Not published until Python 3.16.0 is released and certified.


4. Multi-Platform CI Matrix

Automated verification runs across all certified runtimes and operating systems. Every advertised version (3.11–3.15) is a gating job on all three operating systems. The next feature release runs as an experimental 3.16-dev job: it may use pre-release interpreters, never blocks a merge, skips the Codecov upload, and is not advertised with a Trove classifier. Until a 3.16 build is available on the runners, the job reports a warning and skips the test run instead of falling back to the runner’s default Python.

matrix:
  os: [ubuntu-latest, macos-latest, windows-latest]
  python-version: ['3.11', '3.12', '3.13', '3.14', '3.15']
  include:
    - os: ubuntu-latest
      python-version: 3.16-dev
      experimental: true

5. Python Version Support Lifecycle

findfmt supports every CPython feature release from the oldest version still receiving security fixes to the newest stable release, and tests the next release early without advertising it. Each change below is guarded by tests/unit/test_python_support_policy.py, so a partial update fails CI.

5.1. When the Oldest Version Reaches End of Life

  1. Raise requires-python in pyproject.toml, remove the old Trove classifier, and raise ruff’s target-version. Re-lock with uv lock and regenerate .clusterfuzzlite/requirements.txt.

  2. Remove the version from the test-matrix in .github/workflows/ci.yml, and remove compatibility code that only the old version needed (sys.version_info guards and fallback imports). In the packaging-smoke-test job, raise the minimum python-version and the Python that pip must refuse.

  3. Just before merging, remove the three Test (<os> - Python <old>) required status checks from branch protection on main. Otherwise the pull request waits for checks that no longer run.

  4. Update the supported range in this guide, docs/source/quality/index.md, CONTRIBUTING.md, SECURITY.md, and assets/social-preview.svg (then regenerate the PNG), regenerate the documentation catalogs (make -C docs intl-update), and record the change as breaking in the changelog. Python 3.10 was dropped this way in #441.

5.2. When a New Version Is Released

  1. Move the version from the experimental <version>-dev matrix entry into the gating python-version list, and point the experimental entry at the next feature release.

  2. Add the new Trove classifier and raise pyproject-fmt --max-supported-python in .pre-commit-config.yaml.

  3. Move the single-interpreter jobs (quality gate, documentation, and release) and the maximum python-version of the packaging smoke test to the new version once the toolchain passes on it. Update the container image when matching uv builder and Python runtime images exist for the same Debian release.

  4. After the new jobs report green, add the three Test (<os> - Python <new>) checks to the required status checks on main. Never require the experimental job.

  5. Update the docs as in step 4 of §5.1. Python 3.15 was added this way in #335 and #440.