Search code examples
pythonmypy

mypy unreachable on Guard Clause


I have a problem where when I try to check if the given value's type is not what I expect I'll log it and raise an error.

However, mypy is complaining. What I'm doing wrong?

Simplified example:

from __future__ import annotations
from typing import Union
from logging import getLogger


class MyClass:
    def __init__(self, value: Union[float, int]) -> None:
        self.logger = getLogger("dummy")
        self.value = value

    def __add__(self, other: Union[MyClass, float, int]) -> MyClass:
        if not isinstance(other, (MyClass, float, int)):
            self.logger.error("Other must be either MyClass, float or int") # error: Statement is unreachable  [unreachable]
            raise NotImplementedError

        return self.add(other)

    def add(self, other: Union[MyClass, float, int]) -> MyClass:
        if isinstance(other, MyClass):
            return MyClass(self.value + other.value)

        return MyClass(self.value + other)

Please notice it does not complain when I run it on mypy-play.net but locally it raises:

main.py:13: error: Statement is unreachable  [unreachable]
Found 1 error in 1 file (checked 1 source file)

Solution

  • Mypy is complaining because due to the input you set Union[MyClass, float, int] and your condition if not isinstance(other, (MyClass, float, int)):, if the arguments follows the given types, the code will never be reached.

    Mypy expect that everybody using your code will sent correct argument types (that's why you add types). You can disable this warning either with a type: ignore[unreachable] or just by unsettling the option in local.

    For the mypy-playground, you have to activate the option Option to activate --warn unreachable