Skip to content

chore(python): support CPython 3.14 - #371

Open
devgtv wants to merge 6 commits into
AlertaDengue:mainfrom
devgtv:chore/support-python-314
Open

devgtv wants to merge 6 commits into
AlertaDengue:mainfrom
devgtv:chore/support-python-314

Conversation

@devgtv

@devgtv devgtv commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Summary

The <3.14 cap was the only thing keeping 3.14 out. No application code changes are needed — the suite passes unchanged on all four interpreters, with the locked dependency versions.

Interpreter Result
CPython 3.11.17 1780 passed, 6 skipped, 15 warnings
CPython 3.12.15 1780 passed, 6 skipped, 15 warnings
CPython 3.13.16 1780 passed, 6 skipped, 15 warnings
CPython 3.14.7 1780 passed, 6 skipped, 22 warnings

Identical counts across the matrix. The tree uses nothing removed since 3.11: no distutils, pkg_resources, imp, utcnow(), utcfromtimestamp(), or bare get_event_loop().

What changed

File Change
pyproject.toml python = ">=3.11,<3.14" → >=3.11,<3.15
pyproject.toml (dev) black ^22.6.0 → ^24.2.0, flake8 ^5.0.4 → ^7.0.0
.github/workflows/python-package.yml matrix "3.11","3.12","3.13" → adds "3.14"
.pre-commit-config.yaml flake8-implicit-str-concat==0.4.0 → ==0.6.0
conda/dev.yaml python>=3.11,<3.14 → <3.15
poetry.lock regenerated — only black, flake8, pycodestyle, pyflakes move

Every runtime dependency keeps its resolved version (numpy 2.4.6, pandas 2.3.3, pyarrow 24.0.0 on all four). numpy already carried a python_version == "3.11" split and needed no new marker.

Two dev tools were broken on 3.12+

Both fail for the same reason: they touch ast.Str, which no longer exists.

black 22.12.0 — what the ^22.6.0 dev pin resolved to — aborts with cannot format: module 'ast' has no attribute 'Str' on five files (api/types.py, api/metadata/columns.py, cli/configure.py, tests/api/test_databases.py, tests/api/ducklake/test_adapters.py). Already broken on 3.12/3.13 today; 3.14 just makes it universal.

flake8-implicit-str-concat 0.4.0 is the blocker for CI specifically. It raises the same AttributeError out of flake8's multiprocessing pool, taking down the whole run. Since it is the hook the Linting step runs, a 3.14 matrix entry would have gone red before reaching the tests. 0.6.0 is the first release that works.

Why the plugin is pinned to ==0.6.0

0.7.0 also runs on 3.14, but it adds an ISC004 check that flags eight existing implicit concatenations in api/saude/databases.py. Those are a separate concern, so the pin stays at the oldest release that unblocks 3.14 — and it is pinned exactly, like every other plugin in that file, so a pre-commit autoupdate cannot silently shift the result.

I verified the real CI lint command (pre-commit run --files pysus/**/*) end to end on 3.14: all ten hooks pass, including black, flake8 and mypy.

CI on this PR

All green, including both new 3.14 entries:

tests (ubuntu-latest,  3.11/3.12/3.13/3.14)   pass
tests (windows-latest, 3.11/3.12/3.13/3.14)   pass
docs                                          pass
docker-tests                                  pass

docker-tests passing matters too: the Dockerfile is still on 3.12, and this confirms nothing in the dependency changes broke the image build or the suite inside it.

Not included, deliberately

  • Dockerfile stays on python:3.12-slim. 3.12 is still supported and I could not build the image here to verify. Worth a follow-up.
  • .readthedocs.yaml stays on 3.11 — docs builds do not need the newest interpreter.
  • api/metadata/columns.py is left as-is despite four pre-existing lint findings and a black diff, all from 0048008 (fix: improve metadata group discovery and loading #348).

Follow-up worth filing separately

The CI lint step runs pre-commit run --files pysus/**/*. Without globstar, that glob expands to the files at depth 2 only — 96 paths, against 208 tracked .py files. pre-commit discards the directories it matches and flake8 therefore never recurses into them, so api/metadata/columns.py and tests/cli/test_dadosgov.py are never linted. That is why columns.py has sat in main with whitespace problems, and test_dadosgov.py with two ISC001 hits, while CI stayed green.

Fixing the glob would suddenly lint ~208 files and surface a backlog, so it deserves its own PR rather than riding along here.

The cap on the interpreter was the only thing keeping 3.14 out. No
application code changes are needed: the suite passes unchanged on
3.14.7 with the locked dependency versions (1780 passed, 6 skipped),
and the tree uses nothing that has been removed since 3.11 -- no
distutils, pkg_resources, imp, utcnow(), or bare get_event_loop().

Two dev tools did need fixing, both for the same reason: they touch
ast.Str, which no longer exists on 3.12+. black 22.12 (what the
`^22.6.0` dev pin resolved to) aborts with "cannot format: module 'ast'
has no attribute 'Str'" on five files, and flake8-implicit-str-concat
0.4.0 takes down the whole flake8 run from its multiprocessing pool.
The latter is the pre-commit hook CI actually runs, so a 3.14 matrix
entry would have gone red at the Linting step before reaching the tests.

flake8-implicit-str-concat is capped at >=0.6.0, the first release that
works on 3.14. 0.7.0 would also run, but it adds an ISC004 check that
flags eight existing implicit concatenations in saude/databases.py, which
is out of scope here.

The lock moves only black, flake8, pycodestyle and pyflakes. Every
runtime dependency keeps its resolved version; numpy already carried a
python_version == "3.11" split and needs no new marker.
@codecov-commenter

codecov-commenter commented Oct 2, 2026 •

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (main@9db5915). Learn more about missing BASE report.
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #371   +/-   ##
=======================================
  Coverage        ?   97.20%           
=======================================
  Files           ?      180           
  Lines           ?    23286           
  Branches        ?        0           
=======================================
  Hits            ?    22635           
  Misses          ?      651           
  Partials        ?        0           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

devgtv added 5 commits October 2, 2026 17:50
The previous commit used `>=0.6.0`, which resolves to 0.7.0. That
version works on 3.14 too, but it adds an ISC004 check that flags eight
existing implicit concatenations in api/saude/databases.py. Confirmed by
running the lint under 3.11, 3.12, 3.13 and 3.14.

Pin it exactly, matching the style of every other plugin in this file, so
the lint result cannot shift underneath us the next time pre-commit
autoupdate runs. 0.6.0 is the oldest release that does not crash on 3.14,
and it reports no findings the newer ones would flag.
- Fix trailing/extra blank lines and comment indentation in
  `pysus/api/metadata/columns.py` (pre-existing whitespace from AlertaDengue#348)
- Wrap long endpoint strings in `pysus/api/saude/databases.py` to satisfy
  flake8 E501 while keeping values identical and ISC004 clean. Also
  validates with black 24.2.
ISC004 findings were resolved (endpoint strings wrapped to avoid implicit
concatenation in collections or made single-line as needed), so we can
adopt 0.7.0 without new warnings.

This branch has not been deployed

No deployments
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