How to tackle "Statement is unreachable [unreachable]" with mypy when setting attribute value in a method?
09:22 23 Mar 2024

Problem description

Suppose a following test

class Foo:

    def __init__(self):
        self.value: int | None = None

    def set_value(self, value: int | None):
        self.value = value


def test_foo():

    foo = Foo()
    assert foo.value is None
    foo.set_value(1)
    assert isinstance(foo.value, int)
    assert foo.value == 1 # unreachable

The test:

  • First, checks that foo.value is something
  • Then, sets the value using a method.
  • Then it checks that the foo.value has changed.

When running the test with mypy version 1.9.0 (latest at the time of writing), and having warn_unreachable set to True, one gets:

(venv) niko@niko-ubuntu-home:~/code/myproj$ python -m mypy tests/test_foo.py 
tests/test_foo.py:16: error: Statement is unreachable  [unreachable]
Found 1 error in 1 file (checked 1 source file)

What I have found

from safe_assert import safe_assert

def test_foo():

    foo = Foo()
    safe_assert(foo.value is None)
    foo.set_value(1)
    safe_assert(isinstance(foo.value, int))
    assert foo.value == 1

the problem persists (safe-assert 0.4.0)[1]. This time, both mypy and VS Code Pylance think that foo.set_value(1) two lines above is not reachable.

Question

How can I say to mypy that the foo.value has changed to int and that it should continue checking also everything under the assert isinstance(foo.value, int) line?


[1] UPDATE: The safe_assert v. 0.5.0 has fixed the issue

python mypy python-typing