Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why won't mypy understand this object instantiation?

I'm trying to define a class that takes another class as an attribute _model and will instantiate objects of that class.

from abc import ABC
from typing import Generic, TypeVar, Any, ClassVar, Type

Item = TypeVar("Item", bound=Any)


class SomeClass(Generic[Item], ABC):
    _model: ClassVar[Type[Item]]

    def _compose_item(self, **attrs: Any) -> Item:
        return self._model(**attrs)

I think it should be obvious that self._model(**attrs) returns an instance of Item, since _model is explicitly declared as Type[Item] and attrs is declared as Dict[str, Any].

But what I'm getting from mypy 0.910 is:

test.py: note: In member "_compose_item" of class "SomeClass":
test.py:11: error: Returning Any from function declared to return "Item"
            return self._model(**attrs)
            ^

What am I doing wrong?

like image 230
jpmelos Avatar asked Sep 26 '21 22:09

jpmelos


People also ask

How to ignore mypy error?

You can use a special comment # type: ignore[code, ...] to only ignore errors with a specific error code (or codes) on a particular line. This can be used even if you have not configured mypy to show error codes. Currently it's only possible to disable arbitrary error codes on individual lines using this comment.

What is MYPY Python?

“Mypy is an optional static type checker for Python that aims to combine the benefits of dynamic (or 'duck') typing and static typing. Mypy combines the expressive power and convenience of Python with a powerful type system and compile-time type checking.” A little background on the Mypy project.

Why is assert not working in mypy?

Again, mypy will not report any errors. The type of foo.bar is str, and mypy reasons that it can never be None. Hence the assert statement will always fail and the statement below will never be executed. (Note that in Python, None is not an empty reference but an object of type None .)

Why can’t I install mypy?

Statically typed code is often identical to normal Python code (except for type annotations), but sometimes you need to do things slightly differently. If installation fails, you’ve probably hit one of these issues: Mypy needs Python 3.5 or later to run. You may have to run pip like this: python3 -m pip install mypy.

How do you check if a type is INT in mypy?

Mypy can usually infer the types correctly when using isinstance type tests, but for other kinds of checks you may need to add an explicit type cast: def f(o: object) -> None: if type(o) is int: o = cast(int, o) g(o + 1) # This would be an error without the cast ... else: ...

Why does mypy report an error when I try to call none?

(Note that in Python, None is not an empty reference but an object of type None .) In this example mypy will go on to check the last line and report an error, since mypy thinks that the condition could be either True or False: If you use the --warn-unreachable flag, mypy will generate an error about each unreachable code block.


1 Answers

MyPy can sometimes be a bit funny about the types of classes. You can solve this by specifying _model as Callable[..., Item] (which, after all, isn't a lie) instead of Type[Item]:

from abc import ABC
from typing import Generic, TypeVar, Any, ClassVar, Callable

Item = TypeVar("Item")


class SomeClass(Generic[Item], ABC):
    _model: ClassVar[Callable[..., Item]]

    def _compose_item(self, **attrs: Any) -> Item:
        return self._model(**attrs)
like image 52
Alex Waygood Avatar answered Oct 23 '22 05:10

Alex Waygood