Skip to content

Python 3.13 and 3.14 support (re-lands #88), and a 6x faster import - #90

Merged
maxipavlovic merged 5 commits into
masterfrom
fix/python-3.13-3.14-and-import-time
Nov 3, 2026
Merged

maxipavlovic merged 5 commits into
masterfrom
fix/python-3.13-3.14-and-import-time

Conversation

@maxipavlovic

Copy link
Copy Markdown
Member

What

Why

  • On Python 3.13, a list comprehension over a ResourceSet raises TypeError: 'ResourceIterator' object is not iterable. The existing iteration tests fail there, and so does connect-cli.
  • import connect.client took 1.2 s, almost all of it inflect, and every extension, report and CLI command pays it.

Key decisions

How it worked before / after

master this PR
Python 3.13 list comprehensions over results fail work
Python 3.14 lint can't run lint and tests pass
import connect.client (3.13, M1 Pro) 1,165 ms 196 ms

Locally, lint is clean and 410 tests pass on Python 3.10, 3.13 and 3.14.

pcaro and others added 3 commits November 1, 2026 11:27
Extend the CI build matrix and PyPI trove classifiers to cover Python
3.13 and 3.14.

Two runtime issues surfaced on the new versions and are fixed here:

- Python 3.13+ enforces that an object returned by __iter__ must itself
  be a proper iterator (i.e. define __iter__). AbstractIterator and
  AbstractAsyncIterator only defined __next__/__anext__, so iterating a
  ResourceSet raised 'ResourceIterator object is not iterable'. Add
  __iter__/__aiter__ returning self.

- httpcore 1.0.6 crashed at import on Python 3.14 (setting __module__ on
  typing.Union). Bump httpcore 1.0.6 -> 1.0.9 (and h11 0.14 -> 0.16) in
  the lock file; both are transitive deps, so no pyproject change needed.

All 407 tests pass on 3.12, 3.13 and 3.14.

(cherry picked from commit 6353e58)
help_formatter imported inflect at module level, and inflect takes most of a
second to import. So every `import connect.client` paid it, and with it every
extension, report and CLI command, although only the help of a resource uses
it: on Python 3.13, `import connect.client` took 1,165 ms. It now takes
196 ms. A test checks that importing the client leaves inflect unimported.
The test matrix now includes Python 3.14, where flake8 could not run:

- flake8-future-import uses ast.Str, which Python 3.14 removed. It goes: its
  last release is from 2022, its FI1 codes are on the ignore list, and code
  that requires Python 3.10 needs no __future__ imports.
- flake8-bugbear was capped below 23, and those releases crash on Python
  3.14's syntax tree. It now requires 24 or newer, as in connect-cli.

The newer bugbear flags one test that expected any Exception (B017). It now
matches the error the test raises. No other locked version changes.
Loading inflect lazily added a branch to format_resource and took its
cognitive complexity to 16, one over Sonar's limit of 15. The lazy load moves
into a small _singular helper. Behaviour is unchanged.
Sonar (python:S5778) flagged four exception tests that also ran their setup
inside pytest.raises, so a setup error of the same type would have passed
them. The setup now runs first. The test whose mocked request is meant not to
match starts and resets the mocker itself, so the unused mock isn't reported.
@sonarqubecloud

sonarqubecloud Bot commented Nov 2, 2026

Copy link
Copy Markdown

@arnaugiralt arnaugiralt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

lgtm

@pcaro pcaro 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.

lgtm

@maxipavlovic
maxipavlovic merged commit a846a1c into master Nov 3, 2026
10 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.

3 participants