pythonpytestpython-typingmypy

How to make mypy ignore pytest.approx in a code outside of test functions


I want to use pytest.approx(...) inside immutable dataclasses (frozen=True) in my unittest, so I can use a single assert to check possibly quite complex structures.

This works fine when I use these structures inside test functions, but when I declare a global variable/constant which uses approx, I get an error in mypy.

Example code:

from pytest import approx
from typing import Final
from dataclasses import dataclass

@dataclass(frozen=True)
class A:
    x: float


EXPECTED_VALUE_1: Final = A(approx(0.5)) # <- this is the problem

def test_1():
    assert A(0.5) == EXPECTED_VALUE_1

def test_2():
    expected_value_2 = A(approx(0.5)) # <- this is fine
    assert A(0.5) == expected_value_2

The error:

$ mypy .
a.py:10: error: Argument 1 to "A" has incompatible type "ApproxBase"; expected "float"  [arg-type]
Found 1 error in 1 file (checked 1 source file)

I think I know why - mypy by default ignores untyped functions (and my unittest functions are all untyped), but outside those functions it checks.

I've found 2 solutions:

  1. add # type: ignore where this happens - which is in my opinion ugly and makes the code less readable
  2. using pytest.fixture in place of a global constant. But in many cases, I have a lot of these EXPECTED_... constants (which are using approx) and converting them to fixtures makes code a lot longer and less readable, so, for simple, immutable data, I would like to keep using these global constants.

Can I somehow configure mypy to just ignore every call to approx and check everything else?

Configuration:

Suggested solutions/duplicate questions:


Solution

  • You can go with duck-like-typing and define statically different version of approx:

    from typing import TYPE_CHECKING
    if TYPE_CHECKING:
        def approx[T](expected: T, rel=None, abs=None, nan_ok=False) -> T: ...
    else:
        from pytest import approx
    

    With this approx(0.5) will viewed as a float by your type-checker, at runtime the normal ApproxBase is used.