Mypy Callable type does not seem to work inside a class

Viewed 2085

I am trying to use type hinting on a callback function/method which is passed as an argument. See the below example. The "function based" implementation works: Mypy reports the expected error.

error: Argument 1 to "main_with_callback" has incompatible type "Callable[[], Any]"; expected "Callable[[str], Any]"

If I do the same from inside a class. The error is not reported. It seems only the return type of the Callable definition is evaluated. I can't see anything wrong. Anyone a suggestion ?

from typing import Callable, Any

# Functions with callback as argument.

def callback():
    print("any arg")


def main_with_callback(callback: Callable[[str], Any]):
    callback("this is the callback")


main_with_callback(callback)

# Class with callback as argument.

class A:
    def __init__(self):
        self.main_with_callback(self.the_callback)

    def main_with_callback(self, _callback: Callable[[str], Any]):
        _callback("this is the callback")

    def the_callback(self):
        print("called")


a = A()

1 Answers

Mypy docs says that:

Functions that do not have any annotations (neither for any argument nor for the return type) are not type-checked

And in other words here:

bodies of functions that don’t have any explicit types in their function annotation are dynamically typed (operations are checked at runtime). Code outside functions is statically typed by default, and types of variables are inferred.

The call main_with_callback is outside any function, hence, static type checking is performed for this by default. But call self.main_with_callback is inside not annotated __init__ function and for this dynamic type checking is performed.

To enable static type checking for code inside __init__ you can add some annotations for __init__, or use mypy command line options described here, e.g --check-untyped-defs

class A:
    def __init__(self) -> None:
        self.main_with_callback(self.the_callback) # error
        reveal_type(self.the_callback)
Related