Hello comtypesers!
Inspired by recent work and discussions in #947 and #949, I believe we must ensure this static typing quality directly in CI.
To guarantee reliable type inference moving forward, I propose to integrate static type checking into our CI pipeline.
I think that one of the defining strengths of comtypes is that it allows us to interact with COM interfaces as statically-typed Python classes generated via client.GetModule—a key differentiator from IDispatch-based libraries.
Along with this change, support for Python 3.9 will be dropped, making Python 3.10+ required.
What is the CI Type-Checking Setup?
To continuously verify that both statically defined modules and dynamically generated code expose correct types, I have set up a standalone type verification harness:
- Clean Installation Verification:
The workflow builds comtypes as an sdist, installs it into an isolated virtual environment (.venv), and verifies type hints against the installed package.
- Multi-Checker Coverage:
Different type checkers have different inference rules and strictness.
The CI job validates our code against type checkers.
- Targeted Typetests:
Under type-check/tests/, test cases explicitly exercise type inference across:
- Package typing export (
py.typed and public API visibility)
- Dynamically generated COM classes via
client.GetModule
Why Drop Python 3.9?
- Python 3.9 is Past EOL:
Python 3.9 reached its official End of Life (EOL) about a year ago.
- Ecosystem & Mypy 2.x Requirements:
Key dependencies and tooling in the typing ecosystem have moved on.
Specifically, mypy 2.x has already dropped support for Python 3.9.
Maintaining compatibility with 3.9 while running modern type checkers adds unjustified maintenance friction.
- Modern Type Syntax (
| via PEP 604):
Dropping Python 3.9 allows us to modernize all type annotations by adopting the standard pipe operator (int | str instead of Union[int, str], str | None instead of Optional[str]).
This improves readability across both hand-written modules and dynamically generated code.
Transition Plan & Phasing
To balance developer experience and backward compatibility, I plan to roll this out in phases:
- First Step: CI Type-Checking on Python 3.10+:
The type-checking CI pipeline will initially target Python 3.10 and newer (3.10, 3.11, 3.12, 3.13, 3.14).
- Runtime Support for Python 3.9:
For the time being, runtime compatibility with Python 3.9 will be maintained, and the A | B union syntax will NOT be introduced into the main codebase yet (standard unit tests will continue to run on Python 3.9).
- Post-1.5.0 Support Drop:
However, after the 1.5.0 release, Python 3.9 is very likely to be dropped from supported Python versions entirely.
I look forward to hearing your thoughts and feedback!
Hello
comtypesers!Inspired by recent work and discussions in #947 and #949, I believe we must ensure this static typing quality directly in CI.
To guarantee reliable type inference moving forward, I propose to integrate static type checking into our CI pipeline.
I think that one of the defining strengths of
comtypesis that it allows us to interact with COM interfaces as statically-typed Python classes generated viaclient.GetModule—a key differentiator fromIDispatch-based libraries.Along with this change, support for Python 3.9 will be dropped, making Python 3.10+ required.
What is the CI Type-Checking Setup?
To continuously verify that both statically defined modules and dynamically generated code expose correct types, I have set up a standalone type verification harness:
The workflow builds
comtypesas ansdist, installs it into an isolated virtual environment (.venv), and verifies type hints against the installed package.Different type checkers have different inference rules and strictness.
The CI job validates our code against type checkers.
Under
type-check/tests/, test cases explicitly exercise type inference across:py.typedand public API visibility)client.GetModuleWhy Drop Python 3.9?
Python 3.9 reached its official End of Life (EOL) about a year ago.
Key dependencies and tooling in the typing ecosystem have moved on.
Specifically,
mypy2.x has already dropped support for Python 3.9.Maintaining compatibility with 3.9 while running modern type checkers adds unjustified maintenance friction.
|via PEP 604):Dropping Python 3.9 allows us to modernize all type annotations by adopting the standard pipe operator (
int | strinstead ofUnion[int, str],str | Noneinstead ofOptional[str]).This improves readability across both hand-written modules and dynamically generated code.
Transition Plan & Phasing
To balance developer experience and backward compatibility, I plan to roll this out in phases:
The type-checking CI pipeline will initially target Python 3.10 and newer (
3.10,3.11,3.12,3.13,3.14).For the time being, runtime compatibility with Python 3.9 will be maintained, and the
A | Bunion syntax will NOT be introduced into the main codebase yet (standard unit tests will continue to run on Python 3.9).However, after the
1.5.0release, Python 3.9 is very likely to be dropped from supported Python versions entirely.I look forward to hearing your thoughts and feedback!