this is from November 2021, but it was just linked in the release announcement for urllib3 v2.0.0 a few days ago:
Strictly type-hinted APIs
The entire urllib3 v2.0.0 package now has strict type hints included with every install. This means that auto-complete and type-checking tooling like mypy will natively work with the urllib3 module making it even easier to use with confidence. As a part of adding type hints to our entire API, we also wrote an extensive case study for adding type hints to urllib3 and what we learned (and fixed!) along the way.
talks about how they incrementally added type hints to an existing large-ish codebase, including their test suite itself, and the benefits they got from doing that:
When we originally started this journey our primary goal was to provide a good experience for users who wanted to use type checking tools with urllib3. We weren’t expecting to find and fix many defects.
After all, urllib3 has over 1800 test cases, 100% test line coverage, and is likely some of the most pervasive third-party Python code in the solar system.
Despite all of the above, the inclusion of type checking to our CI has yielded many improvements to our code that likely wouldn't have been discovered otherwise. For this reason we recommend projects evaluate adding type hints and strict type checking to their development workflow instead of relying on testing alone.
[...]
We wanted to add Mypy to our continuous integration to ensure new contributors wouldn’t accidentally break type hints but we also wanted to add Mypy incrementally so it wouldn’t grind all our development to a halt.
If you’ve ever tried running Mypy on a single file in a project without any type hints you’re unlikely to only receive errors from the file you ran Mypy on. Instead you’re likely to receive type errors from files where you imported other APIs, both within the project and third-party modules.
This makes adding type hints seem like a daunting task, either needing to be added all at once or with tons of temporary # type: ignore annotations along the way to ensure Mypy continues to pass in CI.
Our solution to this was to maintain a list of files in our project that we knew had correct type hints. Mypy would be run one by one on every file and the list of issues that were detected by Mypy would be gathered up, de-duplicated, and crucially we’d filter out files that weren’t on the “known-good” list.
This meant that once a file was complete we’d add the path to the known-good list to ensure that future contributions wouldn’t regress on our type hints.
(but for a healthy defense of python’s dynamic typing, see: Python’s “Disappointing” Superpowers)















