-
Type:
Task
-
Resolution: Unresolved
-
Priority:
Major - P3
-
None
-
Affects Version/s: None
-
Component/s: Typing
-
None
-
Python Drivers
-
None
-
None
-
None
-
None
-
None
-
None
Context
PyMongo ships py.typed, so a consumer's type checker reads our annotations. One that also reports library-code errors, such as mypy --no-silence-site-packages, gets errors originating inside pymongo and bson rather than in its own code. Reproduce against a plain install:
python -m venv /tmp/c && /tmp/c/bin/pip install pymongo mypy
printf 'from pymongo import MongoClient\n' > /tmp/app.py
/tmp/c/bin/python -m mypy --no-silence-site-packages /tmp/app.py
Most of the errors are imports of optional dependencies a consumer has no reason to install. One example, which also shows an existing suppression that names the wrong error code and therefore suppresses nothing:
pymongo/compression_support.py:31: error: Cannot find implementation or library stub for module named "snappy" [import-not-found] pymongo/compression_support.py:31: note: Error code "import-not-found" not covered by "type: ignore[import-untyped]" comment
The remediation is an inline suppression naming the code mypy actually reports, paired with unused-ignore so it does not itself fail in our typing environment, where the optional packages are installed. PYTHON-6032 did this for _otel.py:
from opentelemetry import context, trace # type:ignore[import-not-found,unused-ignore]
A minority of the errors are real annotation gaps rather than missing imports, and should be fixed rather than suppressed.
Our own CI cannot catch any of this: just typing installs every extra and applies the ignore_missing_imports overrides in pyproject.toml, and neither reaches a consumer. Only inline comments in shipped source do.
Definition of done
- No errors originating in pymongo or bson when a consumer type-checks library code against a plain pip install pymongo.
- Existing suppressions name the code mypy actually reports.
- Genuine annotation gaps are fixed, not suppressed.
- A regression check that runs against an install with no extras. Adding extras to a typing job hides the problem instead of testing it.
Pitfalls
- Some findings live in the generated synchronous tree and must be fixed in pymongo/asynchronous/ or tools/synchro.py. At least one is a synchro artifact: an await asyncio.gather(...) carrying a correct func-returns-value ignore becomes a bare call once the await is stripped, and then reports call-overload instead.
- Verify against a real install and clear .mypy_cache between runs. uv run --with <path> serves cached builds, and stale caches change the reported count.