Skip to content

feat: Add support Python 3.15 and lazy imports - #211

Open
Daverball wants to merge 4 commits into
mainfrom
feat/py315
Open

Daverball wants to merge 4 commits into
mainfrom
feat/py315

Conversation

@Daverball

@Daverball Daverball commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator

Python 3.15 adds lazy imports which provide a new way to reduce the import overhead of type hints. It is however not as reliable, since inspecting __annotations__ will always trigger the lazy imports for symbols used in annotations, even if a format like annotationlib.Format.FORWARDREF is used and there is no way to inspect it in a different way that doesn't trigger the imports.

Nevertheless we want to recognize lazy imports and not push people away from them, so for the purposes of TC001, TC002 and TC003 these imports are ignored, just like existing imports inside type checking blocks are. On the contrary we will never flag lazy imports with TC004 or intend to add a similar rule for lazy imports, since there's both many other reasons why you may want the import to be lazy (like breaking import cycles, without putting the import into a function) and no clear indication for when deferred annotations will be inspected, so we mostly couldn't tell when the lazy imports will be triggered anyways. We instead defer the management of lazy imports to other existing linters like flake8-lazy and ruff, which both provide dedicated rules for managing them and should work well hand in hand with flake8-type-checking in this mode.

For good interoperability between flake8-lazy and flake8-type-checking we support their f-string based way of putting relative imports into __lazy_modules__, since otherwise there's no reliable way to map relative imports to the absolute names used in __lazy_modules__, without adding a lot of code, configuration options and overhead to determine the parent module(s) of the file we're linting.

There are a couple of new settings related to lazy imports. Please refer to the README for when and how to use them.

This also drops support for Python 3.10 which will reach its EOL at the end of October (this also seems like a good opportunity for us to refactor some our AST traversal code into match statements, which are well suited for this task).


This also adds zizmor as a security linter for our GitHub Actions workflows. I used actions-up to update and pin the workflows to their current latest version in order to comply with zizmor's recommendations.

@codecov

codecov Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.15152% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.0%. Comparing base (9a76be3) to head (604e4cc).

Files with missing lines Patch % Lines
flake8_type_checking/checker.py 95.0% 8 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##            main    #211     +/-   ##
=======================================
+ Coverage   96.5%   97.0%   +0.4%     
=======================================
  Files          4       4             
  Lines        968    1000     +32     
=======================================
+ Hits         935     970     +35     
+ Misses        33      30      -3     
Files with missing lines Coverage Δ
flake8_type_checking/constants.py 100.0% <100.0%> (ø)
flake8_type_checking/plugin.py 100.0% <100.0%> (ø)
flake8_type_checking/checker.py 96.7% <95.0%> (+0.4%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Daverball
Daverball requested a review from sondrelg September 24, 2026 07:37
@Daverball
Daverball force-pushed the feat/py315 branch 2 times, most recently from 00bd6a8 to e7bd178 Compare September 24, 2026 09:51
@Daverball

Copy link
Copy Markdown
Collaborator Author

@sondrelg Do you think you could take a quick look at what's being proposed here? (I don't think this needs an in-depth line-by-line review, but if you want to do that, I recommend looking at the individual commits separately, to get a cleaner diff) That way we could have this ready in time for the release of Python 3.15

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.

1 participant