Search code examples
pythonmypypython-typingpydantic

How to run mypy on 3rd party package version sensitive code


I'm currently responsible to write library code that is both compatible with pydantic v1 and v2.

Getting the code functional is more or less straightforward since you can make version sensitive choices in your code to satisfy your test suite, e.g. using patterns like this:

import pydantic

PYDANTIC_VERSION = packaging.version.parse(pydantic.__version__)

if PYDANTIC_VERSION.major == 1:
    # do some v1 things
else:
    # do some v2 things

However, getting this code compatible with mypy type checks seems difficult since mypy will not resolve the PYDANTIC_VERSION variable and always run through both sides of the if blocks. This will constantly trigger mypy errors in both worlds inside our CI (where mypy is supposed to run against both versions).

This makes total sense since mypy is not a runtime type checker, but I wonder if there any best practices to achieve such a goal.

The issue isn't really unique to pydantic, that's just an example. I know that such version switches do work on the interpreter version (sys.version_info) but I cannot find a way to have mypy skip over an entire block of code if the version of pydantic is equal to either 1.x.x or 2.x.x

I've searched issues on mypy and Stack Overflow, but given the thousands of issues and articles it's very hard to find existing (eventually solved or fixed) details on the topic.


Solution

  • --always-true and --always-false exist, so you can make a boolean flag named PYDANTIC_V1 and run Mypy twice on the same code:

    $ pip install "pydantic==1.*"
    $ mypy file.py --always-true=PYDANTIC_V1
    
    $ pip install -U pydantic
    $ mypy file.py --always-false=PYDANTIC_V1